Finished the great internal machine reorganization and added the FIC PO-6000.
This commit is contained in:
@@ -30,12 +30,15 @@ add_library(chipset OBJECT
|
||||
ali1621.c
|
||||
ali6117.c
|
||||
ali1409.c
|
||||
headland.c
|
||||
ims8848.c
|
||||
intel_82335.c
|
||||
compaq.c
|
||||
compaq_386.c
|
||||
contaq_82c59x.c
|
||||
cs4031.c
|
||||
grid1520.c
|
||||
gc100.c
|
||||
headland.c
|
||||
ims8848.c
|
||||
intel_82335.c
|
||||
intel_420ex.c
|
||||
intel_4x0.c
|
||||
intel_i450kx.c
|
||||
@@ -43,6 +46,7 @@ add_library(chipset OBJECT
|
||||
intel_piix.c
|
||||
isa486c.c
|
||||
../ioapic.c
|
||||
laserxt.c
|
||||
neat.c
|
||||
olivetti_eva.c
|
||||
opti283.c
|
||||
@@ -55,6 +59,7 @@ add_library(chipset OBJECT
|
||||
opti822.c
|
||||
opti895.c
|
||||
opti5x7.c
|
||||
philips.c
|
||||
scamp.c
|
||||
scat.c
|
||||
sis_85c310.c
|
||||
@@ -77,10 +82,9 @@ add_library(chipset OBJECT
|
||||
sis_5595_pmu.c
|
||||
sis_55xx.c
|
||||
sl82c461.c
|
||||
stpc.c
|
||||
via_vt82c49x.c
|
||||
via_vt82c505.c
|
||||
gc100.c
|
||||
stpc.c
|
||||
umc_8886.c
|
||||
umc_hb4.c
|
||||
umc_8890.c
|
||||
|
||||
135
src/chipset/compaq.c
Normal file
135
src/chipset/compaq.c
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* 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 the Compaq 386 memory controller.
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2023 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#include <math.h>
|
||||
#include <86box/86box.h>
|
||||
#include "cpu.h"
|
||||
#include <86box/io.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/pit.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/rom.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/keyboard.h>
|
||||
#include <86box/fdd.h>
|
||||
#include <86box/fdc.h>
|
||||
#include <86box/fdc_ext.h>
|
||||
#include <86box/hdc.h>
|
||||
#include <86box/hdc_ide.h>
|
||||
#include <86box/machine.h>
|
||||
#include <86box/video.h>
|
||||
#include <86box/vid_cga.h>
|
||||
#include <86box/vid_cga_comp.h>
|
||||
#include <86box/plat_unused.h>
|
||||
#include <86box/chipset.h>
|
||||
|
||||
/* Compaq Deskpro 386 remaps RAM from 0xA0000-0xFFFFF to 0xFA0000-0xFFFFFF */
|
||||
typedef struct cpq_t {
|
||||
mem_mapping_t ram_mapping;
|
||||
} cpq_t;
|
||||
|
||||
static uint8_t
|
||||
read_ram(uint32_t addr, UNUSED(void *priv))
|
||||
{
|
||||
addr = (addr & 0x7ffff) + 0x80000;
|
||||
addreadlookup(mem_logical_addr, addr);
|
||||
|
||||
return (ram[addr]);
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
read_ramw(uint32_t addr, UNUSED(void *priv))
|
||||
{
|
||||
addr = (addr & 0x7ffff) + 0x80000;
|
||||
addreadlookup(mem_logical_addr, addr);
|
||||
|
||||
return (*(uint16_t *) &ram[addr]);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
read_raml(uint32_t addr, UNUSED(void *priv))
|
||||
{
|
||||
addr = (addr & 0x7ffff) + 0x80000;
|
||||
addreadlookup(mem_logical_addr, addr);
|
||||
|
||||
return (*(uint32_t *) &ram[addr]);
|
||||
}
|
||||
|
||||
static void
|
||||
write_ram(uint32_t addr, uint8_t val, UNUSED(void *priv))
|
||||
{
|
||||
addr = (addr & 0x7ffff) + 0x80000;
|
||||
addwritelookup(mem_logical_addr, addr);
|
||||
|
||||
mem_write_ramb_page(addr, val, &pages[addr >> 12]);
|
||||
}
|
||||
|
||||
static void
|
||||
write_ramw(uint32_t addr, uint16_t val, UNUSED(void *priv))
|
||||
{
|
||||
addr = (addr & 0x7ffff) + 0x80000;
|
||||
addwritelookup(mem_logical_addr, addr);
|
||||
|
||||
mem_write_ramw_page(addr, val, &pages[addr >> 12]);
|
||||
}
|
||||
|
||||
static void
|
||||
write_raml(uint32_t addr, uint32_t val, UNUSED(void *priv))
|
||||
{
|
||||
addr = (addr & 0x7ffff) + 0x80000;
|
||||
addwritelookup(mem_logical_addr, addr);
|
||||
|
||||
mem_write_raml_page(addr, val, &pages[addr >> 12]);
|
||||
}
|
||||
|
||||
static void
|
||||
compaq_close(void *priv)
|
||||
{
|
||||
cpq_t *dev = (cpq_t *) priv;
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
static void *
|
||||
compaq_init(UNUSED(const device_t *info))
|
||||
{
|
||||
cpq_t *dev = (cpq_t *) calloc(1, sizeof(cpq_t));
|
||||
|
||||
mem_remap_top(384);
|
||||
mem_mapping_add(&dev->ram_mapping, 0xfa0000, 0x60000,
|
||||
read_ram, read_ramw, read_raml,
|
||||
write_ram, write_ramw, write_raml,
|
||||
0xa0000 + ram, MEM_MAPPING_INTERNAL, NULL);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
const device_t compaq_device = {
|
||||
.name = "Compaq Memory Control",
|
||||
.internal_name = "compaq",
|
||||
.flags = 0,
|
||||
.local = 0,
|
||||
.init = compaq_init,
|
||||
.close = compaq_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
333
src/chipset/grid1520.c
Normal file
333
src/chipset/grid1520.c
Normal file
@@ -0,0 +1,333 @@
|
||||
/*
|
||||
* 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 GRiD GRiDcase 1520
|
||||
*
|
||||
* The GRiDcase 1520 is a 286-based portable.
|
||||
* These are HDDs supported by GRiD1520 (and probably other 15XX) BIOS
|
||||
* "CP3022",5
|
||||
* "CP3024",5, 615,4,17 BIOS table type 2
|
||||
* "CP344",6,
|
||||
* "CP3044",9, 980,5,17 BIOS table type 17
|
||||
* "CP3042",9
|
||||
* "CP3104",7, 776,8,33 extended type 224 (separate entry outside BIOS table)
|
||||
* The only way to run unpatched BIOS is to run exactly that (or larger)
|
||||
* geometry and report model name correctly in response to IDENTYIFY command.
|
||||
* Alternatively you can use RomBuster to patch the BIOS.
|
||||
* https://classicbits.net/coding-and-software/my-software/rombuster/
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <86box/86box.h>
|
||||
#include "cpu.h"
|
||||
#include <86box/timer.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/fdd.h>
|
||||
#include <86box/fdc.h>
|
||||
#include <86box/fdc_ext.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/keyboard.h>
|
||||
#include <86box/machine.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/rom.h>
|
||||
#include <86box/vid_cga.h>
|
||||
#include <86box/plat_unused.h>
|
||||
#include <86box/chipset.h>
|
||||
|
||||
#define GRID_APPROM_SELECT 0x440
|
||||
#define GRID_APPROM_ENABLE 0x405
|
||||
|
||||
/*
|
||||
approm mapping regs?
|
||||
XXX_7FA equ 7FAh
|
||||
XXX_7F8 equ 7F8h
|
||||
XXX_7F9 equ 7F9h
|
||||
XXX_BD0 equ 0BD0h
|
||||
XXX_BD1 equ 0BD1h
|
||||
*/
|
||||
|
||||
#define GRID_EMS_PAGE_0 0x0258
|
||||
#define GRID_EMS_PAGE_1 0x4258
|
||||
#define GRID_EMS_PAGE_2 0x8258
|
||||
#define GRID_EMS_PAGE_3 0xC258
|
||||
#define GRID_TURBO 0x416
|
||||
#define GRID_UNUSED_424 0x424
|
||||
#define GRID_426 0x426
|
||||
#define GRID_HIGH_ENABLE 0xFFF
|
||||
#define GRID_ROM_SUBSYSTEM 0x6F8
|
||||
|
||||
// EMS window
|
||||
#define GRID_EMS_BASE 0xE0000
|
||||
#define GRID_EMS_PAGE_SIZE 0x4000
|
||||
#define GRID_EMS_PAGE_MASK 0x3FFF
|
||||
#define GRID_EMS_PAGE_SHIFT 14
|
||||
// physical base of extended memory
|
||||
#define GRID_EXTENDED_BASE 0xA0000
|
||||
#define GRID_1M 0x100000
|
||||
|
||||
typedef struct {
|
||||
uint8_t grid_unknown;
|
||||
uint8_t grid_unused_424;
|
||||
uint8_t grid_426;
|
||||
uint8_t grid_high_enable;
|
||||
uint8_t grid_ems_page[4];
|
||||
mem_mapping_t grid_ems_mapping[4];
|
||||
uint8_t grid_turbo;
|
||||
uint8_t grid_rom_enable;
|
||||
uint8_t grid_rom_select;
|
||||
} grid_t;
|
||||
|
||||
|
||||
static uint32_t get_grid_ems_paddr(grid_t *dev, uint32_t addr) {
|
||||
uint32_t slot = (addr >> GRID_EMS_PAGE_SHIFT) & 0x3;
|
||||
uint32_t paddr = addr;
|
||||
|
||||
if (dev->grid_ems_page[slot] & 0x80)
|
||||
paddr = GRID_EXTENDED_BASE + ((uint32_t)(dev->grid_ems_page[slot] & 0x7F) << GRID_EMS_PAGE_SHIFT) + (addr & GRID_EMS_PAGE_MASK);
|
||||
|
||||
return paddr;
|
||||
}
|
||||
|
||||
static void grid_ems_mem_write8(uint32_t addr, uint8_t val, void *priv) {
|
||||
grid_t *dev = (grid_t *) priv;
|
||||
|
||||
addr = get_grid_ems_paddr(dev, addr);
|
||||
|
||||
if (addr < (mem_size << 10))
|
||||
ram[addr] = val;
|
||||
}
|
||||
|
||||
static uint8_t grid_ems_mem_read8(uint32_t addr, void *priv) {
|
||||
grid_t *dev = (grid_t *) priv;
|
||||
uint8_t val = 0xFF;
|
||||
|
||||
addr = get_grid_ems_paddr(dev, addr);
|
||||
|
||||
if (addr < (mem_size << 10))
|
||||
val = ram[addr];
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void grid_ems_mem_write16(uint32_t addr, uint16_t val, void *priv) {
|
||||
grid_t *dev = (grid_t *) priv;
|
||||
|
||||
addr = get_grid_ems_paddr(dev, addr);
|
||||
|
||||
if (addr < (mem_size << 10))
|
||||
*(uint16_t *)&(ram[addr]) = val;
|
||||
}
|
||||
|
||||
static uint16_t grid_ems_mem_read16(uint32_t addr, void *priv) {
|
||||
grid_t *dev = (grid_t *) priv;
|
||||
uint16_t val = 0xFFFF;
|
||||
|
||||
addr = get_grid_ems_paddr(dev, addr);
|
||||
|
||||
if (addr < (mem_size << 10))
|
||||
val = *(uint16_t *)&(ram[addr]);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void grid_ems_update_mapping(grid_t *dev, uint32_t slot) {
|
||||
uint32_t vaddr = GRID_EMS_BASE + (slot << GRID_EMS_PAGE_SHIFT);
|
||||
if (dev->grid_ems_page[slot] & 0x80) {
|
||||
uint32_t paddr;
|
||||
mem_mapping_enable(&dev->grid_ems_mapping[slot]);
|
||||
paddr = get_grid_ems_paddr(dev, vaddr);
|
||||
mem_mapping_set_exec(&dev->grid_ems_mapping[slot], ram + paddr);
|
||||
} else {
|
||||
mem_mapping_disable(&dev->grid_ems_mapping[slot]);
|
||||
}
|
||||
}
|
||||
|
||||
static void grid_io_write(uint16_t port, uint8_t val, void *priv) {
|
||||
grid_t *dev = (grid_t *) priv;
|
||||
|
||||
switch (port) {
|
||||
case GRID_426:
|
||||
dev->grid_426 = val;
|
||||
break;
|
||||
case GRID_UNUSED_424:
|
||||
dev->grid_unused_424 = val;
|
||||
break;
|
||||
case GRID_ROM_SUBSYSTEM:
|
||||
case GRID_ROM_SUBSYSTEM+1:
|
||||
case GRID_ROM_SUBSYSTEM+2:
|
||||
case GRID_ROM_SUBSYSTEM+3:
|
||||
case GRID_ROM_SUBSYSTEM+4:
|
||||
case GRID_ROM_SUBSYSTEM+5:
|
||||
case GRID_ROM_SUBSYSTEM+6:
|
||||
case GRID_ROM_SUBSYSTEM+7:
|
||||
break;
|
||||
case GRID_APPROM_SELECT:
|
||||
dev->grid_rom_select = val;
|
||||
break;
|
||||
case GRID_APPROM_ENABLE:
|
||||
dev->grid_rom_enable = val;
|
||||
break;
|
||||
case GRID_TURBO:
|
||||
if ((dev->grid_turbo ^ val) & 1) {
|
||||
dev->grid_turbo = val;
|
||||
if (dev->grid_turbo)
|
||||
cpu_dynamic_switch(cpu);
|
||||
else
|
||||
cpu_dynamic_switch(0); /* 286/6 */
|
||||
}
|
||||
break;
|
||||
case GRID_EMS_PAGE_0:
|
||||
case GRID_EMS_PAGE_1:
|
||||
case GRID_EMS_PAGE_2:
|
||||
case GRID_EMS_PAGE_3: {
|
||||
uint32_t slot = (port >> 14) & 0x3;
|
||||
if (dev->grid_ems_page[slot] == val)
|
||||
break; // no change
|
||||
|
||||
dev->grid_ems_page[slot] = val;
|
||||
if (dev->grid_high_enable & 0x1)
|
||||
break; // XMS is enabled
|
||||
grid_ems_update_mapping(dev, slot);
|
||||
|
||||
flushmmucache();
|
||||
break;
|
||||
}
|
||||
case GRID_HIGH_ENABLE: {
|
||||
if (((val ^ dev->grid_high_enable) & 0x1) == 0)
|
||||
break; // no change
|
||||
dev->grid_high_enable = val;
|
||||
if (dev->grid_high_enable & 0x1) {
|
||||
for (uint8_t i = 0; i < 4; i++)
|
||||
mem_mapping_disable(&dev->grid_ems_mapping[i]);
|
||||
mem_mapping_enable(&ram_high_mapping);
|
||||
} else {
|
||||
mem_mapping_disable(&ram_high_mapping);
|
||||
for (uint8_t i = 0; i < 4; i++)
|
||||
grid_ems_update_mapping(dev, i);
|
||||
}
|
||||
flushmmucache();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t grid_io_read(uint16_t port, void *priv) {
|
||||
grid_t *dev = (grid_t *) priv;
|
||||
|
||||
switch (port) {
|
||||
case GRID_426:
|
||||
return dev->grid_426;
|
||||
break;
|
||||
case GRID_UNUSED_424:
|
||||
return dev->grid_unused_424;
|
||||
break;
|
||||
case GRID_ROM_SUBSYSTEM:
|
||||
return 0x99;
|
||||
break;
|
||||
case GRID_ROM_SUBSYSTEM+1:
|
||||
case GRID_ROM_SUBSYSTEM+2:
|
||||
case GRID_ROM_SUBSYSTEM+3:
|
||||
case GRID_ROM_SUBSYSTEM+4:
|
||||
case GRID_ROM_SUBSYSTEM+5:
|
||||
case GRID_ROM_SUBSYSTEM+6:
|
||||
case GRID_ROM_SUBSYSTEM+7:
|
||||
break;
|
||||
case GRID_APPROM_SELECT:
|
||||
return dev->grid_rom_select;
|
||||
case GRID_APPROM_ENABLE:
|
||||
return dev->grid_rom_enable;
|
||||
case GRID_TURBO:
|
||||
return dev->grid_turbo;
|
||||
case GRID_HIGH_ENABLE:
|
||||
return dev->grid_high_enable;
|
||||
case GRID_EMS_PAGE_0:
|
||||
case GRID_EMS_PAGE_1:
|
||||
case GRID_EMS_PAGE_2:
|
||||
case GRID_EMS_PAGE_3: {
|
||||
uint32_t slot = (port >> 14) & 0x3;
|
||||
|
||||
return dev->grid_ems_page[slot];
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
static void *
|
||||
grid_init(UNUSED(const device_t *info))
|
||||
{
|
||||
grid_t *dev = calloc(1, sizeof(grid_t));
|
||||
|
||||
io_sethandler(GRID_ROM_SUBSYSTEM, 0x0008, grid_io_read, NULL, NULL, grid_io_write, NULL, NULL, dev);
|
||||
io_sethandler(GRID_UNUSED_424, 0x0001, grid_io_read, NULL, NULL, grid_io_write, NULL, NULL, dev);
|
||||
io_sethandler(GRID_426, 0x0001, grid_io_read, NULL, NULL, grid_io_write, NULL, NULL, dev);
|
||||
io_sethandler(GRID_APPROM_SELECT, 0x0001, grid_io_read, NULL, NULL, grid_io_write, NULL, NULL, dev);
|
||||
io_sethandler(GRID_APPROM_ENABLE, 0x0001, grid_io_read, NULL, NULL, grid_io_write, NULL, NULL, dev);
|
||||
io_sethandler(GRID_TURBO, 0x0001, grid_io_read, NULL, NULL, grid_io_write, NULL, NULL, dev);
|
||||
dev->grid_turbo = 0x1;
|
||||
|
||||
io_sethandler(GRID_HIGH_ENABLE, 0x0001, grid_io_read, NULL, NULL, grid_io_write, NULL, NULL, dev);
|
||||
io_sethandler(GRID_EMS_PAGE_0, 0x0001, grid_io_read, NULL, NULL, grid_io_write, NULL, NULL, dev);
|
||||
io_sethandler(GRID_EMS_PAGE_1, 0x0001, grid_io_read, NULL, NULL, grid_io_write, NULL, NULL, dev);
|
||||
io_sethandler(GRID_EMS_PAGE_2, 0x0001, grid_io_read, NULL, NULL, grid_io_write, NULL, NULL, dev);
|
||||
io_sethandler(GRID_EMS_PAGE_3, 0x0001, grid_io_read, NULL, NULL, grid_io_write, NULL, NULL, dev);
|
||||
|
||||
dev->grid_high_enable = 1;
|
||||
for (uint8_t slot = 0; slot < 4; slot++) {
|
||||
dev->grid_ems_page[slot] = 0;
|
||||
mem_mapping_add(&dev->grid_ems_mapping[slot], GRID_EMS_BASE + (slot << GRID_EMS_PAGE_SHIFT), GRID_EMS_PAGE_SIZE, grid_ems_mem_read8, grid_ems_mem_read16, NULL,
|
||||
grid_ems_mem_write8, grid_ems_mem_write16, NULL, ram + GRID_EXTENDED_BASE + (slot << GRID_EMS_PAGE_SHIFT), MEM_MAPPING_EXTERNAL, dev);
|
||||
mem_mapping_disable(&dev->grid_ems_mapping[slot]);
|
||||
}
|
||||
flushmmucache();
|
||||
return dev;
|
||||
}
|
||||
|
||||
static void grid_close(void *priv) {
|
||||
grid_t *dev = (grid_t *) priv;
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
static void grid_reset(void *priv) {
|
||||
grid_t *dev = (grid_t *) priv;
|
||||
|
||||
dev->grid_high_enable = 1;
|
||||
mem_mapping_enable(&ram_high_mapping);
|
||||
dev->grid_turbo = 0x1;
|
||||
for (uint8_t slot = 0; slot < 4; slot++) {
|
||||
dev->grid_ems_page[slot] = 0;
|
||||
mem_mapping_disable(&dev->grid_ems_mapping[slot]);
|
||||
}
|
||||
flushmmucache();
|
||||
dev->grid_unknown = 0;
|
||||
dev->grid_unused_424 = 0;
|
||||
dev->grid_426 = 0;
|
||||
dev->grid_rom_enable = 0;
|
||||
dev->grid_rom_select = 0;
|
||||
}
|
||||
|
||||
const device_t grid1520_device = {
|
||||
.name = "GRiDcase 1520 chipset",
|
||||
.internal_name = "grid1520",
|
||||
.flags = 0,
|
||||
.local = 0,
|
||||
.init = grid_init,
|
||||
.close = grid_close,
|
||||
.reset = grid_reset,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
473
src/chipset/laserxt.c
Normal file
473
src/chipset/laserxt.c
Normal file
@@ -0,0 +1,473 @@
|
||||
/*
|
||||
* 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 VTech LaserXT chipset.
|
||||
*
|
||||
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Jasmine Iwanek, <jriwanek@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2025 Sarah Walker.
|
||||
* Copyright 2016-2025 Miran Grca.
|
||||
* Copyright 2017-2025 Fred N. van Kempen.
|
||||
* Copyright 2025 Jasmine Iwanek.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <86box/86box.h>
|
||||
#include "cpu.h"
|
||||
#include <86box/io.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/nmi.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/pit.h>
|
||||
#include <86box/rom.h>
|
||||
#include <86box/machine.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/fdd.h>
|
||||
#include <86box/fdc.h>
|
||||
#include <86box/fdc_ext.h>
|
||||
#include <86box/gameport.h>
|
||||
#include <86box/keyboard.h>
|
||||
#include <86box/plat_unused.h>
|
||||
|
||||
#define EMS_TOTAL_MAX 0x00100000
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t page;
|
||||
uint8_t ctrl;
|
||||
|
||||
uint32_t phys;
|
||||
uint32_t virt;
|
||||
|
||||
mem_mapping_t mapping;
|
||||
|
||||
uint8_t *ram;
|
||||
|
||||
void *parent;
|
||||
} lxt_ems_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int ems_base_idx;
|
||||
|
||||
lxt_ems_t ems[4];
|
||||
|
||||
uint16_t io_base;
|
||||
uint32_t base;
|
||||
|
||||
uint32_t mem_size;
|
||||
|
||||
uint8_t *ram;
|
||||
|
||||
void *parent;
|
||||
} lxt_ems_board_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int is_lxt3;
|
||||
|
||||
lxt_ems_board_t *ems_boards[2];
|
||||
} lxt_t;
|
||||
|
||||
static void
|
||||
ems_update_virt(lxt_ems_t *dev, uint8_t new_page)
|
||||
{
|
||||
lxt_ems_board_t *board = (lxt_ems_board_t *) dev->parent;
|
||||
lxt_t *lxt = (lxt_t *) board->parent;
|
||||
|
||||
dev->page = new_page;
|
||||
|
||||
if (new_page & 0x80) {
|
||||
if (lxt->is_lxt3) {
|
||||
/* Point invalid pages at 1 MB which is outside the maximum. */
|
||||
if ((new_page & 0x7f) >= 0x40)
|
||||
dev->virt = EMS_TOTAL_MAX;
|
||||
else
|
||||
dev->virt = ((new_page & 0x7f) << 14);
|
||||
} else
|
||||
dev->virt = ((new_page & 0x0f) << 14) + ((new_page & 0x40) << 12);
|
||||
|
||||
if (dev->virt >= board->mem_size)
|
||||
dev->virt = EMS_TOTAL_MAX;
|
||||
} else
|
||||
dev->virt = EMS_TOTAL_MAX;
|
||||
|
||||
dev->ram = board->ram + dev->virt;
|
||||
|
||||
if ((new_page & 0x80) && (dev->virt != EMS_TOTAL_MAX)) {
|
||||
mem_mapping_enable(&dev->mapping);
|
||||
|
||||
mem_mapping_set_exec(&dev->mapping, dev->ram);
|
||||
mem_mapping_set_p(&dev->mapping, dev->ram);
|
||||
} else
|
||||
mem_mapping_disable(&dev->mapping);
|
||||
|
||||
flushmmucache();
|
||||
}
|
||||
|
||||
static void
|
||||
lxt_ems_out(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
lxt_ems_board_t *dev = (lxt_ems_board_t *) priv;
|
||||
uint8_t reg = port >> 14;
|
||||
uint32_t saddrs[8] = { 0xc4000, 0xc8000, 0xcc000, 0xd0000,
|
||||
0xd4000, 0xd8000, 0xdc000, 0xe0000 };
|
||||
uint32_t saddr;
|
||||
|
||||
if (port & 0x0001) {
|
||||
dev->ems[reg].ctrl = val;
|
||||
|
||||
if (reg < 0x03) {
|
||||
dev->ems_base_idx = (dev->ems_base_idx & ~(0x04 >> (2 - reg))) |
|
||||
((dev->ems[reg].ctrl & 0x80) >> (7 - reg));
|
||||
|
||||
saddr = saddrs[dev->ems_base_idx];
|
||||
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
uint32_t base = saddr + (i * 0x4000);
|
||||
mem_mapping_set_addr(&dev->ems[i].mapping, base, 0x4000);
|
||||
if (!(dev->ems[i].page & 0x80) || (dev->ems[i].virt == EMS_TOTAL_MAX))
|
||||
mem_mapping_disable(&dev->ems[i].mapping);
|
||||
}
|
||||
}
|
||||
|
||||
flushmmucache();
|
||||
} else if (!(port & 0x0001)) {
|
||||
dev->ems[reg].page = val;
|
||||
ems_update_virt(&dev->ems[reg], val);
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
lxt_ems_in(uint16_t port, void *priv)
|
||||
{
|
||||
lxt_ems_board_t *dev = (lxt_ems_board_t *) priv;
|
||||
uint8_t reg = port >> 14;
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
if (port & 0x0001)
|
||||
ret = dev->ems[reg].ctrl;
|
||||
else
|
||||
ret = dev->ems[reg].page;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
lxt_ems_write(uint32_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
uint8_t *mem = (uint8_t *) priv;
|
||||
|
||||
mem[addr & 0x3fff] = val;
|
||||
}
|
||||
|
||||
static void
|
||||
lxt_ems_writew(uint32_t addr, uint16_t val, void *priv)
|
||||
{
|
||||
uint8_t *mem = (uint8_t *) priv;
|
||||
|
||||
*(uint16_t *) &(mem[addr & 0x3fff]) = val;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
lxt_ems_read(uint32_t addr, void *priv)
|
||||
{
|
||||
uint8_t *mem = (uint8_t *) priv;
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
ret = mem[addr & 0x3fff];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
lxt_ems_readw(uint32_t addr, void *priv)
|
||||
{
|
||||
uint8_t *mem = (uint8_t *) priv;
|
||||
uint16_t ret = 0xff;
|
||||
|
||||
ret = *(uint16_t *) &(mem[addr & 0x3fff]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static lxt_ems_board_t *
|
||||
lxt_ems_init(lxt_t *parent, int en, uint16_t io, uint32_t mem)
|
||||
{
|
||||
lxt_ems_board_t *dev = (lxt_ems_board_t *) calloc(1, sizeof(lxt_ems_board_t));
|
||||
|
||||
if (en) {
|
||||
dev->parent = parent;
|
||||
|
||||
if (io != 0x0000) {
|
||||
io_sethandler(io , 0x0002, lxt_ems_in, NULL, NULL, lxt_ems_out, NULL, NULL, dev);
|
||||
io_sethandler(io | 0x4000, 0x0002, lxt_ems_in, NULL, NULL, lxt_ems_out, NULL, NULL, dev);
|
||||
io_sethandler(io | 0x8000, 0x0002, lxt_ems_in, NULL, NULL, lxt_ems_out, NULL, NULL, dev);
|
||||
io_sethandler(io | 0xc000, 0x0002, lxt_ems_in, NULL, NULL, lxt_ems_out, NULL, NULL, dev);
|
||||
}
|
||||
|
||||
dev->ram = (uint8_t *) calloc(mem, sizeof(uint8_t));
|
||||
dev->mem_size = mem;
|
||||
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
uint8_t *ptr = dev->ram + (i << 14);
|
||||
|
||||
if (parent->is_lxt3)
|
||||
mem_mapping_add(&dev->ems[i].mapping, 0xe0000 + (i << 14), 0x4000,
|
||||
lxt_ems_read, lxt_ems_readw, NULL,
|
||||
lxt_ems_write, lxt_ems_writew, NULL,
|
||||
ptr, 0, ptr);
|
||||
else
|
||||
mem_mapping_add(&dev->ems[i].mapping, 0xe0000 + (i << 14), 0x4000,
|
||||
lxt_ems_read, NULL, NULL,
|
||||
lxt_ems_write, NULL, NULL,
|
||||
ptr, 0, ptr);
|
||||
|
||||
mem_mapping_disable(&dev->ems[i].mapping);
|
||||
|
||||
dev->ems[i].page = 0x7f;
|
||||
dev->ems[i].ctrl = (i == 3) ? 0x00 : 0x80;
|
||||
|
||||
dev->ems[i].parent = dev;
|
||||
|
||||
ems_update_virt(&(dev->ems[i]), dev->ems[i].page);
|
||||
}
|
||||
}
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
static void
|
||||
lxt_close(void *priv)
|
||||
{
|
||||
lxt_t *dev = (lxt_t *) priv;
|
||||
int ems_boards = (1 - dev->is_lxt3) + 1;
|
||||
|
||||
for (int i = 0; i < ems_boards; i++)
|
||||
if (dev->ems_boards[i] != NULL) {
|
||||
if (dev->ems_boards[i]->ram != NULL)
|
||||
free(dev->ems_boards[i]->ram);
|
||||
free(dev->ems_boards[i]);
|
||||
}
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
static void *
|
||||
lxt_init(const device_t *info)
|
||||
{
|
||||
lxt_t * dev = (lxt_t *) calloc(1, sizeof(lxt_t));
|
||||
int ems_boards = (1 - info->local) + 1;
|
||||
int ems_en[2] = { 0 };
|
||||
uint16_t ems_io[2] = { 0 };
|
||||
uint32_t ems_mem[2] = { 0 };
|
||||
char conf_str[512] = { 0 };
|
||||
|
||||
dev->is_lxt3 = info->local;
|
||||
|
||||
for (int i = 0; i < ems_boards; i++) {
|
||||
sprintf(conf_str, "ems_%i_enable", i + 1);
|
||||
ems_en[i] = device_get_config_int(conf_str);
|
||||
|
||||
sprintf(conf_str, "ems_%i_base", i + 1);
|
||||
ems_io[i] = device_get_config_hex16(conf_str);
|
||||
|
||||
sprintf(conf_str, "ems_%i_mem_size", i + 1);
|
||||
ems_mem[i] = device_get_config_int(conf_str) << 10;
|
||||
|
||||
dev->ems_boards[i] = lxt_ems_init(dev, ems_en[i], ems_io[i], ems_mem[i]);
|
||||
}
|
||||
|
||||
mem_set_mem_state(0x0c0000, 0x40000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
static const device_config_t laserxt_config[] = {
|
||||
{
|
||||
.name = "ems_1_base",
|
||||
.description = "EMS 1 Address",
|
||||
.type = CONFIG_HEX16,
|
||||
.default_string = NULL,
|
||||
.default_int = 0,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.selection = {
|
||||
{ .description = "Disabled", .value = 0 },
|
||||
{ .description = "0x208", .value = 0x208 },
|
||||
{ .description = "0x218", .value = 0x218 },
|
||||
{ .description = "0x258", .value = 0x258 },
|
||||
{ .description = "0x268", .value = 0x268 },
|
||||
{ .description = "0x2A8", .value = 0x2a8 },
|
||||
{ .description = "0x2B8", .value = 0x2b8 },
|
||||
{ .description = "0x2E8", .value = 0x2e8 },
|
||||
{ .description = "" }
|
||||
},
|
||||
.bios = { { 0 } }
|
||||
},
|
||||
{
|
||||
.name = "ems_2_base",
|
||||
.description = "EMS 2 Address",
|
||||
.type = CONFIG_HEX16,
|
||||
.default_string = NULL,
|
||||
.default_int = 0,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.selection = {
|
||||
{ .description = "Disabled", .value = 0 },
|
||||
{ .description = "0x208", .value = 0x208 },
|
||||
{ .description = "0x218", .value = 0x218 },
|
||||
{ .description = "0x258", .value = 0x258 },
|
||||
{ .description = "0x268", .value = 0x268 },
|
||||
{ .description = "0x2A8", .value = 0x2a8 },
|
||||
{ .description = "0x2B8", .value = 0x2b8 },
|
||||
{ .description = "0x2E8", .value = 0x2e8 },
|
||||
{ .description = "" }
|
||||
},
|
||||
.bios = { { 0 } }
|
||||
},
|
||||
{
|
||||
.name = "ems_1_mem_size",
|
||||
.description = "EMS 1 Memory Size",
|
||||
.type = CONFIG_SPINNER,
|
||||
.default_string = NULL,
|
||||
.default_int = 0,
|
||||
.file_filter = NULL,
|
||||
.spinner = {
|
||||
.min = 0,
|
||||
.max = 512,
|
||||
.step = 32
|
||||
},
|
||||
.selection = { { 0 } },
|
||||
.bios = { { 0 } }
|
||||
},
|
||||
{
|
||||
.name = "ems_2_mem_size",
|
||||
.description = "EMS 2 Memory Size",
|
||||
.type = CONFIG_SPINNER,
|
||||
.default_string = NULL,
|
||||
.default_int = 0,
|
||||
.file_filter = NULL,
|
||||
.spinner = {
|
||||
.min = 0,
|
||||
.max = 512,
|
||||
.step = 32
|
||||
},
|
||||
.selection = { { 0 } },
|
||||
.bios = { { 0 } }
|
||||
},
|
||||
{
|
||||
.name = "ems_1_enable",
|
||||
.description = "Enable EMS 1",
|
||||
.type = CONFIG_BINARY,
|
||||
.default_string = NULL,
|
||||
.default_int = 0,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.selection = { { 0 } },
|
||||
.bios = { { 0 } }
|
||||
},
|
||||
{
|
||||
.name = "ems_2_enable",
|
||||
.description = "Enable EMS 2",
|
||||
.type = CONFIG_BINARY,
|
||||
.default_string = NULL,
|
||||
.default_int = 0,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.selection = { { 0 } },
|
||||
.bios = { { 0 } }
|
||||
},
|
||||
{ .name = "", .description = "", .type = CONFIG_END }
|
||||
};
|
||||
|
||||
const device_t laserxt_device = {
|
||||
.name = "VTech Laser Turbo XT",
|
||||
.internal_name = "laserxt",
|
||||
.flags = 0,
|
||||
.local = 0,
|
||||
.init = lxt_init,
|
||||
.close = lxt_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = laserxt_config
|
||||
};
|
||||
|
||||
static const device_config_t lxt3_config[] = {
|
||||
{
|
||||
.name = "ems_1_base",
|
||||
.description = "EMS Address",
|
||||
.type = CONFIG_HEX16,
|
||||
.default_string = NULL,
|
||||
.default_int = 0,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.selection = {
|
||||
{ .description = "Disabled", .value = 0 },
|
||||
{ .description = "0x208", .value = 0x208 },
|
||||
{ .description = "0x218", .value = 0x218 },
|
||||
{ .description = "0x258", .value = 0x258 },
|
||||
{ .description = "0x268", .value = 0x268 },
|
||||
{ .description = "0x2A8", .value = 0x2a8 },
|
||||
{ .description = "0x2B8", .value = 0x2b8 },
|
||||
{ .description = "0x2E8", .value = 0x2e8 },
|
||||
{ .description = "" }
|
||||
},
|
||||
.bios = { { 0 } }
|
||||
},
|
||||
{
|
||||
.name = "ems_1_mem_size",
|
||||
.description = "EMS Memory Size",
|
||||
.type = CONFIG_SPINNER,
|
||||
.default_string = NULL,
|
||||
.default_int = 0,
|
||||
.file_filter = NULL,
|
||||
.spinner = {
|
||||
.min = 0,
|
||||
.max = 1024,
|
||||
.step = 32
|
||||
},
|
||||
.selection = { { 0 } },
|
||||
.bios = { { 0 } }
|
||||
},
|
||||
{
|
||||
.name = "ems_1_enable",
|
||||
.description = "Enable EMS",
|
||||
.type = CONFIG_BINARY,
|
||||
.default_string = NULL,
|
||||
.default_int = 0,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.selection = { { 0 } },
|
||||
.bios = { { 0 } }
|
||||
},
|
||||
{ .name = "", .description = "", .type = CONFIG_END }
|
||||
};
|
||||
|
||||
const device_t lxt3_device = {
|
||||
.name = "VTech Laser Turbo XT",
|
||||
.internal_name = "laserxt",
|
||||
.flags = 0,
|
||||
.local = 1,
|
||||
.init = lxt_init,
|
||||
.close = lxt_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = lxt3_config
|
||||
};
|
||||
148
src/chipset/philips.c
Normal file
148
src/chipset/philips.c
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* 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 the Philips XT-compatible machines.
|
||||
*
|
||||
* Authors: EngiNerd <webmaster.crrc@yahoo.it>
|
||||
*
|
||||
* Copyright 2020-2025 EngiNerd.
|
||||
*/
|
||||
#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 <86box/nmi.h>
|
||||
#include "cpu.h"
|
||||
#include <86box/timer.h>
|
||||
#include <86box/pit.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/fdd.h>
|
||||
#include <86box/fdc.h>
|
||||
#include <86box/fdc_ext.h>
|
||||
#include <86box/hdc.h>
|
||||
#include <86box/gameport.h>
|
||||
#include <86box/ibm_5161.h>
|
||||
#include <86box/keyboard.h>
|
||||
#include <86box/rom.h>
|
||||
#include <86box/machine.h>
|
||||
#include <86box/chipset.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/video.h>
|
||||
#include <86box/plat_unused.h>
|
||||
|
||||
typedef struct philips_t {
|
||||
uint8_t reg;
|
||||
} philips_t;
|
||||
|
||||
#ifdef ENABLE_PHILIPS_LOG
|
||||
int philips_do_log = ENABLE_PHILIPS_LOG;
|
||||
static void
|
||||
philips_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (philips_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
# define philips_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
static void
|
||||
philips_write(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
philips_t *dev = (philips_t *) priv;
|
||||
|
||||
switch (port) {
|
||||
/* port 0xc0
|
||||
* bit 7: turbo
|
||||
* bits 4-5: rtc read/set (I2C Bus SDA/SCL?)
|
||||
* bit 2: parity disabled
|
||||
*/
|
||||
case 0xc0:
|
||||
dev->reg = val;
|
||||
if (val & 0x80)
|
||||
cpu_dynamic_switch(cpu);
|
||||
else
|
||||
cpu_dynamic_switch(0);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
philips_log("Philips XT Mainboard: Write %02x at %02x\n", val, port);
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
philips_read(uint16_t port, void *priv)
|
||||
{
|
||||
const philips_t *dev = (philips_t *) priv;
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
switch (port) {
|
||||
/* port 0xc0
|
||||
* bit 7: turbo
|
||||
* bits 4-5: rtc read/set
|
||||
* bit 2: parity disabled
|
||||
*/
|
||||
case 0xc0:
|
||||
ret = dev->reg;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
philips_log("Philips XT Mainboard: Read %02x at %02x\n", ret, port);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
philips_close(void *priv)
|
||||
{
|
||||
philips_t *dev = (philips_t *) priv;
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
static void *
|
||||
philips_init(UNUSED(const device_t *info))
|
||||
{
|
||||
philips_t *dev = (philips_t *) malloc(sizeof(philips_t));
|
||||
memset(dev, 0, sizeof(philips_t));
|
||||
|
||||
dev->reg = 0x40;
|
||||
|
||||
io_sethandler(0x0c0, 0x01, philips_read, NULL, NULL, philips_write, NULL, NULL, dev);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
const device_t philips_device = {
|
||||
.name = "Philips XT Mainboard",
|
||||
.internal_name = "philips",
|
||||
.flags = 0,
|
||||
.local = 0,
|
||||
.init = philips_init,
|
||||
.close = philips_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
Reference in New Issue
Block a user