Merge pull request #1354 from tiseno100/master

Implemented the OPTi 822 VLB to PCI bridge
This commit is contained in:
Miran Grča
2021-04-06 07:24:36 +02:00
committed by GitHub
8 changed files with 418 additions and 39 deletions

View File

@@ -15,7 +15,7 @@
add_library(chipset OBJECT acc2168.c cs8230.c ali1217.c ali1429.c ali1489.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 opti895.c opti5x7.c scamp.c scat.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
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

View File

@@ -32,32 +32,6 @@
#include <86box/port_92.h>
#include <86box/chipset.h>
/* Shadow RAM */
/* Register 4h: C0000-CFFFF range | Register 5h: D0000-DFFFF range */
#define CURRENT_REGISTER dev->regs[4 + !!(i & 4)]
/*
Bits 7-6: xC000-xFFFF
Bits 5-4: x8000-xBFFF
Bits 3-2: x4000-x7FFF
Bits 0-1: x0000-x3FFF
x-y
0 0 Read/Write AT bus
1 0 Read from AT - Write to DRAM
1 1 Read from DRAM - Write to DRAM
0 1 Read from DRAM (write protected)
*/
#define CAN_READ (1 << (i - (4 * !!(i & 4))) * 2)
#define CAN_WRITE (1 << ((i - (4 * !!(i & 4))) * 2 + 1))
/* Shadow Recalc for the C/D segments */
#define SHADOW_RECALC (((CURRENT_REGISTER & CAN_READ) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((CURRENT_REGISTER & CAN_WRITE) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY))
/* Shadow Recalc for the E/F segments */
#define SHADOW_EF_RECALC (((dev->regs[6] & CAN_READ) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[6] & CAN_WRITE) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY))
typedef struct
{
uint8_t idx, regs[16];
@@ -83,17 +57,36 @@ opti5x7_log(const char *fmt, ...)
#endif
static void
shadow_map(opti5x7_t *dev)
opti5x7_shadow_map(int cur_reg, opti5x7_t *dev)
{
for (int i = 0; i < 8; i++)
/*
Register 4h: Cxxxx Segment
Register 5h: Dxxxx Segment
Bits 7-6: xC000-xFFFF
Bits 5-4: x8000-xBFFF
Bits 3-2: x4000-x7FFF
Bits 0-1: x0000-x3FFF
x-y
0 0 Read/Write AT bus
1 0 Read from AT - Write to DRAM
1 1 Read from DRAM - Write to DRAM
0 1 Read from DRAM (write protected)
*/
if (cur_reg == 0x06)
{
mem_set_mem_state_both(0xc0000 + (i << 14), 0x4000, SHADOW_RECALC);
if (i < 2)
mem_set_mem_state_both(0xe0000 + (i << 16), 0x10000, SHADOW_EF_RECALC);
mem_set_mem_state_both(0xe0000, 0x10000, ((dev->regs[6] & 1) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[6] & 2) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY));
mem_set_mem_state_both(0xf0000, 0x10000, ((dev->regs[6] & 4) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[6] & 8) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY));
}
shadowbios = !!(dev->regs[0x06] & 5);
shadowbios_write = !!(dev->regs[0x06] & 0x0a);
flushmmucache();
else
{
for (int i = 0; i < 4; i++)
mem_set_mem_state_both(0xc0000 + ((cur_reg & 1) << 16) + (i << 14), 0x4000, ((dev->regs[cur_reg] & (1 << (2 * i))) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[cur_reg] & (2 << (2 * i))) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY));
}
flushmmucache_nopc();
}
static void
@@ -107,7 +100,6 @@ opti5x7_write(uint16_t addr, uint8_t val, void *priv)
dev->idx = val;
break;
case 0x24:
opti5x7_log("OPTi 5x7: dev->regs[%02x] = %02x\n", dev->idx, val);
switch (dev->idx)
{
case 0x00: /* DRAM Configuration Register #1 */
@@ -116,7 +108,7 @@ opti5x7_write(uint16_t addr, uint8_t val, void *priv)
case 0x01: /* DRAM Control Register #1 */
dev->regs[dev->idx] = val;
break;
case 0x02: /* Cache Control Register #1 */
case 0x02: /* Cache Control Register #1 */
dev->regs[dev->idx] = val;
cpu_cache_ext_enabled = !!(dev->regs[0x02] & 0x0c);
cpu_update_waitstates();
@@ -128,7 +120,7 @@ opti5x7_write(uint16_t addr, uint8_t val, void *priv)
case 0x05: /* Shadow RAM Control Register #2 */
case 0x06: /* Shadow RAM Control Register #3 */
dev->regs[dev->idx] = val;
shadow_map(dev);
opti5x7_shadow_map(dev->idx, dev);
break;
case 0x07: /* Tag Test Register */
case 0x08: /* CPU Cache Control Register #1 */
@@ -148,6 +140,7 @@ opti5x7_write(uint16_t addr, uint8_t val, void *priv)
dev->regs[dev->idx] = val;
break;
}
opti5x7_log("OPTi 5x7: dev->regs[%02x] = %02x\n", dev->idx, dev->regs[dev->idx]);
break;
}
}

322
src/chipset/opti822.c Normal file
View File

@@ -0,0 +1,322 @@
/*
* 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 82C822 VESA Local Bus to PCI Bridge Interface.
*
*
* 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/pci.h>
#include <86box/chipset.h>
/* Shadow RAM */
#define SYSTEM_READ ((dev->pci_conf[0x44] & 2) ? MEM_READ_INTERNAL : MEM_READ_EXTANY)
#define SYSTEM_WRITE ((dev->pci_conf[0x44] & 1) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)
#define SHADOW_READ ((dev->pci_conf[cur_reg] & (1 << (4 + i))) ? MEM_READ_INTERNAL : MEM_READ_EXTANY)
#define SHADOW_WRITE ((dev->pci_conf[cur_reg] & (1 << i)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)
#ifdef ENABLE_OPTI822_LOG
int opti822_do_log = ENABLE_OPTI822_LOG;
static void
opti822_log(const char *fmt, ...)
{
va_list ap;
if (opti822_do_log)
{
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define opti822_log(fmt, ...)
#endif
typedef struct opti822_t
{
uint8_t pci_conf[256];
} opti822_t;
int opti822_irq_routing[7] = {5, 9, 0x0a, 0x0b, 0x0c, 0x0e, 0x0f};
void opti822_shadow(int cur_reg, opti822_t *dev)
{
if (cur_reg == 0x44)
mem_set_mem_state_both(0xf0000, 0x10000, SYSTEM_READ | SYSTEM_WRITE);
else
for (int i = 0; i < 4; i++)
mem_set_mem_state_both(0xe0000 - (((cur_reg & 3) - 1) << 16) + (i << 14), 0x4000, SHADOW_READ | SHADOW_WRITE);
flushmmucache_nopc();
}
static void
opti822_write(int func, int addr, uint8_t val, void *priv)
{
opti822_t *dev = (opti822_t *)priv;
switch (func)
{
case 0x04: /* Command Register */
dev->pci_conf[addr] = val & 0x40;
break;
case 0x05: /* Command Register */
dev->pci_conf[addr] = val & 1;
break;
case 0x06: /* Status Register */
dev->pci_conf[addr] |= val & 0xc0;
break;
case 0x07: /* Status Register */
dev->pci_conf[addr] = val & 0xa9;
break;
case 0x40:
dev->pci_conf[addr] = val & 0xc0;
break;
case 0x41:
dev->pci_conf[addr] = val & 0xcf;
break;
case 0x42:
dev->pci_conf[addr] = val & 0xf8;
break;
case 0x43:
dev->pci_conf[addr] = val;
break;
case 0x44: /* Shadow RAM */
case 0x45:
case 0x46:
case 0x47:
dev->pci_conf[addr] = (addr == 0x44) ? (val & 0xcb) : val;
opti822_shadow(addr, dev);
break;
case 0x48:
case 0x49:
case 0x4a:
case 0x4b:
case 0x4c:
case 0x4d:
case 0x4e:
case 0x4f:
case 0x50:
case 0x51:
case 0x52:
case 0x53:
case 0x54:
case 0x55:
case 0x56:
case 0x57:
dev->pci_conf[addr] = val;
break;
case 0x58:
dev->pci_conf[addr] = val & 0xfc;
break;
case 0x59:
case 0x5a:
case 0x5b:
case 0x5c:
case 0x5d:
case 0x5e:
case 0x5f:
dev->pci_conf[addr] = val;
break;
case 0x60:
dev->pci_conf[addr] = val & 0xfc;
break;
case 0x61:
case 0x62:
case 0x63:
case 0x64:
case 0x65:
case 0x66:
case 0x67:
dev->pci_conf[addr] = val;
break;
case 0x68:
dev->pci_conf[addr] = val & 0xfc;
break;
case 0x69:
case 0x6a:
case 0x6b:
case 0x6c:
case 0x6d:
case 0x6e:
case 0x6f:
dev->pci_conf[addr] = val;
break;
case 0x70:
dev->pci_conf[addr] = val & 0xfc;
break;
case 0x71:
case 0x72:
case 0x73:
dev->pci_conf[addr] = val;
break;
case 0x74:
dev->pci_conf[addr] = val & 0xfc;
break;
case 0x75:
case 0x76:
dev->pci_conf[addr] = val;
break;
case 0x77:
dev->pci_conf[addr] = val & 0xe7;
break;
case 0x78:
dev->pci_conf[addr] = val;
break;
case 0x79:
dev->pci_conf[addr] = val & 0xfc;
break;
case 0x7a:
case 0x7b:
case 0x7c:
case 0x7d:
case 0x7e:
dev->pci_conf[addr] = val;
break;
case 0x7f:
dev->pci_conf[addr] = val & 3;
break;
case 0x80:
case 0x81:
case 0x82:
case 0x84:
case 0x85:
case 0x86:
dev->pci_conf[addr] = val;
break;
case 0x88: /* PCI IRQ Routing */
case 0x89: /* Very hacky implementation. Needs surely a rewrite after */
case 0x8a: /* a PCI rework happens. */
case 0x8b:
case 0x8c:
case 0x8d:
case 0x8e:
case 0x8f:
dev->pci_conf[addr] = val;
if (addr % 2)
{
pci_set_irq_routing(PCI_INTB, ((val & 0x0f) != 0) ? opti822_irq_routing[(val & 7) - 1] : PCI_IRQ_DISABLED);
pci_set_irq_routing(PCI_INTA, (((val >> 4) & 0x0f) != 0) ? opti822_irq_routing[((val >> 4) & 7) - 1] : PCI_IRQ_DISABLED);
}
else
{
pci_set_irq_routing(PCI_INTD, ((val & 0x0f) != 0) ? opti822_irq_routing[(val & 7) - 1] : PCI_IRQ_DISABLED);
pci_set_irq_routing(PCI_INTC, (((val >> 4) & 0x0f) != 0) ? opti822_irq_routing[((val >> 4) & 7) - 1] : PCI_IRQ_DISABLED);
}
break;
}
opti822_log("OPTI822: dev->pci_conf[%02x] = %02x\n", addr, dev->pci_conf[addr]);
}
static uint8_t
opti822_read(int func, int addr, void *priv)
{
opti822_t *dev = (opti822_t *)priv;
return dev->pci_conf[addr];
}
static void
opti822_reset(void *priv)
{
opti822_t *dev = (opti822_t *)priv;
dev->pci_conf[0x00] = 0x45;
dev->pci_conf[0x01] = 0x10;
dev->pci_conf[0x02] = 0x22;
dev->pci_conf[0x03] = 0xc8;
dev->pci_conf[0x04] = 7;
dev->pci_conf[0x06] = 0x40;
dev->pci_conf[0x07] = 1;
dev->pci_conf[0x08] = 1;
dev->pci_conf[0x0b] = 6;
dev->pci_conf[0x0d] = 0x20;
dev->pci_conf[0x40] = 1;
dev->pci_conf[0x43] = 0x20;
dev->pci_conf[0x52] = 6;
dev->pci_conf[0x53] = 0x90;
}
static void
opti822_close(void *priv)
{
opti822_t *dev = (opti822_t *)priv;
free(dev);
}
static void *
opti822_init(const device_t *info)
{
opti822_t *dev = (opti822_t *)malloc(sizeof(opti822_t));
memset(dev, 0, sizeof(opti822_t));
pci_add_card(PCI_ADD_NORTHBRIDGE, opti822_read, opti822_write, dev);
opti822_reset(dev);
return dev;
}
const device_t opti822_device = {
"OPTi 82C822 PCIB",
DEVICE_PCI,
0,
opti822_init,
opti822_close,
opti822_reset,
{NULL},
NULL,
NULL,
NULL};

View File

@@ -95,7 +95,9 @@ extern const device_t opti291_device;
extern const device_t opti493_device;
extern const device_t opti495_device;
extern const device_t opti802g_device;
extern const device_t opti822_device;
extern const device_t opti895_device;
extern const device_t opti5x7_device;
/* SiS */

View File

@@ -381,6 +381,9 @@ extern const device_t *at_cpqiii_get_device(void);
/* m_at_socket4_5.c */
extern int machine_at_excalibur_init(const machine_t *);
extern int machine_at_hot543_init(const machine_t *);
extern int machine_at_p54vl_init(const machine_t *);
extern int machine_at_batman_init(const machine_t *);
extern int machine_at_ambradp60_init(const machine_t *);
extern int machine_at_dellxp60_init(const machine_t *);

View File

@@ -63,6 +63,61 @@ machine_at_excalibur_init(const machine_t *model)
return ret;
}
int
machine_at_hot543_init(const machine_t *model)
{
int ret;
ret = bios_load_linear("roms/machines/hot543/543_R21.BIN",
0x000e0000, 131072, 0);
if (bios_only || !ret)
return ret;
machine_at_common_init(model);
pci_init(PCI_CONFIG_TYPE_1);
pci_register_slot(0x10, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4);
pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1);
pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2);
device_add(&opti5x7_device);
device_add(&opti822_device);
device_add(&sst_flash_29ee010_device);
device_add(&keyboard_at_device);
if (fdc_type == FDC_INTERNAL)
device_add(&fdc_at_device);
return ret;
}
int
machine_at_p54vl_init(const machine_t *model)
{
int ret;
ret = bios_load_linear("roms/machines/p54vl/SM507.ROM",
0x000e0000, 131072, 0);
if (bios_only || !ret)
return ret;
machine_at_common_init(model);
pci_init(PCI_CONFIG_TYPE_1);
pci_register_slot(0x10, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x11, PCI_CARD_NORMAL, 1, 2, 3, 4);
pci_register_slot(0x12, PCI_CARD_NORMAL, 2, 3, 4, 1);
pci_register_slot(0x13, PCI_CARD_NORMAL, 3, 4, 1, 2);
device_add(&opti5x7_device);
device_add(&opti822_device);
device_add(&sst_flash_29ee010_device);
device_add(&keyboard_at_ami_device);
if (fdc_type == FDC_INTERNAL)
device_add(&fdc_at_device);
return ret;
}
static void
machine_at_premiere_common_init(const machine_t *model, int pci_switch)

View File

@@ -284,6 +284,10 @@ const machine_t machines[] = {
{ "[i430FX] NEC PowerMate V", "powermate_v", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 2.0, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_powermate_v_init, NULL },
{ "[i430FX] PC Partner MB500N", "mb500n", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 50000000, 66666667, 3380, 3520, 1.5, 3.0, MACHINE_PCI | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_mb500n_init, NULL },
/* OPTi 596/597/822 */
{ "[OPTi 597] Shuttle HOT-543", "hot543", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 60000000, 66666667, 3520, 3520, 1.5, 1.5, MACHINE_PCI | MACHINE_VLB, 8192, 131072, 8192, 127, machine_at_hot543_init, NULL },
{ "[OPTi 597] Supermicro P54VL-PCI", "p54vl", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, 0, 60000000, 66666667, 3520, 3520, 1.5, 1.5, MACHINE_PCI | MACHINE_VLB, 8192, 131072, 8192, 127, machine_at_p54vl_init, NULL },
/* SiS 85C50x */
{ "[SiS 85C50x] ASUS PCI/I-P54SP4", "p54sp4", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, CPU_BLOCK(CPU_K5, CPU_5K86), 40000000, 66666667, 3380, 3520, 1.5, 1.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_p54sp4_init, NULL },
{ "[SiS 85C50x] BCM SQ-588", "sq588", MACHINE_TYPE_SOCKET5, CPU_PKG_SOCKET5_7, CPU_BLOCK(CPU_PENTIUMMMX), 50000000, 66666667, 3520, 3520, 1.5, 1.5, MACHINE_PCI | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL, 8192, 131072, 8192, 127, machine_at_sq588_init, NULL },

View File

@@ -623,7 +623,7 @@ CPUOBJ := cpu.o cpu_table.o \
CHIPSETOBJ := acc2168.o cs8230.o ali1217.o ali1429.o ali1489.o headland.o intel_82335.o cs4031.o \
intel_420ex.o intel_4x0.o intel_sio.o intel_piix.o ioapic.o \
neat.o opti495.o opti895.o opti5x7.o scamp.o scat.o via_vt82c49x.o via_vt82c505.o \
neat.o opti495.o opti822.o opti895.o opti5x7.o scamp.o scat.o via_vt82c49x.o via_vt82c505.o \
gc100.o olivetti_eva.o \
sis_85c310.o sis_85c4xx.o sis_85c496.o sis_85c50x.o stpc.o opti283.o opti291.o \
umc_8886.o umc_8890.o umc_hb4.o \