Merge pull request #577 from 86Box/feature/scamp

Added the SCAMP chipset, onboard AVGA2 and corresponding machine (Com…
This commit is contained in:
OBattler
2020-01-22 17:41:14 +01:00
committed by GitHub
11 changed files with 840 additions and 32 deletions

View File

@@ -64,6 +64,9 @@ extern const device_t sis_85c50x_device;
/* VIA */
extern const device_t via_mvp3_device;
/* VLSI */
extern const device_t vlsi_scamp_device;
/* WD */
extern const device_t wd76c10_device;

756
src/chipset/scamp.c Normal file
View File

@@ -0,0 +1,756 @@
/*
* 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.
*
* Emulation of VLSI 82C311 ("SCAMP") chipset.
*
* Note: The datasheet mentions that the chipset supports up to 8MB
* of DRAM. This is intepreted as 'being able to refresh up to
* 8MB of DRAM chips', because it works fine with bus-based
* memory expansion.
*
* Version: @(#)scamp.c 1.0.0 2020/01/21
*
* 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.h"
#include "../cpu/cpu.h"
#include "../timer.h"
#include "../device.h"
#include "../io.h"
#include "../mem.h"
#include "../nmi.h"
#include "../port_92.h"
#include "chipset.h"
typedef struct {
int cfg_index;
uint8_t cfg_regs[256];
int cfg_enable;
int ram_config;
mem_mapping_t ram_mapping[2];
uint32_t ram_virt_base[2], ram_phys_base[2];
uint32_t ram_mask[2];
int row_virt_shift[2], row_phys_shift[2];
int ram_interleaved[2];
int ibank_shift[2];
} scamp_t;
#define CFG_ID 0x00
#define CFG_SLTPTR 0x02
#define CFG_RAMMAP 0x03
#define CFG_EMSEN1 0x0b
#define CFG_EMSEN2 0x0c
#define CFG_ABAXS 0x0e
#define CFG_CAXS 0x0f
#define CFG_DAXS 0x10
#define CFG_FEAXS 0x11
#define ID_VL82C311 0xd6
#define RAMMAP_REMP386 (1 << 4)
/*Commodore SL386SX requires proper memory slot decoding to detect memory size.
Therefore we emulate the SCAMP memory address decoding, and therefore are
limited to the DRAM combinations supported by the actual chip*/
enum
{
BANK_NONE,
BANK_256K,
BANK_256K_INTERLEAVED,
BANK_1M,
BANK_1M_INTERLEAVED,
BANK_4M,
BANK_4M_INTERLEAVED
};
static const struct
{
int size_kb;
int rammap;
int bank[2];
} ram_configs[] =
{
{512, 0x0, {BANK_256K, BANK_NONE}},
{1024, 0x1, {BANK_256K_INTERLEAVED, BANK_NONE}},
{1536, 0x2, {BANK_256K_INTERLEAVED, BANK_256K}},
{2048, 0x3, {BANK_256K_INTERLEAVED, BANK_256K_INTERLEAVED}},
{3072, 0xc, {BANK_256K_INTERLEAVED, BANK_1M}},
{4096, 0x5, {BANK_1M_INTERLEAVED, BANK_NONE}},
{5120, 0xd, {BANK_256K_INTERLEAVED, BANK_1M_INTERLEAVED}},
{6144, 0x6, {BANK_1M_INTERLEAVED, BANK_1M}},
{8192, 0x7, {BANK_1M_INTERLEAVED, BANK_1M_INTERLEAVED}},
{12288, 0xe, {BANK_1M_INTERLEAVED, BANK_4M}},
{16384, 0x9, {BANK_4M_INTERLEAVED, BANK_NONE}},
};
static const struct
{
int bank[2];
int remapped;
} rammap[16] =
{
{{BANK_256K, BANK_NONE}, 0},
{{BANK_256K_INTERLEAVED, BANK_NONE}, 0},
{{BANK_256K_INTERLEAVED, BANK_256K}, 0},
{{BANK_256K_INTERLEAVED, BANK_256K_INTERLEAVED}, 0},
{{BANK_1M, BANK_NONE}, 0},
{{BANK_1M_INTERLEAVED, BANK_NONE}, 0},
{{BANK_1M_INTERLEAVED, BANK_1M}, 0},
{{BANK_1M_INTERLEAVED, BANK_1M_INTERLEAVED}, 0},
{{BANK_4M, BANK_NONE}, 0},
{{BANK_4M_INTERLEAVED, BANK_NONE}, 0},
{{BANK_NONE, BANK_4M}, 1}, /*Bank 2 remapped to 0*/
{{BANK_NONE, BANK_4M_INTERLEAVED}, 1}, /*Banks 2/3 remapped to 0/1*/
{{BANK_256K_INTERLEAVED, BANK_1M}, 0},
{{BANK_256K_INTERLEAVED, BANK_1M_INTERLEAVED}, 0},
{{BANK_1M_INTERLEAVED, BANK_4M}, 0},
{{BANK_1M_INTERLEAVED, BANK_4M_INTERLEAVED}, 0}, /*Undocumented - probably wrong!*/
};
/*The column bits masked when using 256kbit DRAMs in 4Mbit mode aren't contiguous,
so we use separate routines for that special case*/
static uint8_t
ram_mirrored_256k_in_4mi_read(uint32_t addr, void *priv)
{
scamp_t *dev = (scamp_t *) priv;
int bank = (int)priv;
int row, column, byte;
addr -= dev->ram_virt_base[bank];
byte = addr & 1;
if (!dev->ram_interleaved[bank]) {
if (addr & 0x400)
return 0xff;
addr = (addr & 0x3ff) | ((addr & ~0x7ff) >> 1);
column = (addr >> 1) & dev->ram_mask[bank];
row = ((addr & 0xff000) >> 13) | (((addr & 0x200000) >> 22) << 9);
addr = byte | (column << 1) | (row << dev->row_phys_shift[bank]);
} else {
column = (addr >> 1) & ((dev->ram_mask[bank] << 1) | 1);
row = ((addr & 0x1fe000) >> 13) | (((addr & 0x400000) >> 22) << 9);
addr = byte | (column << 1) | (row << (dev->row_phys_shift[bank]+1));
}
return ram[addr + dev->ram_phys_base[bank]];
}
static void
ram_mirrored_256k_in_4mi_write(uint32_t addr, uint8_t val, void *priv)
{
scamp_t *dev = (scamp_t *) priv;
int bank = (int)priv;
int row, column, byte;
addr -= dev->ram_virt_base[bank];
byte = addr & 1;
if (!dev->ram_interleaved[bank]) {
if (addr & 0x400)
return;
addr = (addr & 0x3ff) | ((addr & ~0x7ff) >> 1);
column = (addr >> 1) & dev->ram_mask[bank];
row = ((addr & 0xff000) >> 13) | (((addr & 0x200000) >> 22) << 9);
addr = byte | (column << 1) | (row << dev->row_phys_shift[bank]);
} else {
column = (addr >> 1) & ((dev->ram_mask[bank] << 1) | 1);
row = ((addr & 0x1fe000) >> 13) | (((addr & 0x400000) >> 22) << 9);
addr = byte | (column << 1) | (row << (dev->row_phys_shift[bank]+1));
}
ram[addr + dev->ram_phys_base[bank]] = val;
}
/*Read/write handlers for interleaved memory banks. We must keep CPU and ram array
mapping linear, otherwise we won't be able to execute code from interleaved banks*/
static uint8_t
ram_mirrored_interleaved_read(uint32_t addr, void *priv)
{
scamp_t *dev = (scamp_t *) priv;
int bank = (int)priv;
int row, column, byte;
addr -= dev->ram_virt_base[bank];
byte = addr & 1;
if (!dev->ram_interleaved[bank]) {
if (addr & 0x400)
return 0xff;
addr = (addr & 0x3ff) | ((addr & ~0x7ff) >> 1);
column = (addr >> 1) & dev->ram_mask[bank];
row = (addr >> dev->row_virt_shift[bank]) & dev->ram_mask[bank];
addr = byte | (column << 1) | (row << dev->row_phys_shift[bank]);
} else {
column = (addr >> 1) & ((dev->ram_mask[bank] << 1) | 1);
row = (addr >> (dev->row_virt_shift[bank]+1)) & dev->ram_mask[bank];
addr = byte | (column << 1) | (row << (dev->row_phys_shift[bank]+1));
}
return ram[addr + dev->ram_phys_base[bank]];
}
static void
ram_mirrored_interleaved_write(uint32_t addr, uint8_t val, void *priv)
{
scamp_t *dev = (scamp_t *) priv;
int bank = (int)priv;
int row, column, byte;
addr -= dev->ram_virt_base[bank];
byte = addr & 1;
if (!dev->ram_interleaved[bank]) {
if (addr & 0x400)
return;
addr = (addr & 0x3ff) | ((addr & ~0x7ff) >> 1);
column = (addr >> 1) & dev->ram_mask[bank];
row = (addr >> dev->row_virt_shift[bank]) & dev->ram_mask[bank];
addr = byte | (column << 1) | (row << dev->row_phys_shift[bank]);
}
else {
column = (addr >> 1) & ((dev->ram_mask[bank] << 1) | 1);
row = (addr >> (dev->row_virt_shift[bank]+1)) & dev->ram_mask[bank];
addr = byte | (column << 1) | (row << (dev->row_phys_shift[bank]+1));
}
ram[addr + dev->ram_phys_base[bank]] = val;
}
static uint8_t
ram_mirrored_read(uint32_t addr, void *priv)
{
scamp_t *dev = (scamp_t *) priv;
int bank = (int)priv;
int row, column, byte;
addr -= dev->ram_virt_base[bank];
byte = addr & 1;
column = (addr >> 1) & dev->ram_mask[bank];
row = (addr >> dev->row_virt_shift[bank]) & dev->ram_mask[bank];
addr = byte | (column << 1) | (row << dev->row_phys_shift[bank]);
return ram[addr + dev->ram_phys_base[bank]];
}
static void
ram_mirrored_write(uint32_t addr, uint8_t val, void *priv)
{
scamp_t *dev = (scamp_t *) priv;
int bank = (int)priv;
int row, column, byte;
addr -= dev->ram_virt_base[bank];
byte = addr & 1;
column = (addr >> 1) & dev->ram_mask[bank];
row = (addr >> dev->row_virt_shift[bank]) & dev->ram_mask[bank];
addr = byte | (column << 1) | (row << dev->row_phys_shift[bank]);
ram[addr + dev->ram_phys_base[bank]] = val;
}
static void
recalc_mappings(void *priv)
{
scamp_t *dev = (scamp_t *) priv;
int c;
uint32_t virt_base = 0;
uint8_t cur_rammap = dev->cfg_regs[CFG_RAMMAP] & 0xf;
int bank_nr = 0;
for (c = 0; c < 2; c++)
mem_mapping_disable(&dev->ram_mapping[c]);
/*Once the BIOS programs the correct DRAM configuration, switch to regular
linear memory mapping*/
if (cur_rammap == ram_configs[dev->ram_config].rammap) {
mem_mapping_set_handler(&ram_low_mapping,
mem_read_ram, mem_read_ramw, mem_read_raml,
mem_write_ram, mem_write_ramw, mem_write_raml);
mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000);
mem_mapping_enable(&ram_high_mapping);
return;
} else {
mem_mapping_set_handler(&ram_low_mapping,
ram_mirrored_read, NULL, NULL,
ram_mirrored_write, NULL, NULL);
mem_mapping_disable(&ram_low_mapping);
}
if (rammap[cur_rammap].bank[0] == BANK_NONE)
bank_nr = 1;
/* pclog("Bank remap, cur_rammap=%x\n", cur_rammap); */
for (; bank_nr < 2; bank_nr++) {
uint32_t old_virt_base = virt_base;
int phys_bank = ram_configs[dev->ram_config].bank[bank_nr];
/* pclog(" Bank %i: phys_bank=%i rammap_bank=%i virt_base=%08x phys_base=%08x\n", bank_nr, phys_bank, rammap[cur_rammap].bank[bank_nr], virt_base, dev->ram_phys_base[bank_nr]); */
dev->ram_virt_base[bank_nr] = virt_base;
if (virt_base == 0) {
switch (rammap[cur_rammap].bank[bank_nr]) {
case BANK_NONE:
fatal("Bank 0 is empty!\n");
break;
case BANK_256K:
if (phys_bank != BANK_NONE) {
mem_mapping_set_addr(&ram_low_mapping, 0, 0x80000);
mem_mapping_set_p(&ram_low_mapping, (void *)bank_nr);
}
virt_base += 512*1024;
dev->row_virt_shift[bank_nr] = 10;
break;
case BANK_256K_INTERLEAVED:
if (phys_bank != BANK_NONE) {
mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000);
mem_mapping_set_p(&ram_low_mapping, (void *)bank_nr);
}
virt_base += 512*1024*2;
dev->row_virt_shift[bank_nr] = 10;
break;
case BANK_1M:
if (phys_bank != BANK_NONE) {
mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000);
mem_mapping_set_p(&ram_low_mapping, (void *)bank_nr);
mem_mapping_set_addr(&dev->ram_mapping[bank_nr], 0x100000, 0x100000);
mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr] + 0x100000]);
}
virt_base += 2048*1024;
dev->row_virt_shift[bank_nr] = 11;
break;
case BANK_1M_INTERLEAVED:
if (phys_bank != BANK_NONE) {
mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000);
mem_mapping_set_p(&ram_low_mapping, (void *)bank_nr);
mem_mapping_set_addr(&dev->ram_mapping[bank_nr], 0x100000, 0x300000);
mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr] + 0x100000]);
}
virt_base += 2048*1024*2;
dev->row_virt_shift[bank_nr] = 11;
break;
case BANK_4M:
if (phys_bank != BANK_NONE) {
mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000);
mem_mapping_set_p(&ram_low_mapping, (void *)bank_nr);
mem_mapping_set_addr(&dev->ram_mapping[bank_nr], 0x100000, 0x700000);
mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr] + 0x100000]);
}
virt_base += 8192*1024;
dev->row_virt_shift[bank_nr] = 12;
break;
case BANK_4M_INTERLEAVED:
if (phys_bank != BANK_NONE) {
mem_mapping_set_addr(&ram_low_mapping, 0, 0xa0000);
mem_mapping_set_p(&ram_low_mapping, (void *)bank_nr);
mem_mapping_set_addr(&dev->ram_mapping[bank_nr], 0x100000, 0xf00000);
mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr] + 0x100000]);
}
virt_base += 8192*1024*2;
dev->row_virt_shift[bank_nr] = 12;
break;
}
} else {
switch (rammap[cur_rammap].bank[bank_nr]) {
case BANK_NONE:
break;
case BANK_256K:
if (phys_bank != BANK_NONE) {
mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x80000);
mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]);
}
virt_base += 512*1024;
dev->row_virt_shift[bank_nr] = 10;
break;
case BANK_256K_INTERLEAVED:
if (phys_bank != BANK_NONE) {
mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x100000);
mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]);
}
virt_base += 512*1024*2;
dev->row_virt_shift[bank_nr] = 10;
break;
case BANK_1M:
if (phys_bank != BANK_NONE) {
mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x200000);
mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]);
}
virt_base += 2048*1024;
dev->row_virt_shift[bank_nr] = 11;
break;
case BANK_1M_INTERLEAVED:
if (phys_bank != BANK_NONE) {
mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x400000);
mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]);
}
virt_base += 2048*1024*2;
dev->row_virt_shift[bank_nr] = 11;
break;
case BANK_4M:
if (phys_bank != BANK_NONE) {
mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x800000);
mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]);
}
virt_base += 8192*1024;
dev->row_virt_shift[bank_nr] = 12;
break;
case BANK_4M_INTERLEAVED:
if (phys_bank != BANK_NONE) {
mem_mapping_set_addr(&dev->ram_mapping[bank_nr], virt_base, 0x1000000);
mem_mapping_set_exec(&dev->ram_mapping[bank_nr], &ram[dev->ram_phys_base[bank_nr]]);
}
virt_base += 8192*1024*2;
dev->row_virt_shift[bank_nr] = 12;
break;
}
}
switch (rammap[cur_rammap].bank[bank_nr]) {
case BANK_256K: case BANK_1M: case BANK_4M:
mem_mapping_set_handler(&dev->ram_mapping[bank_nr],
ram_mirrored_read, NULL, NULL,
ram_mirrored_write, NULL, NULL);
if (!old_virt_base)
mem_mapping_set_handler(&ram_low_mapping,
ram_mirrored_read, NULL, NULL,
ram_mirrored_write, NULL, NULL);
/*pclog(" not interleaved\n");*/
break;
case BANK_256K_INTERLEAVED: case BANK_1M_INTERLEAVED:
mem_mapping_set_handler(&dev->ram_mapping[bank_nr],
ram_mirrored_interleaved_read, NULL, NULL,
ram_mirrored_interleaved_write, NULL, NULL);
if (!old_virt_base)
mem_mapping_set_handler(&ram_low_mapping,
ram_mirrored_interleaved_read, NULL, NULL,
ram_mirrored_interleaved_write, NULL, NULL);
/*pclog(" interleaved\n");*/
break;
case BANK_4M_INTERLEAVED:
if (phys_bank == BANK_256K || phys_bank == BANK_256K_INTERLEAVED) {
mem_mapping_set_handler(&dev->ram_mapping[bank_nr],
ram_mirrored_256k_in_4mi_read, NULL, NULL,
ram_mirrored_256k_in_4mi_write, NULL, NULL);
if (!old_virt_base)
mem_mapping_set_handler(&ram_low_mapping,
ram_mirrored_256k_in_4mi_read, NULL, NULL,
ram_mirrored_256k_in_4mi_write, NULL, NULL);
/*pclog(" 256k in 4mi\n");*/
} else {
mem_mapping_set_handler(&dev->ram_mapping[bank_nr],
ram_mirrored_interleaved_read, NULL, NULL,
ram_mirrored_interleaved_write, NULL, NULL);
if (!old_virt_base)
mem_mapping_set_handler(&ram_low_mapping,
ram_mirrored_interleaved_read, NULL, NULL,
ram_mirrored_interleaved_write, NULL, NULL);
/*pclog(" interleaved\n");*/
}
break;
}
}
}
#define NR_ELEMS(x) (sizeof(x) / sizeof(x[0]))
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
scamp_write(uint16_t addr, uint8_t val, void *priv)
{
scamp_t *dev = (scamp_t *) priv;
/* pclog("scamp_write: addr=%04x val=%02x\n", addr, val); */
switch (addr) {
case 0xec:
if (dev->cfg_enable)
dev->cfg_index = val;
break;
case 0xed:
if (dev->cfg_enable) {
if (dev->cfg_index >= 0x02 && dev->cfg_index <= 0x16) {
dev->cfg_regs[dev->cfg_index] = val;
/* pclog("SCAMP CFG[%02x]=%02x\n", dev->cfg_index, val); */
switch (dev->cfg_index) {
case CFG_SLTPTR:
break;
case CFG_RAMMAP:
recalc_mappings(dev);
mem_mapping_disable(&ram_remapped_mapping);
if (dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386) {
/*Enabling remapping will disable all shadowing*/
mem_remap_top(384);
shadow_control(0xa0000, 0x60000, 0);
} else {
shadow_control(0xa0000, 0x8000, dev->cfg_regs[CFG_ABAXS] & 3);
shadow_control(0xa8000, 0x8000, (dev->cfg_regs[CFG_ABAXS] >> 2) & 3);
shadow_control(0xb0000, 0x8000, (dev->cfg_regs[CFG_ABAXS] >> 4) & 3);
shadow_control(0xb8000, 0x8000, (dev->cfg_regs[CFG_ABAXS] >> 6) & 3);
shadow_control(0xc0000, 0x4000, dev->cfg_regs[CFG_CAXS] & 3);
shadow_control(0xc4000, 0x4000, (dev->cfg_regs[CFG_CAXS] >> 2) & 3);
shadow_control(0xc8000, 0x4000, (dev->cfg_regs[CFG_CAXS] >> 4) & 3);
shadow_control(0xcc000, 0x4000, (dev->cfg_regs[CFG_CAXS] >> 6) & 3);
shadow_control(0xd0000, 0x4000, dev->cfg_regs[CFG_DAXS] & 3);
shadow_control(0xd4000, 0x4000, (dev->cfg_regs[CFG_DAXS] >> 2) & 3);
shadow_control(0xd8000, 0x4000, (dev->cfg_regs[CFG_DAXS] >> 4) & 3);
shadow_control(0xdc000, 0x4000, (dev->cfg_regs[CFG_DAXS] >> 6) & 3);
shadow_control(0xe0000, 0x8000, dev->cfg_regs[CFG_FEAXS] & 3);
shadow_control(0xe8000, 0x8000, (dev->cfg_regs[CFG_FEAXS] >> 2) & 3);
shadow_control(0xf0000, 0x8000, (dev->cfg_regs[CFG_FEAXS] >> 4) & 3);
shadow_control(0xf8000, 0x8000, (dev->cfg_regs[CFG_FEAXS] >> 6) & 3);
}
break;
case CFG_ABAXS:
if (!(dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386)) {
shadow_control(0xa0000, 0x8000, val & 3);
shadow_control(0xa8000, 0x8000, (val >> 2) & 3);
shadow_control(0xb0000, 0x8000, (val >> 4) & 3);
shadow_control(0xb8000, 0x8000, (val >> 6) & 3);
}
break;
case CFG_CAXS:
if (!(dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386)) {
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:
if (!(dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386)) {
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_FEAXS:
if (!(dev->cfg_regs[CFG_RAMMAP] & RAMMAP_REMP386)) {
shadow_control(0xe0000, 0x8000, val & 3);
shadow_control(0xe8000, 0x8000, (val >> 2) & 3);
shadow_control(0xf0000, 0x8000, (val >> 4) & 3);
shadow_control(0xf8000, 0x8000, (val >> 6) & 3);
}
break;
}
}
}
break;
case 0xee:
if (dev->cfg_enable && mem_a20_alt)
outb(0x92, inb(0x92) & ~2);
break;
}
}
static uint8_t
scamp_read(uint16_t addr, void *priv)
{
uint8_t ret = 0xff;
switch (addr) {
case 0xee:
if (!mem_a20_alt)
outb(0x92, inb(0x92) | 2);
break;
case 0xef:
softresetx86();
cpu_set_edx();
break;
}
/* pclog("scamp_read: addr=%04x ret=%02x\n", addr, ret); */
return ret;
}
static void
scamp_close(void *priv)
{
scamp_t *dev = (scamp_t *) priv;
free(dev);
}
static void *
scamp_init(const device_t *info)
{
uint32_t addr;
int c;
scamp_t *dev = (scamp_t *)malloc(sizeof(scamp_t));
memset(dev, 0, sizeof(scamp_t));
dev->cfg_regs[CFG_ID] = ID_VL82C311;
dev->cfg_enable = 1;
io_sethandler(0x00e8, 0x0001,
scamp_read, NULL, NULL, scamp_write, NULL, NULL, dev);
io_sethandler(0x00ea, 0x0006,
scamp_read, NULL, NULL, scamp_write, NULL, NULL, dev);
io_sethandler(0x00f4, 0x0002,
scamp_read, NULL, NULL, scamp_write, NULL, NULL, dev);
io_sethandler(0x00f9, 0x0001,
scamp_read, NULL, NULL, scamp_write, NULL, NULL, dev);
io_sethandler(0x00fb, 0x0001,
scamp_read, NULL, NULL, scamp_write, NULL, NULL, dev);
dev->ram_config = 0;
/*Find best fit configuration for the requested memory size*/
for (c = 0; c < NR_ELEMS(ram_configs); c++) {
if (mem_size < ram_configs[c].size_kb)
break;
dev->ram_config = c;
}
mem_mapping_set_handler(&ram_low_mapping,
ram_mirrored_read, NULL, NULL,
ram_mirrored_write, NULL, NULL);
mem_mapping_disable(&ram_high_mapping);
addr = 0;
for (c = 0; c < 2; c++) {
mem_mapping_add(&dev->ram_mapping[c], 0, 0,
ram_mirrored_read, NULL, NULL,
ram_mirrored_write, NULL, NULL,
&ram[addr], MEM_MAPPING_INTERNAL, (void *)c);
mem_mapping_disable(&dev->ram_mapping[c]);
dev->ram_phys_base[c] = addr;
/* pclog("Bank calc : %i = %08x\n", c ,addr);*/
switch (ram_configs[dev->ram_config].bank[c]) {
case BANK_NONE:
dev->ram_mask[c] = 0;
dev->ram_interleaved[c] = 0;
break;
case BANK_256K:
addr += 512*1024;
dev->ram_mask[c] = 0x1ff;
dev->row_phys_shift[c] = 10;
dev->ram_interleaved[c] = 0;
break;
case BANK_256K_INTERLEAVED:
addr += 512*1024*2;
dev->ram_mask[c] = 0x1ff;
dev->row_phys_shift[c] = 10;
dev->ibank_shift[c] = 19;
dev->ram_interleaved[c] = 1;
break;
case BANK_1M:
addr += 2048*1024;
dev->ram_mask[c] = 0x3ff;
dev->row_phys_shift[c] = 11;
dev->ram_interleaved[c] = 0;
break;
case BANK_1M_INTERLEAVED:
addr += 2048*1024*2;
dev->ram_mask[c] = 0x3ff;
dev->row_phys_shift[c] = 11;
dev->ibank_shift[c] = 21;
dev->ram_interleaved[c] = 1;
break;
case BANK_4M:
addr += 8192*1024;
dev->ram_mask[c] = 0x7ff;
dev->row_phys_shift[c] = 12;
dev->ram_interleaved[c] = 0;
break;
case BANK_4M_INTERLEAVED:
addr += 8192*1024*2;
dev->ram_mask[c] = 0x7ff;
dev->row_phys_shift[c] = 12;
dev->ibank_shift[c] = 23;
dev->ram_interleaved[c] = 1;
break;
}
}
mem_set_mem_state(0xfe0000, 0x20000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
return dev;
}
const device_t vlsi_scamp_device = {
"VLSI SCAMP",
0,
0,
scamp_init, scamp_close, NULL,
NULL, NULL, NULL,
NULL
};

View File

@@ -8,7 +8,7 @@
*
* Implementation of 286 and 386SX machines.
*
* Version: @(#)m_at_286_386sx.c 1.0.2 2019/11/19
* Version: @(#)m_at_286_386sx.c 1.0.3 2020/01/22
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -35,6 +35,7 @@
#include "../floppy/fdc.h"
#include "../disk/hdc.h"
#include "../video/video.h"
#include "../video/vid_cl54xx.h"
#include "../video/vid_et4000.h"
#include "../video/vid_oak_oti.h"
#include "../video/vid_paradise.h"
@@ -409,3 +410,33 @@ machine_at_wd76c10_init(const machine_t *model)
return ret;
}
const device_t *
at_commodore_sl386sx_get_device(void)
{
return &gd5402_onboard_device;
}
int
machine_at_commodore_sl386sx_init(const machine_t *model)
{
int ret;
ret = bios_load_interleaved(L"roms/machines/cbm_sl386sx25/cbm-sl386sx-bios-lo-v1.04-390914-04.bin",
L"roms/machines/cbm_sl386sx25/cbm-sl386sx-bios-hi-v1.04-390915-04.bin",
0x000f0000, 65536, 0);
if (bios_only || !ret)
return ret;
machine_at_common_ide_init(model);
device_add(&keyboard_at_device);
device_add(&fdc_at_device);
device_add(&vlsi_scamp_device);
if (gfxcard == VID_INTERNAL)
device_add(&gd5402_onboard_device);
return ret;
}

View File

@@ -8,7 +8,7 @@
*
* Handling of the emulated machines.
*
* Version: @(#)machine.h 1.0.36 2020/01/20
* Version: @(#)machine.h 1.0.37 2020/01/22
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -201,10 +201,12 @@ extern int machine_at_spc4216p_init(const machine_t *);
extern int machine_at_kmxc02_init(const machine_t *);
extern int machine_at_deskmaster286_init(const machine_t *);
extern int machine_at_commodore_sl386sx_init(const machine_t *);
extern int machine_at_wd76c10_init(const machine_t *);
#ifdef EMU_DEVICE_H
extern const device_t *at_ama932j_get_device(void);
extern const device_t *at_ama932j_get_device(void);
extern const device_t *at_commodore_sl386sx_get_device(void);
#endif
/* m_at_386dx_486.c */

View File

@@ -11,7 +11,7 @@
* NOTES: OpenAT wip for 286-class machine with open BIOS.
* PS2_M80-486 wip, pending receipt of TRM's for machine.
*
* Version: @(#)machine_table.c 1.0.53 2020/01/20
* Version: @(#)machine_table.c 1.0.54 2020/01/22
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -127,6 +127,7 @@ const machine_t machines[] = {
{ "[386SX ISA] AMI Unknown 386SX", "ami386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512,16384, 128, 127, machine_at_headland_init, NULL },
#endif
{ "[386SX ISA] Amstrad MegaPC", "megapc", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC, 1, 32, 1, 127, machine_at_wd76c10_init, NULL },
{ "[386SX ISA] Commodore SL386SX", "cbm_sl386sx25", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC, 1024, 8192, 512, 127, machine_at_commodore_sl386sx_init, at_commodore_sl386sx_get_device },
{ "[386SX ISA] DTK 386SX clone", "dtk386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512, 8192, 128, 127, machine_at_neat_init, NULL },
{ "[386SX ISA] IBM PS/1 model 2121", "ibmps1_2121", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO | MACHINE_VIDEO_FIXED, 1, 6, 1, 63, machine_ps1_m2121_init, NULL },
{ "[386SX ISA] IBM PS/1 m.2121+ISA", "ibmps1_2121_isa", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 1, 6, 1, 63, machine_ps1_m2121_init, NULL },

View File

@@ -11,7 +11,7 @@
* NOTES: OpenAT wip for 286-class machine with open BIOS.
* PS2_M80-486 wip, pending receipt of TRM's for machine.
*
* Version: @(#)machine_table.c 1.0.53 2020/01/20
* Version: @(#)machine_table.c 1.0.54 2020/01/22
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -112,6 +112,7 @@ const machine_t machines[] = {
{ "[386SX ISA] AMI Unknown 386SX", "ami386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512,16384, 128, 127, machine_at_headland_init, NULL },
#endif
{ "[386SX ISA] Amstrad MegaPC", "megapc", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC, 1, 32, 1, 127, machine_at_wd76c10_init, NULL },
{ "[386SX ISA] Commodore SL386SX", "cbm_sl386sx25", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC, 1024, 8192, 512, 127, machine_at_commodore_sl386sx_init, at_commodore_sl386sx_get_device },
{ "[386SX ISA] DTK 386SX clone", "dtk386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512, 8192, 128, 127, machine_at_neat_init, NULL },
{ "[386SX ISA] IBM PS/1 model 2121", "ibmps1_2121", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO | MACHINE_VIDEO_FIXED, 1, 6, 1, 63, machine_ps1_m2121_init, NULL },
{ "[386SX ISA] IBM PS/1 m.2121+ISA", "ibmps1_2121_isa", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 1, 6, 1, 63, machine_ps1_m2121_init, NULL },

View File

@@ -9,7 +9,7 @@
* Emulation of select Cirrus Logic cards (CL-GD 5428,
* CL-GD 5429, CL-GD 5430, CL-GD 5434 and CL-GD 5436 are supported).
*
* Version: @(#)vid_cl_54xx.c 1.0.32 2020/01/11
* Version: @(#)vid_cl_54xx.c 1.0.32 2020/01/22
*
* Authors: TheCollector1995,
* Miran Grca, <mgrca8@gmail.com>
@@ -36,10 +36,13 @@
#include "vid_svga_render.h"
#include "vid_cl54xx.h"
#if defined(DEV_BRANCH) && defined(USE_CL5422)
#define BIOS_GD5402_PATH L"roms/video/cirruslogic/avga2.rom"
#define BIOS_GD5420_PATH L"roms/video/cirruslogic/5420.vbi"
#if defined(DEV_BRANCH) && defined(USE_CL5422)
#define BIOS_GD5422_PATH L"roms/video/cirruslogic/cl5422.bin"
#endif
#define BIOS_GD5426_PATH L"roms/video/cirruslogic/Diamond SpeedStar PRO VLB v3.04.bin"
#define BIOS_GD5428_ISA_PATH L"roms/video/cirruslogic/5428.bin"
#define BIOS_GD5428_PATH L"roms/video/cirruslogic/vlbusjapan.BIN"
@@ -2906,21 +2909,25 @@ static void
gd54xx->has_bios = 1;
switch (id) {
#if defined(DEV_BRANCH) && defined(USE_CL5422)
case CIRRUS_ID_CLGD5402:
romfn = BIOS_GD5402_PATH;
break;
case CIRRUS_ID_CLGD5420:
romfn = BIOS_GD5420_PATH;
break;
#if defined(DEV_BRANCH) && defined(USE_CL5422)
case CIRRUS_ID_CLGD5422:
case CIRRUS_ID_CLGD5424:
romfn = BIOS_GD5422_PATH;
break;
#endif
case CIRRUS_ID_CLGD5426:
romfn = BIOS_GD5426_PATH;
break;
case CIRRUS_ID_CLGD5428:
if (gd54xx->vlb)
romfn = BIOS_GD5428_PATH;
@@ -3021,7 +3028,6 @@ static void
svga->hwcursor.yoff = 32;
svga->hwcursor.xoff = 0;
#if defined(DEV_BRANCH) && defined(USE_CL5422)
if (id >= CIRRUS_ID_CLGD5420) {
gd54xx->vclk_n[0] = 0x4a;
gd54xx->vclk_d[0] = 0x2b;
@@ -3041,16 +3047,6 @@ static void
gd54xx->vclk_n[3] = 0x7e;
gd54xx->vclk_d[3] = 0x33;
}
#else
gd54xx->vclk_n[0] = 0x4a;
gd54xx->vclk_d[0] = 0x2b;
gd54xx->vclk_n[1] = 0x5b;
gd54xx->vclk_d[1] = 0x2f;
gd54xx->vclk_n[2] = 0x45;
gd54xx->vclk_d[2] = 0x30;
gd54xx->vclk_n[3] = 0x7e;
gd54xx->vclk_d[3] = 0x33;
#endif
svga->extra_banks[1] = 0x8000;
@@ -3072,13 +3068,19 @@ static void
return gd54xx;
}
#if defined(DEV_BRANCH) && defined(USE_CL5422)
static int
gd5402_available(void)
{
return rom_present(BIOS_GD5402_PATH);
}
static int
gd5420_available(void)
{
return rom_present(BIOS_GD5420_PATH);
}
#if defined(DEV_BRANCH) && defined(USE_CL5422)
static int
gd5422_available(void)
{
@@ -3186,7 +3188,6 @@ gd54xx_force_redraw(void *p)
gd54xx->svga.fullchange = changeframecount;
}
#if defined(DEV_BRANCH) && defined(USE_CL5422)
static const device_config_t gd5422_config[] =
{
{
@@ -3207,7 +3208,6 @@ static const device_config_t gd5422_config[] =
"","",-1
}
};
#endif
static const device_config_t gd5428_config[] =
{
@@ -3290,7 +3290,6 @@ static const device_config_t gd5434_config[] =
}
};
#if defined(DEV_BRANCH) && defined(USE_CL5422)
const device_t gd5402_isa_device =
{
"Cirrus Logic GD-5402 (ACUMOS AVGA2)",
@@ -3298,7 +3297,20 @@ const device_t gd5402_isa_device =
CIRRUS_ID_CLGD5402,
gd54xx_init, gd54xx_close,
NULL,
gd5420_available, /* Common BIOS between 5402 and 5420 */
gd5402_available,
gd54xx_speed_changed,
gd54xx_force_redraw,
NULL,
};
const device_t gd5402_onboard_device =
{
"Cirrus Logic GD-5402 (ACUMOS AVGA2) (On-Board)",
DEVICE_AT | DEVICE_ISA,
CIRRUS_ID_CLGD5402,
gd54xx_init, gd54xx_close,
NULL,
NULL,
gd54xx_speed_changed,
gd54xx_force_redraw,
NULL,
@@ -3311,12 +3323,13 @@ const device_t gd5420_isa_device =
CIRRUS_ID_CLGD5420,
gd54xx_init, gd54xx_close,
NULL,
gd5420_available, /* Common BIOS between 5402 and 5420 */
gd5420_available,
gd54xx_speed_changed,
gd54xx_force_redraw,
gd5422_config,
};
#if defined(DEV_BRANCH) && defined(USE_CL5422)
const device_t gd5422_isa_device = {
"Cirrus Logic GD-5422",
DEVICE_AT | DEVICE_ISA,

View File

@@ -1,9 +1,10 @@
/* Copyright holders: Sarah Walker
see COPYING for more details
*/
#if defined(DEV_BRANCH) && defined(USE_CL5422)
extern const device_t gd5402_isa_device;
extern const device_t gd5402_onboard_device;
extern const device_t gd5420_isa_device;
#if defined(DEV_BRANCH) && defined(USE_CL5422)
extern const device_t gd5422_isa_device;
extern const device_t gd5424_vlb_device;
#endif

View File

@@ -8,7 +8,7 @@
*
* Define all known video cards.
*
* Version: @(#)vid_table.c 1.0.48 2020/01/20
* Version: @(#)vid_table.c 1.0.49 2020/01/22
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
@@ -94,9 +94,9 @@ video_cards[] = {
#endif
{ "[ISA] CGA", "cga", &cga_device },
{ "[ISA] Chips & Technologies SuperEGA", "superega", &sega_device },
#if defined(DEV_BRANCH) && defined(USE_CL5422)
{ "[ISA] Cirrus Logic CL-GD 5402", "cl_gd5402_isa", &gd5402_isa_device },
{ "[ISA] Cirrus Logic CL-GD 5420", "cl_gd5420_isa", &gd5420_isa_device },
#if defined(DEV_BRANCH) && defined(USE_CL5422)
{ "[ISA] Cirrus Logic CL-GD 5422", "cl_gd5422_isa", &gd5422_isa_device },
#endif
{ "[ISA] Cirrus Logic CL-GD 5428", "cl_gd5428_isa", &gd5428_isa_device },

View File

@@ -565,7 +565,7 @@ CPUOBJ := cpu.o cpu_table.o \
$(DYNARECOBJ)
CHIPSETOBJ := acc2168.o acer_m3a.o ali1429.o headland.o \
intel_4x0.o neat.o opti495.o scat.o \
intel_4x0.o neat.o opti495.o scamp.o scat.o \
sis_85c471.o sis_85c496.o \
via_mvp3.o wd76c10.o

View File

@@ -571,7 +571,7 @@ CPUOBJ := cpu.o cpu_table.o \
$(DYNARECOBJ)
CHIPSETOBJ := acc2168.o acer_m3a.o ali1429.o headland.o \
intel_4x0.o neat.o opti495.o scat.o \
intel_4x0.o neat.o opti495.o scamp.o scat.o \
sis_85c471.o sis_85c496.o \
via_mvp3.o wd76c10.o