diff --git a/src/chipset/amd640.c b/src/chipset/amd640.c new file mode 100644 index 000000000..4cb8625f1 --- /dev/null +++ b/src/chipset/amd640.c @@ -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. +* +* +* +* 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 +#include +#include +#include +#include +#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 +}; \ No newline at end of file diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index a94564e68..e0d7b178c 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -89,6 +89,9 @@ extern const device_t via_apro_device; extern const device_t via_vt82c586b_device; extern const device_t via_vt82c596b_device; +/* AMD */ +extern const device_t amd640_device; + /* VLSI */ extern const device_t vlsi_scamp_device; diff --git a/src/win/Makefile.mingw b/src/win/Makefile.mingw index ca93dd521..08122e8aa 100644 --- a/src/win/Makefile.mingw +++ b/src/win/Makefile.mingw @@ -563,7 +563,8 @@ CHIPSETOBJ := acc2168.o acer_m3a.o cs8230.o ali1429.o headland.o \ intel_420ex.o intel_4x0.o intel_sio.o intel_piix.o ioapic.o \ neat.o opti495.o opti5x7.o scamp.o scat.o \ sis_85c310.o sis_85c471.o sis_85c496.o \ - via_apollo.o via_vpx.o via_vt82c586b.o via_vt82c596b.o wd76c10.o + via_apollo.o via_vpx.o via_vt82c586b.o via_vt82c596b.o wd76c10.o \ + amd640.o MCHOBJ := machine.o machine_table.o \ m_xt.o m_xt_compaq.o \