Merge branch 'master' of https://github.com/86Box/86Box into cleanup30

# Conflicts:
#	src/include/86box/machine.h
#	src/machine/m_at_socket7.c
#	src/machine/machine_table.c
#	src/video/vid_tgui9440.c
#	src/win/win.c
This commit is contained in:
RichardG867
2021-11-14 13:45:37 -03:00
172 changed files with 16726 additions and 5703 deletions

View File

@@ -13,28 +13,13 @@
# Copyright 2020,2021 David Hrdlička.
#
add_library(chipset OBJECT 82c100.c acc2168.c cs8230.c ali1217.c ali1429.c ali1489.c et6000.c headland.c
intel_82335.c cs4031.c intel_420ex.c intel_4x0.c intel_sio.c intel_piix.c ../ioapic.c
neat.c opti283.c opti291.c opti495.c opti822.c opti895.c opti5x7.c scamp.c scat.c
sis_85c310.c sis_85c4xx.c sis_85c496.c sis_85c50x.c sis_5511.c sis_5571.c
umc_8886.c umc_8890.c umc_hb4.c
via_vt82c49x.c via_vt82c505.c sis_85c310.c sis_85c4xx.c sis_85c496.c sis_85c50x.c
gc100.c stpc.c
via_apollo.c via_pipc.c wd76c10.c
vl82c480.c)
if(I450KX)
target_sources(chipset PRIVATE intel_i450kx.c)
endif()
if(M154X)
target_sources(chipset PRIVATE ali1531.c)
target_sources(chipset PRIVATE ali1543.c)
endif()
if(M6117)
target_sources(chipset PRIVATE ali6117.c)
endif()
add_library(chipset OBJECT 82c100.c acc2168.c cs8230.c ali1429.c ali1489.c ali1531.c ali1541.c ali1543.c
ali1621.c ali6117.c headland.c ims8848.c intel_82335.c contaq_82c59x.c cs4031.c intel_420ex.c
intel_4x0.c intel_i450kx.c intel_sio.c intel_piix.c ../ioapic.c neat.c opti283.c opti291.c opti391.c
opti495.c opti822.c opti895.c opti5x7.c scamp.c scat.c sis_85c310.c sis_85c4xx.c
sis_85c496.c sis_85c50x.c sis_5511.c sis_5571.c via_vt82c49x.c via_vt82c505.c sis_85c310.c
sis_85c4xx.c sis_85c496.c sis_85c50x.c gc100.c stpc.c umc_8886.c umc_hb4.c via_apollo.c
via_pipc.c vl82c480.c wd76c10.c)
if(OLIVETTI)
target_sources(chipset PRIVATE olivetti_eva.c)

View File

@@ -1,145 +0,0 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Implementation of the ALi M1217 chipset.
*
* Note: This chipset has no datasheet, everything were done via
* reverse engineering the BIOS of various machines using it.
*
* Authors: Tiseno100
*
* Copyright 2021 Tiseno100
*
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include "cpu.h"
#include <86box/timer.h>
#include <86box/io.h>
#include <86box/device.h>
#include <86box/mem.h>
#include <86box/port_92.h>
#include <86box/chipset.h>
#ifdef ENABLE_ALI1217_LOG
int ali1217_do_log = ENABLE_ALI1217_LOG;
static void
ali1217_log(const char *fmt, ...)
{
va_list ap;
if (ali1217_do_log)
{
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define ali1217_log(fmt, ...)
#endif
typedef struct
{
uint8_t index, regs[256];
int cfg_locked;
} ali1217_t;
static void ali1217_shadow_recalc(int reg_15, ali1217_t *dev)
{
for (uint8_t i = 0; i < 4; i++)
mem_set_mem_state_both((reg_15 ? 0xe0000 : 0xc0000) + (i << 15), 0x8000, ((dev->regs[0x14 + reg_15] & (1 << (i * 2))) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x14 + reg_15] & (1 << ((i * 2) + 1))) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY));
flushmmucache_nopc();
}
static void
ali1217_write(uint16_t addr, uint8_t val, void *priv)
{
ali1217_t *dev = (ali1217_t *)priv;
switch (addr)
{
case 0x22:
dev->index = val;
break;
case 0x23:
if (dev->index != 0x13)
ali1217_log("ALi M1217: dev->regs[%02x] = %02x\n", dev->index, val);
else
dev->cfg_locked = !(val == 0xc5);
if (!dev->cfg_locked)
{
dev->regs[dev->index] = val;
if ((dev->index == 0x14) || (dev->index == 0x15))
ali1217_shadow_recalc(dev->index & 1, dev);
}
break;
}
}
static uint8_t
ali1217_read(uint16_t addr, void *priv)
{
ali1217_t *dev = (ali1217_t *)priv;
return (addr == 0x23) ? dev->regs[dev->index] : 0xff;
}
static void
ali1217_close(void *priv)
{
ali1217_t *dev = (ali1217_t *)priv;
free(dev);
}
static void *
ali1217_init(const device_t *info)
{
ali1217_t *dev = (ali1217_t *)malloc(sizeof(ali1217_t));
memset(dev, 0, sizeof(ali1217_t));
device_add(&port_92_device);
dev->cfg_locked = 1;
/*
ALi M1217 Ports
22h Index Port
23h Data Port
*/
io_sethandler(0x0022, 0x0002, ali1217_read, NULL, NULL, ali1217_write, NULL, NULL, dev);
return dev;
}
const device_t ali1217_device = {
"ALi M1217",
0,
0,
ali1217_init,
ali1217_close,
NULL,
{NULL},
NULL,
NULL,
NULL};

View File

@@ -8,15 +8,71 @@
*
* Implementation of the ALi M1429 chipset.
*
* Note: This chipset has no datasheet, everything were done via
* reverse engineering the BIOS of various machines using it.
* Note: This chipset has no datasheet, everything were done via
* reverse engineering the BIOS of various machines using it.
*
* Authors: Tiseno100
*
* Copyright 2020 Tiseno100
* Authors: Tiseno100,
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2020,2021 Tiseno100.
* Copyright 2021,2021 Miran Grca.
*/
/*
ALi M1429/M1429G Configuration Registers
Notes: Incorporated sometimes with a M1435 PCI-to-VLB Bridge
M1429G is just a 1429 with Green Functionality
SMM in it's entirety needs more research
Warning: Register documentation may be inaccurate!
Register 03h: Write C5h to unlock the configuration registers
Register 10h & 11h: DRAM Bank Configuration
Register 12h:
Bit 2: Memory Remapping Enable (128KB)
Register 13h:
Bit 7: Shadow RAM Enable for F8000-FFFFF
Bit 6: Shadow RAM Enable for F0000-F7FFF
Bit 5: Shadow RAM Enable for E8000-FFFFF
Bit 4: Shadow RAM Enable for E0000-F7FFF
Bit 3: Shadow RAM Enable for D8000-FFFFF
Bit 2: Shadow RAM Enable for D0000-F7FFF
Bit 1: Shadow RAM Enable for C8000-FFFFF
Bit 0: Shadow RAM Enable for C0000-F7FFF
Register 14h:
Bit 1: Shadow RAM Write for Enabled Segments
Bit 0: Shadow RAM Read for Enabled Segments
Register 18h:
Bit 6-5-4 (Cache Size)
0 0 0 32KB
0 0 1 128KB
0 1 0 256KB
0 1 1 512KB
1 0 0 64KB
1 0 1 256KB
1 1 0 512KB
1 1 1 1MB
Bit 1: L2 Cache Enable
Register 20h:
Bits 2-1-0: Bus Clock Speed
0 0 0: 7.1519Mhz (ATCLK2)
0 0 1: CLK2IN/4
0 1 0: CLK2IN/5
0 1 1: CLK2IN/6
1 0 0: CLK2IN/8
1 0 1: CLK2IN/10
1 1 0: CLK2IN/12
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
@@ -38,17 +94,19 @@
#include <86box/smram.h>
#include <86box/chipset.h>
#define disabled_shadow (MEM_READ_EXTANY | MEM_WRITE_EXTANY)
#define GREEN dev->is_g /* Is G Variant */
#ifdef ENABLE_ALI1429_LOG
int ali1429_do_log = ENABLE_ALI1429_LOG;
static void
ali1429_log(const char *fmt, ...)
{
va_list ap;
if (ali1429_do_log)
{
if (ali1429_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
@@ -58,17 +116,17 @@ ali1429_log(const char *fmt, ...)
#define ali1429_log(fmt, ...)
#endif
typedef struct
{
uint8_t index, cfg_locked,
regs[256];
smram_t *smram;
uint8_t is_g, index, cfg_locked, reg_57h,
regs[90];
} ali1429_t;
static void ali1429_shadow_recalc(ali1429_t *dev)
{
static void
ali1429_shadow_recalc(ali1429_t *dev)
{
uint32_t base, i, can_write, can_read;
shadowbios = (dev->regs[0x13] & 0x40) && (dev->regs[0x14] & 0x01);
@@ -77,66 +135,150 @@ static void ali1429_shadow_recalc(ali1429_t *dev)
can_write = (dev->regs[0x14] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
can_read = (dev->regs[0x14] & 0x01) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
for (i = 0; i < 8; i++)
{
for (i = 0; i < 8; i++) {
base = 0xc0000 + (i << 15);
if (dev->regs[0x13] & (1 << i))
mem_set_mem_state_both(base, 0x8000, can_read | can_write);
else
mem_set_mem_state_both(base, 0x8000, disabled_shadow);
mem_set_mem_state_both(base, 0x8000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
}
flushmmucache();
flushmmucache_nopc();
}
static void
ali1429_write(uint16_t addr, uint8_t val, void *priv)
{
ali1429_t *dev = (ali1429_t *)priv;
switch (addr)
{
case 0x22:
dev->index = val;
break;
switch (addr) {
case 0x22:
dev->index = val;
break;
case 0x23:
if (dev->index != 0x03)
ali1429_log("M1429: dev->regs[%02x] = %02x\n", dev->index, val);
case 0x23:
#ifdef ENABLE_ALI1429_LOG
if (dev->index != 0x03)
ali1429_log("M1429: dev->regs[%02x] = %02x\n", dev->index, val);
#endif
if (dev->index == 0x03)
dev->cfg_locked = !(val == 0xc5);
if (dev->index == 0x03)
dev->cfg_locked = !(val == 0xc5);
if (!dev->cfg_locked)
{
dev->regs[dev->index] = val;
if (!dev->cfg_locked) {
/* Common M1429 Registers */
switch (dev->index) {
case 0x10: case 0x11:
dev->regs[dev->index] = val;
break;
switch (dev->index)
{
case 0x13:
case 0x14:
ali1429_shadow_recalc(dev);
break;
case 0x12:
dev->regs[dev->index] = val;
if(val & 4)
mem_remap_top(128);
else
mem_remap_top(0);
break;
case 0x18:
cpu_cache_ext_enabled = !!(val & 2);
cpu_update_waitstates();
break;
}
}
case 0x13: case 0x14:
dev->regs[dev->index] = val;
ali1429_shadow_recalc(dev);
break;
break;
case 0x15: case 0x16:
case 0x17:
dev->regs[dev->index] = val;
break;
case 0x18:
dev->regs[dev->index] = (val & 0x8f) | 0x20;
cpu_cache_ext_enabled = !!(val & 2);
cpu_update_waitstates();
break;
case 0x19: case 0x1a:
case 0x1e:
dev->regs[dev->index] = val;
break;
case 0x20:
dev->regs[dev->index] = val;
switch(val & 7) {
case 0: case 7: /* Illegal */
cpu_set_isa_speed(7159091);
break;
case 1:
cpu_set_isa_speed(cpu_busspeed / 4);
break;
case 2:
cpu_set_isa_speed(cpu_busspeed / 5);
break;
case 3:
cpu_set_isa_speed(cpu_busspeed / 6);
break;
case 4:
cpu_set_isa_speed(cpu_busspeed / 8);
break;
case 5:
cpu_set_isa_speed(cpu_busspeed / 10);
break;
case 6:
cpu_set_isa_speed(cpu_busspeed / 12);
break;
}
break;
case 0x21 ... 0x27:
dev->regs[dev->index] = val;
break;
}
/* M1429G Only Registers */
if (GREEN) {
switch (dev->index) {
case 0x30 ... 0x41:
case 0x43: case 0x45:
case 0x4a:
dev->regs[dev->index] = val;
break;
case 0x57:
dev->reg_57h = val;
break;
}
}
}
break;
}
}
static uint8_t
ali1429_read(uint16_t addr, void *priv)
{
ali1429_t *dev = (ali1429_t *)priv;
return (addr == 0x23) ? dev->regs[dev->index] : 0xff;
uint8_t ret = 0xff;
if ((addr == 0x23) && (dev->index >= 0x10) && (dev->index <= 0x4a))
ret = dev->regs[dev->index];
else if ((addr == 0x23) && (dev->index == 0x57))
ret = dev->reg_57h;
else if (addr == 0x22)
ret = dev->index;
return ret;
}
static void
ali1429_close(void *priv)
{
@@ -145,24 +287,53 @@ ali1429_close(void *priv)
free(dev);
}
static void
ali1429_defaults(ali1429_t *dev)
{
/* M1429 Defaults */
dev->regs[0x10] = 0xf0;
dev->regs[0x11] = 0xff;
dev->regs[0x12] = 0x10;
dev->regs[0x14] = 0x48;
dev->regs[0x15] = 0x40;
dev->regs[0x17] = 0x7a;
dev->regs[0x1a] = 0x80;
dev->regs[0x22] = 0x80;
dev->regs[0x23] = 0x57;
dev->regs[0x25] = 0xc0;
dev->regs[0x27] = 0x30;
/* M1429G Default Registers */
if (GREEN) {
dev->regs[0x31] = 0x88;
dev->regs[0x32] = 0xc0;
dev->regs[0x38] = 0xe5;
dev->regs[0x40] = 0xe3;
dev->regs[0x41] = 2;
dev->regs[0x45] = 0x80;
}
}
static void *
ali1429_init(const device_t *info)
{
ali1429_t *dev = (ali1429_t *)malloc(sizeof(ali1429_t));
memset(dev, 0, sizeof(ali1429_t));
/*
M1429 Ports:
22h Index Port
23h Data Port
dev->cfg_locked = 1;
GREEN = info->local;
/* M1429 Ports:
22h Index Port
23h Data Port
*/
io_sethandler(0x0022, 0x0002, ali1429_read, NULL, NULL, ali1429_write, NULL, NULL, dev);
dev->cfg_locked = 1;
device_add(&apm_device);
device_add(&port_92_device);
/* dev->smram = smram_add(); */
ali1429_defaults(dev);
return dev;
}
@@ -171,10 +342,16 @@ const device_t ali1429_device = {
"ALi M1429",
0,
0,
ali1429_init,
ali1429_close,
NULL,
{NULL},
NULL,
NULL,
NULL};
ali1429_init, ali1429_close, NULL,
{ NULL }, NULL, NULL,
NULL
};
const device_t ali1429g_device = {
"ALi M1429G",
0,
1,
ali1429_init, ali1429_close, NULL,
{ NULL }, NULL, NULL,
NULL
};

View File

@@ -34,6 +34,7 @@
#include <86box/chipset.h>
typedef struct ali1531_t
{
uint8_t pci_conf[256];
@@ -41,201 +42,270 @@ typedef struct ali1531_t
smram_t *smram;
} ali1531_t;
void ali1531_shadow_recalc(int cur_reg, ali1531_t *dev)
{
for (uint32_t i = 0; i < 8; i++)
mem_set_mem_state_both(0xc0000 + ((cur_reg & 1) << 17) + (i << 14), 0x4000, (((dev->pci_conf[0x4c + (cur_reg & 1)] >> i) & 1) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | (((dev->pci_conf[0x4e + (cur_reg & 1)] >> i) & 1) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY));
flushmmucache_nopc();
#ifdef ENABLE_ALI1531_LOG
int ali1531_do_log = ENABLE_ALI1531_LOG;
static void
ali1531_log(const char *fmt, ...)
{
va_list ap;
if (ali1531_do_log)
{
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define ali1531_log(fmt, ...)
#endif
void ali1531_smm_recalc(uint8_t smm_state, ali1531_t *dev)
static void
ali1531_smram_recalc(uint8_t val, ali1531_t *dev)
{
smram_disable_all();
if (dev->pci_conf[0x48] & 1)
{
switch (smm_state)
{
case 0:
smram_enable(dev->smram, 0xd0000, 0xb0000, 0x10000, 0, 1);
smram_map(1, 0xd0000, 0x10000, 1);
break;
case 1:
smram_enable(dev->smram, 0xd0000, 0xb0000, 0x10000, 1, 1);
smram_map(1, 0xd0000, 0x10000, 1);
break;
case 2:
smram_enable(dev->smram, 0xa0000, 0xa0000, 0x20000, 0, 1);
smram_map(1, 0xa0000, 0x20000, (dev->pci_conf[0x48] & 0x10) ? 2 : 1);
break;
case 3:
smram_enable(dev->smram, 0xa0000, 0xa0000, 0x20000, 1, 1);
smram_map(1, 0xa0000, 0x20000, (dev->pci_conf[0x48] & 0x10) ? 2 : 1);
break;
case 4:
smram_enable(dev->smram, 0x30000, 0xb0000, 0x10000, 0, 1);
smram_map(1, 0x30000, 0x10000, 1);
break;
case 5:
smram_enable(dev->smram, 0x30000, 0xb0000, 0x10000, 1, 1);
smram_map(1, 0x30000, 0x10000, 1);
break;
}
if (val & 1) {
switch (val & 0x0c) {
case 0x00:
ali1531_log("SMRAM: D0000 -> B0000 (%i)\n", val & 2);
smram_enable(dev->smram, 0xd0000, 0xb0000, 0x10000, val & 2, 1);
if (val & 0x10)
mem_set_mem_state_smram_ex(1, 0xd0000, 0x10000, 0x02);
break;
case 0x04:
ali1531_log("SMRAM: A0000 -> A0000 (%i)\n", val & 2);
smram_enable(dev->smram, 0xa0000, 0xa0000, 0x20000, val & 2, 1);
if (val & 0x10)
mem_set_mem_state_smram_ex(1, 0xa0000, 0x20000, 0x02);
break;
case 0x08:
ali1531_log("SMRAM: 30000 -> B0000 (%i)\n", val & 2);
smram_enable(dev->smram, 0x30000, 0xb0000, 0x10000, val & 2, 1);
if (val & 0x10)
mem_set_mem_state_smram_ex(1, 0x30000, 0x10000, 0x02);
break;
}
}
flushmmucache_nopc();
}
static void
ali1531_shadow_recalc(int cur_reg, ali1531_t *dev)
{
int i, bit, r_reg, w_reg;
uint32_t base, flags = 0;
shadowbios = shadowbios_write = 0;
for (i = 0; i < 16; i++) {
base = 0x000c0000 + (i << 14);
bit = i & 7;
r_reg = 0x4c + (i >> 3);
w_reg = 0x4e + (i >> 3);
flags = (dev->pci_conf[r_reg] & (1 << bit)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
flags |= ((dev->pci_conf[w_reg] & (1 << bit)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY);
if (base >= 0x000e0000) {
if (dev->pci_conf[r_reg] & (1 << bit))
shadowbios |= 1;
if (dev->pci_conf[w_reg] & (1 << bit))
shadowbios_write |= 1;
}
ali1531_log("%08X-%08X shadow: R%c, W%c\n", base, base + 0x00003fff,
(dev->pci_conf[r_reg] & (1 << bit)) ? 'I' : 'E', (dev->pci_conf[w_reg] & (1 << bit)) ? 'I' : 'E');
mem_set_mem_state_both(base, 0x00004000, flags);
}
flushmmucache_nopc();
}
static void
ali1531_write(int func, int addr, uint8_t val, void *priv)
{
ali1531_t *dev = (ali1531_t *)priv;
switch (addr)
{
case 0x05:
dev->pci_conf[addr] = val & 1;
break;
switch (addr) {
case 0x04:
dev->pci_conf[addr] = val;
break;
case 0x05:
dev->pci_conf[addr] = val & 0x01;
break;
case 0x07:
dev->pci_conf[addr] = val & 0xfe;
break;
case 0x07:
dev->pci_conf[addr] &= ~(val & 0xf8);
break;
case 0x0d:
dev->pci_conf[addr] = val & 0xf8;
break;
case 0x0d:
dev->pci_conf[addr] = val & 0xf8;
break;
case 0x40:
dev->pci_conf[addr] = val & 0xf1;
break;
case 0x2c: /* Subsystem Vendor ID */
case 0x2d:
case 0x2e:
case 0x2f:
if (dev->pci_conf[0x70] & 0x08)
dev->pci_conf[addr] = val;
break;
case 0x41:
dev->pci_conf[addr] = val & 0xdf;
break;
case 0x40:
dev->pci_conf[addr] = val & 0xf1;
break;
case 0x42: /* L2 Cache */
dev->pci_conf[addr] = val & 0xf7;
cpu_cache_ext_enabled = !!(val & 1);
cpu_update_waitstates();
break;
case 0x41:
dev->pci_conf[addr] = (val & 0xd6) | 0x08;
break;
case 0x43: /* L1 Cache */
dev->pci_conf[addr] = val;
cpu_cache_int_enabled = !!(val & 1);
cpu_update_waitstates();
break;
case 0x42: /* L2 Cache */
dev->pci_conf[addr] = val & 0xf7;
cpu_cache_ext_enabled = !!(val & 1);
cpu_update_waitstates();
break;
case 0x47:
dev->pci_conf[addr] = val & 0xfc;
case 0x43: /* L1 Cache */
dev->pci_conf[addr] = val;
cpu_cache_int_enabled = !!(val & 1);
cpu_update_waitstates();
break;
if (mem_size > 0xe00000)
mem_set_mem_state_both(0xe00000, 0x100000, !(val & 0x20) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY));
case 0x44:
dev->pci_conf[addr] = val;
break;
case 0x45:
dev->pci_conf[addr] = val;
break;
if (mem_size > 0xf00000)
mem_set_mem_state_both(0xf00000, 0x100000, !(val & 0x10) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY));
case 0x46:
dev->pci_conf[addr] = val;
break;
mem_set_mem_state_both(0xa0000, 0x20000, (val & 8) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY));
mem_set_mem_state_both(0x80000, 0x20000, (val & 4) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY));
break;
case 0x47:
dev->pci_conf[addr] = val & 0xfc;
case 0x48: /* SMRAM */
dev->pci_conf[addr] = val;
ali1531_smm_recalc((val >> 1) & 7, dev);
break;
if (mem_size > 0xe00000)
mem_set_mem_state_both(0xe00000, 0x100000, (val & 0x20) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL));
case 0x49:
dev->pci_conf[addr] = val & 0x73;
break;
if (mem_size > 0xf00000)
mem_set_mem_state_both(0xf00000, 0x100000, (val & 0x10) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL));
case 0x4c: /* Shadow RAM */
case 0x4d:
case 0x4e:
case 0x4f:
dev->pci_conf[addr] = val;
ali1531_shadow_recalc(addr, dev);
break;
mem_set_mem_state_both(0xa0000, 0x20000, (val & 8) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY));
mem_set_mem_state_both(0x80000, 0x20000, (val & 4) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL));
case 0x57: /* H2PO */
dev->pci_conf[addr] = val & 0x60;
if (!(val & 0x20))
outb(0x92, 0x01);
break;
flushmmucache_nopc();
break;
case 0x58:
dev->pci_conf[addr] = val & 0x83;
break;
case 0x48: /* SMRAM */
dev->pci_conf[addr] = val;
ali1531_smram_recalc(val, dev);
break;
case 0x5b:
dev->pci_conf[addr] = val & 0x4f;
break;
case 0x49:
dev->pci_conf[addr] = val & 0x73;
break;
case 0x5d:
dev->pci_conf[addr] = val & 0x53;
break;
case 0x4a:
dev->pci_conf[addr] = val;
break;
case 0x5f:
dev->pci_conf[addr] = val & 0x7f;
break;
case 0x4c ... 0x4f: /* Shadow RAM */
dev->pci_conf[addr] = val;
ali1531_shadow_recalc(val, dev);
break;
case 0x60: /* DRB's */
case 0x61:
case 0x62:
case 0x63:
case 0x64:
case 0x65:
case 0x66:
case 0x67:
case 0x68:
case 0x69:
case 0x6a:
case 0x6b:
case 0x6c:
case 0x6d:
case 0x6e:
case 0x6f:
dev->pci_conf[addr] = val;
spd_write_drbs(dev->pci_conf, 0x60, 0x6f, 1);
break;
case 0x50: case 0x51: case 0x52: case 0x54:
case 0x55: case 0x56:
dev->pci_conf[addr] = val;
break;
case 0x72:
dev->pci_conf[addr] = val & 0xf;
break;
case 0x57: /* H2PO */
dev->pci_conf[addr] = val & 0x60;
/* Find where the Shut-down Special cycle is initiated. */
// if (!(val & 0x20))
// outb(0x92, 0x01);
break;
case 0x74:
dev->pci_conf[addr] = val & 0x2b;
break;
case 0x58:
dev->pci_conf[addr] = val & 0x86;
break;
case 0x80:
dev->pci_conf[addr] = val & 0x84;
break;
case 0x59: case 0x5a:
case 0x5c:
dev->pci_conf[addr] = val;
break;
case 0x81:
dev->pci_conf[addr] = val & 0x81;
break;
case 0x5b:
dev->pci_conf[addr] = val & 0x4f;
break;
case 0x83:
dev->pci_conf[addr] = val & 0x10;
break;
case 0x5d:
dev->pci_conf[addr] = val & 0x53;
break;
default:
dev->pci_conf[addr] = val;
break;
case 0x5f:
dev->pci_conf[addr] = val & 0x7f;
break;
case 0x60 ... 0x6f: /* DRB's */
dev->pci_conf[addr] = val;
spd_write_drbs_interleaved(dev->pci_conf, 0x60, 0x6f, 1);
break;
case 0x70: case 0x71:
dev->pci_conf[addr] = val;
break;
case 0x72:
dev->pci_conf[addr] = val & 0x0f;
break;
case 0x74:
dev->pci_conf[addr] = val & 0x2b;
break;
case 0x76: case 0x77:
dev->pci_conf[addr] = val;
break;
case 0x80:
dev->pci_conf[addr] = val & 0x84;
break;
case 0x81:
dev->pci_conf[addr] = val & 0x81;
break;
case 0x83:
dev->pci_conf[addr] = val & 0x10;
break;
}
}
static uint8_t
ali1531_read(int func, int addr, void *priv)
{
ali1531_t *dev = (ali1531_t *)priv;
return dev->pci_conf[addr];
uint8_t ret = 0xff;
ret = dev->pci_conf[addr];
return ret;
}
static void
ali1531_reset(void *priv)
{
ali1531_t *dev = (ali1531_t *)priv;
int i;
/* Default Registers */
dev->pci_conf[0x00] = 0xb9;
@@ -267,11 +337,20 @@ ali1531_reset(void *priv)
ali1531_write(0, 0x42, 0x00, dev);
ali1531_write(0, 0x43, 0x00, dev);
ali1531_write(0, 0x47, 0x00, dev);
ali1531_write(0, 0x60, 0x08, dev);
ali1531_write(0, 0x61, 0x40, dev);
ali1531_write(0, 0x48, 0x00, dev);
for (i = 0; i < 4; i++)
ali1531_write(0, 0x4c + i, 0x00, dev);
for (i = 0; i < 16; i += 2) {
ali1531_write(0, 0x60 + i, 0x08, dev);
ali1531_write(0, 0x61 + i, 0x40, dev);
}
}
static void
ali1531_close(void *priv)
{
@@ -281,6 +360,7 @@ ali1531_close(void *priv)
free(dev);
}
static void *
ali1531_init(const device_t *info)
{
@@ -296,6 +376,7 @@ ali1531_init(const device_t *info)
return dev;
}
const device_t ali1531_device = {
"ALi M1531 CPU-to-PCI Bridge",
DEVICE_PCI,
@@ -306,4 +387,5 @@ const device_t ali1531_device = {
{NULL},
NULL,
NULL,
NULL};
NULL
};

656
src/chipset/ali1541.c Normal file
View File

@@ -0,0 +1,656 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Implementation of the ALi M1541/2 CPU-to-PCI Bridge.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2021 Miran Grca.
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/timer.h>
#include <86box/device.h>
#include <86box/io.h>
#include <86box/mem.h>
#include <86box/pci.h>
#include <86box/smram.h>
#include <86box/spd.h>
#include <86box/chipset.h>
typedef struct ali1541_t
{
uint8_t pci_conf[256];
smram_t * smram;
void * agp_bridge;
} ali1541_t;
#ifdef ENABLE_ALI1541_LOG
int ali1541_do_log = ENABLE_ALI1541_LOG;
static void
ali1541_log(const char *fmt, ...)
{
va_list ap;
if (ali1541_do_log)
{
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define ali1541_log(fmt, ...)
#endif
static void
ali1541_smram_recalc(uint8_t val, ali1541_t *dev)
{
smram_disable_all();
if (val & 1) {
switch (val & 0x0c) {
case 0x00:
ali1541_log("SMRAM: D0000 -> B0000 (%i)\n", val & 2);
smram_enable(dev->smram, 0xd0000, 0xb0000, 0x10000, val & 2, 1);
if (val & 0x10)
mem_set_mem_state_smram_ex(1, 0xd0000, 0x10000, 0x02);
break;
case 0x04:
ali1541_log("SMRAM: A0000 -> A0000 (%i)\n", val & 2);
smram_enable(dev->smram, 0xa0000, 0xa0000, 0x20000, val & 2, 1);
if (val & 0x10)
mem_set_mem_state_smram_ex(1, 0xa0000, 0x20000, 0x02);
break;
case 0x08:
ali1541_log("SMRAM: 30000 -> B0000 (%i)\n", val & 2);
smram_enable(dev->smram, 0x30000, 0xb0000, 0x10000, val & 2, 1);
if (val & 0x10)
mem_set_mem_state_smram_ex(1, 0x30000, 0x10000, 0x02);
break;
}
}
flushmmucache_nopc();
}
static void
ali1541_shadow_recalc(int cur_reg, ali1541_t *dev)
{
int i, bit, r_reg, w_reg;
uint32_t base, flags = 0;
shadowbios = shadowbios_write = 0;
for (i = 0; i < 16; i++) {
base = 0x000c0000 + (i << 14);
bit = i & 7;
r_reg = 0x56 + (i >> 3);
w_reg = 0x58 + (i >> 3);
flags = (dev->pci_conf[r_reg] & (1 << bit)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
flags |= ((dev->pci_conf[w_reg] & (1 << bit)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY);
if (base >= 0x000e0000) {
if (dev->pci_conf[r_reg] & (1 << bit))
shadowbios |= 1;
if (dev->pci_conf[w_reg] & (1 << bit))
shadowbios_write |= 1;
}
ali1541_log("%08X-%08X shadow: R%c, W%c\n", base, base + 0x00003fff,
(dev->pci_conf[r_reg] & (1 << bit)) ? 'I' : 'E', (dev->pci_conf[w_reg] & (1 << bit)) ? 'I' : 'E');
mem_set_mem_state_both(base, 0x00004000, flags);
}
flushmmucache_nopc();
}
static void
ali1541_mask_bar(ali1541_t *dev)
{
uint32_t bar, mask;
switch (dev->pci_conf[0xbc] & 0x0f) {
case 0x00:
default:
mask = 0x00000000;
break;
case 0x01:
mask = 0xfff00000;
break;
case 0x02:
mask = 0xffe00000;
break;
case 0x03:
mask = 0xffc00000;
break;
case 0x04:
mask = 0xff800000;
break;
case 0x06:
mask = 0xff000000;
break;
case 0x07:
mask = 0xfe000000;
break;
case 0x08:
mask = 0xfc000000;
break;
case 0x09:
mask = 0xf8000000;
break;
case 0x0a:
mask = 0xf0000000;
break;
}
bar = ((dev->pci_conf[0x13] << 24) | (dev->pci_conf[0x12] << 16)) & mask;
dev->pci_conf[0x12] = (bar >> 16) & 0xff;
dev->pci_conf[0x13] = (bar >> 24) & 0xff;
}
static void
ali1541_write(int func, int addr, uint8_t val, void *priv)
{
ali1541_t *dev = (ali1541_t *)priv;
switch (addr) {
case 0x04:
dev->pci_conf[addr] = val;
break;
case 0x05:
dev->pci_conf[addr] = val & 0x01;
break;
case 0x07:
dev->pci_conf[addr] &= ~(val & 0xf8);
break;
case 0x0d:
dev->pci_conf[addr] = val & 0xf8;
break;
case 0x12:
dev->pci_conf[0x12] = (val & 0xc0);
ali1541_mask_bar(dev);
break;
case 0x13:
dev->pci_conf[0x13] = val;
ali1541_mask_bar(dev);
break;
case 0x2c: /* Subsystem Vendor ID */
case 0x2d:
case 0x2e:
case 0x2f:
if (dev->pci_conf[0x90] & 0x01)
dev->pci_conf[addr] = val;
break;
case 0x34:
if (dev->pci_conf[0x90] & 0x02)
dev->pci_conf[addr] = val;
break;
case 0x40:
dev->pci_conf[addr] = val & 0x7f;
break;
case 0x41:
dev->pci_conf[addr] = val & 0x7f;
break;
case 0x42: /* L2 Cache */
dev->pci_conf[addr] = val;
cpu_cache_ext_enabled = !!(val & 1);
cpu_update_waitstates();
break;
case 0x43: /* PLCTL-Pipe Line Control */
dev->pci_conf[addr] = val & 0xf7;
break;
case 0x44:
dev->pci_conf[addr] = val;
break;
case 0x45:
dev->pci_conf[addr] = val;
break;
case 0x46:
dev->pci_conf[addr] = val & 0xf0;
break;
case 0x47:
dev->pci_conf[addr] = val;
break;
case 0x48:
dev->pci_conf[addr] = val;
break;
case 0x49:
dev->pci_conf[addr] = val;
break;
case 0x4a:
dev->pci_conf[addr] = val & 0xf8;
break;
case 0x4b:
dev->pci_conf[addr] = val;
break;
case 0x4c:
dev->pci_conf[addr] = val;
break;
case 0x4d:
dev->pci_conf[addr] = val;
break;
case 0x4e:
dev->pci_conf[addr] = val;
break;
case 0x4f:
dev->pci_conf[addr] = val;
break;
case 0x50:
dev->pci_conf[addr] = val & 0x71;
break;
case 0x51:
dev->pci_conf[addr] = val;
break;
case 0x52:
dev->pci_conf[addr] = val;
break;
case 0x53:
dev->pci_conf[addr] = val;
break;
case 0x54:
dev->pci_conf[addr] = val & 0x3c;
if (mem_size > 0xe00000)
mem_set_mem_state_both(0xe00000, 0x100000, (val & 0x20) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL));
if (mem_size > 0xf00000)
mem_set_mem_state_both(0xf00000, 0x100000, (val & 0x10) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL));
mem_set_mem_state_both(0xa0000, 0x20000, (val & 8) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY));
mem_set_mem_state_both(0x80000, 0x20000, (val & 4) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL));
flushmmucache_nopc();
break;
case 0x55: /* SMRAM */
dev->pci_conf[addr] = val & 0x1f;
ali1541_smram_recalc(val, dev);
break;
case 0x56 ... 0x59: /* Shadow RAM */
dev->pci_conf[addr] = val;
ali1541_shadow_recalc(val, dev);
break;
case 0x5a: case 0x5b:
dev->pci_conf[addr] = val;
break;
case 0x5c:
dev->pci_conf[addr] = val;
break;
case 0x5d:
dev->pci_conf[addr] = val & 0x17;
break;
case 0x5e:
dev->pci_conf[addr] = val;
break;
case 0x5f:
dev->pci_conf[addr] = val & 0xc1;
break;
case 0x60 ... 0x6f: /* DRB's */
dev->pci_conf[addr] = val;
spd_write_drbs_interleaved(dev->pci_conf, 0x60, 0x6f, 1);
break;
case 0x70:
dev->pci_conf[addr] = val;
break;
case 0x71:
dev->pci_conf[addr] = val;
break;
case 0x72:
dev->pci_conf[addr] = val & 0xc7;
break;
case 0x73:
dev->pci_conf[addr] = val & 0x1f;
break;
case 0x84: case 0x85:
dev->pci_conf[addr] = val;
break;
case 0x86:
dev->pci_conf[addr] = val & 0x0f;
break;
case 0x87: /* H2PO */
dev->pci_conf[addr] = val;
/* Find where the Shut-down Special cycle is initiated. */
// if (!(val & 0x20))
// outb(0x92, 0x01);
break;
case 0x88:
dev->pci_conf[addr] = val;
break;
case 0x89:
dev->pci_conf[addr] = val;
break;
case 0x8a:
dev->pci_conf[addr] = val;
break;
case 0x8b:
dev->pci_conf[addr] = val & 0x3f;
break;
case 0x8c:
dev->pci_conf[addr] = val;
break;
case 0x8d:
dev->pci_conf[addr] = val;
break;
case 0x8e:
dev->pci_conf[addr] = val;
break;
case 0x8f:
dev->pci_conf[addr] = val;
break;
case 0x90:
dev->pci_conf[addr] = val;
pci_bridge_set_ctl(dev->agp_bridge, val);
break;
case 0x91:
dev->pci_conf[addr] = val;
break;
case 0xb4:
if (dev->pci_conf[0x90] & 0x01)
dev->pci_conf[addr] = val & 0x03;
break;
case 0xb5:
if (dev->pci_conf[0x90] & 0x01)
dev->pci_conf[addr] = val & 0x02;
break;
case 0xb7:
if (dev->pci_conf[0x90] & 0x01)
dev->pci_conf[addr] = val;
break;
case 0xb8:
dev->pci_conf[addr] = val & 0x03;
break;
case 0xb9:
dev->pci_conf[addr] = val & 0x03;
break;
case 0xbb:
dev->pci_conf[addr] = val;
break;
case 0xbc:
dev->pci_conf[addr] = val & 0x0f;
ali1541_mask_bar(dev);
break;
case 0xbd:
dev->pci_conf[addr] = val & 0xf0;
break;
case 0xbe: case 0xbf:
dev->pci_conf[addr] = val;
break;
case 0xc0:
dev->pci_conf[addr] = val & 0x90;
break;
case 0xc1: case 0xc2:
case 0xc3:
dev->pci_conf[addr] = val;
break;
case 0xc8: case 0xc9:
dev->pci_conf[addr] = val;
break;
case 0xd1:
dev->pci_conf[addr] = val & 0xf1;
break;
case 0xd2: case 0xd3:
dev->pci_conf[addr] = val;
break;
case 0xe0: case 0xe1:
if (dev->pci_conf[0x90] & 0x20)
dev->pci_conf[addr] = val;
break;
case 0xe2:
if (dev->pci_conf[0x90] & 0x20)
dev->pci_conf[addr] = val & 0x3f;
break;
case 0xe3:
if (dev->pci_conf[0x90] & 0x20)
dev->pci_conf[addr] = val & 0xfe;
break;
case 0xe4:
if (dev->pci_conf[0x90] & 0x20)
dev->pci_conf[addr] = val & 0x03;
break;
case 0xe5:
if (dev->pci_conf[0x90] & 0x20)
dev->pci_conf[addr] = val;
break;
case 0xe6:
if (dev->pci_conf[0x90] & 0x20)
dev->pci_conf[addr] = val & 0xc0;
break;
case 0xe7:
if (dev->pci_conf[0x90] & 0x20)
dev->pci_conf[addr] = val;
break;
case 0xe8: case 0xe9:
if (dev->pci_conf[0x90] & 0x04)
dev->pci_conf[addr] = val;
break;
case 0xea:
dev->pci_conf[addr] = val & 0xcf;
break;
case 0xeb:
dev->pci_conf[addr] = val & 0xcf;
break;
case 0xec:
dev->pci_conf[addr] = val & 0x3f;
break;
case 0xed:
dev->pci_conf[addr] = val;
break;
case 0xee:
dev->pci_conf[addr] = val & 0x3e;
break;
case 0xef:
dev->pci_conf[addr] = val;
break;
case 0xf3:
dev->pci_conf[addr] = val & 0x08;
break;
case 0xf5:
dev->pci_conf[addr] = val;
break;
case 0xf6:
dev->pci_conf[addr] = val;
break;
case 0xf7:
dev->pci_conf[addr] = val & 0x43;
break;
}
}
static uint8_t
ali1541_read(int func, int addr, void *priv)
{
ali1541_t *dev = (ali1541_t *)priv;
uint8_t ret = 0xff;
ret = dev->pci_conf[addr];
return ret;
}
static void
ali1541_reset(void *priv)
{
ali1541_t *dev = (ali1541_t *)priv;
int i;
/* Default Registers */
dev->pci_conf[0x00] = 0xb9;
dev->pci_conf[0x01] = 0x10;
dev->pci_conf[0x02] = 0x41;
dev->pci_conf[0x03] = 0x15;
dev->pci_conf[0x04] = 0x06;
dev->pci_conf[0x05] = 0x00;
dev->pci_conf[0x06] = 0x10;
dev->pci_conf[0x07] = 0x04;
dev->pci_conf[0x08] = 0x00;
dev->pci_conf[0x09] = 0x00;
dev->pci_conf[0x0a] = 0x00;
dev->pci_conf[0x0b] = 0x06;
dev->pci_conf[0x0c] = 0x00;
dev->pci_conf[0x0d] = 0x20;
dev->pci_conf[0x0e] = 0x00;
dev->pci_conf[0x0f] = 0x00;
dev->pci_conf[0x2c] = 0xb9;
dev->pci_conf[0x2d] = 0x10;
dev->pci_conf[0x2e] = 0x41;
dev->pci_conf[0x2f] = 0x15;
dev->pci_conf[0x34] = 0xb0;
dev->pci_conf[0x89] = 0x20;
dev->pci_conf[0x8a] = 0x20;
dev->pci_conf[0x91] = 0x13;
dev->pci_conf[0xb0] = 0x02;
dev->pci_conf[0xb1] = 0xe0;
dev->pci_conf[0xb2] = 0x10;
dev->pci_conf[0xb4] = 0x03;
dev->pci_conf[0xb5] = 0x02;
dev->pci_conf[0xb7] = 0x1c;
dev->pci_conf[0xc8] = 0xbf;
dev->pci_conf[0xc9] = 0x0a;
dev->pci_conf[0xe0] = 0x01;
cpu_cache_int_enabled = 1;
ali1541_write(0, 0x42, 0x00, dev);
ali1541_write(0, 0x54, 0x00, dev);
ali1541_write(0, 0x55, 0x00, dev);
for (i = 0; i < 4; i++)
ali1541_write(0, 0x56 + i, 0x00, dev);
ali1541_write(0, 0x60 + i, 0x07, dev);
ali1541_write(0, 0x61 + i, 0x40, dev);
for (i = 0; i < 14; i += 2) {
ali1541_write(0, 0x62 + i, 0x00, dev);
ali1541_write(0, 0x63 + i, 0x00, dev);
}
}
static void
ali1541_close(void *priv)
{
ali1541_t *dev = (ali1541_t *)priv;
smram_del(dev->smram);
free(dev);
}
static void *
ali1541_init(const device_t *info)
{
ali1541_t *dev = (ali1541_t *)malloc(sizeof(ali1541_t));
memset(dev, 0, sizeof(ali1541_t));
pci_add_card(PCI_ADD_NORTHBRIDGE, ali1541_read, ali1541_write, dev);
dev->smram = smram_add();
ali1541_reset(dev);
dev->agp_bridge = device_add(&ali5243_agp_device);
return dev;
}
const device_t ali1541_device = {
"ALi M1541 CPU-to-PCI Bridge",
DEVICE_PCI,
0,
ali1541_init,
ali1541_close,
ali1541_reset,
{NULL},
NULL,
NULL,
NULL
};

File diff suppressed because it is too large Load Diff

685
src/chipset/ali1621.c Normal file
View File

@@ -0,0 +1,685 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Implementation of the ALi M1621/2 CPU-to-PCI Bridge.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2021 Miran Grca.
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/timer.h>
#include <86box/device.h>
#include <86box/io.h>
#include <86box/mem.h>
#include <86box/pci.h>
#include <86box/smram.h>
#include <86box/spd.h>
#include <86box/chipset.h>
typedef struct ali1621_t
{
uint8_t pci_conf[256];
smram_t * smram[2];
} ali1621_t;
#ifdef ENABLE_ALI1621_LOG
int ali1621_do_log = ENABLE_ALI1621_LOG;
static void
ali1621_log(const char *fmt, ...)
{
va_list ap;
if (ali1621_do_log)
{
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define ali1621_log(fmt, ...)
#endif
/* Table translated to a more sensible format:
Read cycles:
SMREN SMM Mode Code Data
0 X X PCI PCI
1 0 Close PCI PCI
1 0 Lock PCI PCI
1 0 Protect PCI PCI
1 0 Open DRAM DRAM
1 1 Open DRAM DRAM
1 1 Protect DRAM DRAM
1 1 Close DRAM PCI
1 1 Lock DRAM PCI
Write cycles:
SMWEN SMM Mode Data
0 X X PCI
1 0 Close PCI
1 0 Lock PCI
1 0 Protect PCI
1 0 Open DRAM
1 1 Open DRAM
1 1 Protect DRAM
1 1 Close PCI
1 1 Lock PCI
Explanation of the modes based above:
If SM*EN = 0, SMRAM is entirely disabled, otherwise:
If mode is Close or Lock, then SMRAM always goes to PCI outside SMM,
and data to PCI, code to DRAM in SMM;
If mode is Protect, then SMRAM always goes to PCI outside SMM and
DRAM in SMM;
If mode is Open, then SMRAM always goes to DRAM.
Read and write are enabled separately.
*/
static void
ali1621_smram_recalc(uint8_t val, ali1621_t *dev)
{
uint16_t access_smm = 0x0000, access_normal = 0x0000;
smram_disable_all();
if (val & 0xc0) {
/* SMRAM 0: A0000-BFFFF */
if (val & 0x80) {
access_smm = ACCESS_SMRAM_X;
switch (val & 0x30) {
case 0x10: /* Open. */
access_normal = ACCESS_SMRAM_RX;
/* FALLTHROUGH */
case 0x30: /* Protect. */
access_smm |= ACCESS_SMRAM_R;
break;
}
}
if (val & 0x40) switch (val & 0x30) {
case 0x10: /* Open. */
access_normal |= ACCESS_SMRAM_W;
/* FALLTHROUGH */
case 0x30: /* Protect. */
access_smm |= ACCESS_SMRAM_W;
break;
}
smram_enable(dev->smram[0], 0xa0000, 0xa0000, 0x20000, ((val & 0x30) == 0x10), (val & 0x30));
mem_set_access(ACCESS_NORMAL, 3, 0xa0000, 0x20000, access_normal);
mem_set_access(ACCESS_SMM, 3, 0xa0000, 0x20000, access_smm);
}
if (val & 0x08)
smram_enable(dev->smram[1], 0x38000, 0xa8000, 0x08000, 0, 1);
flushmmucache_nopc();
}
static void
ali1621_shadow_recalc(int cur_reg, ali1621_t *dev)
{
int i, r_bit, w_bit, reg;
uint32_t base, flags = 0;
shadowbios = shadowbios_write = 0;
/* C0000-EFFFF */
for (i = 0; i < 12; i++) {
base = 0x000c0000 + (i << 14);
r_bit = (i << 1) + 4;
reg = 0x84;
if (r_bit > 23) {
r_bit &= 7;
reg += 3;
} else if (r_bit > 15) {
r_bit &= 7;
reg += 2;
} else if (r_bit > 7) {
r_bit &= 7;
reg++;
}
w_bit = r_bit + 1;
flags = (dev->pci_conf[reg] & (1 << r_bit)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
flags |= ((dev->pci_conf[reg] & (1 << w_bit)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY);
if (base >= 0x000e0000) {
if (dev->pci_conf[reg] & (1 << r_bit))
shadowbios |= 1;
if (dev->pci_conf[reg] & (1 << r_bit))
shadowbios_write |= 1;
}
ali1621_log("%08X-%08X shadow: R%c, W%c\n", base, base + 0x00003fff,
(dev->pci_conf[reg] & (1 << r_bit)) ? 'I' : 'E', (dev->pci_conf[reg] & (1 << w_bit)) ? 'I' : 'E');
mem_set_mem_state_both(base, 0x00004000, flags);
}
/* F0000-FFFFF */
base = 0x000f0000;
r_bit = 4;
w_bit = 5;
reg = 0x87;
flags = (dev->pci_conf[reg] & (1 << r_bit)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
flags |= ((dev->pci_conf[reg] & (1 << w_bit)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY);
if (dev->pci_conf[reg] & (1 << r_bit))
shadowbios |= 1;
if (dev->pci_conf[reg] & (1 << r_bit))
shadowbios_write |= 1;
ali1621_log("%08X-%08X shadow: R%c, W%c\n", base, base + 0x0000ffff,
(dev->pci_conf[reg] & (1 << r_bit)) ? 'I' : 'E', (dev->pci_conf[reg] & (1 << w_bit)) ? 'I' : 'E');
mem_set_mem_state_both(base, 0x00010000, flags);
flushmmucache_nopc();
}
static void
ali1621_mask_bar(ali1621_t *dev)
{
uint32_t bar, mask;
switch (dev->pci_conf[0xbc] & 0x0f) {
case 0x00:
default:
mask = 0x00000000;
break;
case 0x01:
mask = 0xfff00000;
break;
case 0x02:
mask = 0xffe00000;
break;
case 0x03:
mask = 0xffc00000;
break;
case 0x04:
mask = 0xff800000;
break;
case 0x06:
mask = 0xff000000;
break;
case 0x07:
mask = 0xfe000000;
break;
case 0x08:
mask = 0xfc000000;
break;
case 0x09:
mask = 0xf8000000;
break;
case 0x0a:
mask = 0xf0000000;
break;
}
bar = ((dev->pci_conf[0x13] << 24) | (dev->pci_conf[0x12] << 16)) & mask;
dev->pci_conf[0x12] = (bar >> 16) & 0xff;
dev->pci_conf[0x13] = (bar >> 24) & 0xff;
}
static void
ali1621_write(int func, int addr, uint8_t val, void *priv)
{
ali1621_t *dev = (ali1621_t *)priv;
switch (addr) {
case 0x04:
dev->pci_conf[addr] = val & 0x01;
break;
case 0x05:
dev->pci_conf[addr] = val & 0x01;
break;
case 0x07:
dev->pci_conf[addr] &= ~(val & 0xf0);
break;
case 0x0d:
dev->pci_conf[addr] = val & 0xf8;
break;
case 0x12:
dev->pci_conf[0x12] = (val & 0xc0);
ali1621_mask_bar(dev);
break;
case 0x13:
dev->pci_conf[0x13] = val;
ali1621_mask_bar(dev);
break;
case 0x34:
dev->pci_conf[addr] = val;
break;
case 0x40:
dev->pci_conf[addr] = val;
break;
case 0x41:
dev->pci_conf[addr] = val;
break;
case 0x42:
dev->pci_conf[addr] = val;
break;
case 0x43:
dev->pci_conf[addr] = val;
break;
case 0x44:
dev->pci_conf[addr] = val;
break;
case 0x45:
dev->pci_conf[addr] = val;
break;
case 0x46:
dev->pci_conf[addr] = val;
break;
case 0x47:
dev->pci_conf[addr] = val;
break;
case 0x48:
dev->pci_conf[addr] = val;
break;
case 0x49:
dev->pci_conf[addr] = val;
break;
case 0x4a:
dev->pci_conf[addr] = val;
break;
case 0x4b:
dev->pci_conf[addr] = val & 0x0f;
break;
case 0x4c:
dev->pci_conf[addr] = val;
break;
case 0x4d:
dev->pci_conf[addr] = val;
break;
case 0x4e:
dev->pci_conf[addr] = val;
break;
case 0x4f:
dev->pci_conf[addr] = val;
break;
case 0x50:
dev->pci_conf[addr] = val & 0xef;
break;
case 0x51:
dev->pci_conf[addr] = val;
break;
case 0x52:
dev->pci_conf[addr] = val & 0x9f;
break;
case 0x53:
dev->pci_conf[addr] = val;
break;
case 0x54:
dev->pci_conf[addr] = val & 0xb4;
break;
case 0x55:
dev->pci_conf[addr] = val & 0x01;
break;
case 0x56:
dev->pci_conf[addr] = val & 0x3f;
break;
case 0x57:
dev->pci_conf[addr] = val & 0x08;
break;
case 0x58:
dev->pci_conf[addr] = val;
break;
case 0x59:
dev->pci_conf[addr] = val;
break;
case 0x5a:
dev->pci_conf[addr] = val;
break;
case 0x5c:
dev->pci_conf[addr] = val & 0x01;
break;
case 0x60:
dev->pci_conf[addr] = val;
break;
case 0x61:
dev->pci_conf[addr] = val;
break;
case 0x62:
dev->pci_conf[addr] = val;
break;
case 0x63:
dev->pci_conf[addr] = val;
break;
case 0x64:
dev->pci_conf[addr] = val & 0xb7;
break;
case 0x65:
dev->pci_conf[addr] = val & 0x01;
break;
case 0x66:
dev->pci_conf[addr] &= ~(val & 0x33);
break;
case 0x67:
dev->pci_conf[addr] = val;
break;
case 0x68:
dev->pci_conf[addr] = val;
break;
case 0x69:
dev->pci_conf[addr] = val;
break;
case 0x6c ... 0x7b:
/* Bits 22:20 = DRAM Row size:
- 000: 4 MB;
- 001: 8 MB;
- 010: 16 MB;
- 011: 32 MB;
- 100: 64 MB;
- 101: 128 MB;
- 110: 256 MB;
- 111: Reserved. */
dev->pci_conf[addr] = val;
spd_write_drbs_ali1621(dev->pci_conf, 0x6c, 0x7b);
break;
case 0x7c ... 0x7f:
dev->pci_conf[addr] = val;
break;
case 0x80:
dev->pci_conf[addr] = val;
break;
case 0x81:
dev->pci_conf[addr] = val & 0xdf;
break;
case 0x82:
dev->pci_conf[addr] = val & 0xf7;
break;
case 0x83:
dev->pci_conf[addr] = val & 0xfc;
ali1621_smram_recalc(val & 0xfc, dev);
break;
case 0x84 ... 0x87:
if (addr == 0x87)
dev->pci_conf[addr] = val & 0x3f;
else
dev->pci_conf[addr] = val;
ali1621_shadow_recalc(val, dev);
break;
case 0x88: case 0x89:
dev->pci_conf[addr] = val;
break;
case 0x8a:
dev->pci_conf[addr] = val & 0xc5;
break;
case 0x8b:
dev->pci_conf[addr] = val & 0xbf;
break;
case 0x8c ... 0x8f:
dev->pci_conf[addr] = val;
break;
case 0x90:
dev->pci_conf[addr] = val;
break;
case 0x91:
dev->pci_conf[addr] = val & 0x07;
break;
case 0x94 ... 0x97:
dev->pci_conf[addr] = val;
break;
case 0x98 ... 0x9b:
dev->pci_conf[addr] = val;
break;
case 0x9c ... 0x9f:
dev->pci_conf[addr] = val;
break;
case 0xa0: case 0xa1:
dev->pci_conf[addr] = val;
break;
case 0xbc:
dev->pci_conf[addr] = val & 0x0f;
ali1621_mask_bar(dev);
break;
case 0xbd:
dev->pci_conf[addr] = val & 0xf0;
break;
case 0xbe: case 0xbf:
dev->pci_conf[addr] = val;
break;
case 0xc0:
dev->pci_conf[addr] = val & 0xb1;
break;
case 0xc4 ... 0xc7:
dev->pci_conf[addr] = val;
break;
case 0xc8:
dev->pci_conf[addr] = val & 0x8c;
break;
case 0xc9:
dev->pci_conf[addr] = val;
break;
case 0xca:
dev->pci_conf[addr] = val & 0x7f;
break;
case 0xcb:
dev->pci_conf[addr] = val & 0x87;
break;
case 0xcc ... 0xcf:
dev->pci_conf[addr] = val;
break;
case 0xd0:
dev->pci_conf[addr] = val & 0x80;
break;
case 0xd2:
dev->pci_conf[addr] = val & 0x40;
break;
case 0xd3:
dev->pci_conf[addr] = val & 0xb0;
break;
case 0xd4:
dev->pci_conf[addr] = val;
break;
case 0xd5:
dev->pci_conf[addr] = val & 0xef;
break;
case 0xd6: case 0xd7:
dev->pci_conf[addr] = val;
break;
case 0xf0 ... 0xff:
dev->pci_conf[addr] = val;
break;
}
}
static uint8_t
ali1621_read(int func, int addr, void *priv)
{
ali1621_t *dev = (ali1621_t *)priv;
uint8_t ret = 0xff;
ret = dev->pci_conf[addr];
return ret;
}
static void
ali1621_reset(void *priv)
{
ali1621_t *dev = (ali1621_t *)priv;
int i;
/* Default Registers */
dev->pci_conf[0x00] = 0xb9;
dev->pci_conf[0x01] = 0x10;
dev->pci_conf[0x02] = 0x21;
dev->pci_conf[0x03] = 0x16;
dev->pci_conf[0x04] = 0x06;
dev->pci_conf[0x05] = 0x00;
dev->pci_conf[0x06] = 0x10;
dev->pci_conf[0x07] = 0x04;
dev->pci_conf[0x08] = 0x01;
dev->pci_conf[0x09] = 0x00;
dev->pci_conf[0x0a] = 0x00;
dev->pci_conf[0x0b] = 0x06;
dev->pci_conf[0x10] = 0x08;
dev->pci_conf[0x34] = 0xb0;
dev->pci_conf[0x40] = 0x0c;
dev->pci_conf[0x41] = 0x0c;
dev->pci_conf[0x4c] = 0x04;
dev->pci_conf[0x4d] = 0x04;
dev->pci_conf[0x4e] = 0x7f;
dev->pci_conf[0x4f] = 0x7f;
dev->pci_conf[0x50] = 0x0c;
dev->pci_conf[0x53] = 0x02;
dev->pci_conf[0x5a] = 0x02;
dev->pci_conf[0x63] = 0x02;
dev->pci_conf[0x6c] = dev->pci_conf[0x70] = dev->pci_conf[0x74] = dev->pci_conf[0x78] = 0xff;
dev->pci_conf[0x6d] = dev->pci_conf[0x71] = dev->pci_conf[0x75] = dev->pci_conf[0x79] = 0xff;
dev->pci_conf[0x6e] = dev->pci_conf[0x72] = dev->pci_conf[0x76] = dev->pci_conf[0x7a] = 0x00;
dev->pci_conf[0x6f] = dev->pci_conf[0x73] = dev->pci_conf[0x77] = dev->pci_conf[0x7b] = 0xe0;
dev->pci_conf[0x6f] |= 0x06;
dev->pci_conf[0x7c] = 0x11;
dev->pci_conf[0x7d] = 0xc4;
dev->pci_conf[0x7e] = 0xc7;
dev->pci_conf[0x80] = 0x01;
dev->pci_conf[0x81] = 0xc0;
dev->pci_conf[0x8e] = 0x01;
dev->pci_conf[0xa0] = 0x20;
dev->pci_conf[0xb0] = 0x02;
dev->pci_conf[0xb2] = 0x10;
dev->pci_conf[0xb4] = 0x03;
dev->pci_conf[0xb5] = 0x02;
dev->pci_conf[0xb7] = 0x20;
dev->pci_conf[0xc0] = 0x80;
dev->pci_conf[0xc9] = 0x28;
dev->pci_conf[0xd4] = 0x10;
dev->pci_conf[0xd5] = 0x01;
dev->pci_conf[0xf0] = dev->pci_conf[0xf4] = dev->pci_conf[0xf8] = dev->pci_conf[0xfc] = 0x20;
dev->pci_conf[0xf1] = dev->pci_conf[0xf5] = dev->pci_conf[0xf9] = dev->pci_conf[0xfd] = 0x43;
dev->pci_conf[0xf2] = dev->pci_conf[0xf6] = dev->pci_conf[0xfa] = dev->pci_conf[0xfe] = 0x21;
dev->pci_conf[0xf3] = dev->pci_conf[0xf7] = dev->pci_conf[0xfb] = dev->pci_conf[0xff] = 0x43;
ali1621_write(0, 0x83, 0x08, dev);
for (i = 0; i < 4; i++)
ali1621_write(0, 0x84 + i, 0x00, dev);
}
static void
ali1621_close(void *priv)
{
ali1621_t *dev = (ali1621_t *)priv;
smram_del(dev->smram[1]);
smram_del(dev->smram[0]);
free(dev);
}
static void *
ali1621_init(const device_t *info)
{
ali1621_t *dev = (ali1621_t *)malloc(sizeof(ali1621_t));
memset(dev, 0, sizeof(ali1621_t));
pci_add_card(PCI_ADD_NORTHBRIDGE, ali1621_read, ali1621_write, dev);
dev->smram[0] = smram_add();
dev->smram[1] = smram_add();
ali1621_reset(dev);
device_add(&ali5247_agp_device);
return dev;
}
const device_t ali1621_device = {
"ALi M1621 CPU-to-PCI Bridge",
DEVICE_PCI,
0,
ali1621_init,
ali1621_close,
ali1621_reset,
{NULL},
NULL,
NULL,
NULL
};

View File

@@ -109,7 +109,7 @@ ali6117_recalcmapping(ali6117_t *dev)
}
}
flushmmucache();
flushmmucache_nopc();
}
@@ -127,12 +127,16 @@ ali6117_reg_write(uint16_t addr, uint8_t val, void *priv)
else if (dev->unlocked) {
ali6117_log("ALI6117: regs[%02X] = %02X\n", dev->reg_offset, val);
switch (dev->reg_offset) {
if (!(dev->local & 0x08) || (dev->reg_offset < 0x30)) switch (dev->reg_offset) {
case 0x30: case 0x34: case 0x35: case 0x3e:
case 0x3f: case 0x46: case 0x4c: case 0x6a:
case 0x73:
return; /* read-only registers */
case 0x10:
refresh_at_enable = !(val & 0x02) || !!(dev->regs[0x20] & 0x80);
break;
case 0x12:
val &= 0xf7;
/* FALL-THROUGH */
@@ -184,7 +188,7 @@ ali6117_reg_write(uint16_t addr, uint8_t val, void *priv)
case 0x20:
val &= 0xbf;
refresh_at_enable = !!(val & 0x80);
refresh_at_enable = !(dev->regs[0x10] & 0x02) || !!(val & 0x80);
break;
case 0x31:
@@ -311,13 +315,17 @@ ali6117_reset(void *priv)
dev->regs[0x1b] = 0xf0;
dev->regs[0x1d] = 0xff;
dev->regs[0x20] = 0x80;
dev->regs[0x30] = 0x08;
dev->regs[0x31] = 0x01;
dev->regs[0x34] = 0x04; /* enable internal RTC */
dev->regs[0x35] = 0x20; /* enable internal KBC */
dev->regs[0x36] = dev->local & 0x4; /* M6117D ID */
if (dev->local & 0x08) {
dev->regs[0x30] = 0x08;
dev->regs[0x31] = 0x01;
dev->regs[0x34] = 0x04; /* enable internal RTC */
dev->regs[0x35] = 0x20; /* enable internal KBC */
dev->regs[0x36] = dev->local & 0x07; /* M6117D ID */
}
cpu_set_isa_speed(7159091);
refresh_at_enable = 1;
}
@@ -361,13 +369,28 @@ ali6117_init(const device_t *info)
ali6117_setup(dev);
ali6117_reset(dev);
pic_elcr_io_handler(0);
refresh_at_enable = 0;
if (!(dev->local & 0x08))
pic_elcr_io_handler(0);
return dev;
}
const device_t ali1217_device =
{
"ALi M1217",
DEVICE_AT,
0x8,
ali6117_init,
ali6117_close,
ali6117_reset,
{ NULL },
NULL,
NULL,
NULL
};
const device_t ali6117d_device =
{
"ALi M6117D",

375
src/chipset/contaq_82c59x.c Normal file
View File

@@ -0,0 +1,375 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Implementation of the Contaq/Cypress 82C596(A) and 597 chipsets.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2021 Miran Grca.
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include "cpu.h"
#include <86box/timer.h>
#include <86box/io.h>
#include <86box/device.h>
#include <86box/mem.h>
#include <86box/smram.h>
#include <86box/chipset.h>
#ifdef ENABLE_CONTAQ_82C59X_LOG
int contaq_82c59x_do_log = ENABLE_CONTAQ_82C59X_LOG;
static void
contaq_82c59x_log(const char *fmt, ...)
{
va_list ap;
if (contaq_82c59x_do_log)
{
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define contaq_82c59x_log(fmt, ...)
#endif
typedef struct
{
uint32_t phys, virt;
} mem_remapping_t;
typedef struct
{
uint8_t index, green,
smi_status_set,
regs[256], smi_status[2];
smram_t *smram[2];
} contaq_82c59x_t;
static void
contaq_82c59x_isa_speed_recalc(contaq_82c59x_t *dev)
{
if (dev->regs[0x1c] & 0x02)
cpu_set_isa_speed(7159091);
else {
/* TODO: ISA clock dividers for 386 and alt. 486. */
switch (dev->regs[0x10] & 0x03) {
case 0x00:
cpu_set_isa_speed(cpu_busspeed / 4);
break;
case 0x01:
cpu_set_isa_speed(cpu_busspeed / 6);
break;
case 0x02:
cpu_set_isa_speed(cpu_busspeed / 8);
break;
case 0x03:
cpu_set_isa_speed(cpu_busspeed / 5);
break;
}
}
}
static void
contaq_82c59x_shadow_recalc(contaq_82c59x_t *dev)
{
uint32_t i, base;
uint8_t bit;
shadowbios = shadowbios_write = 0;
/* F0000-FFFFF */
if (dev->regs[0x15] & 0x80) {
shadowbios |= 1;
mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_EXTANY);
} else {
shadowbios_write |= 1;
mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
}
/* C0000-CFFFF */
if (dev->regs[0x15] & 0x01)
mem_set_mem_state_both(0xc0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
else {
for (i = 0; i < 4; i++) {
base = 0xc0000 + (i << 14);
bit = 1 << (i + 2);
if (dev->regs[0x15] & bit) {
if (dev->regs[0x15] & 0x02)
mem_set_mem_state_both(base, 0x04000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL);
else
mem_set_mem_state_both(base, 0x04000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL);
} else
mem_set_mem_state_both(base, 0x04000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
}
}
if (dev->green) {
/* D0000-DFFFF */
if (dev->regs[0x6e] & 0x01)
mem_set_mem_state_both(0xd0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
else {
for (i = 0; i < 4; i++) {
base = 0xd0000 + (i << 14);
bit = 1 << (i + 2);
if (dev->regs[0x6e] & bit) {
if (dev->regs[0x6e] & 0x02)
mem_set_mem_state_both(base, 0x04000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL);
else
mem_set_mem_state_both(base, 0x04000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
} else
mem_set_mem_state_both(base, 0x04000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
}
}
/* E0000-EFFFF */
if (dev->regs[0x6f] & 0x01)
mem_set_mem_state_both(0xe0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
else {
for (i = 0; i < 4; i++) {
base = 0xe0000 + (i << 14);
bit = 1 << (i + 2);
if (dev->regs[0x6f] & bit) {
shadowbios |= 1;
if (dev->regs[0x6f] & 0x02)
mem_set_mem_state_both(base, 0x04000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL);
else {
shadowbios_write |= 1;
mem_set_mem_state_both(base, 0x04000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
}
} else
mem_set_mem_state_both(base, 0x04000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
}
}
}
}
static void
contaq_82c59x_smram_recalc(contaq_82c59x_t *dev)
{
smram_disable(dev->smram[1]);
if (dev->regs[0x70] & 0x04)
smram_enable(dev->smram[1], 0x00040000, 0x000a0000, 0x00020000, 1, 1);
}
static void
contaq_82c59x_write(uint16_t addr, uint8_t val, void *priv)
{
contaq_82c59x_t *dev = (contaq_82c59x_t *)priv;
switch (addr) {
case 0x22:
dev->index = val;
break;
case 0x23:
contaq_82c59x_log("Contaq 82C59x: dev->regs[%02x] = %02x\n", dev->index, val);
if ((dev->index >= 0x60) && !dev->green)
return;
switch (dev->index) {
/* Registers common to 82C596(A) and 82C597. */
case 0x10:
dev->regs[dev->index] = val;
contaq_82c59x_isa_speed_recalc(dev);
break;
case 0x11:
dev->regs[dev->index] = val;
cpu_cache_int_enabled = !!(val & 0x01);
cpu_update_waitstates();
break;
case 0x12: case 0x13:
dev->regs[dev->index] = val;
break;
case 0x14:
dev->regs[dev->index] = val;
reset_on_hlt = !!(val & 0x80);
break;
case 0x15:
dev->regs[dev->index] = val;
contaq_82c59x_shadow_recalc(dev);
break;
case 0x16 ... 0x1b:
dev->regs[dev->index] = val;
break;
case 0x1c:
/* TODO: What's NPRST (generated if bit 3 is set)? */
dev->regs[dev->index] = val;
contaq_82c59x_isa_speed_recalc(dev);
break;
case 0x1d ... 0x1f:
dev->regs[dev->index] = val;
break;
/* Green (82C597-specific) registers. */
case 0x60 ... 0x63:
dev->regs[dev->index] = val;
break;
case 0x64:
dev->regs[dev->index] = val;
if (val & 0x80) {
if (dev->regs[0x65] & 0x80)
smi_line = 1;
dev->smi_status[0] |= 0x10;
}
break;
case 0x65 ... 0x69:
dev->regs[dev->index] = val;
break;
case 0x6a:
dev->regs[dev->index] = val;
dev->smi_status_set = !!(val & 0x80);
break;
case 0x6b ... 0x6d:
dev->regs[dev->index] = val;
break;
case 0x6e: case 0x6f:
dev->regs[dev->index] = val;
contaq_82c59x_shadow_recalc(dev);
break;
case 0x70:
dev->regs[dev->index] = val;
contaq_82c59x_smram_recalc(dev);
break;
case 0x71 ... 0x79:
dev->regs[dev->index] = val;
break;
case 0x7b: case 0x7c:
dev->regs[dev->index] = val;
break;
}
break;
}
}
static uint8_t
contaq_82c59x_read(uint16_t addr, void *priv)
{
contaq_82c59x_t *dev = (contaq_82c59x_t *)priv;
uint8_t ret = 0xff;
if (addr == 0x23) {
if (dev->index == 0x6a) {
ret = dev->smi_status[dev->smi_status_set];
/* I assume it's cleared on read. */
dev->smi_status[dev->smi_status_set] = 0x00;
} else
ret = dev->regs[dev->index];
}
return ret;
}
static void
contaq_82c59x_close(void *priv)
{
contaq_82c59x_t *dev = (contaq_82c59x_t *)priv;
smram_del(dev->smram[1]);
smram_del(dev->smram[0]);
free(dev);
}
static void *
contaq_82c59x_init(const device_t *info)
{
contaq_82c59x_t *dev = (contaq_82c59x_t *)malloc(sizeof(contaq_82c59x_t));
memset(dev, 0x00, sizeof(contaq_82c59x_t));
dev->green = info->local;
io_sethandler(0x0022, 0x0002, contaq_82c59x_read, NULL, NULL, contaq_82c59x_write, NULL, NULL, dev);
contaq_82c59x_isa_speed_recalc(dev);
cpu_cache_int_enabled = 0;
cpu_update_waitstates();
reset_on_hlt = 0;
contaq_82c59x_shadow_recalc(dev);
if (dev->green) {
/* SMRAM 0: Fixed A0000-BFFFF to A0000-BFFFF DRAM. */
dev->smram[0] = smram_add();
smram_enable(dev->smram[0], 0x000a0000, 0x000a0000, 0x00020000, 0, 1);
/* SMRAM 1: Optional. */
dev->smram[1] = smram_add();
contaq_82c59x_smram_recalc(dev);
}
return dev;
}
const device_t contaq_82c596a_device = {
"Contaq 82C596A",
0,
0,
contaq_82c59x_init,
contaq_82c59x_close,
NULL,
{ NULL },
NULL,
NULL,
NULL
};
const device_t contaq_82c597_device = {
"Contaq 82C597",
0,
1,
contaq_82c59x_init,
contaq_82c59x_close,
NULL,
{ NULL },
NULL,
NULL,
NULL
};

411
src/chipset/ims8848.c Normal file
View File

@@ -0,0 +1,411 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Implementation of the IMS 8848/8849 chipset.
*
*
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Tiseno100,
*
* Copyright 2021 Miran Grca.
* Copyright 2021 Tiseno100.
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include "cpu.h"
#include <86box/io.h>
#include <86box/device.h>
#include <86box/mem.h>
#include <86box/smram.h>
#include <86box/pci.h>
#include <86box/port_92.h>
#include <86box/chipset.h>
/*
IMS 884x Configuration Registers
Note: IMS 884x are rebadged ATMEL AT 40411/40412 chipsets
By: Tiseno100, Miran Grca(OBattler)
Register 00h:
Bit 3: F0000-FFFFF Shadow Enable
Bit 2: E0000-EFFFF Shadow Enable
Bit 0: ????
Register 04h:
Bit 3: Cache Write Hit Wait State
Bit 2: Cache Read Hit Wait State
Register 06h:
Bit 3: System BIOS Cacheable (1: Yes / 0: No)
Bit 1: Power Management Mode (1: IRQ / 0: SMI#)
Register 08h:
Bit 2: System BIOS Shadow Write (1: Enable / 0: Disable)
Bit 1: System BIOS Shadow Read?
Register 0Dh:
Bit 0: IO 100H-3FFH Idle Detect (1: Enable / 0: Disable)
Register 0Eh:
Bit 7: DMA & Local Bus Idle Detect (1: Enable / 0: Disable)
Bit 6: Floppy Disk Idle Detect (1: Enable / 0: Disable)
Bit 5: IDE Idle Detect (1: Enable / 0: Disable)
Bit 4: Serial Port Idle Detect (1: Enable / 0: Disable)
Bit 3: Parallel Port Idle Detect (1: Enable / 0: Disable)
Bit 2: Keyboard Idle Detect (1: Enable / 0: Disable)
Bit 1: Video Idle Detect (1: Enable / 0: Disable)
Register 12h:
Bits 3-2: Power Saving Timer (00 = 1 MIN, 01 = 3 MIN, 10 = 5 MIN, 11 = 8 MIN)
Bit 1: Base Memory (1: 512KB / 0: 640KB)
Register 1Ah:
Bit 3: Cache Write Hit W/S For PCI (1: Enabled / 0: Disable)
Bit 2: Cache Read Hit W/S For PCI (1: Enabled / 0: Disable)
Bit 1: VESA Clock Skew (1: 4ns/6ns, 0: No Delay/2ns)
Register 1Bh:
Bit 6: Enable SMRAM (always at 30000-4FFFF) in SMM
Bit 5: ????
Bit 4: Software SMI#
Bit 3: DC000-DFFFF Shadow Enable
Bit 2: D8000-DBFFF Shadow Enable
Bit 1: D4000-D7FFF Shadow Enable
Bit 0: D0000-D3FFF Shadow Enable
Register 1Ch:
Bits 7-4: INTA IRQ routing (0 = disabled, 1 to F = IRQ)
Bit 3: CC000-CFFFF Shadow Enable
Bit 2: C8000-CBFFF Shadow Enable
Bit 1: C4000-C7FFF Shadow Enable
Bit 0: C0000-C3FFF Shadow Enable
Register 1Dh:
Bits 7-4: INTB IRQ routing (0 = disabled, 1 to F = IRQ)
Register 1Eh:
Bits 7-4: INTC IRQ routing (0 = disabled, 1 to F = IRQ)
Bit 1: C4000-C7FFF Cacheable
Bit 0: C0000-C3FFF Cacheable
Register 21h:
Bits 7-4: INTD IRQ routing (0 = disabled, 1 to F = IRQ)
Register 22h:
Bit 5: Local Bus Master #2 select (0 = VESA, 1 = PCI)
Bit 4: Local Bus Master #1 select (0 = VESA, 1 = PCI)
Bits 1-0: Internal HADS# Delay Always (00 = No Delay, 01 = 1 Clk, 10 = 2 Clks)
Register 23h:
Bit 7: Seven Bits Tag (1: Enabled / 0: Disable)
Bit 3: Extend LBRDY#(VL Master) (1: Enabled / 0: Disable)
Bit 2: Sync LRDY#(VL Slave) (1: Enabled / 0: Disable)
Bit 0: HADS# Delay After LB. Cycle (1: Enabled / 0: Disable)
*/
typedef struct
{
uint8_t idx, access_data,
regs[256], pci_conf[256];
smram_t *smram;
} ims8848_t;
#ifdef ENABLE_IMS8848_LOG
int ims8848_do_log = ENABLE_IMS8848_LOG;
static void
ims8848_log(const char *fmt, ...)
{
va_list ap;
if (ims8848_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define ims8848_log(fmt, ...)
#endif
/* Shadow write always enabled, 1B and 1C control C000-DFFF read. */
static void
ims8848_recalc(ims8848_t *dev)
{
int i, state_on;
uint32_t base;
ims8848_log("SHADOW: 00 = %02X, 08 = %02X, 1B = %02X, 1C = %02X\n",
dev->regs[0x00], dev->regs[0x08], dev->regs[0x1b], dev->regs[0x1c]);
state_on = MEM_READ_INTERNAL;
state_on |= (dev->regs[0x08] & 0x04) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
for (i = 0; i < 2; i++) {
base = 0xe0000 + (i << 16);
if (dev->regs[0x00] & (1 << (i + 2)))
mem_set_mem_state_both(base, 0x10000, state_on);
else
mem_set_mem_state_both(base, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
}
for (i = 0; i < 4; i++) {
base = 0xc0000 + (i << 14);
if (dev->regs[0x1c] & (1 << i))
mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
else
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
base = 0xd0000 + (i << 14);
if (dev->regs[0x1b] & (1 << i))
mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
else
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
}
flushmmucache_nopc();
}
static void
ims8848_base_memory(ims8848_t *dev)
{
/* We can use the proper mem_set_access to handle that. */
mem_set_mem_state_both(0x80000, 0x20000, (dev->regs[0x12] & 2) ?
(MEM_READ_DISABLED | MEM_WRITE_DISABLED) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL));
}
static void
ims8848_smram(ims8848_t *dev)
{
smram_disable_all();
smram_enable(dev->smram, 0x00030000, 0x00030000, 0x20000, dev->regs[0x1b] & 0x40, 1);
}
static void
ims8848_write(uint16_t addr, uint8_t val, void *priv)
{
ims8848_t *dev = (ims8848_t *) priv;
uint8_t old = dev->regs[dev->idx];
switch (addr) {
case 0x22:
ims8848_log("[W] IDX = %02X\n", val);
dev->idx = val;
break;
case 0x23:
ims8848_log("[W] IDX IN = %02X\n", val);
if (((val & 0x0f) == ((dev->idx >> 4) & 0x0f)) && ((val & 0xf0) == ((dev->idx << 4) & 0xf0)))
dev->access_data = 1;
break;
case 0x24:
ims8848_log("[W] [%i] REG %02X = %02X\n", dev->access_data, dev->idx, val);
if (dev->access_data) {
dev->regs[dev->idx] = val;
switch (dev->idx) {
case 0x00: case 0x08: case 0x1b: case 0x1c:
/* Shadow RAM */
ims8848_recalc(dev);
if (dev->idx == 0x1b) {
ims8848_smram(dev);
if (!(old & 0x10) && (val & 0x10))
smi_line = 1;
} else if (dev->idx == 0x1c)
pci_set_irq_routing(PCI_INTA, (val >> 4) ? (val >> 4) : PCI_IRQ_DISABLED);
break;
case 0x1d: case 0x1e:
pci_set_irq_routing(PCI_INTB + (dev->idx - 0x1d), (val >> 4) ? (val >> 4) : PCI_IRQ_DISABLED);
break;
case 0x21:
pci_set_irq_routing(PCI_INTD, (val >> 4) ? (val >> 4) : PCI_IRQ_DISABLED);
break;
case 0x12:
/* Base Memory */
ims8848_base_memory(dev);
break;
}
dev->access_data = 0;
}
break;
}
}
static uint8_t
ims8848_read(uint16_t addr, void *priv)
{
uint8_t ret = 0xff;
ims8848_t *dev = (ims8848_t *) priv;
#ifdef ENABLE_IMS8848_LOG
uint8_t old_ad = dev->access_data;
#endif
switch (addr) {
case 0x22:
ims8848_log("[R] IDX = %02X\n", ret);
ret = dev->idx;
break;
case 0x23:
ims8848_log("[R] IDX IN = %02X\n", ret);
ret = (dev->idx >> 4) | (dev->idx << 4);
break;
case 0x24:
if (dev->access_data) {
ret = dev->regs[dev->idx];
dev->access_data = 0;
}
ims8848_log("[R] [%i] REG %02X = %02X\n", old_ad, dev->idx, ret);
break;
}
return ret;
}
static void
ims8849_pci_write(int func, int addr, uint8_t val, void *priv)
{
ims8848_t *dev = (ims8848_t *)priv;
ims8848_log("IMS 884x-PCI: dev->regs[%02x] = %02x POST: %02x\n", addr, val, inb(0x80));
if (func == 0) switch (addr) {
case 0x04:
dev->pci_conf[addr] = val;
break;
case 0x05:
dev->pci_conf[addr] = val & 3;
break;
case 0x07:
dev->pci_conf[addr] &= val & 0xf7;
break;
case 0x0c ... 0x0d:
dev->pci_conf[addr] = val;
break;
case 0x52 ... 0x55:
dev->pci_conf[addr] = val;
break;
}
}
static uint8_t
ims8849_pci_read(int func, int addr, void *priv)
{
ims8848_t *dev = (ims8848_t *)priv;
uint8_t ret = 0xff;
if (func == 0)
ret = dev->pci_conf[addr];
return ret;
}
static void
ims8848_reset(void *priv)
{
ims8848_t *dev = (ims8848_t *)priv;
memset(dev->regs, 0x00, sizeof(dev->regs));
memset(dev->pci_conf, 0x00, sizeof(dev->pci_conf));
dev->pci_conf[0x00] = 0xe0; /* Integrated Micro Solutions (IMS) */
dev->pci_conf[0x01] = 0x10;
dev->pci_conf[0x02] = 0x49; /* 8849 */
dev->pci_conf[0x03] = 0x88;
dev->pci_conf[0x04] = 0x07;
dev->pci_conf[0x07] = 0x02;
dev->pci_conf[0x0b] = 0x06;
ims8848_recalc(dev); /* Shadow RAM Setup */
ims8848_base_memory(dev); /* Base Memory Setup */
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);
ims8848_smram(dev);
}
static void
ims8848_close(void *priv)
{
ims8848_t *dev = (ims8848_t *) priv;
smram_del(dev->smram);
free(dev);
}
static void *
ims8848_init(const device_t *info)
{
ims8848_t *dev = (ims8848_t *) malloc(sizeof(ims8848_t));
memset(dev, 0, sizeof(ims8848_t));
device_add(&port_92_device);
/* IMS 8848:
22h Index
23h Data Unlock
24h Data
IMS 8849:
PCI Device 0: IMS 8849 Dummy for compatibility reasons
*/
io_sethandler(0x0022, 0x0003, ims8848_read, NULL, NULL, ims8848_write, NULL, NULL, dev);
pci_add_card(PCI_ADD_NORTHBRIDGE, ims8849_pci_read, ims8849_pci_write, dev);
dev->smram = smram_add();
smram_set_separate_smram(1);
cpu_cache_ext_enabled = 1;
cpu_update_waitstates();
ims8848_reset(dev);
return dev;
}
const device_t ims8848_device = {
"IMS 8848/8849",
0,
0,
ims8848_init, ims8848_close, ims8848_reset,
{ NULL }, NULL, NULL,
NULL
};

View File

@@ -56,6 +56,7 @@ typedef struct
smram_locked, max_drb,
drb_unit, drb_default;
uint8_t regs[256], regs_locked[256];
uint8_t mem_state[256];
int type;
smram_t *smram_low, *smram_high;
void *agpgart;
@@ -83,23 +84,18 @@ i4x0_log(const char *fmt, ...)
static void
i4x0_map(uint32_t addr, uint32_t size, int state)
i4x0_map(i4x0_t *dev, uint32_t addr, uint32_t size, int state)
{
switch (state & 3) {
case 0:
mem_set_mem_state_both(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
break;
case 1:
mem_set_mem_state_both(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY);
break;
case 2:
mem_set_mem_state_both(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
break;
case 3:
mem_set_mem_state_both(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
break;
uint32_t base = addr >> 12;
int states[4] = { MEM_READ_EXTANY | MEM_WRITE_EXTANY, MEM_READ_INTERNAL | MEM_WRITE_EXTANY,
MEM_READ_EXTANY | MEM_WRITE_INTERNAL, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL };
state &= 3;
if (dev->mem_state[base] != state) {
mem_set_mem_state_both(addr, size, states[state]);
dev->mem_state[base] = state;
flushmmucache_nopc();
}
flushmmucache_nopc();
}
@@ -601,10 +597,10 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case 0x59: /* PAM0 */
if (dev->type <= INTEL_430NX) {
if ((regs[0x59] ^ val) & 0x0f)
i4x0_map(0x80000, 0x20000, val & 0x0f);
i4x0_map(dev, 0x80000, 0x20000, val & 0x0f);
}
if ((regs[0x59] ^ val) & 0xf0) {
i4x0_map(0xf0000, 0x10000, val >> 4);
i4x0_map(dev, 0xf0000, 0x10000, val >> 4);
shadowbios = (val & 0x10);
}
if (dev->type > INTEL_430NX)
@@ -614,44 +610,44 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
break;
case 0x5a: /* PAM1 */
if ((regs[0x5a] ^ val) & 0x0f)
i4x0_map(0xc0000, 0x04000, val & 0xf);
i4x0_map(dev, 0xc0000, 0x04000, val & 0xf);
if ((regs[0x5a] ^ val) & 0xf0)
i4x0_map(0xc4000, 0x04000, val >> 4);
i4x0_map(dev, 0xc4000, 0x04000, val >> 4);
regs[0x5a] = val & 0x77;
break;
case 0x5b: /*PAM2 */
if ((regs[0x5b] ^ val) & 0x0f)
i4x0_map(0xc8000, 0x04000, val & 0xf);
i4x0_map(dev, 0xc8000, 0x04000, val & 0xf);
if ((regs[0x5b] ^ val) & 0xf0)
i4x0_map(0xcc000, 0x04000, val >> 4);
i4x0_map(dev, 0xcc000, 0x04000, val >> 4);
regs[0x5b] = val & 0x77;
break;
case 0x5c: /*PAM3 */
if ((regs[0x5c] ^ val) & 0x0f)
i4x0_map(0xd0000, 0x04000, val & 0xf);
i4x0_map(dev, 0xd0000, 0x04000, val & 0xf);
if ((regs[0x5c] ^ val) & 0xf0)
i4x0_map(0xd4000, 0x04000, val >> 4);
i4x0_map(dev, 0xd4000, 0x04000, val >> 4);
regs[0x5c] = val & 0x77;
break;
case 0x5d: /* PAM4 */
if ((regs[0x5d] ^ val) & 0x0f)
i4x0_map(0xd8000, 0x04000, val & 0xf);
i4x0_map(dev, 0xd8000, 0x04000, val & 0xf);
if ((regs[0x5d] ^ val) & 0xf0)
i4x0_map(0xdc000, 0x04000, val >> 4);
i4x0_map(dev, 0xdc000, 0x04000, val >> 4);
regs[0x5d] = val & 0x77;
break;
case 0x5e: /* PAM5 */
if ((regs[0x5e] ^ val) & 0x0f)
i4x0_map(0xe0000, 0x04000, val & 0xf);
i4x0_map(dev, 0xe0000, 0x04000, val & 0xf);
if ((regs[0x5e] ^ val) & 0xf0)
i4x0_map(0xe4000, 0x04000, val >> 4);
i4x0_map(dev, 0xe4000, 0x04000, val >> 4);
regs[0x5e] = val & 0x77;
break;
case 0x5f: /* PAM6 */
if ((regs[0x5f] ^ val) & 0x0f)
i4x0_map(0xe8000, 0x04000, val & 0xf);
i4x0_map(dev, 0xe8000, 0x04000, val & 0xf);
if ((regs[0x5f] ^ val) & 0xf0)
i4x0_map(0xec000, 0x04000, val >> 4);
i4x0_map(dev, 0xec000, 0x04000, val >> 4);
regs[0x5f] = val & 0x77;
break;
case 0x60: case 0x61: case 0x62: case 0x63: case 0x64:
@@ -1322,11 +1318,11 @@ static void
regs[0x0d] = 0x20;
/* According to information from FreeBSD 3.x source code:
0x00 = 486DX, 0x20 = 486SX, 0x40 = 486DX2 or 486DX4, 0x80 = Pentium OverDrive. */
if (!(hasfpu) && (cpu_multi = 1))
if (!(hasfpu) && (cpu_multi == 1))
regs[0x50] = 0x20;
else if (!(hasfpu) && (cpu_multi = 2))
else if (!(hasfpu) && (cpu_multi == 2))
regs[0x50] = 0x60; /* Guess based on the SX, DX, and DX2 values. */
else if (hasfpu && (cpu_multi = 1))
else if (hasfpu && (cpu_multi == 1))
regs[0x50] = 0x00;
else if (hasfpu && (cpu_multi >= 2) && !(cpu_s->cpu_type == CPU_P24T))
regs[0x50] = 0x40;

View File

@@ -58,71 +58,95 @@ i450kx_log(const char *fmt, ...)
#endif
/* Shadow RAM Flags */
#define LSB_DECISION (((shadow_value & 1) ? MEM_READ_EXTANY : MEM_READ_INTERNAL) | ((shadow_value & 2) ? MEM_WRITE_EXTANY : MEM_WRITE_INTERNAL))
#define MSB_DECISION (((shadow_value & 0x10) ? MEM_READ_EXTANY : MEM_READ_INTERNAL) | ((shadow_value & 0x20) ? MEM_WRITE_EXTANY : MEM_WRITE_INTERNAL))
#define LSB_DECISION_MC (((shadow_value & 1) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((shadow_value & 2) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY))
#define MSB_DECISION_MC (((shadow_value & 0x10) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((shadow_value & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY))
/* SMRAM */
#define SMRAM_ADDR (((dev->pb_pci_conf[0xb9] << 8) | dev->pb_pci_conf[0xb8]) << 17)
#define SMRAM_ADDR_MC (((dev->mc_pci_conf[0xb9] << 8) | dev->mc_pci_conf[0xb8]) << 16)
#define SMRAM_SIZE (((dev->pb_pci_conf[0xbb] >> 4) + 1) * 64)
#define SMRAM_SIZE_MC (((dev->mc_pci_conf[0xbb] >> 4) + 1) * 64)
/* Miscellaneous */
#define ENABLE_SEGMENT (MEM_READ_EXTANY | MEM_WRITE_EXTANY)
#define DISABLE_SEGMENT (MEM_READ_DISABLED | MEM_WRITE_DISABLED)
/* TODO: Finish the bus index stuff. */
typedef struct i450kx_t {
smram_t *smram;
smram_t * smram[2];
uint8_t pb_pci_conf[256], mc_pci_conf[256];
uint8_t pb_pci_conf[256], mc_pci_conf[256];
uint8_t mem_state[2][256];
uint8_t bus_index;
} i450kx_t;
static void
i450kx_shadow(int is_mc, int cur_reg, uint8_t shadow_value, i450kx_t *dev)
i450kx_map(i450kx_t *dev, int bus, uint32_t addr, uint32_t size, int state)
{
if (cur_reg == 0x59) {
mem_set_mem_state_both(0x80000, 0x20000, (is_mc) ? LSB_DECISION_MC : LSB_DECISION);
mem_set_mem_state_both(0xf0000, 0x10000, (is_mc) ? MSB_DECISION_MC : MSB_DECISION);
} else {
mem_set_mem_state_both(0xc0000 + (((cur_reg & 7) - 2) * 0x8000), 0x4000, (is_mc) ? LSB_DECISION_MC : LSB_DECISION);
mem_set_mem_state_both(0xc4000 + (((cur_reg & 7) - 2) * 0x8000), 0x4000, (is_mc) ? MSB_DECISION_MC : MSB_DECISION);
uint32_t base = addr >> 12;
int states[4] = { MEM_READ_EXTANY | MEM_WRITE_EXTANY, MEM_READ_INTERNAL | MEM_WRITE_EXTANY,
MEM_READ_EXTANY | MEM_WRITE_INTERNAL, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL };
state &= 3;
if (dev->mem_state[bus][base] != state) {
if (bus)
mem_set_mem_state_bus_both(addr, size, states[state]);
else
mem_set_mem_state_cpu_both(addr, size, states[state]);
dev->mem_state[bus][base] = state;
flushmmucache_nopc();
}
flushmmucache_nopc();
}
static void
i450kx_smm(uint32_t smram_addr, uint32_t smram_size, i450kx_t *dev)
i450kx_smram_recalc(i450kx_t *dev, int bus)
{
smram_disable_all();
uint8_t *regs = bus ? dev->pb_pci_conf : dev->mc_pci_conf;
uint32_t addr, size;
if ((smram_addr != 0) && !!(dev->mc_pci_conf[0x57] & 8))
smram_enable(dev->smram, smram_addr, smram_addr, smram_size, !!(dev->pb_pci_conf[0x57] & 8), 1);
smram_disable(dev->smram[bus]);
addr = ((uint32_t) regs[0xb8] << 16) | ((uint32_t) regs[0xb9] << 24);
size = (((uint32_t) ((regs[0xbb] >> 4) & 0x0f)) << 16) + 0x00010000;
if ((addr != 0x00000000) && !!(regs[0x57] & 0x08)) {
if (bus)
smram_enable_ex(dev->smram[bus], addr, addr, size, 0, !!(regs[0x57] & 8), 0, 1);
else
smram_enable_ex(dev->smram[bus], addr, addr, size, !!(regs[0x57] & 8), 0, 1, 0);
}
flushmmucache();
}
static void
i450kx_vid_buf_recalc(i450kx_t *dev, int bus)
{
uint8_t *regs = bus ? dev->pb_pci_conf : dev->mc_pci_conf;
// int state = (regs[0x58] & 0x02) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_DISABLED | MEM_WRITE_DISABLED);
int state = (regs[0x58] & 0x02) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY);
if (bus)
mem_set_mem_state_bus_both(0x000a0000, 0x00020000, state);
else
mem_set_mem_state_cpu_both(0x000a0000, 0x00020000, state);
flushmmucache_nopc();
}
static void
pb_write(int func, int addr, uint8_t val, void *priv)
{
i450kx_t *dev = (i450kx_t *)priv;
switch (addr) {
case 0x04:
dev->pb_pci_conf[addr] &= val & 0xd7;
break;
// pclog("i450KX-PB: [W] dev->pb_pci_conf[%02X] = %02X POST: %02X\n", addr, val, inb(0x80));
i450kx_log("i450KX-PB: [W] dev->pb_pci_conf[%02X] = %02X POST: %02X\n", addr, val, inb(0x80));
case 0x06:
dev->pb_pci_conf[addr] = val & 0x80;
if (func == 0) switch (addr) {
case 0x04:
dev->pb_pci_conf[addr] = (dev->pb_pci_conf[addr] & 0x04) | (val & 0x53);
break;
case 0x05:
dev->pb_pci_conf[addr] = val & 0x01;
break;
case 0x07:
dev->pb_pci_conf[addr] &= ~(val & 0xf9);
break;
case 0x0d:
dev->pb_pci_conf[addr] = val;
break;
@@ -131,63 +155,106 @@ pb_write(int func, int addr, uint8_t val, void *priv)
dev->pb_pci_conf[addr] = val & 0xcf;
break;
case 0x40:
case 0x41:
case 0x40: case 0x41:
dev->pb_pci_conf[addr] = val;
break;
case 0x43:
dev->pb_pci_conf[addr] = val & 0x80;
break;
case 0x48:
dev->pb_pci_conf[addr] = val & 6;
dev->pb_pci_conf[addr] = val & 0x06;
break;
case 0x4a:
case 0x4b:
case 0x4a: case 0x4b:
dev->pb_pci_conf[addr] = val;
// if (addr == 0x4a)
// pci_remap_bus(dev->bus_index, val);
break;
case 0x4c:
dev->pb_pci_conf[addr] = val & 0xd8;
dev->pb_pci_conf[addr] = (dev->pb_pci_conf[addr] & 0x01) | (val & 0xd8);
break;
case 0x51:
dev->pb_pci_conf[addr] = val;
break;
case 0x53:
dev->pb_pci_conf[addr] = val & 2;
dev->pb_pci_conf[addr] = val & 0x02;
break;
case 0x54:
dev->pb_pci_conf[addr] = val & 0x7b;
break;
case 0x55:
dev->pb_pci_conf[addr] = val & 2;
dev->pb_pci_conf[addr] = val & 0x03;
break;
case 0x57:
dev->pb_pci_conf[addr] = val & 8;
i450kx_smm(SMRAM_ADDR, SMRAM_SIZE, dev);
dev->pb_pci_conf[addr] = val & 0x08;
i450kx_smram_recalc(dev, 1);
break;
case 0x58:
dev->pb_pci_conf[addr] = val & 2;
mem_set_mem_state_both(0xa0000, 0x20000, (val & 2) ? ENABLE_SEGMENT : DISABLE_SEGMENT);
dev->pb_pci_conf[addr] = val & 0x02;
i450kx_vid_buf_recalc(dev, 1);
break;
case 0x59:
case 0x5a:
case 0x5b:
case 0x5c:
case 0x5d:
case 0x5e:
case 0x5f:
dev->pb_pci_conf[addr] = val & 0x33;
i450kx_shadow(0, addr, val, dev);
case 0x59: /* PAM0 */
if ((dev->pb_pci_conf[0x59] ^ val) & 0x0f)
i450kx_map(dev, 1, 0x80000, 0x20000, val & 0x0f);
if ((dev->pb_pci_conf[0x59] ^ val) & 0xf0) {
i450kx_map(dev, 1, 0xf0000, 0x10000, val >> 4);
shadowbios = (val & 0x10);
}
dev->pb_pci_conf[0x59] = val & 0x33;
break;
case 0x5a: /* PAM1 */
if ((dev->pb_pci_conf[0x5a] ^ val) & 0x0f)
i450kx_map(dev, 1, 0xc0000, 0x04000, val & 0xf);
if ((dev->pb_pci_conf[0x5a] ^ val) & 0xf0)
i450kx_map(dev, 1, 0xc4000, 0x04000, val >> 4);
dev->pb_pci_conf[0x5a] = val & 0x33;
break;
case 0x5b: /*PAM2 */
if ((dev->pb_pci_conf[0x5b] ^ val) & 0x0f)
i450kx_map(dev, 1, 0xc8000, 0x04000, val & 0xf);
if ((dev->pb_pci_conf[0x5b] ^ val) & 0xf0)
i450kx_map(dev, 1, 0xcc000, 0x04000, val >> 4);
dev->pb_pci_conf[0x5b] = val & 0x33;
break;
case 0x5c: /*PAM3 */
if ((dev->pb_pci_conf[0x5c] ^ val) & 0x0f)
i450kx_map(dev, 1, 0xd0000, 0x04000, val & 0xf);
if ((dev->pb_pci_conf[0x5c] ^ val) & 0xf0)
i450kx_map(dev, 1, 0xd4000, 0x04000, val >> 4);
dev->pb_pci_conf[0x5c] = val & 0x33;
break;
case 0x5d: /* PAM4 */
if ((dev->pb_pci_conf[0x5d] ^ val) & 0x0f)
i450kx_map(dev, 1, 0xd8000, 0x04000, val & 0xf);
if ((dev->pb_pci_conf[0x5d] ^ val) & 0xf0)
i450kx_map(dev, 1, 0xdc000, 0x04000, val >> 4);
dev->pb_pci_conf[0x5d] = val & 0x33;
break;
case 0x5e: /* PAM5 */
if ((dev->pb_pci_conf[0x5e] ^ val) & 0x0f)
i450kx_map(dev, 1, 0xe0000, 0x04000, val & 0xf);
if ((dev->pb_pci_conf[0x5e] ^ val) & 0xf0)
i450kx_map(dev, 1, 0xe4000, 0x04000, val >> 4);
dev->pb_pci_conf[0x5e] = val & 0x33;
break;
case 0x5f: /* PAM6 */
if ((dev->pb_pci_conf[0x5f] ^ val) & 0x0f)
i450kx_map(dev, 1, 0xe8000, 0x04000, val & 0xf);
if ((dev->pb_pci_conf[0x5f] ^ val) & 0xf0)
i450kx_map(dev, 1, 0xec000, 0x04000, val >> 4);
dev->pb_pci_conf[0x5f] = val & 0x33;
break;
case 0x70:
dev->pb_pci_conf[addr] = val & 0xfc;
dev->pb_pci_conf[addr] = val & 0xf8;
break;
case 0x71:
@@ -197,47 +264,49 @@ pb_write(int func, int addr, uint8_t val, void *priv)
case 0x78:
dev->pb_pci_conf[addr] = val & 0xf0;
break;
case 0x79:
dev->pb_pci_conf[addr] = val & 0xfc;
break;
case 0x7c:
dev->pb_pci_conf[addr] = val & 0x5f;
case 0x7a:
dev->pb_pci_conf[addr] = val;
break;
case 0x7b:
dev->pb_pci_conf[addr] = val & 0x0f;
break;
case 0x7c:
dev->pb_pci_conf[addr] = val & 0x9f;
break;
case 0x7d:
dev->pb_pci_conf[addr] = val & 0x1a;
break;
case 0x7e:
dev->pb_pci_conf[addr] = val & 0xf0;
break;
case 0x7f:
case 0x88:
case 0x89:
case 0x8a:
dev->pb_pci_conf[addr] = val;
break;
case 0x88: case 0x89:
dev->pb_pci_conf[addr] = val;
break;
case 0x8b:
dev->pb_pci_conf[addr] = val & 0x80;
break;
case 0x9c:
dev->pb_pci_conf[addr] = val & 1;
break;
case 0xa4:
dev->pb_pci_conf[addr] = val & 0xf9;
break;
case 0xa5:
case 0xa6:
case 0x8c: case 0x8d:
dev->pb_pci_conf[addr] = val;
break;
case 0x9c:
dev->pb_pci_conf[addr] = val & 0x01;
break;
case 0xa4:
dev->pb_pci_conf[addr] = val & 0xf8;
break;
case 0xa5: case 0xa6:
dev->pb_pci_conf[addr] = val;
break;
case 0xa7:
dev->pb_pci_conf[addr] = val & 0x0f;
break;
@@ -245,36 +314,45 @@ pb_write(int func, int addr, uint8_t val, void *priv)
case 0xb0:
dev->pb_pci_conf[addr] = val & 0xe0;
break;
case 0xb1:
dev->pb_pci_conf[addr] = val & 0x1f;
dev->pb_pci_conf[addr] = val & /*0x1a*/ 0x1f;
break;
case 0xb4:
dev->pb_pci_conf[addr] = val & 0xe8;
dev->pb_pci_conf[addr] = val & 0xe0;
break;
case 0xb5:
dev->pb_pci_conf[addr] = val & 0x1f;
break;
case 0xb8:
case 0xb9:
case 0xb8: case 0xb9:
dev->pb_pci_conf[addr] = val;
i450kx_smram_recalc(dev, 1);
break;
case 0xbb:
dev->pb_pci_conf[addr] = !(addr == 0xbb) ? val : (val & 0xf0);
i450kx_smm(SMRAM_ADDR, SMRAM_SIZE, dev);
dev->pb_pci_conf[addr] = val & 0xf0;
i450kx_smram_recalc(dev, 1);
break;
case 0xbc:
dev->pb_pci_conf[addr] = val & 0x11;
break;
case 0xc0:
dev->pb_pci_conf[addr] = val & 0xdf;
break;
case 0xc1:
dev->pb_pci_conf[addr] = val & 0x3f;
break;
case 0xc4:
dev->pb_pci_conf[addr] = val & 5;
dev->pb_pci_conf[addr] &= ~(val & 0x0f);
break;
case 0xc5:
dev->pb_pci_conf[addr] = val & 0x0a;
dev->pb_pci_conf[addr] &= ~(val & 0x0a);
break;
case 0xc6:
dev->pb_pci_conf[addr] = val & 0x1d;
dev->pb_pci_conf[addr] &= ~(val & 0x1f);
break;
case 0xc8:
@@ -286,7 +364,6 @@ pb_write(int func, int addr, uint8_t val, void *priv)
dev->pb_pci_conf[addr] = val;
break;
}
i450kx_log("i450KX-PB: dev->regs[%02x] = %02x POST: %02x\n", addr, dev->pb_pci_conf[addr], inb(0x80));
}
@@ -294,7 +371,30 @@ static uint8_t
pb_read(int func, int addr, void *priv)
{
i450kx_t *dev = (i450kx_t *)priv;
return dev->pb_pci_conf[addr];
uint8_t ret = 0xff;
if (func == 0)
ret = dev->pb_pci_conf[addr];
// pclog("i450KX-PB: [R] dev->pb_pci_conf[%02X] = %02X POST: %02X\n", addr, ret, inb(0x80));
return ret;
}
/* A way to use spd_write_drbs_interlaved() and convert the output to what we need. */
static void
mc_fill_drbs(i450kx_t *dev)
{
int i;
spd_write_drbs_interleaved(dev->mc_pci_conf, 0x60, 0x6f, 4);
for (i = 0x60; i <= 0x6f; i++) {
if (i & 0x01)
dev->mc_pci_conf[i] = 0x00;
else
dev->mc_pci_conf[i] &= 0x7f;
}
}
@@ -303,75 +403,97 @@ mc_write(int func, int addr, uint8_t val, void *priv)
{
i450kx_t *dev = (i450kx_t *)priv;
switch (addr)
{
// pclog("i450KX-MC: [W] dev->mc_pci_conf[%02X] = %02X POST: %02X\n", addr, val, inb(0x80));
i450kx_log("i450KX-MC: [W] dev->mc_pci_conf[%02X] = %02X POST: %02X\n", addr, val, inb(0x80));
if (func == 0) switch (addr) {
case 0x4c:
dev->mc_pci_conf[addr] = val & 0xdf;
break;
case 0x4d:
dev->mc_pci_conf[addr] = val & 0xdf;
dev->mc_pci_conf[addr] = val & 0xff;
break;
case 0x57:
dev->mc_pci_conf[addr] = val & 8;
i450kx_smm(SMRAM_ADDR, SMRAM_SIZE, dev);
dev->mc_pci_conf[addr] = val & 0x08;
i450kx_smram_recalc(dev, 0);
break;
case 0x58:
dev->mc_pci_conf[addr] = val & 2;
dev->mc_pci_conf[addr] = val & 0x02;
i450kx_vid_buf_recalc(dev, 0);
break;
case 0x59:
case 0x5a:
case 0x5b:
case 0x5c:
case 0x5d:
case 0x5e:
case 0x5f:
dev->mc_pci_conf[addr] = val & 0x33;
i450kx_shadow(1, addr, val, dev);
case 0x59: /* PAM0 */
if ((dev->mc_pci_conf[0x59] ^ val) & 0x0f)
i450kx_map(dev, 0, 0x80000, 0x20000, val & 0x0f);
if ((dev->mc_pci_conf[0x59] ^ val) & 0xf0) {
i450kx_map(dev, 0, 0xf0000, 0x10000, val >> 4);
shadowbios = (val & 0x10);
}
dev->mc_pci_conf[0x59] = val & 0x33;
break;
case 0x5a: /* PAM1 */
if ((dev->mc_pci_conf[0x5a] ^ val) & 0x0f)
i450kx_map(dev, 0, 0xc0000, 0x04000, val & 0xf);
if ((dev->mc_pci_conf[0x5a] ^ val) & 0xf0)
i450kx_map(dev, 0, 0xc4000, 0x04000, val >> 4);
dev->mc_pci_conf[0x5a] = val & 0x33;
break;
case 0x5b: /*PAM2 */
if ((dev->mc_pci_conf[0x5b] ^ val) & 0x0f)
i450kx_map(dev, 0, 0xc8000, 0x04000, val & 0xf);
if ((dev->mc_pci_conf[0x5b] ^ val) & 0xf0)
i450kx_map(dev, 0, 0xcc000, 0x04000, val >> 4);
dev->mc_pci_conf[0x5b] = val & 0x33;
break;
case 0x5c: /*PAM3 */
if ((dev->mc_pci_conf[0x5c] ^ val) & 0x0f)
i450kx_map(dev, 0, 0xd0000, 0x04000, val & 0xf);
if ((dev->mc_pci_conf[0x5c] ^ val) & 0xf0)
i450kx_map(dev, 0, 0xd4000, 0x04000, val >> 4);
dev->mc_pci_conf[0x5c] = val & 0x33;
break;
case 0x5d: /* PAM4 */
if ((dev->mc_pci_conf[0x5d] ^ val) & 0x0f)
i450kx_map(dev, 0, 0xd8000, 0x04000, val & 0xf);
if ((dev->mc_pci_conf[0x5d] ^ val) & 0xf0)
i450kx_map(dev, 0, 0xdc000, 0x04000, val >> 4);
dev->mc_pci_conf[0x5d] = val & 0x33;
break;
case 0x5e: /* PAM5 */
if ((dev->mc_pci_conf[0x5e] ^ val) & 0x0f)
i450kx_map(dev, 0, 0xe0000, 0x04000, val & 0xf);
if ((dev->mc_pci_conf[0x5e] ^ val) & 0xf0)
i450kx_map(dev, 0, 0xe4000, 0x04000, val >> 4);
dev->mc_pci_conf[0x5e] = val & 0x33;
break;
case 0x5f: /* PAM6 */
if ((dev->mc_pci_conf[0x5f] ^ val) & 0x0f)
i450kx_map(dev, 0, 0xe8000, 0x04000, val & 0xf);
if ((dev->mc_pci_conf[0x5f] ^ val) & 0xf0)
i450kx_map(dev, 0, 0xec000, 0x04000, val >> 4);
dev->mc_pci_conf[0x5f] = val & 0x33;
break;
case 0x60:
case 0x61:
case 0x62:
case 0x63:
case 0x64:
case 0x65:
case 0x66:
case 0x67:
case 0x68:
case 0x69:
case 0x6a:
case 0x6b:
case 0x6c:
case 0x6d:
case 0x6e:
case 0x6f:
dev->mc_pci_conf[addr] = ((addr & 0x0f) % 2) ? 0 : (val & 0x7f);
spd_write_drbs(dev->mc_pci_conf, 0x60, 0x6f, 4);
case 0x60 ... 0x6f:
dev->mc_pci_conf[addr] = ((addr & 0x0f) & 0x01) ? 0x00 : (val & 0x7f);
mc_fill_drbs(dev);
break;
case 0x74:
case 0x75:
case 0x76:
case 0x77:
case 0x74 ... 0x77:
dev->mc_pci_conf[addr] = val;
break;
case 0x78:
dev->mc_pci_conf[addr] = val & 0xf0;
break;
case 0x79:
dev->mc_pci_conf[addr] = val & 0xfe;
break;
case 0x7a:
dev->mc_pci_conf[addr] = val;
break;
case 0x7b:
dev->mc_pci_conf[addr] = val & 0x0f;
break;
@@ -379,45 +501,36 @@ mc_write(int func, int addr, uint8_t val, void *priv)
case 0x7c:
dev->mc_pci_conf[addr] = val & 0x1f;
break;
case 0x7d:
dev->mc_pci_conf[addr] = val & 0x0c;
break;
case 0x7e:
dev->mc_pci_conf[addr] = val & 0xf0;
break;
case 0x7f:
dev->mc_pci_conf[addr] = val;
break;
case 0x88:
case 0x89:
case 0x88: case 0x89:
dev->mc_pci_conf[addr] = val;
break;
case 0x8b:
dev->mc_pci_conf[addr] = val & 0x80;
break;
case 0x8c:
case 0x8d:
case 0x8c: case 0x8d:
dev->mc_pci_conf[addr] = val;
break;
case 0xa4:
dev->mc_pci_conf[addr] = val & 1;
dev->mc_pci_conf[addr] = val & 0x01;
break;
case 0xa5:
dev->pb_pci_conf[addr] = val & 0xf0;
break;
case 0xa6:
dev->mc_pci_conf[addr] = val;
break;
case 0xa7:
dev->mc_pci_conf[addr] = val & 0x0f;
break;
@@ -425,49 +538,56 @@ mc_write(int func, int addr, uint8_t val, void *priv)
case 0xa8:
dev->mc_pci_conf[addr] = val & 0xfe;
break;
case 0xa9:
case 0xaa:
case 0xab:
case 0xac:
case 0xad:
case 0xae:
case 0xa9 ... 0xab:
dev->mc_pci_conf[addr] = val;
break;
case 0xac ... 0xae:
dev->mc_pci_conf[addr] = val;
break;
case 0xaf:
dev->mc_pci_conf[addr] = val & 0x7f;
break;
case 0xb8:
case 0xb9:
case 0xb8: case 0xb9:
dev->mc_pci_conf[addr] = val;
i450kx_smram_recalc(dev, 0);
break;
case 0xbb:
dev->mc_pci_conf[addr] = !(addr == 0xbb) ? val : (val & 0xf0);
i450kx_smm(SMRAM_ADDR_MC, SMRAM_SIZE_MC, dev);
dev->mc_pci_conf[addr] = val & 0xf0;
i450kx_smram_recalc(dev, 0);
break;
case 0xbc:
dev->mc_pci_conf[addr] = val & 1;
dev->mc_pci_conf[addr] = val & 0x01;
break;
case 0xc0:
dev->mc_pci_conf[addr] = val & 7;
dev->mc_pci_conf[addr] = val & 0x07;
break;
case 0xc2:
dev->mc_pci_conf[addr] = val & 3;
dev->mc_pci_conf[addr] &= ~(val & 0x03);
break;
case 0xc4:
dev->mc_pci_conf[addr] = val & 0x3f;
dev->mc_pci_conf[addr] = val & 0xbf;
break;
case 0xc5:
dev->mc_pci_conf[addr] = val & 0x03;
break;
case 0xc6:
dev->mc_pci_conf[addr] = val & 0x19;
dev->mc_pci_conf[addr] &= ~(val & 0x19);
break;
case 0xc8:
dev->mc_pci_conf[addr] = val & 0x1f;
break;
case 0xca: case 0xcb:
dev->mc_pci_conf[addr] = val;
break;
}
i450kx_log("i450KX-MC: dev->regs[%02x] = %02x POST: %02x\n", addr, dev->mc_pci_conf[addr], inb(0x80));
}
@@ -475,7 +595,14 @@ static uint8_t
mc_read(int func, int addr, void *priv)
{
i450kx_t *dev = (i450kx_t *)priv;
return dev->mc_pci_conf[addr];
uint8_t ret = 0xff;
if (func == 0)
ret = dev->mc_pci_conf[addr];
// pclog("i450KX-MC: [R] dev->mc_pci_conf[%02X] = %02X POST: %02X\n", addr, ret, inb(0x80));
return ret;
}
@@ -483,57 +610,168 @@ static void
i450kx_reset(void *priv)
{
i450kx_t *dev = (i450kx_t *)priv;
uint32_t i;
/* CONFLICTS WARNING! We do not program anything on reset due to that */
// pclog("i450KX: i450kx_reset()\n");
/* Defaults PB */
dev->pb_pci_conf[0x00] = 0x86;
dev->pb_pci_conf[0x01] = 0x80;
dev->pb_pci_conf[0x02] = 0xc4;
dev->pb_pci_conf[0x03] = 0x84;
dev->pb_pci_conf[0x05] = 4;
dev->pb_pci_conf[0x04] = 0x07;
dev->pb_pci_conf[0x05] = 0x00;
dev->pb_pci_conf[0x06] = 0x40;
dev->pb_pci_conf[0x07] = 2;
dev->pb_pci_conf[0x08] = 2;
dev->pb_pci_conf[0x0b] = 6;
dev->pb_pci_conf[0x0c] = 8;
dev->pb_pci_conf[0x07] = 0x02;
dev->pb_pci_conf[0x08] = 0x02;
dev->pb_pci_conf[0x09] = 0x00;
dev->pb_pci_conf[0x0a] = 0x00;
dev->pb_pci_conf[0x0b] = 0x06;
dev->pb_pci_conf[0x0c] = 0x08;
dev->pb_pci_conf[0x0d] = 0x20;
dev->pb_pci_conf[0x49] = 0x14;
dev->pb_pci_conf[0x4c] = 0x39;
dev->pb_pci_conf[0x58] = 2;
dev->pb_pci_conf[0x59] = 0x30;
dev->pb_pci_conf[0x5a] = 0x33;
dev->pb_pci_conf[0x5b] = 0x33;
dev->pb_pci_conf[0x5c] = 0x33;
dev->pb_pci_conf[0x5d] = 0x33;
dev->pb_pci_conf[0x5e] = 0x33;
dev->pb_pci_conf[0x5f] = 0x33;
dev->pb_pci_conf[0xa4] = 1;
dev->pb_pci_conf[0x0e] = 0x00;
dev->pb_pci_conf[0x0f] = 0x00;
dev->pb_pci_conf[0x40] = 0x00;
dev->pb_pci_conf[0x41] = 0x00;
dev->pb_pci_conf[0x42] = 0x00;
dev->pb_pci_conf[0x43] = 0x00;
dev->pb_pci_conf[0x48] = 0x06;
dev->pb_pci_conf[0x49] = 0x19;
dev->pb_pci_conf[0x4a] = 0x00;
dev->pb_pci_conf[0x4b] = 0x00;
dev->pb_pci_conf[0x4c] = 0x19;
dev->pb_pci_conf[0x51] = 0x80;
dev->pb_pci_conf[0x53] = 0x00;
dev->pb_pci_conf[0x54] = 0x00;
dev->pb_pci_conf[0x55] = 0x00;
dev->pb_pci_conf[0x57] = 0x00;
dev->pb_pci_conf[0x58] = 0x02;
dev->pb_pci_conf[0x70] = 0x00;
dev->pb_pci_conf[0x71] = 0x00;
dev->pb_pci_conf[0x78] = 0x00;
dev->pb_pci_conf[0x79] = 0x00;
dev->pb_pci_conf[0x7a] = 0x00;
dev->pb_pci_conf[0x7b] = 0x00;
dev->pb_pci_conf[0x7c] = 0x00;
dev->pb_pci_conf[0x7d] = 0x00;
dev->pb_pci_conf[0x7e] = 0x00;
dev->pb_pci_conf[0x7f] = 0x00;
dev->pb_pci_conf[0x88] = 0x00;
dev->pb_pci_conf[0x89] = 0x00;
dev->pb_pci_conf[0x8a] = 0x00;
dev->pb_pci_conf[0x8b] = 0x00;
dev->pb_pci_conf[0x8c] = 0x00;
dev->pb_pci_conf[0x8d] = 0x00;
dev->pb_pci_conf[0x8e] = 0x00;
dev->pb_pci_conf[0x8f] = 0x00;
dev->pb_pci_conf[0x9c] = 0x00;
dev->pb_pci_conf[0xa4] = 0x01;
dev->pb_pci_conf[0xa5] = 0xc0;
dev->pb_pci_conf[0xa6] = 0xfe;
dev->pb_pci_conf[0xc8] = 3;
dev->pb_pci_conf[0xb8] = 5;
dev->pb_pci_conf[0xa7] = 0x00;
/* Note: Do NOT reset these two registers on programmed (TRC) hard reset! */
// dev->pb_pci_conf[0xb0] = 0x00;
// dev->pb_pci_conf[0xb1] = 0x00;
dev->pb_pci_conf[0xb4] = 0x00;
dev->pb_pci_conf[0xb5] = 0x00;
dev->pb_pci_conf[0xb8] = 0x05;
dev->pb_pci_conf[0xb9] = 0x00;
dev->pb_pci_conf[0xba] = 0x00;
dev->pb_pci_conf[0xbb] = 0x00;
dev->pb_pci_conf[0xbc] = 0x01;
dev->pb_pci_conf[0xc0] = 0x02;
dev->pb_pci_conf[0xc1] = 0x00;
dev->pb_pci_conf[0xc2] = 0x00;
dev->pb_pci_conf[0xc3] = 0x00;
dev->pb_pci_conf[0xc4] = 0x00;
dev->pb_pci_conf[0xc5] = 0x00;
dev->pb_pci_conf[0xc6] = 0x00;
dev->pb_pci_conf[0xc7] = 0x00;
dev->pb_pci_conf[0xc8] = 0x03;
dev->pb_pci_conf[0xc9] = 0x00;
dev->pb_pci_conf[0xca] = 0x00;
dev->pb_pci_conf[0xcb] = 0x00;
// pci_remap_bus(dev->bus_index, 0x00);
i450kx_smram_recalc(dev, 1);
i450kx_vid_buf_recalc(dev, 1);
pb_write(0, 0x59, 0x30, dev);
for (i = 0x5a; i <= 0x5f; i++)
pb_write(0, i, 0x33, dev);
/* Defaults MC */
dev->mc_pci_conf[0x00] = 0x86;
dev->mc_pci_conf[0x01] = 0x80;
dev->mc_pci_conf[0x02] = 0xc5;
dev->mc_pci_conf[0x03] = 0x84;
dev->mc_pci_conf[0x04] = 0x00;
dev->mc_pci_conf[0x05] = 0x00;
dev->mc_pci_conf[0x06] = 0x80;
dev->mc_pci_conf[0x08] = 4;
dev->mc_pci_conf[0x0b] = 5;
dev->mc_pci_conf[0x07] = 0x00;
dev->mc_pci_conf[0x08] = 0x04;
dev->mc_pci_conf[0x09] = 0x00;
dev->mc_pci_conf[0x0a] = 0x00;
dev->mc_pci_conf[0x0b] = 0x05;
dev->mc_pci_conf[0x49] = 0x14;
dev->mc_pci_conf[0x4c] = 0x0b;
dev->mc_pci_conf[0x4d] = 0x08;
dev->mc_pci_conf[0x4e] = 0x00;
dev->mc_pci_conf[0x4f] = 0x00;
dev->mc_pci_conf[0x57] = 0x00;
dev->mc_pci_conf[0x58] = 0x00;
dev->mc_pci_conf[0x74] = 0x00;
dev->mc_pci_conf[0x75] = 0x00;
dev->mc_pci_conf[0x76] = 0x00;
dev->mc_pci_conf[0x77] = 0x00;
dev->mc_pci_conf[0x78] = 0x10;
dev->mc_pci_conf[0xa4] = 1;
dev->mc_pci_conf[0x79] = 0x00;
dev->mc_pci_conf[0x7a] = 0x00;
dev->mc_pci_conf[0x7b] = 0x00;
dev->mc_pci_conf[0x7c] = 0x00;
dev->mc_pci_conf[0x7d] = 0x00;
dev->mc_pci_conf[0x7e] = 0x10;
dev->mc_pci_conf[0x7f] = 0x00;
dev->mc_pci_conf[0x88] = 0x00;
dev->mc_pci_conf[0x89] = 0x00;
dev->mc_pci_conf[0x8a] = 0x00;
dev->mc_pci_conf[0x8b] = 0x00;
dev->mc_pci_conf[0x8c] = 0x00;
dev->mc_pci_conf[0x8d] = 0x00;
dev->mc_pci_conf[0x8e] = 0x00;
dev->mc_pci_conf[0x8f] = 0x00;
dev->mc_pci_conf[0xa4] = 0x01;
dev->mc_pci_conf[0xa5] = 0xc0;
dev->mc_pci_conf[0xa6] = 0xfe;
dev->mc_pci_conf[0xa7] = 0x00;
dev->mc_pci_conf[0xa8] = 0x00;
dev->mc_pci_conf[0xa9] = 0x00;
dev->mc_pci_conf[0xaa] = 0x00;
dev->mc_pci_conf[0xab] = 0x00;
dev->mc_pci_conf[0xac] = 0x16;
dev->mc_pci_conf[0xad] = 0x35;
dev->mc_pci_conf[0xae] = 0xdf;
dev->mc_pci_conf[0xaf] = 0x30;
dev->mc_pci_conf[0xb8] = 0x0a;
dev->mc_pci_conf[0xbc] = 1;
dev->mc_pci_conf[0xb9] = 0x00;
dev->mc_pci_conf[0xba] = 0x00;
dev->mc_pci_conf[0xbb] = 0x00;
dev->mc_pci_conf[0xbc] = 0x01;
dev->mc_pci_conf[0xc0] = 0x00;
dev->mc_pci_conf[0xc1] = 0x00;
dev->mc_pci_conf[0xc2] = 0x00;
dev->mc_pci_conf[0xc3] = 0x00;
dev->mc_pci_conf[0xc4] = 0x00;
dev->mc_pci_conf[0xc5] = 0x00;
dev->mc_pci_conf[0xc6] = 0x00;
dev->mc_pci_conf[0xc7] = 0x00;
i450kx_smram_recalc(dev, 0);
i450kx_vid_buf_recalc(dev, 0);
mc_write(0, 0x59, 0x03, dev);
for (i = 0x5a; i <= 0x5f; i++)
mc_write(0, i, 0x00, dev);
for (i = 0x60; i <= 0x6f; i++)
dev->mc_pci_conf[i] = 0x01;
}
@@ -542,7 +780,8 @@ i450kx_close(void *priv)
{
i450kx_t *dev = (i450kx_t *)priv;
smram_del(dev->smram);
smram_del(dev->smram[1]);
smram_del(dev->smram[0]);
free(dev);
}
@@ -552,10 +791,11 @@ i450kx_init(const device_t *info)
{
i450kx_t *dev = (i450kx_t *)malloc(sizeof(i450kx_t));
memset(dev, 0, sizeof(i450kx_t));
pci_add_card(PCI_ADD_NORTHBRIDGE, pb_read, pb_write, dev); /* Device 19: Intel 450KX PCI Bridge PB */
pci_add_card(PCI_ADD_NORTHBRIDGE, mc_read, mc_write, dev); /* Device 14: Intel 450KX Memory Controller MC */
pci_add_card(PCI_ADD_NORTHBRIDGE, pb_read, pb_write, dev); /* Device 19h: Intel 450KX PCI Bridge PB */
pci_add_card(PCI_ADD_AGPBRIDGE, mc_read, mc_write, dev); /* Device 14h: Intel 450KX Memory Controller MC */
dev->smram = smram_add();
dev->smram[0] = smram_add();
dev->smram[1] = smram_add();
cpu_cache_int_enabled = 1;
cpu_cache_ext_enabled = 1;

View File

@@ -47,7 +47,7 @@
#include <86box/hdc_ide_sff8038i.h>
#include <86box/usb.h>
#include <86box/machine.h>
#include <86box/smbus_piix4.h>
#include <86box/smbus.h>
#include <86box/chipset.h>
@@ -281,7 +281,7 @@ piix_trap_io(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv)
if (*(trap->en_reg) & trap->en_mask) {
*(trap->sts_reg) |= trap->sts_mask;
acpi_raise_smi(trap->dev->acpi);
acpi_raise_smi(trap->dev->acpi, 1);
}
}
@@ -690,6 +690,8 @@ piix_write(int func, int addr, uint8_t val, void *priv)
case 0xab:
if (dev->type == 3)
fregs[addr] &= (val & 0x01);
else if (dev->type < 3)
fregs[addr] = val;
break;
case 0xb0:
if (dev->type == 4)
@@ -1406,6 +1408,17 @@ piix_reset(void *p)
piix_write(3, 0x91, 0x00, p);
piix_write(3, 0xd2, 0x00, p);
}
sff_set_irq_mode(dev->bm[0], 0, 0);
sff_set_irq_mode(dev->bm[1], 0, 0);
if (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);
}
}
@@ -1461,6 +1474,17 @@ static void
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);
if (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->type >= 3)
dev->usb = device_add(&usb_device);

226
src/chipset/opti391.c Normal file
View File

@@ -0,0 +1,226 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Implementation of the OPTi 82C391/392 chipset.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2021 Miran Grca.
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include "cpu.h"
#include <86box/timer.h>
#include <86box/io.h>
#include <86box/device.h>
#include <86box/mem.h>
#include <86box/chipset.h>
#ifdef ENABLE_OPTI391_LOG
int opti391_do_log = ENABLE_OPTI391_LOG;
static void
opti391_log(const char *fmt, ...)
{
va_list ap;
if (opti391_do_log)
{
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define opti391_log(fmt, ...)
#endif
typedef struct
{
uint32_t phys, virt;
} mem_remapping_t;
typedef struct
{
uint8_t index, regs[256];
} opti391_t;
static void
opti391_shadow_recalc(opti391_t *dev)
{
uint32_t i, base;
uint8_t sh_enable, sh_master;
uint8_t sh_wp, sh_write_internal;
shadowbios = shadowbios_write = 0;
/* F0000-FFFFF */
sh_enable = !(dev->regs[0x22] & 0x80);
if (sh_enable)
mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
else
mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED);
sh_write_internal = (dev->regs[0x26] & 0x40);
/* D0000-EFFFF */
for (i = 0; i < 8; i++) {
base = 0xd0000 + (i << 14);
if (base >= 0xe0000) {
sh_master = (dev->regs[0x22] & 0x40);
sh_wp = (dev->regs[0x22] & 0x10);
} else {
sh_master = (dev->regs[0x22] & 0x20);
sh_wp = (dev->regs[0x22] & 0x08);
}
sh_enable = dev->regs[0x23] & (1 << i);
if (sh_master) {
if (sh_enable) {
if (sh_wp)
mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED);
else
mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
} else if (sh_write_internal)
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
else
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
} else if (sh_write_internal)
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
else
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
}
/* C0000-CFFFF */
sh_master = !(dev->regs[0x26] & 0x10);
sh_wp = (dev->regs[0x26] & 0x20);
for (i = 0; i < 4; i++) {
base = 0xc0000 + (i << 14);
sh_enable = dev->regs[0x26] & (1 << i);
if (sh_master) {
if (sh_enable) {
if (sh_wp)
mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED);
else
mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
} else if (sh_write_internal)
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
else
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
} else if (sh_write_internal)
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
else
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
}
}
static void
opti391_write(uint16_t addr, uint8_t val, void *priv)
{
opti391_t *dev = (opti391_t *)priv;
switch (addr) {
case 0x22:
dev->index = val;
break;
case 0x24:
opti391_log("OPTi 391: dev->regs[%02x] = %02x\n", dev->index, val);
switch (dev->index) {
case 0x20:
dev->regs[dev->index] = (dev->regs[dev->index] & 0xc0) | (val & 0x3f);
break;
case 0x21: case 0x24: case 0x25: case 0x27:
case 0x28: case 0x29: case 0x2a: case 0x2b:
dev->regs[dev->index] = val;
break;
case 0x22: case 0x23:
case 0x26:
dev->regs[dev->index] = val;
opti391_shadow_recalc(dev);
break;
}
break;
}
}
static uint8_t
opti391_read(uint16_t addr, void *priv)
{
opti391_t *dev = (opti391_t *)priv;
uint8_t ret = 0xff;
if (addr == 0x24)
ret = dev->regs[dev->index];
return ret;
}
static void
opti391_close(void *priv)
{
opti391_t *dev = (opti391_t *)priv;
free(dev);
}
static void *
opti391_init(const device_t *info)
{
opti391_t *dev = (opti391_t *)malloc(sizeof(opti391_t));
memset(dev, 0x00, sizeof(opti391_t));
io_sethandler(0x0022, 0x0001, opti391_read, NULL, NULL, opti391_write, NULL, NULL, dev);
io_sethandler(0x0024, 0x0001, opti391_read, NULL, NULL, opti391_write, NULL, NULL, dev);
dev->regs[0x21] = 0x84;
dev->regs[0x24] = 0x07;
dev->regs[0x25] = 0xf0;
dev->regs[0x26] = 0x30;
dev->regs[0x27] = 0x91;
dev->regs[0x28] = 0x80;
dev->regs[0x29] = 0x10;
dev->regs[0x2a] = 0x80;
dev->regs[0x2b] = 0x10;
opti391_shadow_recalc(dev);
return dev;
}
const device_t opti391_device = {
"OPTi 82C391",
0,
0,
opti391_init,
opti391_close,
NULL,
{ NULL },
NULL,
NULL,
NULL
};

264
src/chipset/opti499.c Normal file
View File

@@ -0,0 +1,264 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Implementation of the OPTi 82C493/82C499 chipset.
*
*
*
* Authors: Tiseno100,
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2020 Tiseno100.
* Copyright 2016-2020 Miran Grca.
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include "cpu.h"
#include <86box/io.h>
#include <86box/device.h>
#include <86box/mem.h>
#include <86box/port_92.h>
#include <86box/chipset.h>
typedef struct
{
uint8_t idx,
regs[256], scratch[2];
} opti499_t;
#ifdef ENABLE_OPTI499_LOG
int opti499_do_log = ENABLE_OPTI499_LOG;
static void
opti499_log(const char *fmt, ...)
{
va_list ap;
if (opti499_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define opti499_log(fmt, ...)
#endif
static void
opti499_recalc(opti499_t *dev)
{
uint32_t base;
uint32_t i, shflags = 0;
shadowbios = 0;
shadowbios_write = 0;
if (dev->regs[0x22] & 0x80) {
shadowbios = 1;
shadowbios_write = 0;
shflags = MEM_READ_EXTANY | MEM_WRITE_INTERNAL;
} else {
shadowbios = 0;
shadowbios_write = 1;
shflags = MEM_READ_INTERNAL | MEM_WRITE_DISABLED;
}
mem_set_mem_state_both(0xf0000, 0x10000, shflags);
for (i = 0; i < 8; i++) {
base = 0xd0000 + (i << 14);
if ((dev->regs[0x22] & ((base >= 0xe0000) ? 0x20 : 0x40)) &&
(dev->regs[0x23] & (1 << i))) {
shflags = MEM_READ_INTERNAL;
shflags |= (dev->regs[0x22] & ((base >= 0xe0000) ? 0x08 : 0x10)) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
} else {
if (dev->regs[0x2d] && (1 << ((i >> 1) + 2)))
shflags = MEM_READ_EXTANY | MEM_WRITE_EXTANY;
else
shflags = MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL;
}
mem_set_mem_state_both(base, 0x4000, shflags);
}
for (i = 0; i < 4; i++) {
base = 0xc0000 + (i << 14);
if ((dev->regs[0x26] & 0x10) && (dev->regs[0x26] & (1 << i))) {
shflags = MEM_READ_INTERNAL;
shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
} else {
if (dev->regs[0x26] & 0x40) {
if (dev->regs[0x2d] && (1 << (i >> 1)))
shflags = MEM_READ_EXTANY;
else
shflags = MEM_READ_EXTERNAL;
shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
} else {
if (dev->regs[0x2d] && (1 << (i >> 1)))
shflags = MEM_READ_EXTANY | MEM_WRITE_EXTANY;
else
shflags = MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL;
}
}
mem_set_mem_state_both(base, 0x4000, shflags);
}
flushmmucache_nopc();
}
static void
opti499_write(uint16_t addr, uint8_t val, void *priv)
{
opti499_t *dev = (opti499_t *) priv;
switch (addr) {
case 0x22:
opti499_log("[%04X:%08X] [W] dev->idx = %02X\n", CS, cpu_state.pc, val);
dev->idx = val;
break;
case 0x24:
if ((dev->idx >= 0x20) && (dev->idx <= 0x2d)) {
if (dev->idx == 0x20)
dev->regs[dev->idx] = (dev->regs[dev->idx] & 0xc0) | (val & 0x3f);
else
dev->regs[dev->idx] = val;
opti499_log("[%04X:%08X] [W] dev->regs[%04X] = %02X\n", CS, cpu_state.pc, dev->idx, val);
switch(dev->idx) {
case 0x20:
reset_on_hlt = !(val & 0x02);
break;
case 0x21:
cpu_cache_ext_enabled = !!(dev->regs[0x21] & 0x10);
cpu_update_waitstates();
break;
case 0x22: case 0x23:
case 0x26: case 0x2d:
opti499_recalc(dev);
break;
}
}
break;
case 0xe1: case 0xe2:
dev->scratch[addr] = val;
break;
}
}
static uint8_t
opti499_read(uint16_t addr, void *priv)
{
uint8_t ret = 0xff;
opti499_t *dev = (opti499_t *) priv;
switch (addr) {
case 0x22:
opti499_log("[%04X:%08X] [R] dev->idx = %02X\n", CS, cpu_state.pc, ret);
break;
case 0x24:
if ((dev->idx >= 0x20) && (dev->idx <= 0x2d)) {
if (dev->idx == 0x2d)
ret = dev->regs[dev->idx] & 0xbf;
else
ret = dev->regs[dev->idx];
opti499_log("[%04X:%08X] [R] dev->regs[%04X] = %02X\n", CS, cpu_state.pc, dev->idx, ret);
}
break;
case 0xe1:
case 0xe2:
ret = dev->scratch[addr];
break;
}
return ret;
}
static void
opti499_reset(void *priv)
{
opti499_t *dev = (opti499_t *) priv;
memset(dev->regs, 0xff, sizeof(dev->regs));
memset(&(dev->regs[0x20]), 0x00, 14 * sizeof(uint8_t));
dev->scratch[0] = dev->scratch[1] = 0xff;
dev->regs[0x22] = 0x84;
dev->regs[0x24] = 0x87;
dev->regs[0x25] = 0xf0;
dev->regs[0x27] = 0xd1;
dev->regs[0x28] = dev->regs[0x2a] = 0x80;
dev->regs[0x29] = dev->regs[0x2b] = 0x10;
dev->regs[0x2d] = 0x40;
reset_on_hlt = 1;
cpu_cache_ext_enabled = 0;
cpu_update_waitstates();
opti499_recalc(dev);
free(dev);
}
static void
opti499_close(void *priv)
{
opti499_t *dev = (opti499_t *) priv;
free(dev);
}
static void *
opti499_init(const device_t *info)
{
opti499_t *dev = (opti499_t *) malloc(sizeof(opti499_t));
memset(dev, 0, sizeof(opti499_t));
device_add(&port_92_device);
io_sethandler(0x0022, 0x0001, opti499_read, NULL, NULL, opti499_write, NULL, NULL, dev);
io_sethandler(0x0024, 0x0001, opti499_read, NULL, NULL, opti499_write, NULL, NULL, dev);
opti499_reset(dev);
io_sethandler(0x00e1, 0x0002, opti499_read, NULL, NULL, opti499_write, NULL, NULL, dev);
return dev;
}
const device_t opti499_device = {
"OPTi 82C499",
0,
1,
opti499_init, opti499_close, opti499_reset,
{ NULL }, NULL, NULL,
NULL
};

View File

@@ -43,6 +43,7 @@ typedef struct
} opti895_t;
#define ENABLE_OPTI895_LOG 1
#ifdef ENABLE_OPTI895_LOG
int opti895_do_log = ENABLE_OPTI895_LOG;
@@ -91,11 +92,15 @@ opti895_recalc(opti895_t *dev)
shflags = MEM_READ_INTERNAL;
shflags |= (dev->regs[0x22] & ((base >= 0xe0000) ? 0x08 : 0x10)) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
} else {
if (dev->regs[0x26] & 0x40) {
shflags = MEM_READ_EXTANY;
shflags = (dev->regs[0x2d] & (1 << ((i >> 1) + 2))) ? MEM_READ_EXTANY : MEM_READ_EXTERNAL;
if (dev->regs[0x26] & 0x40)
shflags |= (dev->regs[0x22] & ((base >= 0xe0000) ? 0x08 : 0x10)) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
} else
shflags = MEM_READ_EXTANY | MEM_WRITE_EXTANY;
else {
if (dev->regs[0x26] & 0x80)
shflags |= (dev->regs[0x2d] & (1 << ((i >> 1) + 2))) ? MEM_WRITE_EXTANY : MEM_WRITE_EXTERNAL;
else
shflags |= MEM_WRITE_EXTERNAL;
}
}
mem_set_mem_state_both(base, 0x4000, shflags);
@@ -108,17 +113,21 @@ opti895_recalc(opti895_t *dev)
shflags = MEM_READ_INTERNAL;
shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
} else {
if (dev->regs[0x26] & 0x40) {
shflags = MEM_READ_EXTANY;
shflags = (dev->regs[0x2d] & (1 << (i >> 1))) ? MEM_READ_EXTANY : MEM_READ_EXTERNAL;
if (dev->regs[0x26] & 0x40)
shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
} else
shflags = MEM_READ_EXTANY | MEM_WRITE_EXTANY;
else {
if (dev->regs[0x26] & 0x80)
shflags |= (dev->regs[0x2d] & (1 << (i >> 1))) ? MEM_WRITE_EXTANY : MEM_WRITE_EXTERNAL;
else
shflags |= MEM_WRITE_EXTERNAL;
}
}
mem_set_mem_state_both(base, 0x4000, shflags);
}
flushmmucache();
flushmmucache_nopc();
}
@@ -138,7 +147,7 @@ opti895_write(uint16_t addr, uint8_t val, void *priv)
}
break;
case 0x24:
if (((dev->idx >= 0x20) && (dev->idx <= 0x2c)) ||
if (((dev->idx >= 0x20) && (dev->idx <= 0x2f)) ||
((dev->idx >= 0xe0) && (dev->idx <= 0xef))) {
dev->regs[dev->idx] = val;
opti895_log("dev->regs[%04x] = %08x\n", dev->idx, val);
@@ -152,6 +161,7 @@ opti895_write(uint16_t addr, uint8_t val, void *priv)
case 0x22:
case 0x23:
case 0x26:
case 0x2d:
opti895_recalc(dev);
break;
@@ -177,7 +187,7 @@ opti895_write(uint16_t addr, uint8_t val, void *priv)
case 0xe1:
case 0xe2:
dev->scratch[addr] = val;
dev->scratch[addr - 0xe1] = val;
break;
}
}
@@ -195,7 +205,7 @@ opti895_read(uint16_t addr, void *priv)
ret = dev->regs[dev->idx];
break;
case 0x24:
if (((dev->idx >= 0x20) && (dev->idx <= 0x2c)) ||
if (((dev->idx >= 0x20) && (dev->idx <= 0x2f)) ||
((dev->idx >= 0xe0) && (dev->idx <= 0xef))) {
ret = dev->regs[dev->idx];
if (dev->idx == 0xe0)
@@ -204,7 +214,7 @@ opti895_read(uint16_t addr, void *priv)
break;
case 0xe1:
case 0xe2:
ret = dev->scratch[addr];
ret = dev->scratch[addr - 0xe1];
break;
}

View File

@@ -79,40 +79,56 @@ typedef struct sis_5511_t
} sis_5511_t;
static void
sis_5511_shadow_recalc(int cur_reg, sis_5511_t *dev)
sis_5511_shadow_recalc(sis_5511_t *dev)
{
if (cur_reg == 0x86)
mem_set_mem_state_both(0xf0000, 0x10000, ((dev->pci_conf[cur_reg] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->pci_conf[cur_reg] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY));
else
{
mem_set_mem_state_both(0xc0000 + ((cur_reg & 7) << 15), 0x4000, ((dev->pci_conf[cur_reg] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->pci_conf[cur_reg] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY));
mem_set_mem_state_both(0xc4000 + ((cur_reg & 7) << 15), 0x4000, ((dev->pci_conf[cur_reg] & 8) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->pci_conf[cur_reg] & 2) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY));
}
int i, state;
uint32_t base;
flushmmucache_nopc();
for (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");
} 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);
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);
}
}
flushmmucache_nopc();
}
static void
sis_5511_smram_recalc(sis_5511_t *dev)
{
smram_disable_all();
smram_disable_all();
switch (dev->pci_conf[0x65] >> 6)
{
case 0:
smram_enable(dev->smram, 0x000e0000, 0x000e0000, 0x8000, dev->pci_conf[0x65] & 0x10, 1);
break;
case 1:
smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x8000, dev->pci_conf[0x65] & 0x10, 1);
break;
case 2:
smram_enable(dev->smram, 0x000e0000, 0x000b0000, 0x8000, dev->pci_conf[0x65] & 0x10, 1);
break;
}
switch (dev->pci_conf[0x65] >> 6) {
case 0:
smram_enable(dev->smram, 0x000e0000, 0x000e0000, 0x8000, dev->pci_conf[0x65] & 0x10, 1);
break;
case 1:
smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x8000, dev->pci_conf[0x65] & 0x10, 1);
break;
case 2:
smram_enable(dev->smram, 0x000e0000, 0x000b0000, 0x8000, dev->pci_conf[0x65] & 0x10, 1);
break;
}
flushmmucache();
}
void sis_5513_ide_handler(sis_5511_t *dev)
{
ide_pri_disable();
@@ -140,31 +156,19 @@ void sis_5513_bm_handler(sis_5511_t *dev)
sff_bus_master_handler(dev->ide_drive[1], dev->pci_conf_sb[1][4] & 4, BUS_MASTER_BASE + 8);
}
static void
sis_5511_write(int func, int addr, uint8_t val, void *priv)
{
sis_5511_t *dev = (sis_5511_t *)priv;
sis_5511_t *dev = (sis_5511_t *)priv;
switch (addr)
{
case 0x04: /* Command - low byte */
dev->pci_conf[addr] = val;
break;
case 0x05: /* Command - high byte */
dev->pci_conf[addr] = val;
break;
case 0x06: /* Status - Low Byte */
dev->pci_conf[addr] &= val;
break;
case 0x07: /* Status - High Byte */
dev->pci_conf[addr] &= 0x16;
switch (addr) {
case 0x07: /* Status - High Byte */
dev->pci_conf[addr] &= 0xb0;
break;
case 0x50:
dev->pci_conf[addr] = (val & 0xf9) | 4;
dev->pci_conf[addr] = val;
cpu_cache_ext_enabled = !!(val & 0x40);
cpu_update_waitstates();
break;
@@ -177,8 +181,7 @@ sis_5511_write(int func, int addr, uint8_t val, void *priv)
dev->pci_conf[addr] = val & 0x3f;
break;
case 0x53:
case 0x54:
case 0x53: case 0x54:
dev->pci_conf[addr] = val;
break;
@@ -186,15 +189,17 @@ sis_5511_write(int func, int addr, uint8_t val, void *priv)
dev->pci_conf[addr] = val & 0xf8;
break;
case 0x57:
case 0x58:
case 0x59:
case 0x56 ... 0x59:
dev->pci_conf[addr] = val;
break;
case 0x5a:
/* TODO: Fast Gate A20 Emulation and Fast Reset Emulation on the KBC.
The former (bit 7) means the chipset intercepts D1h to 64h and 00h to 60h.
The latter (bit 6) means the chipset intercepts all odd FXh to 64h.
Bit 5 sets fast reset latency. This should be fixed on the other SiS
chipsets as well. */
dev->pci_conf[addr] = val;
port_92_set_features(dev->port_92, !!(val & 0x40), !!(val & 0x80));
break;
case 0x5b:
@@ -214,22 +219,18 @@ sis_5511_write(int func, int addr, uint8_t val, void *priv)
break;
case 0x5f:
dev->pci_conf[addr] = val;
dev->pci_conf[addr] = val & 0xfe;
break;
case 0x60:
dev->pci_conf[addr] = val & 0x3e;
if (!!(val & 2) && (dev->pci_conf[0x68] & 1))
{
if ((dev->pci_conf[0x68] & 1) && (val & 2)) {
smi_line = 1;
dev->pci_conf[0x69] |= 1;
}
break;
case 0x61: /* STPCLK# Assertion Timer */
case 0x62: /* STPCLK# De-assertion Timer */
case 0x63: /* System Standby Timer */
case 0x64:
case 0x61 ... 0x64:
dev->pci_conf[addr] = val;
break;
@@ -242,8 +243,7 @@ sis_5511_write(int func, int addr, uint8_t val, void *priv)
dev->pci_conf[addr] = val & 0x7f;
break;
case 0x67:
case 0x68:
case 0x67: case 0x68:
dev->pci_conf[addr] = val;
break;
@@ -251,11 +251,7 @@ sis_5511_write(int func, int addr, uint8_t val, void *priv)
dev->pci_conf[addr] &= val;
break;
case 0x6a:
case 0x6b:
case 0x6c:
case 0x6d:
case 0x6e:
case 0x6a ... 0x6e:
dev->pci_conf[addr] = val;
break;
@@ -329,8 +325,7 @@ sis_5511_write(int func, int addr, uint8_t val, void *priv)
case 0x85:
case 0x86:
dev->pci_conf[addr] = val & ((addr == 0x86) ? 0xe8 : 0xee);
sis_5511_shadow_recalc(addr, dev);
sis_5511_smram_recalc(dev);
sis_5511_shadow_recalc(dev);
break;
case 0x90: /* 5512 General Purpose Register Index */
@@ -620,24 +615,45 @@ sis_5513_isa_read(uint16_t addr, void *priv)
return 0xff;
}
static void
sis_5511_reset(void *priv)
{
sis_5511_t *dev = (sis_5511_t *)priv;
sis_5511_t *dev = (sis_5511_t *)priv;
/* SiS 5511 */
dev->pci_conf[0x00] = 0x39;
dev->pci_conf[0x01] = 0x10;
dev->pci_conf[0x02] = 0x11;
dev->pci_conf[0x03] = 0x55;
dev->pci_conf[0x04] = 0x07;
dev->pci_conf[0x05] = dev->pci_conf[0x06] = 0x00;
dev->pci_conf[0x07] = 0x02;
dev->pci_conf[0x08] = 0x00;
dev->pci_conf[0x09] = dev->pci_conf[0x0a] = 0x00;
dev->pci_conf[0x0b] = 0x06;
dev->pci_conf[0x50] = dev->pci_conf[0x51] = 0x00;
dev->pci_conf[0x52] = 0x20;
dev->pci_conf[0x53] = dev->pci_conf[0x54] = 0x00;
dev->pci_conf[0x55] = dev->pci_conf[0x56] = 0x00;
dev->pci_conf[0x57] = dev->pci_conf[0x58] = 0x00;
dev->pci_conf[0x59] = dev->pci_conf[0x5a] = 0x00;
dev->pci_conf[0x5b] = dev->pci_conf[0x5c] = 0x00;
dev->pci_conf[0x5d] = dev->pci_conf[0x5e] = 0x00;
dev->pci_conf[0x5f] = dev->pci_conf[0x60] = 0x00;
dev->pci_conf[0x61] = dev->pci_conf[0x62] = 0xff;
dev->pci_conf[0x63] = 0xff;
dev->pci_conf[0x64] = dev->pci_conf[0x65] = 0x00;
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;
cpu_cache_ext_enabled = 0;
cpu_update_waitstates();
/* SiS 5511 */
dev->pci_conf[0x00] = 0x39;
dev->pci_conf[0x01] = 0x10;
dev->pci_conf[0x02] = 0x11;
dev->pci_conf[0x03] = 0x55;
dev->pci_conf[0x04] = 7;
dev->pci_conf[0x07] = 2;
dev->pci_conf[0x0b] = 6;
dev->pci_conf[0x52] = 0x20;
dev->pci_conf[0x61] = 0xff;
dev->pci_conf[0x62] = 0xff;
dev->pci_conf[0x63] = 0xff;
dev->pci_conf[0x67] = 0xff;
dev->pci_conf[0x6b] = 0xff;
dev->pci_conf[0x6c] = 0xff;
dev->pci_conf[0x70] = 4;
@@ -652,6 +668,15 @@ sis_5511_reset(void *priv)
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);
/* SiS 5513 */
dev->pci_conf_sb[0][0x00] = 0x39;

View File

@@ -22,6 +22,7 @@
#define HAVE_STDARG_H
#include <86box/86box.h>
#include "cpu.h"
#include "x86.h"
#include <86box/timer.h>
#include <86box/io.h>
#include <86box/device.h>
@@ -39,6 +40,7 @@ typedef struct
reg_base, reg_last,
reg_00, is_471,
regs[39], scratch[2];
uint32_t mem_state[8];
smram_t *smram;
port_92_t *port_92;
} sis_85c4xx_t;
@@ -47,7 +49,7 @@ typedef struct
static void
sis_85c4xx_recalcmapping(sis_85c4xx_t *dev)
{
uint32_t base;
uint32_t base, n = 0;
uint32_t i, shflags = 0;
uint32_t readext, writeext;
uint8_t romcs = 0xc0, cur_romcs;
@@ -73,12 +75,25 @@ sis_85c4xx_recalcmapping(sis_85c4xx_t *dev)
shadowbios_write |= (base >= 0xe0000) && !(dev->regs[0x02] & 0x40);
shflags = (dev->regs[0x02] & 0x80) ? MEM_READ_INTERNAL : readext;
shflags |= (dev->regs[0x02] & 0x40) ? writeext : MEM_WRITE_INTERNAL;
mem_set_mem_state(base, 0x8000, shflags);
} else
mem_set_mem_state(base, 0x8000, readext | writeext);
if (dev->mem_state[i] != shflags) {
n++;
mem_set_mem_state(base, 0x8000, shflags);
if ((base >= 0xf0000) && (dev->mem_state[i] & MEM_READ_INTERNAL) && !(shflags & MEM_READ_INTERNAL))
mem_invalidate_range(base, base + 0x7fff);
dev->mem_state[i] = shflags;
}
} else {
shflags = readext | writeext;
if (dev->mem_state[i] != shflags) {
n++;
mem_set_mem_state(base, 0x8000, shflags);
dev->mem_state[i] = shflags;
}
}
}
flushmmucache_nopc();
if (n > 0)
flushmmucache_nopc();
}
@@ -141,7 +156,8 @@ sis_85c4xx_out(uint16_t port, uint8_t val, void *priv)
case 0x02: case 0x03:
case 0x08:
sis_85c4xx_recalcmapping(dev);
if (valxor)
sis_85c4xx_recalcmapping(dev);
break;
case 0x0b:
@@ -237,6 +253,69 @@ sis_85c4xx_in(uint16_t port, void *priv)
}
static void
sis_85c4xx_reset(void *priv)
{
sis_85c4xx_t *dev = (sis_85c4xx_t *) priv;
int mem_size_mb = mem_size >> 10;
static uint8_t ram_4xx[64] = { 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00,
0x19, 0x00, 0x06, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static uint8_t ram_471[64] = { 0x00, 0x00, 0x01, 0x01, 0x02, 0x20, 0x09, 0x09, 0x04, 0x04, 0x05, 0x05, 0x0b, 0x0b, 0x0b, 0x0b,
0x13, 0x21, 0x06, 0x06, 0x0d, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
0x1b, 0x1b, 0x1b, 0x1b, 0x0f, 0x0f, 0x0f, 0x0f, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e };
memset(dev->regs, 0x00, sizeof(dev->regs));
if (cpu_s->rspeed < 25000000)
dev->regs[0x08] = 0x80;
if (dev->is_471) {
dev->regs[0x09] = 0x40;
if (mem_size_mb >= 64) {
if ((mem_size_mb >= 65) && (mem_size_mb < 68))
dev->regs[0x09] |= 0x22;
else
dev->regs[0x09] |= 0x24;
} else
dev->regs[0x09] |= ram_471[mem_size_mb];
dev->regs[0x11] = 0x09;
dev->regs[0x12] = 0xff;
dev->regs[0x1f] = 0x20; /* Video access enabled. */
dev->regs[0x23] = 0xf0;
dev->regs[0x26] = 0x01;
smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x00010000, 0, 1);
port_92_remove(dev->port_92);
mem_remap_top(256);
soft_reset_mask = 0;
} else {
/* Bits 6 and 7 must be clear on the SiS 40x. */
if (dev->reg_base == 0x60)
dev->reg_00 = 0x24;
if (mem_size_mb == 64)
dev->regs[0x00] = 0x1f;
else if (mem_size_mb < 64)
dev->regs[0x00] = ram_4xx[mem_size_mb];
dev->regs[0x11] = 0x01;
}
dev->scratch[0] = dev->scratch[1] = 0xff;
cpu_cache_ext_enabled = 0;
cpu_update_waitstates();
sis_85c4xx_recalcmapping(dev);
}
static void
sis_85c4xx_close(void *priv)
{
@@ -252,8 +331,6 @@ sis_85c4xx_close(void *priv)
static void *
sis_85c4xx_init(const device_t *info)
{
int mem_size_mb;
sis_85c4xx_t *dev = (sis_85c4xx_t *) malloc(sizeof(sis_85c4xx_t));
memset(dev, 0, sizeof(sis_85c4xx_t));
@@ -261,161 +338,22 @@ sis_85c4xx_init(const device_t *info)
dev->reg_base = info->local & 0xff;
mem_size_mb = mem_size >> 10;
if (cpu_s->rspeed < 25000000)
dev->regs[0x08] = 0x80;
if (dev->is_471) {
dev->reg_last = dev->reg_base + 0x76;
dev->regs[0x09] = 0x40;
switch (mem_size_mb) {
case 0: case 1:
dev->regs[0x09] |= 0x00;
break;
case 2: case 3:
dev->regs[0x09] |= 0x01;
break;
case 4:
dev->regs[0x09] |= 0x02;
break;
case 5:
dev->regs[0x09] |= 0x20;
break;
case 6: case 7:
dev->regs[0x09] |= 0x09;
break;
case 8: case 9:
dev->regs[0x09] |= 0x04;
break;
case 10: case 11:
dev->regs[0x09] |= 0x05;
break;
case 12: case 13: case 14: case 15:
dev->regs[0x09] |= 0x0b;
break;
case 16:
dev->regs[0x09] |= 0x13;
break;
case 17:
dev->regs[0x09] |= 0x21;
break;
case 18: case 19:
dev->regs[0x09] |= 0x06;
break;
case 20: case 21: case 22: case 23:
dev->regs[0x09] |= 0x0d;
break;
case 24: case 25: case 26: case 27:
case 28: case 29: case 30: case 31:
dev->regs[0x09] |= 0x0e;
break;
case 32: case 33: case 34: case 35:
dev->regs[0x09] |= 0x1b;
break;
case 36: case 37: case 38: case 39:
dev->regs[0x09] |= 0x0f;
break;
case 40: case 41: case 42: case 43:
case 44: case 45: case 46: case 47:
dev->regs[0x09] |= 0x17;
break;
case 48:
dev->regs[0x09] |= 0x1e;
break;
default:
if (mem_size_mb < 64)
dev->regs[0x09] |= 0x1e;
else if ((mem_size_mb >= 65) && (mem_size_mb < 68))
dev->regs[0x09] |= 0x22;
else
dev->regs[0x09] |= 0x24;
break;
}
dev->regs[0x11] = 0x09;
dev->regs[0x12] = 0xff;
dev->regs[0x1f] = 0x20; /* Video access enabled. */
dev->regs[0x23] = 0xf0;
dev->regs[0x26] = 0x01;
dev->smram = smram_add();
smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x00010000, 0, 1);
dev->port_92 = device_add(&port_92_device);
port_92_remove(dev->port_92);
} else {
} else
dev->reg_last = dev->reg_base + 0x11;
/* Bits 6 and 7 must be clear on the SiS 40x. */
if (dev->reg_base == 0x60)
dev->reg_00 = 0x24;
switch (mem_size_mb) {
case 1:
default:
dev->regs[0x00] = 0x00;
break;
case 2:
dev->regs[0x00] = 0x01;
break;
case 4:
dev->regs[0x00] = 0x02;
break;
case 6:
dev->regs[0x00] = 0x03;
break;
case 8:
dev->regs[0x00] = 0x04;
break;
case 10:
dev->regs[0x00] = 0x05;
break;
case 12:
dev->regs[0x00] = 0x0b;
break;
case 16:
dev->regs[0x00] = 0x19;
break;
case 18:
dev->regs[0x00] = 0x06;
break;
case 20:
dev->regs[0x00] = 0x14;
break;
case 24:
dev->regs[0x00] = 0x15;
break;
case 32:
dev->regs[0x00] = 0x1b;
break;
case 36:
dev->regs[0x00] = 0x16;
break;
case 40:
dev->regs[0x00] = 0x17;
break;
case 48:
dev->regs[0x00] = 0x1e;
break;
case 64:
dev->regs[0x00] = 0x1f;
break;
}
dev->regs[0x11] = 0x01;
}
io_sethandler(0x0022, 0x0002,
sis_85c4xx_in, NULL, NULL, sis_85c4xx_out, NULL, NULL, dev);
dev->scratch[0] = dev->scratch[1] = 0xff;
io_sethandler(0x00e1, 0x0002,
sis_85c4xx_in, NULL, NULL, sis_85c4xx_out, NULL, NULL, dev);
sis_85c4xx_recalcmapping(dev);
sis_85c4xx_reset(dev);
return dev;
}
@@ -425,7 +363,7 @@ const device_t sis_85c401_device = {
"SiS 85c401/85c402",
0,
0x060,
sis_85c4xx_init, sis_85c4xx_close, NULL,
sis_85c4xx_init, sis_85c4xx_close, sis_85c4xx_reset,
{ NULL }, NULL, NULL,
NULL
};
@@ -434,7 +372,7 @@ const device_t sis_85c460_device = {
"SiS 85c460",
0,
0x050,
sis_85c4xx_init, sis_85c4xx_close, NULL,
sis_85c4xx_init, sis_85c4xx_close, sis_85c4xx_reset,
{ NULL }, NULL, NULL,
NULL
};
@@ -444,7 +382,7 @@ const device_t sis_85c461_device = {
"SiS 85c461",
0,
0x050,
sis_85c4xx_init, sis_85c4xx_close, NULL,
sis_85c4xx_init, sis_85c4xx_close, sis_85c4xx_reset,
{ NULL }, NULL, NULL,
NULL
};
@@ -453,7 +391,7 @@ const device_t sis_85c471_device = {
"SiS 85c407/85c471",
0,
0x150,
sis_85c4xx_init, sis_85c4xx_close, NULL,
sis_85c4xx_init, sis_85c4xx_close, sis_85c4xx_reset,
{ NULL }, NULL, NULL,
NULL
};

View File

@@ -89,7 +89,7 @@ sis_85c50x_shadow_recalc(sis_85c50x_t *dev)
mem_set_mem_state_both(base, 0x4000, (dev->pci_conf[0x56] & (1 << (7 - i))) ? (can_read | can_write) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY));
}
flushmmucache();
flushmmucache_nopc();
}
@@ -107,8 +107,7 @@ sis_85c50x_smm_recalc(sis_85c50x_t *dev)
switch ((dev->pci_conf[0x65] & 0xe0) >> 5) {
case 0x00:
if (!(dev->pci_conf[0x54] & 0xc0))
smram_enable(dev->smram, 0xe0000, 0xe0000, 0x8000, (dev->pci_conf[0x65] & 0x10), 1);
smram_enable(dev->smram, 0xe0000, 0xe0000, 0x8000, (dev->pci_conf[0x65] & 0x10), 1);
break;
case 0x01:
smram_enable(dev->smram, 0xb0000, ram_base, 0x10000, (dev->pci_conf[0x65] & 0x10), 1);

View File

@@ -12,14 +12,17 @@
* reverse engineering the BIOS of various machines using it.
*
* Authors: Tiseno100,
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2021 Tiseno100.
* Copyright 2021 Miran Grca.
*/
/* UMC 8886 Configuration Registers
/*
UMC 8886xx Configuration Registers
TODO:
- More Appropriate Bitmasking(If it's even possible)
Note: PMU functionality is quite basic. There may be Enable/Disable bits, IRQ/SMI picks and it also
required for 386_common.c to get patched in order to function properly.
Warning: Register documentation may be inaccurate!
@@ -34,11 +37,9 @@
Bits 7-4 PCI IRQ for INTD
Bits 3-0 PCI IRQ for INTC
Function 0 Register 46:
Bit 7: Replace SMI request for non-SMM CPU's (1: IRQ15/0: IRQ10)
Function 0 Register 51:
Bit 2: VGA Power Down (0: Standard/1: VESA DPMS)
Function 0 Register 46 (corrected by Miran Grca):
Bit 7: IRQ SMI Request (1: IRQ 15, 0: IRQ 10)
Bit 6: PMU Trigger(1: By IRQ/0: By SMI)
Function 0 Register 56:
Bit 1-0 ISA Bus Speed
@@ -46,10 +47,22 @@
0 1 PCICLK/4
1 0 PCICLK/2
Function 0 Register A2 - non-software SMI# status register
(documented by Miran Grca):
Bit 4: I set, graphics card goes into sleep mode
This register is most likely R/WC
Function 0 Register A3 (added more details by Miran Grca):
Bit 7: Unlock SMM
Bit 6: Software SMI trigger (also doubles as software SMI# status register,
cleared by writing a 0 to it - see the handler used by Phoenix BIOS'es):
If Function 0 Register 46 Bit 6 is set, it raises the specified IRQ (15
or 10) instead.
Function 0 Register A4:
Bit 0: Host to PCI Clock (1: 1 by 1/0: 1 by half)
Function 1 Register 4:
Function 1 Register 4: (UMC 8886AF/8886BF Only!)
Bit 0: Enable Internal IDE
*/
@@ -69,23 +82,28 @@
#include <86box/hdd.h>
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
#include <86box/pic.h>
#include <86box/pci.h>
#include <86box/chipset.h>
#define IDE_BIT 0x01
#ifdef ENABLE_UMC_8886_LOG
int umc_8886_do_log = ENABLE_UMC_8886_LOG;
static void
umc_8886_log(const char *fmt, ...)
{
va_list ap;
if (umc_8886_do_log)
{
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
if (umc_8886_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
@@ -94,23 +112,24 @@ umc_8886_log(const char *fmt, ...)
/* PCI IRQ Flags */
#define INTA (PCI_INTA + (2 * !(addr & 1)))
#define INTB (PCI_INTB + (2 * !(addr & 1)))
#define IRQRECALCA (((val & 0xf0) != 0) ? ((val & 0xf0) >> 4) : PCI_IRQ_DISABLED)
#define IRQRECALCB (((val & 0x0f) != 0) ? (val & 0x0f) : PCI_IRQ_DISABLED)
#define INTA (PCI_INTA + (2 * !(addr & 1)))
#define INTB (PCI_INTB + (2 * !(addr & 1)))
#define IRQRECALCA (((val & 0xf0) != 0) ? ((val & 0xf0) >> 4) : PCI_IRQ_DISABLED)
#define IRQRECALCB (((val & 0x0f) != 0) ? (val & 0x0f) : PCI_IRQ_DISABLED)
/* Disable Internal IDE Flag needed for the BF Southbridge variant */
#define HAS_IDE dev->has_ide
/* Disable Internal IDE Flag needed for the AF or BF Southbridge variant */
#define HAS_IDE dev->has_ide
/* Southbridge Revision */
#define SB_ID dev->sb_id
#define SB_ID dev->sb_id
typedef struct umc_8886_t
{
uint8_t pci_conf_sb[2][256]; /* PCI Registers */
uint16_t sb_id; /* Southbridge Revision */
int has_ide; /* Check if Southbridge Revision is AF or F */
uint8_t max_func, /* Last function number */
pci_conf_sb[2][256]; /* PCI Registers */
uint16_t sb_id; /* Southbridge Revision */
int has_ide; /* Check if Southbridge Revision is AF or F */
} umc_8886_t;
@@ -121,39 +140,66 @@ umc_8886_ide_handler(int status)
ide_sec_disable();
if (status) {
ide_pri_enable();
ide_sec_enable();
ide_pri_enable();
ide_sec_enable();
}
}
static void
um8886_write(int func, int addr, uint8_t val, void *priv)
umc_8886_write(int func, int addr, uint8_t val, void *priv)
{
umc_8886_t *dev = (umc_8886_t *)priv;
umc_8886_log("UM8886: dev->regs[%02x] = %02x (%02x)\n", addr, val, func);
/* We don't know the RW status of registers but Phoenix writes on some RO registers too*/
if (addr > 3) switch (func) {
case 0: /* Southbridge */
if (func <= dev->max_func) switch (func) {
case 0: /* PCI to ISA Bridge */
umc_8886_log("UM8886: dev->regs[%02x] = %02x POST %02x\n", addr, val, inb(0x80));
switch (addr) {
case 0x43:
case 0x44:
case 0x04: case 0x05:
dev->pci_conf_sb[func][addr] = val;
break;
case 0x07:
dev->pci_conf_sb[func][addr] &= ~(val & 0xf9);
break;
case 0x0c: case 0x0d:
dev->pci_conf_sb[func][addr] = val;
break;
case 0x40: case 0x41:
case 0x42:
dev->pci_conf_sb[func][addr] = val;
break;
case 0x43: case 0x44:
dev->pci_conf_sb[func][addr] = val;
pci_set_irq_routing(INTA, IRQRECALCA);
pci_set_irq_routing(INTB, IRQRECALCB);
break;
case 0x45:
dev->pci_conf_sb[func][addr] = val;
break;
case 0x46:
dev->pci_conf_sb[func][addr] = val & 0xaf;
/* Bit 6 seems to be the IRQ/SMI# toggle, 1 = IRQ, 0 = SMI#. */
dev->pci_conf_sb[func][addr] = val;
break;
case 0x47:
dev->pci_conf_sb[func][addr] = val & 0x4f;
dev->pci_conf_sb[func][addr] = val;
break;
case 0x50: case 0x51: case 0x52: case 0x53:
case 0x54: case 0x55:
dev->pci_conf_sb[func][addr] = val;
break;
case 0x56:
dev->pci_conf_sb[func][addr] = val;
switch (val & 2) {
case 0:
cpu_set_isa_pci_div(3);
@@ -165,52 +211,78 @@ um8886_write(int func, int addr, uint8_t val, void *priv)
cpu_set_isa_pci_div(2);
break;
}
break;
case 0x57:
dev->pci_conf_sb[func][addr] = val & 0x38;
case 0x70 ... 0x76:
case 0x80: case 0x81:
case 0x90 ... 0x92:
case 0xa0 ... 0xa1:
dev->pci_conf_sb[func][addr] = val;
break;
case 0x71:
dev->pci_conf_sb[func][addr] = val & 1;
case 0xa2:
dev->pci_conf_sb[func][addr] &= ~val;
break;
case 0x90:
dev->pci_conf_sb[func][addr] = val & 2;
break;
case 0xa3:
/* SMI Provocation (Bit 7 Enable SMM + Bit 6 Software SMI) */
if (((val & 0xc0) == 0xc0) && !(dev->pci_conf_sb[0][0xa3] & 0x40)) {
if (dev->pci_conf_sb[0][0x46] & 0x40)
picint(1 << ((dev->pci_conf_sb[0][0x46] & 0x80) ? 15 : 10));
else
smi_line = 1;
dev->pci_conf_sb[0][0xa3] |= 0x04;
}
case 0x92:
dev->pci_conf_sb[func][addr] = val & 0x1f;
break;
case 0xa0:
dev->pci_conf_sb[func][addr] = val & 0xfc;
dev->pci_conf_sb[func][addr] = val;
break;
case 0xa4:
dev->pci_conf_sb[func][addr] = val & 0x89;
dev->pci_conf_sb[func][addr] = val;
cpu_set_pci_speed(cpu_busspeed / ((val & 1) ? 1 : 2));
break;
default:
case 0xa5 ... 0xa8:
dev->pci_conf_sb[func][addr] = val;
break;
}
break;
case 1: /* IDE Controller */
dev->pci_conf_sb[func][addr] = val;
if ((addr == 4) && HAS_IDE)
umc_8886_ide_handler(val & 1);
case 1: /* IDE Controller */
umc_8886_log("UM8886-IDE: dev->regs[%02x] = %02x POST: %02x\n", addr, val, inb(0x80));
switch (addr) {
case 0x04:
dev->pci_conf_sb[func][addr] = val;
umc_8886_ide_handler(val & 1);
break;
case 0x07:
dev->pci_conf_sb[func][addr] &= ~(val & 0xf9);
break;
case 0x3c:
case 0x40: case 0x41:
dev->pci_conf_sb[func][addr] = val;
break;
}
break;
}
}
static uint8_t
um8886_read(int func, int addr, void *priv)
umc_8886_read(int func, int addr, void *priv)
{
umc_8886_t *dev = (umc_8886_t *)priv;
return dev->pci_conf_sb[func][addr];
uint8_t ret = 0xff;
if (func <= dev->max_func)
ret = dev->pci_conf_sb[func][addr];
return ret;
}
@@ -219,26 +291,57 @@ umc_8886_reset(void *priv)
{
umc_8886_t *dev = (umc_8886_t *)priv;
/* Defaults */
dev->pci_conf_sb[0][0] = 0x60; /* UMC */
memset(dev->pci_conf_sb[0], 0x00, sizeof(dev->pci_conf_sb[0]));
memset(dev->pci_conf_sb[1], 0x00, sizeof(dev->pci_conf_sb[1]));
dev->pci_conf_sb[0][0] = 0x60; /* UMC */
dev->pci_conf_sb[0][1] = 0x10;
dev->pci_conf_sb[0][2] = (SB_ID & 0xff); /* 8886xx */
dev->pci_conf_sb[0][2] = (SB_ID & 0xff); /* 8886xx */
dev->pci_conf_sb[0][3] = ((SB_ID >> 8) & 0xff);
dev->pci_conf_sb[0][8] = 1;
dev->pci_conf_sb[0][4] = 0x0f;
dev->pci_conf_sb[0][7] = 2;
dev->pci_conf_sb[0][8] = 0x0e;
dev->pci_conf_sb[0][0x09] = 0x00;
dev->pci_conf_sb[0][0x0a] = 0x01;
dev->pci_conf_sb[0][0x0b] = 0x06;
for (int i = 1; i < 5; i++) /* Disable all IRQ interrupts */
pci_set_irq_routing(i, PCI_IRQ_DISABLED);
dev->pci_conf_sb[0][0x40] = 1;
dev->pci_conf_sb[0][0x41] = 6;
dev->pci_conf_sb[0][0x42] = 8;
dev->pci_conf_sb[0][0x43] = 0x9a;
dev->pci_conf_sb[0][0x44] = 0xbc;
dev->pci_conf_sb[0][0x45] = 4;
dev->pci_conf_sb[0][0x47] = 0x40;
dev->pci_conf_sb[0][0x50] = 1;
dev->pci_conf_sb[0][0x51] = 3;
dev->pci_conf_sb[0][0xa8] = 0x20;
if (HAS_IDE) {
dev->pci_conf_sb[1][0] = 0x60; /* UMC */
dev->pci_conf_sb[1][1] = 0x10;
dev->pci_conf_sb[1][2] = 0x3a; /* 8886BF IDE */
dev->pci_conf_sb[1][3] = 0x67;
dev->pci_conf_sb[1][4] = 1; /* Start with Internal IDE Enabled */
dev->pci_conf_sb[1][8] = 0x10;
dev->pci_conf_sb[1][0x09] = 0x0f;
dev->pci_conf_sb[1][0x0a] = dev->pci_conf_sb[1][0x0b] = 1;
umc_8886_ide_handler(1);
}
for (int i = 1; i < 5; i++) /* Disable all IRQ interrupts */
pci_set_irq_routing(i, PCI_IRQ_DISABLED);
cpu_set_isa_pci_div(3);
cpu_set_pci_speed(cpu_busspeed / 2);
}
@@ -257,12 +360,14 @@ umc_8886_init(const device_t *info)
umc_8886_t *dev = (umc_8886_t *)malloc(sizeof(umc_8886_t));
memset(dev, 0, sizeof(umc_8886_t));
dev->has_ide = (info->local == 0x886a);
pci_add_card(PCI_ADD_SOUTHBRIDGE, um8886_read, um8886_write, dev); /* Device 12: UMC 8886xx */
dev->has_ide = !!(info->local == 0x886a);
pci_add_card(PCI_ADD_SOUTHBRIDGE, umc_8886_read, umc_8886_write, dev); /* Device 12: UMC 8886xx */
/* Add IDE if UM8886AF variant */
if (HAS_IDE)
device_add(&ide_pci_2ch_device);
device_add(&ide_pci_2ch_device);
dev->max_func = (HAS_IDE) ? 1 : 0;
/* Get the Southbridge Revision */
SB_ID = info->local;
@@ -277,24 +382,16 @@ const device_t umc_8886f_device = {
"UMC 8886F",
DEVICE_PCI,
0x8886,
umc_8886_init,
umc_8886_close,
umc_8886_reset,
{ NULL },
NULL,
NULL,
umc_8886_init, umc_8886_close, umc_8886_reset,
{ NULL }, NULL, NULL,
NULL
};
const device_t umc_8886af_device = {
"UMC 8886AF",
"UMC 8886AF/8886BF",
DEVICE_PCI,
0x886a,
umc_8886_init,
umc_8886_close,
umc_8886_reset,
{ NULL },
NULL,
NULL,
umc_8886_init, umc_8886_close, umc_8886_reset,
{ NULL }, NULL, NULL,
NULL
};

View File

@@ -1,180 +0,0 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Implementation of the UMC 8890 Chipset.
*
* Note: This chipset has no datasheet, everything were done via
* reverse engineering the BIOS of various machines using it.
*
*
* Authors: Tiseno100,
*
* Copyright 2021 Tiseno100.
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include "cpu.h"
#include <86box/timer.h>
#include <86box/io.h>
#include <86box/device.h>
#include <86box/apm.h>
#include <86box/mem.h>
#include <86box/pci.h>
#include <86box/port_92.h>
#include <86box/smram.h>
#include <86box/chipset.h>
#ifdef ENABLE_UMC_8890_LOG
int umc_8890_do_log = ENABLE_UMC_8890_LOG;
static void
umc_8890_log(const char *fmt, ...)
{
va_list ap;
if (umc_8890_do_log)
{
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define umc_8890_log(fmt, ...)
#endif
/* Shadow RAM Flags */
#define ENABLE_SHADOW (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL)
#define DISABLE_SHADOW (MEM_READ_EXTANY | MEM_WRITE_EXTANY)
typedef struct umc_8890_t
{
apm_t *apm;
smram_t *smram;
uint8_t pci_conf[256];
} umc_8890_t;
uint16_t umc_8890_shadow_flag(uint8_t flag)
{
return (flag & 1) ? (MEM_READ_INTERNAL | ((flag & 2) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL)) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY);
}
void umc_8890_shadow(umc_8890_t *dev)
{
mem_set_mem_state_both(0xe0000, 0x10000, umc_8890_shadow_flag((dev->pci_conf[0x5f] & 0x0c) >> 2));
mem_set_mem_state_both(0xf0000, 0x10000, umc_8890_shadow_flag((dev->pci_conf[0x5f] & 0xc0) >> 6));
for(int i = 0; i < 8; i++)
mem_set_mem_state_both(0xc0000 + (i << 14), 0x4000, umc_8890_shadow_flag(!!(dev->pci_conf[0x5d] & (1 << i))));
flushmmucache_nopc();
}
static void
um8890_write(int func, int addr, uint8_t val, void *priv)
{
umc_8890_t *dev = (umc_8890_t *)priv;
dev->pci_conf[addr] = val;
switch (addr)
{
case 0x5c:
case 0x5d:
case 0x5e:
case 0x5f:
umc_8890_shadow(dev);
break;
case 0x65: /* We don't know the default SMRAM values */
smram_disable_all();
smram_enable(dev->smram, 0xe0000, 0xe0000, 0x10000, dev->pci_conf[0x65] & 0x10, 1);
flushmmucache_nopc();
break;
}
umc_8890_log("UM8890: dev->regs[%02x] = %02x POST: %02x\n", addr, dev->pci_conf[addr], inb(0x80));
}
static uint8_t
um8890_read(int func, int addr, void *priv)
{
umc_8890_t *dev = (umc_8890_t *)priv;
return dev->pci_conf[addr];
}
static void
umc_8890_reset(void *priv)
{
umc_8890_t *dev = (umc_8890_t *)priv;
/* Defaults */
dev->pci_conf[0] = 0x60; /* UMC */
dev->pci_conf[1] = 0x10;
dev->pci_conf[2] = 0x91; /* 8891F */
dev->pci_conf[3] = 0x88;
dev->pci_conf[8] = 1;
dev->pci_conf[0x09] = 0x00;
dev->pci_conf[0x0a] = 0x00;
dev->pci_conf[0x0b] = 0x06;
}
static void
umc_8890_close(void *priv)
{
umc_8890_t *dev = (umc_8890_t *)priv;
smram_del(dev->smram);
free(dev);
}
static void *
umc_8890_init(const device_t *info)
{
umc_8890_t *dev = (umc_8890_t *)malloc(sizeof(umc_8890_t));
memset(dev, 0, sizeof(umc_8890_t));
pci_add_card(PCI_ADD_NORTHBRIDGE, um8890_read, um8890_write, dev); /* Device 0: UMC 8890 */
/* APM */
dev->apm = device_add(&apm_pci_device);
/* SMRAM(Needs excessive documentation before we begin SMM implementation) */
dev->smram = smram_add();
/* Port 92 */
device_add(&port_92_pci_device);
umc_8890_reset(dev);
return dev;
}
const device_t umc_8890_device = {
"UMC 8890(8891BF/8892BF)",
DEVICE_PCI,
0x886a,
umc_8890_init,
umc_8890_close,
umc_8890_reset,
{NULL},
NULL,
NULL,
NULL};

View File

@@ -15,71 +15,77 @@
* around the web.
*
* Authors: Tiseno100,
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2021 Tiseno100.
* Copyright 2021 Miran Grca.
*/
/*
UMC HB4 Configuration Registers
UMC HB4 Configuration Registers
Sources & Notes:
Cache registers were found at Vogons: https://www.vogons.org/viewtopic.php?f=46&t=68829&start=20
Basic Reverse engineering effort was done personally by me
Sources & Notes:
Cache registers were found at Vogons: https://www.vogons.org/viewtopic.php?f=46&t=68829&start=20
Basic Reverse engineering effort was done personally by me
TODO:
- APM, SMM, SMRAM registers(Did some early work. Still quite incomplete)
- More Appropriate Bitmasking(If it's even possible)
Warning: Register documentation may be inaccurate!
Warning: Register documentation may be inaccurate!
UMC 8881x:
UMC 8881x:
Register 50:
Bit 7: Enable L2 Cache
Bit 6: Cache Policy (0: Write Thru / 1: Write Back)
Register 50:
Bit 7: Enable L2 Cache
Bit 6: Cache Policy (0: Write Thru / 1: Write Back)
Bit 5-4 Cache Speed
0 0 Read 3-2-2-2 Write 3T
0 1 Read 3-1-1-1 Write 3T
1 0 Read 2-2-2-2 Write 2T
1 1 Read 2-1-1-1 Write 2T
Bit 5-4 Cache Speed
0 0 Read 3-2-2-2 Write 3T
0 1 Read 3-1-1-1 Write 3T
1 0 Read 2-2-2-2 Write 2T
1 1 Read 2-1-1-1 Write 2T
Bit 3 Cache Banks (0: 1 Bank / 1: 2 Banks)
Bit 3 Cache Banks (0: 1 Bank / 1: 2 Banks)
Bit 2-1-0 Cache Size
0 0 0 0KB
0 0 1 64KB
x-x-x Multiplications of 2(64*2 for 0 1 0) till 2MB
Bit 2-1-0 Cache Size
0 0 0 0KB
0 0 1 64KB
x-x-x Multiplications of 2(64*2 for 0 1 0) till 2MB
Register 51:
Bit 7-6 DRAM Read Speed
5-4 DRAM Write Speed
0 0 1 Waits
0 1 1 Waits
1 0 1 Wait
1 1 0 Waits
Register 51:
Bit 7-6 DRAM Read Speed
5-4 DRAM Write Speed
0 0 1 Waits
0 1 1 Waits
1 0 1 Wait
1 1 0 Waits
Bit 3 Resource Lock Enable
Bit 2 Graphics Adapter (0: VL Bus / 1: PCI Bus)
Bit 1 L1 WB Policy (0: WT / 1: WB)
Bit 0 L2 Cache Tag Lenght (0: 7 Bits / 1: 8 Bits)
Bit 3 Resource Lock Enable
Bit 2 Graphics Adapter (0: VL Bus / 1: PCI Bus)
Bit 1 L1 WB Policy (0: WT / 1: WB)
Bit 0 L2 Cache Tag Lenght (0: 7 Bits / 1: 8 Bits)
Register 52:
Bit 7: Host-to-PCI Post Write (0: 1 Wait State / 1: 0 Wait States)
Register 52:
Bit 7: Host-to-PCI Post Write (0: 1 Wait State / 1: 0 Wait States)
Register 54:
Bit 7: DC000-DFFFF Read Enable
Bit 6: D8000-DBFFF Read Enable
Bit 5: D4000-D7FFF Read Enable
Bit 4: D0000-D3FFF Read Enable
Bit 3: CC000-CFFFF Read Enable
Bit 2: C8000-CBFFF Read Enable
Bit 1: C0000-C7FFF Read Enable
Bit 0: Enable C0000-DFFFF Shadow Segment Bits
Register 54:
Bit 7: DC000-DFFFF
Bit 6: D8000-DBFFF
Bit 5: D4000-D7FFF
Bit 4: D0000-D3FFF
Bit 3: CC000-CFFFF
Bit 2: C8000-CBFFF
Bit 1: C0000-C7FFF
Bit 0: Reserved
Register 55:
Bit 7: E0000-FFFF Read Enable
Bit 6: Shadow Write Status (1: Write Protect/0: Write)
Register 55:
Bit 7: Enable Shadow Reads For System & Selected Segments
Bit 6: Write Protect Enable
Register 56h & 57h: DRAM Bank 0 Configuration
Register 58h & 59h: DRAM Bank 1 Configuration
Register 60:
Bit 5: If set and SMRAM is enabled, data cycles go to PCI and code cycles go to DRAM
Bit 0: SMRAM Local Access Enable - if set, SMRAM is also enabled outside SMM
SMRAM appears to always be enabled in SMM, and always set to A0000-BFFFF.
*/
#include <stdarg.h>
@@ -91,161 +97,331 @@ Bit 6: Write Protect Enable
#define HAVE_STDARG_H
#include <86box/86box.h>
#include "cpu.h"
#include "x86.h"
#include <86box/timer.h>
#include <86box/io.h>
#include <86box/device.h>
#include <86box/apm.h>
#include <86box/mem.h>
#include <86box/pci.h>
#include <86box/port_92.h>
#include <86box/smram.h>
#ifdef USE_DYNAREC
# include "codegen_public.h"
#else
#ifdef USE_NEW_DYNAREC
# define PAGE_MASK_SHIFT 6
#else
# define PAGE_MASK_INDEX_MASK 3
# define PAGE_MASK_INDEX_SHIFT 10
# define PAGE_MASK_SHIFT 4
#endif
# define PAGE_MASK_MASK 63
#endif
#include <86box/chipset.h>
#ifdef ENABLE_HB4_LOG
int hb4_do_log = ENABLE_HB4_LOG;
static void
hb4_log(const char *fmt, ...)
{
va_list ap;
if (hb4_do_log)
{
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
if (hb4_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define hb4_log(fmt, ...)
#endif
/* Shadow RAM Flags */
#define CAN_READ ((dev->pci_conf[0x55] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY)
#define CAN_WRITE ((dev->pci_conf[0x55] & 0x40) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL)
#define DISABLE (MEM_READ_EXTANY | MEM_WRITE_EXTANY)
typedef struct hb4_t
{
apm_t *apm;
smram_t *smram;
uint8_t pci_conf[256]; /* PCI Registers */
uint8_t shadow,
shadow_read, shadow_write,
pci_conf[256]; /* PCI Registers */
int mem_state[9];
smram_t *smram[3]; /* SMRAM Handlers */
} hb4_t;
void hb4_shadow(int cur_addr, hb4_t *dev)
{
mem_set_mem_state_both(0xc0000, 0x8000, (dev->pci_conf[0x54] & 2) ? (CAN_READ | CAN_WRITE) : DISABLE);
for (int i = 2; i < 8; i++)
mem_set_mem_state_both(0xc8000 + ((i - 2) << 14), 0x4000, (dev->pci_conf[0x54] & (1 << i)) ? (CAN_READ | CAN_WRITE) : DISABLE);
mem_set_mem_state_both(0xe0000, 0x20000, CAN_READ | CAN_WRITE);
static int shadow_bios[4] = { (MEM_READ_EXTANY | MEM_WRITE_INTERNAL), (MEM_READ_EXTANY | MEM_WRITE_EXTANY),
(MEM_READ_INTERNAL | MEM_WRITE_INTERNAL), (MEM_READ_INTERNAL | MEM_WRITE_EXTANY) };
static int shadow_read[2] = { MEM_READ_EXTANY, MEM_READ_INTERNAL };
static int shadow_write[2] = { MEM_WRITE_INTERNAL, MEM_WRITE_EXTANY };
int
hb4_shadow_bios_high(hb4_t *dev)
{
int state;
state = shadow_bios[dev->pci_conf[0x55] >> 6];
if (state != dev->mem_state[8]) {
mem_set_mem_state_both(0xf0000, 0x10000, state);
if ((dev->mem_state[8] & MEM_READ_INTERNAL) && !(state & MEM_READ_INTERNAL))
mem_invalidate_range(0xf0000, 0xfffff);
dev->mem_state[8] = state;
return 1;
}
return 0;
}
int
hb4_shadow_bios_low(hb4_t *dev)
{
int state;
state = shadow_bios[(dev->pci_conf[0x55] >> 6) & (dev->shadow | 0x01)];
if (state != dev->mem_state[7]) {
mem_set_mem_state_both(0xe0000, 0x10000, state);
dev->mem_state[7] = state;
return 1;
}
return 0;
}
int
hb4_shadow_main(hb4_t *dev)
{
int i, state;
int n = 0;
for (i = 0; i < 6; i++) {
state = shadow_read[dev->shadow && ((dev->pci_conf[0x54] >> (i + 2)) & 0x01)] |
shadow_write[(dev->pci_conf[0x55] >> 6) & 0x01];
if (state != dev->mem_state[i + 1]) {
n++;
mem_set_mem_state_both(0xc8000 + (i << 14), 0x4000, state);
dev->mem_state[i + 1] = state;
}
}
return n;
}
int
hb4_shadow_video(hb4_t *dev)
{
int state;
state = shadow_read[dev->shadow && ((dev->pci_conf[0x54] >> 1) & 0x01)] |
shadow_write[(dev->pci_conf[0x55] >> 6) & 0x01];
if (state != dev->mem_state[0]) {
mem_set_mem_state_both(0xc0000, 0x8000, state);
dev->mem_state[0] = state;
return 1;
}
return 0;
}
void
hb4_shadow(hb4_t *dev)
{
int n = 0;
hb4_log("SHADOW: %02X%02X\n", dev->pci_conf[0x55], dev->pci_conf[0x54]);
n = hb4_shadow_bios_high(dev);
n += hb4_shadow_bios_low(dev);
n += hb4_shadow_main(dev);
n += hb4_shadow_video(dev);
if (n > 0)
flushmmucache_nopc();
}
static void
um8881_write(int func, int addr, uint8_t val, void *priv)
hb4_smram(hb4_t *dev)
{
smram_disable_all();
/* Bit 0, if set, enables SMRAM access outside SMM. SMRAM appears to be always enabled
in SMM, and is always set to A0000-BFFFF. */
smram_enable(dev->smram[0], 0x000a0000, 0x000a0000, 0x20000, dev->pci_conf[0x60] & 0x01, 1);
/* There's a mirror of the SMRAM at 0E0A0000, mapped to A0000. */
smram_enable(dev->smram[1], 0x0e0a0000, 0x000a0000, 0x20000, dev->pci_conf[0x60] & 0x01, 1);
/* There's another mirror of the SMRAM at 4E0A0000, mapped to A0000. */
smram_enable(dev->smram[2], 0x4e0a0000, 0x000a0000, 0x20000, dev->pci_conf[0x60] & 0x01, 1);
/* Bit 5 seems to set data to go to PCI and code to DRAM. The Samsung SPC7700P-LW uses
this. */
if (dev->pci_conf[0x60] & 0x20) {
if (dev->pci_conf[0x60] & 0x01)
mem_set_mem_state_smram_ex(0, 0x000a0000, 0x20000, 0x02);
mem_set_mem_state_smram_ex(1, 0x000a0000, 0x20000, 0x02);
}
}
static void
hb4_write(int func, int addr, uint8_t val, void *priv)
{
hb4_t *dev = (hb4_t *)priv;
hb4_log("UM8881: dev->regs[%02x] = %02x\n", addr, val);
if (addr > 3) /* We don't know the RW status of registers but Phoenix writes on some RO registers too*/
hb4_log("UM8881: dev->regs[%02x] = %02x POST: %02x \n", addr, val, inb(0x80));
switch (addr)
{
case 0x50:
dev->pci_conf[addr] = ((val & 0xf8) | 4); /* Hardcode Cache Size to 512KB */
cpu_cache_ext_enabled = !!(val & 0x80); /* Fixes freezing issues on the HOT-433A*/
cpu_update_waitstates();
break;
switch (addr) {
case 0x04: case 0x05:
dev->pci_conf[addr] = val;
break;
case 0x54:
case 0x55:
dev->pci_conf[addr] = val & (!(addr & 1) ? 0xfe : 0xff);
hb4_shadow(addr, dev);
break;
case 0x07:
dev->pci_conf[addr] &= ~(val & 0xf9);
break;
case 0x60:
dev->pci_conf[addr] = val & 0x3f;
break;
case 0x0c: case 0x0d:
dev->pci_conf[addr] = val;
break;
case 0x61:
dev->pci_conf[addr] = val & 0x0f;
break;
case 0x50:
dev->pci_conf[addr] = ((val & 0xf8) | 4); /* Hardcode Cache Size to 512KB */
cpu_cache_ext_enabled = !!(val & 0x80); /* Fixes freezing issues on the HOT-433A*/
cpu_update_waitstates();
break;
default:
dev->pci_conf[addr] = val;
break;
}
case 0x51: case 0x52:
dev->pci_conf[addr] = val;
break;
case 0x53:
dev->pci_conf[addr] = val;
hb4_log("HB53: %02X\n", val);
break;
case 0x55:
dev->shadow_read = (val & 0x80);
dev->shadow_write = (val & 0x40);
dev->pci_conf[addr] = val;
hb4_shadow(dev);
break;
case 0x54:
dev->shadow = (val & 0x01) << 1;
dev->pci_conf[addr] = val;
hb4_shadow(dev);
break;
case 0x56 ... 0x5f:
dev->pci_conf[addr] = val;
break;
case 0x60:
dev->pci_conf[addr] = val;
hb4_smram(dev);
break;
case 0x61:
dev->pci_conf[addr] = val;
break;
}
}
static uint8_t
um8881_read(int func, int addr, void *priv)
hb4_read(int func, int addr, void *priv)
{
hb4_t *dev = (hb4_t *)priv;
return dev->pci_conf[addr];
uint8_t ret = 0xff;
if (func == 0)
ret = dev->pci_conf[addr];
return ret;
}
static void
hb4_reset(void *priv)
{
hb4_t *dev = (hb4_t *)priv;
memset(dev->pci_conf, 0x00, sizeof(dev->pci_conf));
/* Defaults */
dev->pci_conf[0] = 0x60; /* UMC */
dev->pci_conf[1] = 0x10;
dev->pci_conf[2] = 0x81; /* 8881x */
dev->pci_conf[3] = 0x88;
dev->pci_conf[8] = 1;
dev->pci_conf[7] = 2;
dev->pci_conf[8] = 4;
dev->pci_conf[0x09] = 0x00;
dev->pci_conf[0x0a] = 0x00;
dev->pci_conf[0x0b] = 0x06;
dev->pci_conf[0x51] = 1;
dev->pci_conf[0x52] = 1;
dev->pci_conf[0x5a] = 4;
dev->pci_conf[0x5c] = 0xc0;
dev->pci_conf[0x5d] = 0x20;
dev->pci_conf[0x5f] = 0xff;
hb4_write(0, 0x54, 0x00, dev);
hb4_write(0, 0x55, 0x00, dev);
hb4_write(0, 0x60, 0x80, dev);
cpu_cache_ext_enabled = 0;
cpu_update_waitstates();
memset(dev->mem_state, 0x00, sizeof(dev->mem_state));
}
static void
hb4_close(void *priv)
{
hb4_t *dev = (hb4_t *)priv;
//smram_del(dev->smram);
free(dev);
}
static void *
hb4_init(const device_t *info)
{
hb4_t *dev = (hb4_t *)malloc(sizeof(hb4_t));
memset(dev, 0, sizeof(hb4_t));
pci_add_card(PCI_ADD_NORTHBRIDGE, um8881_read, um8881_write, dev); /* Device 10: UMC 8881x */
/* APM */
dev->apm = device_add(&apm_pci_device);
/* SMRAM(Needs excessive documentation before we begin SMM implementation) */
//dev->smram = smram_add();
pci_add_card(PCI_ADD_NORTHBRIDGE, hb4_read, hb4_write, dev); /* Device 10: UMC 8881x */
/* Port 92 */
device_add(&port_92_pci_device);
/* SMRAM */
dev->smram[0] = smram_add();
dev->smram[1] = smram_add();
dev->smram[2] = smram_add();
hb4_reset(dev);
return dev;
}
const device_t umc_hb4_device = {
"UMC HB4(8881F)",
DEVICE_PCI,
0x886a,
hb4_init,
hb4_close,
hb4_reset,
{NULL},
NULL,
NULL,
NULL};
hb4_init, hb4_close, hb4_reset,
{ NULL }, NULL, NULL,
NULL
};

View File

@@ -234,13 +234,12 @@ via_apollo_host_bridge_write(int func, int addr, uint8_t val, void *priv)
return;
/*Read-only addresses*/
if ((addr < 4) || ((addr >= 5) && (addr < 7)) || ((addr >= 8) && (addr < 0xd)) ||
((addr >= 0xe) && (addr < 0x12)) || ((addr >= 0x14) && (addr < 0x50)) ||
(addr == 0x69) || ((addr >= 0x79) && (addr < 0x7e)) ||
((addr >= 0x81) && (addr < 0x84)) || ((addr >= 0x85) && (addr < 0x88)) ||
((addr >= 0x8c) && (addr < 0xa8)) || ((addr >= 0xaa) && (addr < 0xac)) ||
((addr >= 0xad) && (addr < 0xf0)) || ((addr >= 0xf8) && (addr < 0xfc)) ||
(addr == 0xfd))
if ((addr < 4) || ((addr > 5) && (addr < 7)) || ((addr >= 8) && (addr < 0xd)) ||
((addr >= 0xe) && (addr != 0x0f) && (addr < 0x12)) || ((addr >= 0x14) && (addr < 0x50)) ||
((addr > 0x7a) && (addr < 0x7e)) || ((addr >= 0x81) && (addr < 0x84)) ||
((addr >= 0x85) && (addr < 0x88)) || ((addr >= 0x8c) && (addr < 0xa8)) ||
((addr >= 0xaa) && (addr < 0xac)) || ((addr > 0xad) && (addr < 0xf0)) ||
((addr >= 0xf8) && (addr < 0xfc)))
return;
if (((addr == 0x12) || (addr == 0x13)) && (dev->id < VIA_597))
return;

View File

@@ -46,7 +46,7 @@
#include <86box/hdc_ide_sff8038i.h>
#include <86box/usb.h>
#include <86box/machine.h>
#include <86box/smbus_piix4.h>
#include <86box/smbus.h>
#include <86box/chipset.h>
#include <86box/sio.h>
#include <86box/hwm.h>
@@ -172,7 +172,7 @@ pipc_trap_io_pact(int size, uint16_t addr, uint8_t write, uint8_t val, void *pri
*(trap->sts_reg) |= trap->mask;
trap->dev->acpi->regs.glbsts |= 0x0001;
if (trap->dev->acpi->regs.glben & 0x0001)
acpi_raise_smi(trap->dev->acpi);
acpi_raise_smi(trap->dev->acpi, 1);
}
}
@@ -184,7 +184,7 @@ pipc_io_trap_glb(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv
if (*(trap->en_reg) & trap->mask) {
*(trap->sts_reg) |= trap->mask;
acpi_raise_smi(trap->dev->acpi);
acpi_raise_smi(trap->dev->acpi, 1);
}
}

View File

@@ -133,9 +133,9 @@ vt82c49x_recalc(vt82c49x_t *dev)
state = (dev->regs[0x33] & 0x10) ? MEM_WRITE_ROMCS : MEM_WRITE_EXTERNAL;
if ((dev->regs[0x32]) & (1 << (bit + 1)))
state = MEM_READ_INTERNAL;
state |= MEM_READ_INTERNAL;
else
state = (dev->regs[0x33] & 0x10) ? MEM_READ_ROMCS : MEM_READ_EXTERNAL;
state |= (dev->regs[0x33] & 0x10) ? MEM_READ_ROMCS : MEM_READ_EXTERNAL;
} else if ((base >= 0xe8000) && (base <= 0xeffff)) {
if (dev->regs[0x40] & 0x20)
state = MEM_WRITE_DISABLED;

View File

@@ -98,9 +98,18 @@ vl82c480_write(uint16_t addr, uint8_t val, void *p)
default:
dev->regs[dev->idx] = val;
break;
case 0x04:
if (dev->regs[0x00] == 0x98)
dev->regs[dev->idx] = (dev->regs[dev->idx] & 0x08) | (val & 0xf7);
else
dev->regs[dev->idx] = val;
break;
case 0x05:
dev->regs[dev->idx] = (dev->regs[dev->idx] & 0x10) | (val & 0xef);
break;
case 0x07:
dev->regs[dev->idx] = (dev->regs[dev->idx] & 0x40) | (val & 0xbf);
break;
case 0x0d: case 0x0e: case 0x0f: case 0x10:
case 0x11: case 0x12:
dev->regs[dev->idx] = val;
@@ -163,11 +172,13 @@ vl82c480_init(const device_t *info)
vl82c480_t *dev = (vl82c480_t *)malloc(sizeof(vl82c480_t));
memset(dev, 0, sizeof(vl82c480_t));
dev->regs[0x00] = 0x90;
dev->regs[0x00] = info->local;
dev->regs[0x01] = 0xff;
dev->regs[0x02] = 0x8a;
dev->regs[0x03] = 0x88;
dev->regs[0x06] = 0x1b;
if (info->local == 0x98)
dev->regs[0x07] = 0x21;
dev->regs[0x08] = 0x38;
io_sethandler(0x00ec, 0x0004, vl82c480_read, NULL, NULL, vl82c480_write, NULL, NULL, dev);
@@ -181,7 +192,17 @@ vl82c480_init(const device_t *info)
const device_t vl82c480_device = {
"VLSI VL82c480",
0,
0,
0x90,
vl82c480_init, vl82c480_close, NULL,
{ NULL }, NULL, NULL,
NULL
};
const device_t vl82c486_device = {
"VLSI VL82c486",
0,
0x98,
vl82c480_init, vl82c480_close, NULL,
{ NULL }, NULL, NULL,
NULL