Files
86Box/src/chipset/intel_i450kx.c

832 lines
25 KiB
C

/*
* 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 Intel 450KX Mars Chipset.
*
* i450GX is way more popular of an option but needs more stuff.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Tiseno100,
*
* Copyright 2021-2024 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/timer.h>
#include <86box/io.h>
#include <86box/device.h>
#include <86box/mem.h>
#include <86box/pci.h>
#include <86box/plat_unused.h>
#include <86box/smram.h>
#include <86box/spd.h>
#include <86box/chipset.h>
#ifdef ENABLE_450KX_LOG
int i450kx_do_log = ENABLE_450KX_LOG;
static void
i450kx_log(const char *fmt, ...)
{
va_list ap;
if (i450kx_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define i450kx_log(fmt, ...)
#endif
/* TODO: Finish the bus index stuff. */
typedef struct i450kx_t {
smram_t *smram[2];
uint8_t bus_index;
uint8_t pb_slot;
uint8_t mc_slot;
uint8_t pad;
uint8_t pb_pci_conf[256];
uint8_t mc_pci_conf[256];
uint8_t mem_state[2][256];
} i450kx_t;
static void
i450kx_map(i450kx_t *dev, int bus, uint32_t addr, uint32_t size, int state)
{
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();
}
}
static void
i450kx_smram_recalc(i450kx_t *dev, int bus)
{
const uint8_t *regs = bus ? dev->pb_pci_conf : dev->mc_pci_conf;
uint32_t addr;
uint32_t size;
int enable = bus ? !(regs[0x57] & 0x08) : (regs[0x57] & 0x08);
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) && enable) {
if (bus)
smram_enable_ex(dev->smram[bus], addr, addr, size, 0, 0, 0, enable);
else
smram_enable_ex(dev->smram[bus], addr, addr, size, 0, 0, enable, 0);
}
flushmmucache();
}
static void
i450kx_vid_buf_recalc(i450kx_t *dev, int bus)
{
const uint8_t *regs = bus ? dev->pb_pci_conf : dev->mc_pci_conf;
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;
if (func == 0) {
i450kx_log("[%04X:%08X] i450KX-PB: [W] dev->pb_pci_conf[%02X] = %02X\n", CS, cpu_state.pc,
addr, val);
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;
case 0x0f:
dev->pb_pci_conf[addr] = val & 0xcf;
break;
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 & 0x06;
break;
case 0x4a:
case 0x4b:
dev->pb_pci_conf[addr] = val;
#if 0
if (addr == 0x4a)
pci_remap_bus(dev->bus_index, val);
#endif
break;
case 0x4c:
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 & 0x02;
break;
case 0x54:
dev->pb_pci_conf[addr] = val & 0x7b;
break;
case 0x55:
dev->pb_pci_conf[addr] = val & 0x03;
break;
case 0x57:
dev->pb_pci_conf[addr] = val & 0x08;
i450kx_smram_recalc(dev, 1);
break;
case 0x58:
dev->pb_pci_conf[addr] = val & 0x02;
i450kx_vid_buf_recalc(dev, 1);
break;
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 & 0xf8;
break;
case 0x71:
dev->pb_pci_conf[addr] = val & 0x71;
break;
case 0x78:
dev->pb_pci_conf[addr] = val & 0xf0;
break;
case 0x79:
dev->pb_pci_conf[addr] = val & 0xfc;
break;
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:
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 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;
case 0xb0:
dev->pb_pci_conf[addr] = val & 0xe0;
break;
case 0xb1:
dev->pb_pci_conf[addr] = val & /*0x1a*/ 0x1f;
break;
case 0xb8:
case 0xb9:
dev->pb_pci_conf[addr] = val;
i450kx_smram_recalc(dev, 1);
break;
case 0xbb:
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 & 0x0f);
break;
case 0xc5:
dev->pb_pci_conf[addr] &= ~(val & 0x0a);
break;
case 0xc6:
dev->pb_pci_conf[addr] &= ~(val & 0x1f);
break;
case 0xc8:
dev->pb_pci_conf[addr] = val & 0x1f;
break;
case 0xca:
case 0xcb:
dev->pb_pci_conf[addr] = val;
break;
default:
break;
}
}
}
static uint8_t
pb_read(int func, int addr, void *priv)
{
const i450kx_t *dev = (i450kx_t *) priv;
uint8_t ret = 0xff;
if (func == 0) {
ret = dev->pb_pci_conf[addr];
i450kx_log("[%04X:%08X] i450KX-PB: [R] dev->pb_pci_conf[%02X] = %02X\n", CS, cpu_state.pc,
addr, ret);
}
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)
{
spd_write_drbs_interleaved(dev->mc_pci_conf, 0x60, 0x6f, 4);
for (uint8_t i = 0x60; i <= 0x6f; i++) {
if (i & 0x01)
dev->mc_pci_conf[i] = 0x00;
else
dev->mc_pci_conf[i] &= 0x7f;
}
}
static void
mc_write(int func, int addr, uint8_t val, void *priv)
{
i450kx_t *dev = (i450kx_t *) priv;
if (func == 0) {
i450kx_log("[%04X:%08X] i450KX-MC: [W] dev->mc_pci_conf[%02X] = %02X\n", CS, cpu_state.pc,
addr, val);
switch (addr) {
case 0x4c:
dev->mc_pci_conf[addr] = val & 0xdf;
break;
case 0x4d:
dev->mc_pci_conf[addr] = val & 0xff;
break;
case 0x57:
dev->mc_pci_conf[addr] = val & 0x08;
i450kx_smram_recalc(dev, 0);
break;
case 0x58:
dev->mc_pci_conf[addr] = val & 0x02;
i450kx_vid_buf_recalc(dev, 0);
break;
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 ... 0x6f:
dev->mc_pci_conf[addr] = ((addr & 0x0f) & 0x01) ? 0x00 : (val & 0x7f);
mc_fill_drbs(dev);
break;
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;
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:
dev->mc_pci_conf[addr] = val;
break;
case 0x8b:
dev->mc_pci_conf[addr] = val & 0x80;
break;
case 0x8c:
case 0x8d:
dev->mc_pci_conf[addr] = val;
break;
case 0xa4:
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;
case 0xa8:
dev->mc_pci_conf[addr] = val & 0xfe;
break;
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:
dev->mc_pci_conf[addr] = val;
i450kx_smram_recalc(dev, 0);
break;
case 0xbb:
dev->mc_pci_conf[addr] = val & 0xf0;
i450kx_smram_recalc(dev, 0);
break;
case 0xbc:
dev->mc_pci_conf[addr] = val & 0x01;
break;
case 0xc0:
dev->mc_pci_conf[addr] = val & 0x07;
break;
case 0xc2:
dev->mc_pci_conf[addr] &= ~(val & 0x03);
break;
case 0xc4:
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);
break;
case 0xc8:
dev->mc_pci_conf[addr] = val & 0x1f;
break;
case 0xca:
case 0xcb:
dev->mc_pci_conf[addr] = val;
break;
default:
break;
}
}
}
static uint8_t
mc_read(int func, int addr, void *priv)
{
const i450kx_t *dev = (i450kx_t *) priv;
uint8_t ret = 0xff;
if (func == 0) {
ret = dev->mc_pci_conf[addr];
i450kx_log("[%04X:%08X] i450KX-MC: [R] dev->mc_pci_conf[%02X] = %02X\n", CS, cpu_state.pc,
addr, ret);
}
return ret;
}
static void
i450kx_reset(void *priv)
{
i450kx_t *dev = (i450kx_t *) priv;
uint32_t i;
/* 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[0x04] = 0x07;
dev->pb_pci_conf[0x05] = 0x00;
dev->pb_pci_conf[0x06] = 0x40;
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[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[0xa7] = 0x00;
/* Note: Do NOT reset these two registers on programmed (TRC) hard reset! */
#if 0
dev->pb_pci_conf[0xb0] = 0x00;
dev->pb_pci_conf[0xb1] = 0x00;
#endif
dev->pb_pci_conf[0xb4] = 0xff;
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;
#if 0
pci_remap_bus(dev->bus_index, 0x00);
#endif
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[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[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[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;
}
static void
i450kx_close(void *priv)
{
i450kx_t *dev = (i450kx_t *) priv;
smram_del(dev->smram[1]);
smram_del(dev->smram[0]);
free(dev);
}
static void *
i450kx_init(UNUSED(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, &dev->pb_slot); /* Device 19h: Intel 450KX PCI Bridge PB */
pci_add_card(PCI_ADD_NORTHBRIDGE_SEC, mc_read, mc_write, dev, &dev->mc_slot); /* Device 14h: Intel 450KX Memory Controller MC */
dev->smram[0] = smram_add();
dev->smram[1] = smram_add();
cpu_cache_int_enabled = 1;
cpu_cache_ext_enabled = 1;
cpu_update_waitstates();
i450kx_reset(dev);
return dev;
}
const device_t i450kx_device = {
.name = "Intel 450KX (Mars)",
.internal_name = "i450kx",
.flags = DEVICE_PCI,
.local = 0,
.init = i450kx_init,
.close = i450kx_close,
.reset = i450kx_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};