diff --git a/src/chipset/CMakeLists.txt b/src/chipset/CMakeLists.txt index 0406ea0b8..4daccd2d8 100644 --- a/src/chipset/CMakeLists.txt +++ b/src/chipset/CMakeLists.txt @@ -14,7 +14,7 @@ # add_library(chipset OBJECT 82c100.c acc2168.c cs8230.c ali1429.c ali1435.c ali1489.c - ali1531.c ali1541.c ali1543.c ali1621.c ali6117.c headland.c ims8848.c intel_82335.c + ali1531.c ali1541.c ali1543.c ali1621.c ali6117.c ali1409.c headland.c ims8848.c intel_82335.c compaq_386.c contaq_82c59x.c cs4031.c intel_420ex.c intel_4x0.c intel_i450kx.c intel_sio.c intel_piix.c ../ioapic.c neat.c opti283.c opti291.c opti391.c opti495.c opti602.c opti822.c opti895.c opti5x7.c scamp.c scat.c sis_85c310.c sis_85c4xx.c diff --git a/src/chipset/ali1409.c b/src/chipset/ali1409.c new file mode 100644 index 000000000..3e4286f80 --- /dev/null +++ b/src/chipset/ali1409.c @@ -0,0 +1,199 @@ +/* + * 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 ALi M1409 chipset. + * + * Note: This chipset has no datasheet, everything were done via + * reverse engineering. + * + * + * + * Authors: Jose Phillips, + * Sarah Walker, + * + * Copyright 2024 Jose Phillips. + * Copyright 2008-2018 Sarah Walker. + */ + + +#include +#include +#include +#include +#include +#include +#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/apm.h> +#include <86box/mem.h> +#include <86box/fdd.h> +#include <86box/fdc.h> +#include <86box/smram.h> +#include <86box/chipset.h> + + + +#ifdef ENABLE_ALI1409_LOG +int ali1409_do_log = ENABLE_ALI1409_LOG; + +static void +ali1409_log(const char *fmt, ...) +{ + va_list ap; + + if (ali1409_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define ali1409_log(fmt, ...) +#endif + +typedef struct ali_1409_t { + uint8_t is_g; + uint8_t index; + uint8_t cfg_locked; + uint8_t reg_57h; + uint8_t regs[256]; + uint8_t last_reg; +} ali1409_t; + + +static void +ali1409_write(uint16_t addr, uint8_t val, void *priv) +{ + ali1409_t *dev = (ali1409_t *) priv; + ali1409_log ("INPUT:addr %02x ,Value %02x \n" , addr , val); + + if (addr & 1) { + if (dev->cfg_locked) { + if (dev->last_reg == 0x14 && val == 0x09) + dev->cfg_locked = 0; + + dev->last_reg = val; + return; + } + + if (dev->index == 0xff && val == 0xff) + dev->cfg_locked = 1; + else { + ali1409_log("Write reg %02x %02x %08x\n", dev->index, val, cs); + dev->regs[dev->index] = val; + + switch (dev->index) { + case 0xa: + switch ((val >> 4) & 3) { + case 0: + mem_set_mem_state(0xe0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + break; + case 1: + mem_set_mem_state(0xe0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL); + break; + case 2: + mem_set_mem_state(0xe0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); + break; + case 3: + mem_set_mem_state(0xe0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + } + break; + case 0xb: + switch ((val >> 4) & 3) { + case 0: + mem_set_mem_state(0xf0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); + break; + case 1: + mem_set_mem_state(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_EXTANY); + break; + case 2: + mem_set_mem_state(0xf0000, 0x10000, MEM_READ_EXTANY| MEM_WRITE_INTERNAL); + break; + case 3: + mem_set_mem_state(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + break; + } + break; + } + } + } else + dev->index = val; +} + + +static uint8_t +ali1409_read(uint16_t addr, void *priv) +{ + ali1409_log ("reading at %02X\n",addr); + const ali1409_t *dev = (ali1409_t *) priv; + uint8_t ret = 0xff; + + if (dev->cfg_locked) + ret = 0xff; + if (addr & 1) { + if ((dev->index >= 0xc0 || dev->index == 0x20) && cpu_iscyrix) + ret = 0xff; + ret = dev->regs[dev->index]; + } else + ret = dev->index; + return ret; +} + + + +static void +ali1409_close(void *priv) +{ + ali1409_t *dev = (ali1409_t *) priv; + + free(dev); +} + +static void * +ali1409_init(const device_t *info) +{ + ali1409_t *dev = (ali1409_t *) malloc(sizeof(ali1409_t)); + memset(dev, 0, sizeof(ali1409_t)); + + dev->cfg_locked = 1; + + /* M1409 Ports: + 22h Index Port + 23h Data Port + */ + + ali1409_log ("Bus speed: %i",cpu_busspeed); + + + io_sethandler(0x0022, 0x0002, ali1409_read, NULL, NULL, ali1409_write, NULL, NULL, dev); + io_sethandler(0x037f, 0x0001, ali1409_read, NULL, NULL, ali1409_write, NULL, NULL, dev); + io_sethandler(0x03f3, 0x0001, ali1409_read, NULL, NULL, ali1409_write, NULL, NULL, dev); + + return dev; +} + +const device_t ali1409_device = { + .name = "ALi M1409", + .internal_name = "ali1409", + .flags = 0, + .local = 0, + .init = ali1409_init, + .close = ali1409_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + diff --git a/src/include/86box/chipset.h b/src/include/86box/chipset.h index d5a96baf9..4be7c2ae2 100644 --- a/src/include/86box/chipset.h +++ b/src/include/86box/chipset.h @@ -24,6 +24,7 @@ extern const device_t acc2168_device; extern const device_t ali1217_device; extern const device_t ali1429_device; extern const device_t ali1429g_device; +extern const device_t ali1409_device; extern const device_t ali1435_device; extern const device_t ali1489_device; extern const device_t ali1531_device; diff --git a/src/include/86box/machine.h b/src/include/86box/machine.h index a5b922358..7ff00ed52 100644 --- a/src/include/86box/machine.h +++ b/src/include/86box/machine.h @@ -481,6 +481,7 @@ extern int machine_at_325ax_init(const machine_t *); extern int machine_at_mr1217_init(const machine_t *); extern int machine_at_pja511m_init(const machine_t *); extern int machine_at_prox1332_init(const machine_t *); +extern int machine_at_acer100t_init(const machine_t *); extern int machine_at_awardsx_init(const machine_t *); diff --git a/src/include/86box/video.h b/src/include/86box/video.h index 83930122b..ed7064f9c 100644 --- a/src/include/86box/video.h +++ b/src/include/86box/video.h @@ -453,6 +453,7 @@ extern const device_t oti037c_device; extern const device_t oti067_device; extern const device_t oti067_acer386_device; extern const device_t oti067_ama932j_device; +extern const device_t oti077_acer100t_device; extern const device_t oti077_device; /* Paradise/WD (S)VGA */ diff --git a/src/machine/m_at_286_386sx.c b/src/machine/m_at_286_386sx.c index b2470bae2..a1c3d7772 100644 --- a/src/machine/m_at_286_386sx.c +++ b/src/machine/m_at_286_386sx.c @@ -705,6 +705,31 @@ machine_at_awardsx_init(const machine_t *model) return ret; } +int +machine_at_acer100t_init(const machine_t *model) +{ + int ret; + + ret = bios_load_linear("roms/machines/acer100t/acer386.bin", + 0x000f0000, 65536, 0); + + if (bios_only || !ret) + return ret; + + machine_at_ps2_ide_init(model); + + if (fdc_type == FDC_INTERNAL) + device_add(&fdc_at_device); + + device_add(&ali1409_device); + if (gfxcard[0] == VID_INTERNAL) + device_add(&oti077_acer100t_device); + + + return ret; +} + + int machine_at_arb1374_init(const machine_t *model) { diff --git a/src/machine/machine_table.c b/src/machine/machine_table.c index 69a87e325..f97fab901 100644 --- a/src/machine/machine_table.c +++ b/src/machine/machine_table.c @@ -4168,6 +4168,46 @@ const machine_t machines[] = { .vid_device = NULL, .snd_device = NULL, .net_device = NULL + }, + { + .name = "[ALI M1409] Acer 100T", + .internal_name = "acer100t", + .type = MACHINE_TYPE_386SX, + .chipset = MACHINE_CHIPSET_ALI_M1409, + .init = machine_at_acer100t_init, + .p1_handler = NULL, + .gpio_handler = NULL, + .available_flag = MACHINE_AVAILABLE, + .gpio_acpi_handler = NULL, + .cpu = { + .package = CPU_PKG_386SX, + .block = CPU_BLOCK_NONE, + .min_bus = 16000000, + .max_bus = 25000000, /* Limited to 25 due a inaccurate cpu speed */ + .min_voltage = 0, + .max_voltage = 0, + .min_multi = 0, + .max_multi = 0, + + }, + .bus_flags = MACHINE_PS2_PCI, + .flags = MACHINE_IDE | MACHINE_VIDEO , /* Machine has internal OTI 077 Video card*/ + .ram = { + .min = 2048, + .max = 16256, + .step = 128 + }, + .nvrmask = 127, + .kbc_device = NULL, + .kbc_p1 = 0xff, + .gpio = 0xffffffff, + .gpio_acpi = 0xffffffff, + .device = NULL, + .fdc_device = NULL, + .sio_device = NULL, + .vid_device = &oti077_acer100t_device, + .snd_device = NULL, + .net_device = NULL }, /* Has IBM PS/2 Type 1 KBC firmware. */ { diff --git a/src/video/vid_oak_oti.c b/src/video/vid_oak_oti.c index f5bc449e6..f21e9d66c 100644 --- a/src/video/vid_oak_oti.c +++ b/src/video/vid_oak_oti.c @@ -36,13 +36,16 @@ #define BIOS_067_M300_08_PATH "roms/machines/m30008/EVC_BIOS.ROM" #define BIOS_067_M300_15_PATH "roms/machines/m30015/EVC_BIOS.ROM" #define BIOS_077_PATH "roms/video/oti/oti077.vbi" +#define BIOS_077_ACER100T_PATH "roms/machines/acer100t/oti077_acer100t.BIN" + enum { OTI_037C = 0, OTI_067 = 2, OTI_067_AMA932J = 3, OTI_067_M300 = 4, - OTI_077 = 5 + OTI_077 = 5, + OTI_077_ACER100T = 6 }; typedef struct { @@ -92,7 +95,7 @@ oti_out(uint16_t addr, uint8_t val, void *priv) case 0x3c7: case 0x3c8: case 0x3c9: - if (oti->chip_id == OTI_077) + if (oti->chip_id == OTI_077 || oti->chip_id == OTI_077_ACER100T) sc1148x_ramdac_out(addr, 0, val, svga->ramdac, svga); else svga_out(addr, val, svga); @@ -153,7 +156,7 @@ oti_out(uint16_t addr, uint8_t val, void *priv) mem_mapping_disable(&svga->mapping); else mem_mapping_enable(&svga->mapping); - } else if (oti->chip_id == OTI_077) { + } else if (oti->chip_id == OTI_077 || oti->chip_id == OTI_077_ACER100T) { svga->vram_display_mask = (val & 0x0c) ? oti->vram_mask : 0x3ffff; switch ((val & 0xc0) >> 6) { @@ -238,7 +241,7 @@ oti_in(uint16_t addr, void *priv) case 0x3c7: case 0x3c8: case 0x3c9: - if (oti->chip_id == OTI_077) + if (oti->chip_id == OTI_077 || oti->chip_id == OTI_077_ACER100T) return sc1148x_ramdac_in(addr, 0, svga->ramdac, svga); return svga_in(addr, svga); @@ -464,6 +467,12 @@ oti_init(const device_t *info) oti->pos = 0x08; /* Tell the BIOS the I/O ports are already enabled to avoid a double I/O handler mess. */ io_sethandler(0x46e8, 1, oti_pos_in, NULL, NULL, oti_pos_out, NULL, NULL, oti); break; + case OTI_077_ACER100T: + romfn = BIOS_077_ACER100T_PATH; + oti->vram_size = device_get_config_int("memory"); + oti->pos = 0x08; /* Tell the BIOS the I/O ports are already enabled to avoid a double I/O handler mess. */ + io_sethandler(0x46e8, 1, oti_pos_in, NULL, NULL, oti_pos_out, NULL, NULL, oti); + break; default: break; @@ -476,12 +485,19 @@ oti_init(const device_t *info) oti->vram_mask = (oti->vram_size << 10) - 1; - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_oti); + if (oti->chip_id == OTI_077_ACER100T){ + /* josephillips: Required to show all BIOS + information on Acer 100T only + */ + video_inform(0x1,&timing_oti); + }else{ + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_oti); + } svga_init(info, &oti->svga, oti, oti->vram_size << 10, oti_recalctimings, oti_in, oti_out, NULL, NULL); - if (oti->chip_id == OTI_077) + if (oti->chip_id == OTI_077 || oti->chip_id == OTI_077_ACER100T) oti->svga.ramdac = device_add(&sc11487_ramdac_device); /*Actually a 82c487, probably a clone.*/ io_sethandler(0x03c0, 32, @@ -489,7 +505,7 @@ oti_init(const device_t *info) oti->svga.miscout = 1; oti->svga.packed_chain4 = 1; - + return oti; } @@ -531,6 +547,12 @@ oti067_ama932j_available(void) return (rom_present(BIOS_067_AMA932J_PATH)); } +static int +oti077_acer100t_available(void) +{ + return (rom_present(BIOS_077_ACER100T_PATH)); +} + static int oti067_077_available(void) { @@ -597,6 +619,35 @@ static const device_config_t oti067_ama932j_config[] = { } }; +static const device_config_t oti077_acer100t_config[] = { + { + .name = "memory", + .description = "Memory size", + .type = CONFIG_SELECTION, + .default_int = 512, + .selection = { + { + .description = "256 kB", + .value = 256 + }, + { + .description = "512 kB", + .value = 512 + }, + { + .description = "1 MB", + .value = 1024 + }, + { + .description = "" + } + } + }, + { + .type = CONFIG_END + } +}; + static const device_config_t oti077_config[] = { { .name = "memory", @@ -683,6 +734,21 @@ const device_t oti067_ama932j_device = { .config = oti067_ama932j_config }; +const device_t oti077_acer100t_device = { + .name = "Oak OTI-077 (Acer 100T)", + .internal_name = "oti077_acer100t", + .flags = DEVICE_ISA, + .local = 6, + .init = oti_init, + .close = oti_close, + .reset = NULL, + { .available = oti077_acer100t_available }, + .speed_changed = oti_speed_changed, + .force_redraw = oti_force_redraw, + .config = oti077_acer100t_config +}; + + const device_t oti077_device = { .name = "Oak OTI-077", .internal_name = "oti077",