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:
@@ -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)
|
||||
|
||||
@@ -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};
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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
656
src/chipset/ali1541.c
Normal 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
685
src/chipset/ali1621.c
Normal 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
|
||||
};
|
||||
@@ -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
375
src/chipset/contaq_82c59x.c
Normal 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
411
src/chipset/ims8848.c
Normal 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
|
||||
};
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
226
src/chipset/opti391.c
Normal 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
264
src/chipset/opti499.c
Normal 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
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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};
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user