This commit is contained in:
RichardG867
2020-06-26 18:05:57 -03:00
51 changed files with 1867 additions and 299 deletions

230
src/chipset/amd640.c Normal file
View File

@@ -0,0 +1,230 @@
/*
*
* 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.>
*
* Basic AMD 640 North Bridge emulation
*
* Looks similar to the VIA VP2
* while it's southbridge(AMD-645) is just a 586B [TODO: Probs write it if it has differences]
*
* Copyright(C) 2020 Tiseno100
*
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include <86box/mem.h>
#include <86box/io.h>
#include <86box/rom.h>
#include <86box/pci.h>
#include <86box/device.h>
#include <86box/keyboard.h>
#include <86box/chipset.h>
typedef struct amd640_t {
uint8_t regs[256];
} amd640_t;
static void
amd640_map(uint32_t addr, uint32_t size, int state)
{
switch (state & 3) {
case 0:
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
break;
case 1:
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
break;
case 2:
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY);
break;
case 3:
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
break;
}
flushmmucache_nopc();
}
static void
amd640_write(int func, int addr, uint8_t val, void *priv)
{
amd640_t *dev = (amd640_t *) priv;
/* Read-Only Registers */
switch(addr){
case 0x00: case 0x01: case 0x08: case 0x09:
case 0x0a: case 0x0b: case 0x0c: case 0x0e:
case 0x0f:
return;
}
switch(addr){
/* Command */
case 0x04:
dev->regs[0x04] = (dev->regs[0x04] & ~0x40) | (val & 0x40);
/* Status */
case 0x07:
dev->regs[0x07] &= ~(val & 0xb0);
break;
/* Shadow RAM registers */
case 0x61:
if ((dev->regs[0x61] ^ val) & 0x03)
amd640_map(0xc0000, 0x04000, val & 0x03);
if ((dev->regs[0x61] ^ val) & 0x0c)
amd640_map(0xc4000, 0x04000, (val & 0x0c) >> 2);
if ((dev->regs[0x61] ^ val) & 0x30)
amd640_map(0xc8000, 0x04000, (val & 0x30) >> 4);
if ((dev->regs[0x61] ^ val) & 0xc0)
amd640_map(0xcc000, 0x04000, (val & 0xc0) >> 6);
dev->regs[0x61] = val;
return;
case 0x62:
if ((dev->regs[0x62] ^ val) & 0x03)
amd640_map(0xd0000, 0x04000, val & 0x03);
if ((dev->regs[0x62] ^ val) & 0x0c)
amd640_map(0xd4000, 0x04000, (val & 0x0c) >> 2);
if ((dev->regs[0x62] ^ val) & 0x30)
amd640_map(0xd8000, 0x04000, (val & 0x30) >> 4);
if ((dev->regs[0x62] ^ val) & 0xc0)
amd640_map(0xdc000, 0x04000, (val & 0xc0) >> 6);
dev->regs[0x62] = val;
return;
case 0x63:
if ((dev->regs[0x63] ^ val) & 0x30) {
amd640_map(0xf0000, 0x10000, (val & 0x30) >> 4);
shadowbios = (((val & 0x30) >> 4) & 0x02);
}
if ((dev->regs[0x63] ^ val) & 0xc0)
amd640_map(0xe0000, 0x10000, (val & 0xc0) >> 6);
dev->regs[0x63] = val;
return;
case 0x65: /* DRAM Control Register #1 */
dev->regs[0x65] = (dev->regs[0x65] & ~0x20) | (val & 0x20);
case 0x66: /* DRAM Control Register #2 */
dev->regs[0x66] = (dev->regs[0x66] & ~0x05) | (val & 0x05);
case 0x67: /* 32-Bit DRAM Width Control Register */
dev->regs[0x67] = (dev->regs[0x67] & ~0xc0) | (val & 0xc0);
case 0x68: /* Reserved (But referenced by the BIOS?) */
dev->regs[0x68] = (dev->regs[0x68] & ~0x40) | (val & 0x40);
case 0x6d: /* DRAM Drive Strength Control Register */
dev->regs[0x6d] = (dev->regs[0x6d] & ~0x6f) | (val & 0x6f);
case 0x70: /* PCI Buffer Control Register */
dev->regs[0x70] = (dev->regs[0x70] & ~0x01) | (val & 0x01);
case 0x71: /* Processor-to-PCI Control Register #1 */
dev->regs[0x71] = (dev->regs[0x71] & ~0x4e) | (val & 0x4e);
case 0x73: /* PCI Initiator Control Register #1 */
dev->regs[0x73] = (dev->regs[0x73] & ~0x0c) | (val & 0x0c);
case 0x75: /* PCI Arbitration Control Register #1 */
dev->regs[0x75] = (dev->regs[0x75] & ~0xc7) | (val & 0xc7);
default:
dev->regs[addr] = val;
break;
}
}
static uint8_t
amd640_read(int func, int addr, void *priv)
{
amd640_t *dev = (amd640_t *) priv;
uint8_t ret = 0xff;
if(func == 0){
ret = dev->regs[addr];
}
return ret;
}
static void
amd640_reset(void *priv)
{
amd640_write(0, 0x63, amd640_read(0, 0x63, priv) & 0xcf, priv);
}
static void *
amd640_init(const device_t *info)
{
amd640_t *dev = (amd640_t *) malloc(sizeof(amd640_t));
pci_add_card(PCI_ADD_NORTHBRIDGE, amd640_read, amd640_write, dev);
dev->regs[0x00] = 0x06; /* AMD */
dev->regs[0x01] = 0x11;
dev->regs[0x02] = 0x95; /* 640 */
dev->regs[0x03] = 0x15;
dev->regs[0x04] = 7; /* Command */
dev->regs[0x06] = 0xa0; /* Status */
dev->regs[0x07] = 2;
dev->regs[0x08] = 0x02; /* Revision ID: 0x02 = D, 0x03 = E, 0x04 = F */
dev->regs[0x0b] = 6; /* Base Class Code */
dev->regs[0x52] = 2; /* Non-Cacheable control */
dev->regs[0x58] = 0x40; /* DRAM Configuration register 1 */
dev->regs[0x59] = 5; /* DRAM Configuration register 2 */
/* DRAM Bank Endings */
dev->regs[0x5a] = 1;
dev->regs[0x5b] = 1;
dev->regs[0x5c] = 1;
dev->regs[0x5d] = 1;
dev->regs[0x5e] = 1;
dev->regs[0x5f] = 1;
dev->regs[0x64] = 0xab;
return dev;
}
static void
amd640_close(void *priv)
{
amd640_t *dev = (amd640_t *) priv;
free(dev);
}
const device_t amd640_device = {
"AMD-640 System Controller",
DEVICE_PCI,
0,
amd640_init,
amd640_close,
amd640_reset,
NULL,
NULL,
NULL,
NULL
};

View File

@@ -1,11 +1,42 @@
/* Intel 82335 SX emulation, used by the Phoenix 386 clone. */
/*
* 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 82335(KU82335) chipset.
*
*
*
* Authors: Sarah Walker, <tommowalker@tommowalker.co.uk>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2020 Sarah Walker.
* Copyright 2016-2020 Miran Grca.
* Copyright 2020 Tiseno100
*
*/
#include <stdio.h>
#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/keyboard.h>
#include <86box/mem.h>
#include <86box/fdd.h>
#include <86box/fdc.h>
#include <86box/chipset.h>
typedef struct
{
@@ -13,26 +44,23 @@ typedef struct
uint8_t reg_23;
} i82335_t;
i82335_t i82335;
static uint8_t i82335_read(uint16_t addr, void *priv);
uint8_t i82335_read(uint16_t addr, void *priv);
void i82335_write(uint16_t addr, uint8_t val, void *priv)
static void
i82335_write(uint16_t addr, uint8_t val, void *priv)
{
int i = 0;
i82335_t *dev = (i82335_t *) priv;
int mem_write = 0;
// pclog("i82335_write(%04X, %02X)\n", addr, val);
switch (addr)
{
case 0x22:
if ((val ^ i82335.reg_22) & 1)
if ((val ^ dev->reg_22) & 1)
{
if (val & 1)
{
for (i = 0; i < 8; i++)
for (int i = 0; i < 8; i++)
{
mem_set_mem_state(0xe0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
shadowbios = 1;
@@ -40,7 +68,7 @@ void i82335_write(uint16_t addr, uint8_t val, void *priv)
}
else
{
for (i = 0; i < 8; i++)
for (int i = 0; i < 8; i++)
{
mem_set_mem_state(0xe0000, 0x20000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
shadowbios = 0;
@@ -50,16 +78,17 @@ void i82335_write(uint16_t addr, uint8_t val, void *priv)
flushmmucache();
}
i82335.reg_22 = val | 0xd8;
dev->reg_22 = val | 0xd8;
break;
case 0x23:
i82335.reg_23 = val;
if ((val ^ i82335.reg_22) & 2)
case 0x23:
dev->reg_23 = val;
if ((val ^ dev->reg_22) & 2)
{
if (val & 2)
{
for (i = 0; i < 8; i++)
for (int i = 0; i < 8; i++)
{
mem_set_mem_state(0xc0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
shadowbios = 1;
@@ -67,7 +96,7 @@ void i82335_write(uint16_t addr, uint8_t val, void *priv)
}
else
{
for (i = 0; i < 8; i++)
for (int i = 0; i < 8; i++)
{
mem_set_mem_state(0xc0000, 0x20000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
shadowbios = 0;
@@ -75,11 +104,11 @@ void i82335_write(uint16_t addr, uint8_t val, void *priv)
}
}
if ((val ^ i82335.reg_22) & 0xc)
if ((val ^ dev->reg_22) & 0xc)
{
if (val & 2)
{
for (i = 0; i < 8; i++)
for (int i = 0; i < 8; i++)
{
mem_write = (val & 8) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
mem_set_mem_state(0xa0000, 0x20000, MEM_READ_INTERNAL | mem_write);
@@ -88,7 +117,7 @@ void i82335_write(uint16_t addr, uint8_t val, void *priv)
}
else
{
for (i = 0; i < 8; i++)
for (int i = 0; i < 8; i++)
{
mem_write = (val & 8) ? MEM_WRITE_DISABLED : MEM_WRITE_EXTANY;
mem_set_mem_state(0xa0000, 0x20000, MEM_READ_EXTANY | mem_write);
@@ -97,7 +126,7 @@ void i82335_write(uint16_t addr, uint8_t val, void *priv)
}
}
if ((val ^ i82335.reg_22) & 0xe)
if ((val ^ dev->reg_22) & 0xe)
{
flushmmucache();
}
@@ -105,33 +134,64 @@ void i82335_write(uint16_t addr, uint8_t val, void *priv)
if (val & 0x80)
{
io_removehandler(0x0022, 0x0001, i82335_read, NULL, NULL, i82335_write, NULL, NULL, NULL);
io_removehandler(0x0023, 0x0001, i82335_read, NULL, NULL, i82335_write, NULL, NULL, NULL);
}
break;
}
}
uint8_t i82335_read(uint16_t addr, void *priv)
static uint8_t
i82335_read(uint16_t addr, void *priv)
{
// pclog("i82335_read(%04X)\n", addr);
if (addr == 0x22)
{
return i82335.reg_22;
}
else if (addr == 0x23)
{
return i82335.reg_23;
}
else
{
return 0;
uint8_t ret = 0xff;
i82335_t *dev = (i82335_t *) priv;
switch(addr){
case 0x22:
return dev->reg_22;
break;
case 0x23:
return dev->reg_23;
break;
default:
return 0;
break;
}
return ret;
}
void i82335_init()
static void
i82335_close(void *priv)
{
memset(&i82335, 0, sizeof(i82335_t));
i82335_t *dev = (i82335_t *) priv;
i82335.reg_22 = 0xd8;
io_sethandler(0x0022, 0x0014, i82335_read, NULL, NULL, i82335_write, NULL, NULL, NULL);
free(dev);
}
static void *
i82335_init(const device_t *info)
{
i82335_t *dev = (i82335_t *) malloc(sizeof(i82335_t));
memset(dev, 0, sizeof(i82335_t));
dev->reg_22 = 0xd8;
io_sethandler(0x0022, 0x0001, i82335_read, NULL, NULL, i82335_write, NULL, NULL, dev);
io_sethandler(0x0023, 0x0001, i82335_read, NULL, NULL, i82335_write, NULL, NULL, dev);
return dev;
}
const device_t i82335_device = {
"Intel 82335",
0,
0,
i82335_init, i82335_close, NULL,
NULL, NULL, NULL,
NULL
};

View File

@@ -413,8 +413,9 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
switch (dev->type) {
case INTEL_440LX: case INTEL_440EX:
regs[0x34] = (val & 0xa0);
}
break;
}
break;
case 0x4f:
switch (dev->type) {
@@ -983,7 +984,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
regs[0x7c] = val & 0x8f;
break;
case INTEL_440BX: case INTEL_440GX:
case INTEL_440ZX:
case INTEL_440ZX:
regs[0x7c] = val & 0x1f;
break;
}
@@ -991,7 +992,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
switch (dev->type) {
case INTEL_420TX: case INTEL_420ZX:
case INTEL_430LX: case INTEL_430NX:
regs[0x7c] = val & 0x32;
regs[0x7d] = val & 0x32;
break;
}
case 0x7e: case 0x7f:
@@ -1286,9 +1287,9 @@ i4x0_read(int func, int addr, void *priv)
uint8_t ret = 0xff;
uint8_t *regs = (uint8_t *) dev->regs[func];
if (func > dev->max_func)
if (func > dev->max_func)
ret = 0xff;
else {
else {
ret = regs[addr];
/* Special behavior for 440FX register 0x93 which is basically TRC in PCI space
with the addition of bits 3 and 0. */
@@ -1657,11 +1658,11 @@ static void
regs = (uint8_t *) dev->regs[1];
regs[0x00] = 0x86; regs[0x01] = 0x80; /* Intel */
if(dev->type != INTEL_440GX){
regs[0x02] = 0x91; regs[0x03] = 0x71; /* 82443BX */
} else {
regs[0x02] = 0xa1; regs[0x03] = 0x71; /* 82443GX (They seem to share the same deal*/
}
if(dev->type != INTEL_440GX) {
regs[0x02] = 0x91; regs[0x03] = 0x71; /* 82443BX */
} else {
regs[0x02] = 0xa1; regs[0x03] = 0x71; /* 82443GX (They seem to share the same deal*/
}
regs[0x06] = 0x20; regs[0x07] = 0x02;
regs[0x08] = 0x02;
regs[0x0a] = 0x04; regs[0x0b] = 0x06;

View File

@@ -23,7 +23,7 @@ The earlier 596/597 appears to be register compatible with the 546/547 from test
typedef struct
{
uint8_t cur_reg,
regs[64];
regs[16];
port_92_t *port_92;
} opti5x7_t;
@@ -61,12 +61,10 @@ opti5x7_write(uint16_t addr, uint8_t val, void *priv)
break;
case 0x24:
dev->regs[dev->cur_reg] = val;
if (dev->cur_reg == 0x02) {
cpu_cache_ext_enabled = val & 0x10;
}
if (dev->cur_reg == 0x06) {
if (dev->regs[0x02] & 0x0c)
cpu_cache_ext_enabled = 1;
if (dev->cur_reg == 0x06)
opti5x7_recalcmapping(dev);
}
break;
}
}

185
src/chipset/vl82c480.c Normal file
View File

@@ -0,0 +1,185 @@
/*
* 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 VLSI VL82c480 chipset.
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
*
* Copyright 2020 Sarah Walker.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/timer.h>
#include <86box/device.h>
#include <86box/io.h>
#include <86box/mem.h>
#include <86box/nmi.h>
#include <86box/port_92.h>
#include <86box/chipset.h>
typedef struct {
int cfg_index;
uint8_t cfg_regs[256];
} vl82c480_t;
#define CFG_ID 0x00
#define CFG_AAXS 0x0d
#define CFG_BAXS 0x0e
#define CFG_CAXS 0x0f
#define CFG_DAXS 0x10
#define CFG_EAXS 0x11
#define CFG_FAXS 0x12
#define ID_VL82C480 0x90
static void
shadow_control(uint32_t addr, uint32_t size, int state)
{
/* pclog("shadow_control: addr=%08x size=%04x state=%i\n", addr, size, state); */
switch (state) {
case 0:
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
break;
case 1:
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
break;
case 2:
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY);
break;
case 3:
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
break;
}
flushmmucache_nopc();
}
static void
vl82c480_write(uint16_t addr, uint8_t val, void *p)
{
vl82c480_t *dev = (vl82c480_t *)p;
switch (addr) {
case 0xec:
dev->cfg_index = val;
break;
case 0xed:
if (dev->cfg_index >= 0x01 && dev->cfg_index <= 0x24) {
dev->cfg_regs[dev->cfg_index] = val;
switch (dev->cfg_index) {
case CFG_AAXS:
shadow_control(0xa0000, 0x4000, val & 3);
shadow_control(0xa4000, 0x4000, (val >> 2) & 3);
shadow_control(0xa8000, 0x4000, (val >> 4) & 3);
shadow_control(0xac000, 0x4000, (val >> 6) & 3);
break;
case CFG_BAXS:
shadow_control(0xb0000, 0x4000, val & 3);
shadow_control(0xb4000, 0x4000, (val >> 2) & 3);
shadow_control(0xb8000, 0x4000, (val >> 4) & 3);
shadow_control(0xbc000, 0x4000, (val >> 6) & 3);
break;
case CFG_CAXS:
shadow_control(0xc0000, 0x4000, val & 3);
shadow_control(0xc4000, 0x4000, (val >> 2) & 3);
shadow_control(0xc8000, 0x4000, (val >> 4) & 3);
shadow_control(0xcc000, 0x4000, (val >> 6) & 3);
break;
case CFG_DAXS:
shadow_control(0xd0000, 0x4000, val & 3);
shadow_control(0xd4000, 0x4000, (val >> 2) & 3);
shadow_control(0xd8000, 0x4000, (val >> 4) & 3);
shadow_control(0xdc000, 0x4000, (val >> 6) & 3);
break;
case CFG_EAXS:
shadow_control(0xe0000, 0x4000, val & 3);
shadow_control(0xe4000, 0x4000, (val >> 2) & 3);
shadow_control(0xe8000, 0x4000, (val >> 4) & 3);
shadow_control(0xec000, 0x4000, (val >> 6) & 3);
break;
case CFG_FAXS:
shadow_control(0xf0000, 0x4000, val & 3);
shadow_control(0xf4000, 0x4000, (val >> 2) & 3);
shadow_control(0xf8000, 0x4000, (val >> 4) & 3);
shadow_control(0xfc000, 0x4000, (val >> 6) & 3);
break;
}
}
break;
case 0xee:
if (mem_a20_alt)
outb(0x92, inb(0x92) & ~2);
break;
}
}
static uint8_t
vl82c480_read(uint16_t addr, void *p)
{
vl82c480_t *dev = (vl82c480_t *)p;
uint8_t ret = 0xff;
switch (addr) {
case 0xec:
ret = dev->cfg_index;
break;
case 0xed:
ret = dev->cfg_regs[dev->cfg_index];
break;
case 0xee:
if (!mem_a20_alt)
outb(0x92, inb(0x92) | 2);
break;
case 0xef:
softresetx86();
cpu_set_edx();
break;
}
return ret;
}
static void
vl82c480_close(void *p)
{
vl82c480_t *dev = (vl82c480_t *)p;
free(dev);
}
static void *
vl82c480_init(const device_t *info)
{
vl82c480_t *dev = (vl82c480_t *)malloc(sizeof(vl82c480_t));
memset(dev, 0, sizeof(vl82c480_t));
dev->cfg_regs[CFG_ID] = ID_VL82C480;
io_sethandler(0x00ec, 0x0004, vl82c480_read, NULL, NULL, vl82c480_write, NULL, NULL, dev);
return dev;
}
const device_t vl82c480_device = {
"VLSI VL82c480",
0,
0,
vl82c480_init, vl82c480_close, NULL,
NULL, NULL, NULL,
NULL
};