Merge remote-tracking branch 'upstream/master' into feature/ich2

This commit is contained in:
Jasmine Iwanek
2024-02-22 18:48:16 -05:00
277 changed files with 24707 additions and 8812 deletions

View File

@@ -16,6 +16,8 @@ on:
jobs:
msys2:
# Negative condition disables the job
if: false
name: "Win32 GUI, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, ${{ matrix.environment.msystem }}"
runs-on: windows-2022
@@ -92,7 +94,6 @@ jobs:
rtmidi:p
libslirp:p
fluidsynth:p
libvncserver:p
- name: Checkout repository
uses: actions/checkout@v4

View File

@@ -80,7 +80,6 @@ jobs:
libopenal-dev
libslirp-dev
libfluidsynth-dev
libvncserver-dev
${{ matrix.ui.packages }}
- name: Checkout repository

View File

@@ -82,7 +82,6 @@ jobs:
rtmidi
openal-soft
fluidsynth
libvncserver
${{ matrix.ui.packages }}
- name: Checkout repository

View File

@@ -57,9 +57,6 @@ jobs:
new: on
slug: -NDR
ui:
- name: Win32 GUI
qt: off
static: on
- name: Qt GUI
qt: on
static: on
@@ -107,7 +104,6 @@ jobs:
rtmidi:p
libslirp:p
fluidsynth:p
libvncserver:p
${{ matrix.ui.packages }}
- name: Checkout repository

View File

@@ -83,7 +83,6 @@ jobs:
libopenal-dev
libslirp-dev
libfluidsynth-dev
libvncserver-dev
${{ matrix.ui.packages }}
- name: Checkout repository

View File

@@ -76,7 +76,6 @@ jobs:
rtmidi
openal-soft
fluidsynth
libvncserver
${{ matrix.ui.packages }}
- name: Checkout repository

View File

@@ -110,7 +110,6 @@ jobs:
rtmidi:p
libslirp:p
fluidsynth:p
libvncserver:p
${{ matrix.ui.packages }}
- name: Checkout repository

View File

@@ -155,6 +155,7 @@ cmake_dependent_option(ISAMEM_BRAT "BocaRAM/AT"
cmake_dependent_option(LASERXT "VTech Laser XT" ON "DEV_BRANCH" OFF)
cmake_dependent_option(OLIVETTI "Olivetti M290" ON "DEV_BRANCH" OFF)
cmake_dependent_option(OPEN_AT "OpenAT" ON "DEV_BRANCH" OFF)
cmake_dependent_option(OPL4ML "OPL4-ML daughterboard" ON "DEV_BRANCH" OFF)
cmake_dependent_option(PAS16 "Pro Audio Spectrum 16" ON "DEV_BRANCH" OFF)
cmake_dependent_option(SIO_DETECT "Super I/O Detection Helper" ON "DEV_BRANCH" OFF)
cmake_dependent_option(VGAWONDER "ATI VGA Wonder (ATI-18800)" ON "DEV_BRANCH" OFF)

View File

@@ -30,10 +30,10 @@
#include <time.h>
#include <wchar.h>
#include <stdatomic.h>
#include <unistd.h>
#ifndef _WIN32
# include <pwd.h>
# include <unistd.h>
#endif
#ifdef __APPLE__
# include <string.h>
@@ -1048,6 +1048,7 @@ pc_send_ca(uint16_t sc)
keyboard_input(1, 0x1D); /* Ctrl key pressed */
keyboard_input(1, 0x38); /* Alt key pressed */
keyboard_input(1, sc);
usleep(50000);
keyboard_input(0, sc);
keyboard_input(0, 0x38); /* Alt key released */
keyboard_input(0, 0x1D); /* Ctrl key released */

File diff suppressed because it is too large Load Diff

View File

@@ -442,7 +442,7 @@ cdrom_audio_callback(cdrom_t *dev, int16_t *output, int len)
{
int ret = 1;
if (!dev->sound_on || (dev->cd_status != CD_STATUS_PLAYING)) {
if (!dev->sound_on || (dev->cd_status != CD_STATUS_PLAYING) || dev->audio_muted_soft) {
cdrom_log("CD-ROM %i: Audio callback while not playing\n", dev->id);
if (dev->cd_status == CD_STATUS_PLAYING)
dev->seek_pos += (len >> 11);
@@ -557,6 +557,7 @@ cdrom_audio_play(cdrom_t *dev, uint32_t pos, uint32_t len, int ismsf)
len += pos;
}
dev->audio_muted_soft = 0;
/* Do this at this point, since it's at this point that we know the
actual LBA position to start playing from. */
if (!(dev->ops->track_type(dev, pos) & CD_TRACK_AUDIO)) {
@@ -578,6 +579,7 @@ cdrom_audio_track_search(cdrom_t *dev, uint32_t pos, int type, uint8_t playbit)
int m = 0;
int s = 0;
int f = 0;
uint32_t pos2 = 0;
if (dev->cd_status == CD_STATUS_DATA_ONLY)
return 0;
@@ -614,14 +616,21 @@ cdrom_audio_track_search(cdrom_t *dev, uint32_t pos, int type, uint8_t playbit)
break;
}
pos2 = pos - 1;
if (pos2 == 0xffffffff)
pos2 = pos + 1;
/* Do this at this point, since it's at this point that we know the
actual LBA position to start playing from. */
if (!(dev->ops->track_type(dev, pos) & CD_TRACK_AUDIO)) {
cdrom_log("CD-ROM %i: LBA %08X not on an audio track\n", dev->id, pos);
cdrom_stop(dev);
return 0;
}
if (!(dev->ops->track_type(dev, pos2) & CD_TRACK_AUDIO)) {
cdrom_log("CD-ROM %i: Track Search: LBA %08X not on an audio track\n", dev->id, pos);
dev->audio_muted_soft = 1;
if (dev->ops->track_type(dev, pos) & CD_TRACK_AUDIO)
dev->audio_muted_soft = 0;
} else
dev->audio_muted_soft = 0;
cdrom_log("Track Search Toshiba: Muted?=%d, LBA=%08X.\n", dev->audio_muted_soft, pos);
dev->cd_buflen = 0;
dev->cd_status = playbit ? CD_STATUS_PLAYING : CD_STATUS_PAUSED;
return 1;
@@ -647,6 +656,7 @@ cdrom_audio_track_search_pioneer(cdrom_t *dev, uint32_t pos, uint8_t playbit)
dev->seek_pos = pos;
dev->audio_muted_soft = 0;
/* Do this at this point, since it's at this point that we know the
actual LBA position to start playing from. */
if (!(dev->ops->track_type(dev, pos) & CD_TRACK_AUDIO)) {
@@ -676,6 +686,7 @@ cdrom_audio_play_pioneer(cdrom_t *dev, uint32_t pos)
pos = MSFtoLBA(m, s, f) - 150;
dev->cd_end = pos;
dev->audio_muted_soft = 0;
dev->cd_buflen = 0;
dev->cd_status = CD_STATUS_PLAYING;
return 1;
@@ -717,16 +728,7 @@ cdrom_audio_play_toshiba(cdrom_t *dev, uint32_t pos, int type)
break;
}
cdrom_log("Toshiba/NEC Play Audio: MSF = %06x, type = %02x, cdstatus = %02x\n", pos, type, dev->cd_status);
/* Do this at this point, since it's at this point that we know the
actual LBA position to start playing from. */
if (!(dev->ops->track_type(dev, pos) & CD_TRACK_AUDIO)) {
cdrom_log("CD-ROM %i: LBA %08X not on an audio track\n", dev->id, pos);
cdrom_stop(dev);
return 0;
}
cdrom_log("Toshiba Play Audio: Muted?=%d, LBA=%08X.\n", dev->audio_muted_soft, pos);
dev->cd_buflen = 0;
dev->cd_status = CD_STATUS_PLAYING;
return 1;
@@ -770,6 +772,7 @@ cdrom_audio_scan(cdrom_t *dev, uint32_t pos, int type)
break;
}
dev->audio_muted_soft = 0;
/* Do this at this point, since it's at this point that we know the
actual LBA position to start playing from. */
if (!(dev->ops->track_type(dev, pos) & CD_TRACK_AUDIO)) {
@@ -1007,6 +1010,11 @@ cdrom_get_current_subcodeq_playstatus(cdrom_t *dev, uint8_t *b)
else
ret = (dev->cd_status == CD_STATUS_PLAYING) ? 0x00 : dev->audio_op;
/*If a valid audio track is detected with audio on, unmute it.*/
if (dev->ops->track_type(dev, dev->seek_pos) & CD_TRACK_AUDIO)
dev->audio_muted_soft = 0;
cdrom_log("SubCodeQ: Play Status: Seek LBA=%08x, CDEND=%08x, mute=%d.\n", dev->seek_pos, dev->cd_end, dev->audio_muted_soft);
b[0] = subc.attr;
b[1] = bin2bcd(subc.track);
b[2] = bin2bcd(subc.index);
@@ -1952,8 +1960,18 @@ cdrom_hard_reset(void)
dev->cd_status = CD_STATUS_EMPTY;
if (dev->host_drive == 200)
if (dev->host_drive == 200) {
#ifdef _WIN32
if ((strlen(dev->image_path) >= 1) && (dev->image_path[strlen(dev->image_path) - 1] == '/'))
dev->image_path[strlen(dev->image_path) - 1] = '\\';
#else
if ((strlen(dev->image_path) >= 1) &&
(dev->image_path[strlen(dev->image_path) - 1] == '\\'))
dev->image_path[strlen(dev->image_path) - 1] = '/';
#endif
cdrom_image_open(dev, dev->image_path);
}
}
}
@@ -2042,6 +2060,15 @@ cdrom_reload(uint8_t id)
if (dev->prev_host_drive == 200) {
/* Reload a previous image. */
strcpy(dev->image_path, dev->prev_image_path);
#ifdef _WIN32
if ((strlen(dev->image_path) >= 1) && (dev->image_path[strlen(dev->image_path) - 1] == '/'))
dev->image_path[strlen(dev->image_path) - 1] = '\\';
#else
if ((strlen(dev->image_path) >= 1) && (dev->image_path[strlen(dev->image_path) - 1] == '\\'))
dev->image_path[strlen(dev->image_path) - 1] = '/';
#endif
cdrom_image_open(dev, dev->image_path);
cdrom_insert(id);

View File

@@ -18,9 +18,11 @@ add_library(chipset OBJECT 82c100.c acc2168.c cs8230.c ali1429.c ali1435.c ali14
compaq_386.c contaq_82c59x.c cs4031.c intel_420ex.c intel_4x0.c intel_i450kx.c
intel_815ep.c intel_ich2.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
sis_85c496.c sis_85c50x.c sis_5511.c sis_5571.c via_vt82c49x.c via_vt82c505.c
gc100.c stpc.c umc_8886.c umc_hb4.c
via_apollo.c via_pipc.c vl82c480.c wd76c10.c)
sis_85c496.c sis_85c50x.c sis_5511.c sis_5571.c sis_5581.c sis_5591.c sis_5600.c
sis_5511_h2p.c sis_5571_h2p.c sis_5581_h2p.c sis_5591_h2p.c sis_5600_h2p.c
sis_5513_p2i.c sis_5513_ide.c sis_5572_usb.c sis_5595_pmu.c sis_55xx.c via_vt82c49x.c
via_vt82c505.c sis_85c310.c sis_85c4xx.c sis_85c496.c sis_85c50x.c gc100.c stpc.c
umc_8886.c umc_hb4.c umc_8890.c via_apollo.c via_pipc.c vl82c480.c wd76c10.c)
if(OLIVETTI)
target_sources(chipset PRIVATE olivetti_eva.c)

View File

@@ -311,8 +311,10 @@ contaq_82c59x_close(void *priv)
{
contaq_82c59x_t *dev = (contaq_82c59x_t *) priv;
smram_del(dev->smram[1]);
smram_del(dev->smram[0]);
if (dev->green) {
smram_del(dev->smram[1]);
smram_del(dev->smram[0]);
}
free(dev);
}

View File

@@ -1522,6 +1522,8 @@ i4x0_read(int func, int addr, void *priv)
with the addition of bits 3 and 0. */
if ((func == 0) && (addr == 0x93) && ((dev->type == INTEL_440FX) || (dev->type == INTEL_440LX) || (dev->type == INTEL_440EX)))
ret = (ret & 0xf9) | (pci_read(0x0cf9, NULL) & 0x06);
else if ((func == 0) && (addr == 0x52) && (dev->type == INTEL_430TX) && !strcmp(machine_get_internal_name(), "tomahawk"))
ret = 0xb2;
}
return ret;

View File

@@ -8,19 +8,14 @@
*
* Implementation of the Intel 450KX Mars Chipset.
*
* i450GX is way more popular of an option but needs more stuff.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Tiseno100,
*
* Authors: Tiseno100
*
* Copyright 2021-2024 Miran Grca.
* Copyright 2021 Tiseno100.
*/
/*
Note: i450KX PB manages PCI memory access with MC manages DRAM memory access.
Due to 86Box limitations we can't manage them seperately thus it is dev branch till then.
i450GX is way more popular of an option but needs more stuff.
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
@@ -97,17 +92,18 @@ i450kx_smram_recalc(i450kx_t *dev, int bus)
const uint8_t *regs = bus ? dev->pb_pci_conf : dev->mc_pci_conf;
uint32_t addr;
uint32_t size;
int enable = bus ? !(regs[0x57] & 0x08) : (regs[0x57] & 0x08);
smram_disable(dev->smram[bus]);
addr = ((uint32_t) regs[0xb8] << 16) | ((uint32_t) regs[0xb9] << 24);
size = (((uint32_t) ((regs[0xbb] >> 4) & 0x0f)) << 16) + 0x00010000;
if ((addr != 0x00000000) && !!(regs[0x57] & 0x08)) {
if ((addr != 0x00000000) && enable) {
if (bus)
smram_enable_ex(dev->smram[bus], addr, addr, size, 0, !!(regs[0x57] & 8), 0, 1);
smram_enable_ex(dev->smram[bus], addr, addr, size, 0, 0, 0, enable);
else
smram_enable_ex(dev->smram[bus], addr, addr, size, !!(regs[0x57] & 8), 0, 1, 0);
smram_enable_ex(dev->smram[bus], addr, addr, size, 0, 0, enable, 0);
}
flushmmucache();
@@ -118,10 +114,8 @@ i450kx_vid_buf_recalc(i450kx_t *dev, int bus)
{
const uint8_t *regs = bus ? dev->pb_pci_conf : dev->mc_pci_conf;
#if 0
// int state = (regs[0x58] & 0x02) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_DISABLED | MEM_WRITE_DISABLED);
#endif
int state = (regs[0x58] & 0x02) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY);
int state = (regs[0x58] & 0x02) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) :
(MEM_READ_EXTANY | MEM_WRITE_EXTANY);
if (bus)
mem_set_mem_state_bus_both(0x000a0000, 0x00020000, state);
@@ -136,10 +130,10 @@ pb_write(int func, int addr, uint8_t val, void *priv)
{
i450kx_t *dev = (i450kx_t *) priv;
// pclog("i450KX-PB: [W] dev->pb_pci_conf[%02X] = %02X POST: %02X\n", addr, val, inb(0x80));
i450kx_log("i450KX-PB: [W] dev->pb_pci_conf[%02X] = %02X POST: %02X\n", addr, val, inb(0x80));
if (func == 0) {
i450kx_log("[%04X:%08X] i450KX-PB: [W] dev->pb_pci_conf[%02X] = %02X\n", CS, cpu_state.pc,
addr, val);
if (func == 0)
switch (addr) {
case 0x04:
dev->pb_pci_conf[addr] = (dev->pb_pci_conf[addr] & 0x04) | (val & 0x53);
@@ -373,6 +367,7 @@ pb_write(int func, int addr, uint8_t val, void *priv)
default:
break;
}
}
}
static uint8_t
@@ -381,10 +376,12 @@ pb_read(int func, int addr, void *priv)
const i450kx_t *dev = (i450kx_t *) priv;
uint8_t ret = 0xff;
if (func == 0)
if (func == 0) {
ret = dev->pb_pci_conf[addr];
// pclog("i450KX-PB: [R] dev->pb_pci_conf[%02X] = %02X POST: %02X\n", addr, ret, inb(0x80));
i450kx_log("[%04X:%08X] i450KX-PB: [R] dev->pb_pci_conf[%02X] = %02X\n", CS, cpu_state.pc,
addr, ret);
}
return ret;
}
@@ -407,10 +404,10 @@ mc_write(int func, int addr, uint8_t val, void *priv)
{
i450kx_t *dev = (i450kx_t *) priv;
// pclog("i450KX-MC: [W] dev->mc_pci_conf[%02X] = %02X POST: %02X\n", addr, val, inb(0x80));
i450kx_log("i450KX-MC: [W] dev->mc_pci_conf[%02X] = %02X POST: %02X\n", addr, val, inb(0x80));
if (func == 0) {
i450kx_log("[%04X:%08X] i450KX-MC: [W] dev->mc_pci_conf[%02X] = %02X\n", CS, cpu_state.pc,
addr, val);
if (func == 0)
switch (addr) {
case 0x4c:
dev->mc_pci_conf[addr] = val & 0xdf;
@@ -600,6 +597,7 @@ mc_write(int func, int addr, uint8_t val, void *priv)
default:
break;
}
}
}
static uint8_t
@@ -608,10 +606,12 @@ mc_read(int func, int addr, void *priv)
const i450kx_t *dev = (i450kx_t *) priv;
uint8_t ret = 0xff;
if (func == 0)
if (func == 0) {
ret = dev->mc_pci_conf[addr];
// pclog("i450KX-MC: [R] dev->mc_pci_conf[%02X] = %02X POST: %02X\n", addr, ret, inb(0x80));
i450kx_log("[%04X:%08X] i450KX-MC: [R] dev->mc_pci_conf[%02X] = %02X\n", CS, cpu_state.pc,
addr, ret);
}
return ret;
}
@@ -622,10 +622,6 @@ i450kx_reset(void *priv)
i450kx_t *dev = (i450kx_t *) priv;
uint32_t i;
#if 0
// pclog("i450KX: i450kx_reset()\n");
#endif
/* Defaults PB */
dev->pb_pci_conf[0x00] = 0x86;
dev->pb_pci_conf[0x01] = 0x80;

View File

@@ -1578,7 +1578,16 @@ piix_init(const device_t *info)
dev->acpi = device_add(&acpi_intel_device);
acpi_set_slot(dev->acpi, dev->pci_slot);
acpi_set_nvr(dev->acpi, dev->nvr);
acpi_set_gpireg2_default(dev->acpi, (dev->type > 4) ? 0xf1 : 0xdd);
/*
TriGem Richmond:
- Bit 5: Manufacturing jumper, must be set;
- Bit 4: CMOS clear jumper, must be clear;
- Bit 0: Password switch, must be clear.
*/
if (!strcmp(machine_get_internal_name(), "richmond"))
acpi_set_gpireg2_default(dev->acpi, 0xee);
else
acpi_set_gpireg2_default(dev->acpi, (dev->type > 4) ? 0xf1 : 0xdd);
acpi_set_trap_update(dev->acpi, piix_trap_update, dev);
dev->ddma = device_add(&ddma_device);

View File

@@ -25,9 +25,10 @@
#include <86box/device.h>
#include <86box/io.h>
#include <86box/timer.h>
#include <86box/mem.h>
#include <86box/nvr.h>
#include <86box/apm.h>
#include <86box/acpi.h>
#include <86box/hdd.h>
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
@@ -41,7 +42,7 @@
#include <86box/port_92.h>
#include <86box/smram.h>
#include <86box/spd.h>
#include <86box/sis_55xx.h>
#include <86box/chipset.h>
#ifdef ENABLE_SIS_5511_LOG
@@ -63,573 +64,53 @@ sis_5511_log(const char *fmt, ...)
#endif
typedef struct sis_5511_t {
uint8_t index;
uint8_t nb_slot;
uint8_t sb_slot;
uint8_t pad;
uint8_t nb_slot;
uint8_t sb_slot;
uint8_t regs[16];
uint8_t states[7];
void *h2p;
uint8_t slic_regs[4096];
void *p2i;
void *ide;
uint8_t pci_conf[256];
uint8_t pci_conf_sb[2][256];
mem_mapping_t slic_mapping;
sff8038i_t *bm[2];
smram_t *smram;
port_92_t *port_92;
void *pit;
nvr_t *nvr;
uint8_t (*pit_read_reg)(void *priv, uint8_t reg);
sis_55xx_common_t *sis;
} sis_5511_t;
static void
sis_5511_shadow_recalc(sis_5511_t *dev)
sis_5511_write(int func, int addr, uint8_t val, void *priv)
{
int state;
uint32_t base;
for (uint8_t i = 0x80; i <= 0x86; i++) {
if (i == 0x86) {
if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0xa0) {
state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
mem_set_mem_state_both(0xf0000, 0x10000, state);
sis_5511_log("000F0000-000FFFFF\n");
}
} else {
base = ((i & 0x07) << 15) + 0xc0000;
if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0xa0) {
state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
mem_set_mem_state_both(base, 0x4000, state);
sis_5511_log("%08X-%08X\n", base, base + 0x3fff);
}
if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0x0a) {
state = (dev->pci_conf[i] & 0x08) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
state |= (dev->pci_conf[i] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
mem_set_mem_state_both(base + 0x4000, 0x4000, state);
sis_5511_log("%08X-%08X\n", base + 0x4000, base + 0x7fff);
}
}
dev->states[i & 0x0f] = dev->pci_conf[i];
}
flushmmucache_nopc();
}
static void
sis_5511_smram_recalc(sis_5511_t *dev)
{
smram_disable_all();
switch (dev->pci_conf[0x65] >> 6) {
case 0:
smram_enable(dev->smram, 0x000e0000, 0x000e0000, 0x8000, dev->pci_conf[0x65] & 0x10, 1);
break;
case 1:
smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x8000, dev->pci_conf[0x65] & 0x10, 1);
break;
case 2:
smram_enable(dev->smram, 0x000e0000, 0x000b0000, 0x8000, dev->pci_conf[0x65] & 0x10, 1);
break;
default:
break;
}
flushmmucache();
}
static void
sis_5511_write(UNUSED(int func), int addr, uint8_t val, void *priv)
{
sis_5511_t *dev = (sis_5511_t *) priv;
const sis_5511_t *dev = (sis_5511_t *) priv;
sis_5511_log("SiS 5511: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
if (func == 0x00) switch (addr) {
case 0x07: /* Status - High Byte */
dev->pci_conf[addr] &= 0xb0;
break;
case 0x50:
dev->pci_conf[addr] = val;
cpu_cache_ext_enabled = !!(val & 0x40);
cpu_update_waitstates();
break;
case 0x51:
dev->pci_conf[addr] = val & 0xfe;
break;
case 0x52:
dev->pci_conf[addr] = val & 0x3f;
break;
case 0x53:
case 0x54:
dev->pci_conf[addr] = val;
break;
case 0x55:
dev->pci_conf[addr] = val & 0xf8;
break;
case 0x56 ... 0x59:
dev->pci_conf[addr] = val;
break;
case 0x5a:
/* TODO: Fast Gate A20 Emulation and Fast Reset Emulation on the KBC.
The former (bit 7) means the chipset intercepts D1h to 64h and 00h to 60h.
The latter (bit 6) means the chipset intercepts all odd FXh to 64h.
Bit 5 sets fast reset latency. This should be fixed on the other SiS
chipsets as well. */
dev->pci_conf[addr] = val;
break;
case 0x5b:
dev->pci_conf[addr] = val & 0xf7;
break;
case 0x5c:
dev->pci_conf[addr] = val & 0xcf;
break;
case 0x5d:
dev->pci_conf[addr] = val;
break;
case 0x5e:
dev->pci_conf[addr] = val & 0xfe;
break;
case 0x5f:
dev->pci_conf[addr] = val & 0xfe;
break;
case 0x60:
dev->pci_conf[addr] = val & 0x3e;
if ((dev->pci_conf[0x68] & 1) && (val & 2)) {
smi_raise();
dev->pci_conf[0x69] |= 1;
}
break;
case 0x61 ... 0x64:
dev->pci_conf[addr] = val;
break;
case 0x65:
dev->pci_conf[addr] = val & 0xd0;
sis_5511_smram_recalc(dev);
break;
case 0x66:
dev->pci_conf[addr] = val & 0x7f;
break;
case 0x67:
case 0x68:
dev->pci_conf[addr] = val;
break;
case 0x69:
dev->pci_conf[addr] &= val;
break;
case 0x6a ... 0x6e:
dev->pci_conf[addr] = val;
break;
case 0x6f:
dev->pci_conf[addr] = val & 0x3f;
break;
case 0x70: /* DRAM Bank Register 0-0 */
case 0x72: /* DRAM Bank Register 0-1 */
case 0x74: /* DRAM Bank Register 1-0 */
case 0x76: /* DRAM Bank Register 1-1 */
case 0x78: /* DRAM Bank Register 2-0 */
case 0x7a: /* DRAM Bank Register 2-1 */
case 0x7c: /* DRAM Bank Register 3-0 */
case 0x7e: /* DRAM Bank Register 3-1 */
spd_write_drbs(dev->pci_conf, 0x70, 0x7e, 0x82);
break;
case 0x71: /* DRAM Bank Register 0-0 */
dev->pci_conf[addr] = val;
break;
case 0x75: /* DRAM Bank Register 1-0 */
case 0x79: /* DRAM Bank Register 2-0 */
case 0x7d: /* DRAM Bank Register 3-0 */
dev->pci_conf[addr] = val & 0x7f;
break;
case 0x73: /* DRAM Bank Register 0-1 */
case 0x77: /* DRAM Bank Register 1-1 */
case 0x7b: /* DRAM Bank Register 2-1 */
case 0x7f: /* DRAM Bank Register 3-1 */
dev->pci_conf[addr] = val & 0x83;
break;
case 0x80 ... 0x85:
dev->pci_conf[addr] = val & 0xee;
sis_5511_shadow_recalc(dev);
break;
case 0x86:
dev->pci_conf[addr] = val & 0xe8;
sis_5511_shadow_recalc(dev);
break;
case 0x90 ... 0x93: /* 5512 General Purpose Register Index */
dev->pci_conf[addr] = val;
break;
default:
break;
}
}
static void
sis_5511_slic_write(uint32_t addr, uint8_t val, void *priv)
{
sis_5511_t *dev = (sis_5511_t *) priv;
addr &= 0x00000fff;
switch (addr) {
case 0x00000000:
case 0x00000008: /* 0x00000008 is a SiS 5512 register. */
dev->slic_regs[addr] = val;
break;
case 0x00000010:
case 0x00000018:
case 0x00000028:
case 0x00000038:
dev->slic_regs[addr] = val & 0x01;
break;
case 0x00000030:
dev->slic_regs[addr] = val & 0x0f;
mem_mapping_set_addr(&dev->slic_mapping,
(((uint32_t) (val & 0x0f)) << 28) | 0x0fc00000, 0x00001000);
break;
}
if (func == 0x00)
sis_5511_host_to_pci_write(addr, val, dev->h2p);
}
static uint8_t
sis_5511_read(UNUSED(int func), int addr, void *priv)
sis_5511_read(int func, int addr, void *priv)
{
const sis_5511_t *dev = (sis_5511_t *) priv;
uint8_t ret = 0xff;
if (func == 0x00)
ret = dev->pci_conf[addr];
ret = sis_5511_host_to_pci_read(addr, dev->h2p);
sis_5511_log("SiS 5511: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
return ret;
}
static uint8_t
sis_5511_slic_read(uint32_t addr, void *priv)
{
sis_5511_t *dev = (sis_5511_t *) priv;
uint8_t ret = 0xff;
addr &= 0x00000fff;
switch (addr) {
case 0x00000008: /* 0x00000008 is a SiS 5512 register. */
ret = dev->slic_regs[addr];
break;
}
return ret;
}
void
sis_5513_pci_to_isa_write(int addr, uint8_t val, sis_5511_t *dev)
{
sis_5511_log("SiS 5513 P2I: [W] dev->pci_conf_sb[0][%02X] = %02X\n", addr, val);
switch (addr) {
case 0x04: /* Command */
dev->pci_conf_sb[0][addr] = val & 0x0f;
break;
case 0x07: /* Status */
dev->pci_conf_sb[0][addr] = (dev->pci_conf_sb[0][addr] & 0x06) & ~(val & 0x30);
break;
case 0x40: /* BIOS Control Register */
dev->pci_conf_sb[0][addr] = val & 0x3f;
break;
case 0x41: /* INTA# Remapping Control Register */
case 0x42: /* INTB# Remapping Control Register */
case 0x43: /* INTC# Remapping Control Register */
case 0x44: /* INTD# Remapping Control Register */
dev->pci_conf_sb[0][addr] = val & 0x8f;
pci_set_irq_routing(addr & 0x07, (val & 0x80) ? PCI_IRQ_DISABLED : (val & 0x0f));
break;
case 0x48: /* ISA Master/DMA Memory Cycle Control Register 1 */
case 0x49: /* ISA Master/DMA Memory Cycle Control Register 2 */
case 0x4a: /* ISA Master/DMA Memory Cycle Control Register 3 */
case 0x4b: /* ISA Master/DMA Memory Cycle Control Register 4 */
dev->pci_conf_sb[0][addr] = val;
break;
case 0x60: /* MIRQ0 Remapping Control Register */
case 0x61: /* MIRQ1 Remapping Control Register */
sis_5511_log("Set MIRQ routing: MIRQ%i -> %02X\n", addr & 0x01, val);
dev->pci_conf_sb[0][addr] = val & 0xcf;
if (val & 0x80)
pci_set_mirq_routing(PCI_MIRQ0 + (addr & 0x01), PCI_IRQ_DISABLED);
else
pci_set_mirq_routing(PCI_MIRQ0 + (addr & 0x01), val & 0xf);
break;
case 0x62: /* On-board Device DMA Control Register */
dev->pci_conf_sb[0][addr] = val;
break;
case 0x63: /* IDEIRQ Remapping Control Register */
sis_5511_log("Set MIRQ routing: IDEIRQ -> %02X\n", val);
dev->pci_conf_sb[0][addr] = val & 0x8f;
if (val & 0x80)
pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED);
else
pci_set_mirq_routing(PCI_MIRQ2, val & 0xf);
break;
case 0x64: /* GPIO0 Control Register */
dev->pci_conf_sb[0][addr] = val & 0xef;
break;
case 0x65:
dev->pci_conf_sb[0][addr] = val & 0x80;
break;
case 0x66: /* GPIO0 Output Mode Control Register */
case 0x67: /* GPIO0 Output Mode Control Register */
dev->pci_conf_sb[0][addr] = val;
break;
case 0x6a: /* GPIO Status Register */
dev->pci_conf_sb[0][addr] |= (val & 0x10);
dev->pci_conf_sb[0][addr] &= ~(val & 0x01);
break;
default:
break;
}
}
static void
sis_5513_ide_irq_handler(sis_5511_t *dev)
{
if (dev->pci_conf_sb[1][0x09] & 0x01) {
/* Primary IDE is native. */
sis_5511_log("Primary IDE IRQ mode: Native, Native\n");
sff_set_irq_mode(dev->bm[0], IRQ_MODE_SIS_551X);
} else {
/* Primary IDE is legacy. */
sis_5511_log("Primary IDE IRQ mode: IRQ14, IRQ15\n");
sff_set_irq_mode(dev->bm[0], IRQ_MODE_LEGACY);
}
if (dev->pci_conf_sb[1][0x09] & 0x04) {
/* Secondary IDE is native. */
sis_5511_log("Secondary IDE IRQ mode: Native, Native\n");
sff_set_irq_mode(dev->bm[1], IRQ_MODE_SIS_551X);
} else {
/* Secondary IDE is legacy. */
sis_5511_log("Secondary IDE IRQ mode: IRQ14, IRQ15\n");
sff_set_irq_mode(dev->bm[1], IRQ_MODE_LEGACY);
}
}
static void
sis_5513_ide_handler(sis_5511_t *dev)
{
uint8_t ide_io_on = dev->pci_conf_sb[1][0x04] & 0x01;
uint16_t native_base_pri_addr = (dev->pci_conf_sb[1][0x11] | dev->pci_conf_sb[1][0x10] << 8) & 0xfffe;
uint16_t native_side_pri_addr = (dev->pci_conf_sb[1][0x15] | dev->pci_conf_sb[1][0x14] << 8) & 0xfffe;
uint16_t native_base_sec_addr = (dev->pci_conf_sb[1][0x19] | dev->pci_conf_sb[1][0x18] << 8) & 0xfffe;
uint16_t native_side_sec_addr = (dev->pci_conf_sb[1][0x1c] | dev->pci_conf_sb[1][0x1b] << 8) & 0xfffe;
uint16_t current_pri_base;
uint16_t current_pri_side;
uint16_t current_sec_base;
uint16_t current_sec_side;
/* Primary Channel Programming */
current_pri_base = (!(dev->pci_conf_sb[1][0x09] & 1)) ? 0x01f0 : native_base_pri_addr;
current_pri_side = (!(dev->pci_conf_sb[1][0x09] & 1)) ? 0x03f6 : native_side_pri_addr;
/* Secondary Channel Programming */
current_sec_base = (!(dev->pci_conf_sb[1][0x09] & 4)) ? 0x0170 : native_base_sec_addr;
current_sec_side = (!(dev->pci_conf_sb[1][0x09] & 4)) ? 0x0376 : native_side_sec_addr;
sis_5511_log("sis_5513_ide_handler(): Disabling primary IDE...\n");
ide_pri_disable();
sis_5511_log("sis_5513_ide_handler(): Disabling secondary IDE...\n");
ide_sec_disable();
if (ide_io_on) {
/* Primary Channel Setup */
if (dev->pci_conf_sb[1][0x4a] & 0x02) {
sis_5511_log("sis_5513_ide_handler(): Primary IDE base now %04X...\n", current_pri_base);
ide_set_base(0, current_pri_base);
sis_5511_log("sis_5513_ide_handler(): Primary IDE side now %04X...\n", current_pri_side);
ide_set_side(0, current_pri_side);
sis_5511_log("sis_5513_ide_handler(): Enabling primary IDE...\n");
ide_pri_enable();
sis_5511_log("SiS 5513 PRI: BASE %04x SIDE %04x\n", current_pri_base, current_pri_side);
}
/* Secondary Channel Setup */
if (dev->pci_conf_sb[1][0x4a] & 0x04) {
sis_5511_log("sis_5513_ide_handler(): Secondary IDE base now %04X...\n", current_sec_base);
ide_set_base(1, current_sec_base);
sis_5511_log("sis_5513_ide_handler(): Secondary IDE side now %04X...\n", current_sec_side);
ide_set_side(1, current_sec_side);
sis_5511_log("sis_5513_ide_handler(): Enabling secondary IDE...\n");
ide_sec_enable();
sis_5511_log("SiS 5513: BASE %04x SIDE %04x\n", current_sec_base, current_sec_side);
}
}
sff_bus_master_handler(dev->bm[0], ide_io_on,
((dev->pci_conf_sb[1][0x20] & 0xf0) | (dev->pci_conf_sb[1][0x21] << 8)) + 0);
sff_bus_master_handler(dev->bm[1], ide_io_on,
((dev->pci_conf_sb[1][0x20] & 0xf0) | (dev->pci_conf_sb[1][0x21] << 8)) + 8);
}
void
sis_5513_ide_write(int addr, uint8_t val, sis_5511_t *dev)
{
sis_5511_log("SiS 5513 IDE: [W] dev->pci_conf_sb[1][%02X] = %02X\n", addr, val);
switch (addr) {
case 0x04: /* Command low byte */
dev->pci_conf_sb[1][addr] = val & 0x05;
sis_5513_ide_handler(dev);
break;
case 0x06: /* Status low byte */
dev->pci_conf_sb[1][addr] = val & 0x20;
break;
case 0x07: /* Status high byte */
dev->pci_conf_sb[1][addr] = (dev->pci_conf_sb[1][addr] & 0x06) & ~(val & 0x38);
break;
case 0x09: /* Programming Interface Byte */
dev->pci_conf_sb[1][addr] = (dev->pci_conf_sb[1][addr] & 0x8a) | (val & 0x05);
sis_5513_ide_irq_handler(dev);
sis_5513_ide_handler(dev);
break;
case 0x0d: /* Latency Timer */
dev->pci_conf_sb[1][addr] = val;
break;
/* Primary Base Address */
case 0x10:
case 0x11:
case 0x14:
case 0x15:
fallthrough;
/* Secondary Base Address */
case 0x18:
case 0x19:
case 0x1c:
case 0x1d:
fallthrough;
/* Bus Mastering Base Address */
case 0x20:
case 0x21:
if (addr == 0x20)
dev->pci_conf_sb[1][addr] = (val & 0xe0) | 0x01;
else
dev->pci_conf_sb[1][addr] = val;
sis_5513_ide_handler(dev);
break;
case 0x30: /* Expansion ROM Base Address */
case 0x31: /* Expansion ROM Base Address */
case 0x32: /* Expansion ROM Base Address */
case 0x33: /* Expansion ROM Base Address */
dev->pci_conf_sb[1][addr] = val;
break;
case 0x40: /* IDE Primary Channel/Master Drive Data Recovery Time Control */
case 0x42: /* IDE Primary Channel/Slave Drive Data Recovery Time Control */
case 0x44: /* IDE Secondary Channel/Master Drive Data Recovery Time Control */
case 0x46: /* IDE Secondary Channel/Slave Drive Data Recovery Time Control */
case 0x48: /* IDE Command Recovery Time Control */
dev->pci_conf_sb[1][addr] = val & 0x0f;
break;
case 0x41: /* IDE Primary Channel/Master Drive DataActive Time Control */
case 0x43: /* IDE Primary Channel/Slave Drive Data Active Time Control */
case 0x45: /* IDE Secondary Channel/Master Drive Data Active Time Control */
case 0x47: /* IDE Secondary Channel/Slave Drive Data Active Time Control */
case 0x49: /* IDE Command Active Time Control */
dev->pci_conf_sb[1][addr] = val & 0x07;
break;
case 0x4a: /* IDE General Control Register 0 */
dev->pci_conf_sb[1][addr] = val & 0x9e;
sis_5513_ide_handler(dev);
break;
case 0x4b: /* IDE General Control Register 1 */
dev->pci_conf_sb[1][addr] = val & 0xef;
break;
case 0x4c: /* Prefetch Count of Primary Channel (Low Byte) */
case 0x4d: /* Prefetch Count of Primary Channel (High Byte) */
case 0x4e: /* Prefetch Count of Secondary Channel (Low Byte) */
case 0x4f: /* Prefetch Count of Secondary Channel (High Byte) */
dev->pci_conf_sb[1][addr] = val;
break;
default:
break;
}
}
static void
sis_5513_write(int func, int addr, uint8_t val, void *priv)
{
sis_5511_t *dev = (sis_5511_t *) priv;
const sis_5511_t *dev = (sis_5511_t *) priv;
switch (func) {
default:
break;
case 0:
sis_5513_pci_to_isa_write(addr, val, dev);
break;
case 1:
sis_5513_ide_write(addr, val, dev);
break;
}
sis_5511_log("SiS 5513: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
if (func == 0x00)
sis_5513_pci_to_isa_write(addr, val, dev->p2i);
else if (func == 0x01)
sis_5513_ide_write(addr, val, dev->ide);
}
static uint8_t
@@ -638,281 +119,21 @@ sis_5513_read(int func, int addr, void *priv)
const sis_5511_t *dev = (sis_5511_t *) priv;
uint8_t ret = 0xff;
if (func == 0x00) {
switch (addr) {
default:
ret = dev->pci_conf_sb[func][addr];
break;
case 0x4c ... 0x4f:
ret = pic_read_icw(0, addr & 0x03);
break;
case 0x50 ... 0x53:
ret = pic_read_icw(1, addr & 0x03);
break;
case 0x54 ... 0x55:
ret = pic_read_ocw(0, addr & 0x01);
break;
case 0x56 ... 0x57:
ret = pic_read_ocw(1, addr & 0x01);
break;
case 0x58 ... 0x5f:
ret = dev->pit_read_reg(dev->pit, addr & 0x07);
break;
}
if (func == 0x00)
ret = sis_5513_pci_to_isa_read(addr, dev->p2i);
else if (func == 0x01)
ret = sis_5513_ide_read(addr, dev->ide);
sis_5511_log("SiS 5513 P2I: [R] dev->pci_conf_sb[0][%02X] = %02X\n", addr, ret);
} else if (func == 0x01) {
if (addr == 0x3d)
ret = (((dev->pci_conf_sb[0x01][0x4b] & 0xc0) == 0xc0) ||
(dev->pci_conf_sb[0x01][0x09] & 0x05)) ? PCI_INTA : 0x00;
else
ret = dev->pci_conf_sb[func][addr];
sis_5511_log("SiS 5513 IDE: [R] dev->pci_conf_sb[1][%02X] = %02X\n", addr, ret);
}
sis_5511_log("SiS 5513: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
return ret;
}
static void
sis_5513_isa_write(uint16_t addr, uint8_t val, void *priv)
{
sis_5511_t *dev = (sis_5511_t *) priv;
switch (addr) {
case 0x22:
dev->index = val - 0x50;
break;
case 0x23:
sis_5511_log("SiS 5513 ISA: [W] dev->regs[%02X] = %02X\n", dev->index + 0x50, val);
switch (dev->index) {
case 0x00:
dev->regs[dev->index] = val & 0xed;
switch (val >> 6) {
case 0:
cpu_set_isa_speed(7159091);
break;
case 1:
cpu_set_isa_pci_div(4);
break;
case 2:
cpu_set_isa_pci_div(3);
break;
default:
break;
}
nvr_bank_set(0, !!(val & 0x08), dev->nvr);
break;
case 0x01:
dev->regs[dev->index] = val & 0xf4;
break;
case 0x03:
dev->regs[dev->index] = val & 3;
break;
case 0x04: /* BIOS Register */
dev->regs[dev->index] = val;
break;
case 0x05:
dev->regs[dev->index] = val;
outb(0x70, val);
break;
case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
dev->regs[dev->index] = val;
break;
default:
break;
}
break;
default:
break;
}
}
static uint8_t
sis_5513_isa_read(uint16_t addr, void *priv)
{
const sis_5511_t *dev = (sis_5511_t *) priv;
uint8_t ret = 0xff;
if (addr == 0x23) {
if (dev->index == 0x05)
ret = inb(0x70);
else
ret = dev->regs[dev->index];
sis_5511_log("SiS 5513 ISA: [R] dev->regs[%02X] = %02X\n", dev->index + 0x50, ret);
}
return ret;
}
static void
sis_5511_reset(void *priv)
{
sis_5511_t *dev = (sis_5511_t *) priv;
/* SiS 5511 */
dev->pci_conf[0x00] = 0x39;
dev->pci_conf[0x01] = 0x10;
dev->pci_conf[0x02] = 0x11;
dev->pci_conf[0x03] = 0x55;
dev->pci_conf[0x04] = 0x07;
dev->pci_conf[0x05] = dev->pci_conf[0x06] = 0x00;
dev->pci_conf[0x07] = 0x02;
dev->pci_conf[0x08] = 0x00;
dev->pci_conf[0x09] = dev->pci_conf[0x0a] = 0x00;
dev->pci_conf[0x0b] = 0x06;
dev->pci_conf[0x50] = dev->pci_conf[0x51] = 0x00;
dev->pci_conf[0x52] = 0x20;
dev->pci_conf[0x53] = dev->pci_conf[0x54] = 0x00;
dev->pci_conf[0x55] = dev->pci_conf[0x56] = 0x00;
dev->pci_conf[0x57] = dev->pci_conf[0x58] = 0x00;
dev->pci_conf[0x59] = dev->pci_conf[0x5a] = 0x00;
dev->pci_conf[0x5b] = dev->pci_conf[0x5c] = 0x00;
dev->pci_conf[0x5d] = dev->pci_conf[0x5e] = 0x00;
dev->pci_conf[0x5f] = dev->pci_conf[0x60] = 0x00;
dev->pci_conf[0x61] = dev->pci_conf[0x62] = 0xff;
dev->pci_conf[0x63] = 0xff;
dev->pci_conf[0x64] = dev->pci_conf[0x65] = 0x00;
dev->pci_conf[0x66] = 0x00;
dev->pci_conf[0x67] = 0xff;
dev->pci_conf[0x68] = dev->pci_conf[0x69] = 0x00;
dev->pci_conf[0x6a] = 0x00;
dev->pci_conf[0x6b] = dev->pci_conf[0x6c] = 0xff;
dev->pci_conf[0x6d] = dev->pci_conf[0x6e] = 0xff;
dev->pci_conf[0x6f] = 0x00;
dev->pci_conf[0x70] = dev->pci_conf[0x72] = 0x04;
dev->pci_conf[0x74] = dev->pci_conf[0x76] = 0x04;
dev->pci_conf[0x78] = dev->pci_conf[0x7a] = 0x04;
dev->pci_conf[0x7c] = dev->pci_conf[0x7e] = 0x04;
dev->pci_conf[0x71] = dev->pci_conf[0x75] = 0x00;
dev->pci_conf[0x73] = dev->pci_conf[0x77] = 0x80;
dev->pci_conf[0x79] = dev->pci_conf[0x7d] = 0x00;
dev->pci_conf[0x7b] = dev->pci_conf[0x7f] = 0x80;
dev->pci_conf[0x80] = dev->pci_conf[0x81] = 0x00;
dev->pci_conf[0x82] = dev->pci_conf[0x83] = 0x00;
dev->pci_conf[0x84] = dev->pci_conf[0x85] = 0x00;
dev->pci_conf[0x86] = 0x00;
cpu_cache_ext_enabled = 0;
cpu_update_waitstates();
sis_5511_smram_recalc(dev);
sis_5511_shadow_recalc(dev);
flushmmucache();
memset(dev->slic_regs, 0x00, 4096 * sizeof(uint8_t));
dev->slic_regs[0x18] = 0x0f;
mem_mapping_set_addr(&dev->slic_mapping, 0xffc00000, 0x00001000);
/* SiS 5513 */
dev->pci_conf_sb[0][0x00] = 0x39;
dev->pci_conf_sb[0][0x01] = 0x10;
dev->pci_conf_sb[0][0x02] = 0x08;
dev->pci_conf_sb[0][0x03] = 0x00;
dev->pci_conf_sb[0][0x04] = 0x07;
dev->pci_conf_sb[0][0x05] = dev->pci_conf_sb[0][0x06] = 0x00;
dev->pci_conf_sb[0][0x07] = 0x02;
dev->pci_conf_sb[0][0x08] = dev->pci_conf_sb[0][0x09] = 0x00;
dev->pci_conf_sb[0][0x0a] = 0x01;
dev->pci_conf_sb[0][0x0b] = 0x06;
dev->pci_conf_sb[0][0x0e] = 0x80;
dev->pci_conf_sb[0][0x40] = 0x00;
dev->pci_conf_sb[0][0x41] = dev->pci_conf_sb[0][0x42] = 0x80;
dev->pci_conf_sb[0][0x43] = dev->pci_conf_sb[0][0x44] = 0x80;
dev->pci_conf_sb[0][0x48] = dev->pci_conf_sb[0][0x49] = 0x00;
dev->pci_conf_sb[0][0x4a] = dev->pci_conf_sb[0][0x4b] = 0x00;
dev->pci_conf_sb[0][0x60] = dev->pci_conf_sb[0][0x61] = 0x80;
dev->pci_conf_sb[0][0x62] = 0x00;
dev->pci_conf_sb[0][0x63] = 0x80;
dev->pci_conf_sb[0][0x64] = 0x00;
dev->pci_conf_sb[0][0x65] = 0x00;
dev->pci_conf_sb[0][0x66] = dev->pci_conf_sb[0][0x67] = 0x00;
dev->pci_conf_sb[0][0x68] = dev->pci_conf_sb[0][0x69] = 0x00;
dev->pci_conf_sb[0][0x6a] = 0x04;
pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED);
pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED);
pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED);
pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED);
pci_set_mirq_routing(PCI_MIRQ0, PCI_IRQ_DISABLED);
pci_set_mirq_routing(PCI_MIRQ1, PCI_IRQ_DISABLED);
pci_set_mirq_routing(PCI_MIRQ2, PCI_IRQ_DISABLED);
dev->regs[0x00] = dev->regs[0x01] = 0x00;
dev->regs[0x03] = dev->regs[0x04] = 0x00;
dev->regs[0x05] = 0x00;
dev->regs[0x08] = dev->regs[0x09] = 0x00;
dev->regs[0x0a] = dev->regs[0x0b] = 0x00;
cpu_set_isa_speed(7159091);
nvr_bank_set(0, 0, dev->nvr);
/* SiS 5513 IDE Controller */
dev->pci_conf_sb[1][0x00] = 0x39;
dev->pci_conf_sb[1][0x01] = 0x10;
dev->pci_conf_sb[1][0x02] = 0x13;
dev->pci_conf_sb[1][0x03] = 0x55;
dev->pci_conf_sb[1][0x04] = dev->pci_conf_sb[1][0x05] = 0x00;
dev->pci_conf_sb[1][0x06] = dev->pci_conf_sb[1][0x07] = 0x00;
dev->pci_conf_sb[1][0x08] = 0x00;
dev->pci_conf_sb[1][0x09] = 0x8a;
dev->pci_conf_sb[1][0x0a] = dev->pci_conf_sb[1][0x0b] = 0x01;
dev->pci_conf_sb[1][0x0c] = dev->pci_conf_sb[1][0x0d] = 0x00;
dev->pci_conf_sb[1][0x0e] = 0x80;
dev->pci_conf_sb[1][0x0f] = 0x00;
dev->pci_conf_sb[1][0x10] = 0xf1;
dev->pci_conf_sb[1][0x11] = 0x01;
dev->pci_conf_sb[1][0x14] = 0xf5;
dev->pci_conf_sb[1][0x15] = 0x03;
dev->pci_conf_sb[1][0x18] = 0x71;
dev->pci_conf_sb[1][0x19] = 0x01;
dev->pci_conf_sb[1][0x1c] = 0x75;
dev->pci_conf_sb[1][0x1d] = 0x03;
dev->pci_conf_sb[1][0x20] = 0x01;
dev->pci_conf_sb[1][0x21] = 0xf0;
dev->pci_conf_sb[1][0x22] = dev->pci_conf_sb[1][0x23] = 0x00;
dev->pci_conf_sb[1][0x24] = dev->pci_conf_sb[1][0x25] = 0x00;
dev->pci_conf_sb[1][0x26] = dev->pci_conf_sb[1][0x27] = 0x00;
dev->pci_conf_sb[1][0x28] = dev->pci_conf_sb[1][0x29] = 0x00;
dev->pci_conf_sb[1][0x2a] = dev->pci_conf_sb[1][0x2b] = 0x00;
dev->pci_conf_sb[1][0x2c] = dev->pci_conf_sb[1][0x2d] = 0x00;
dev->pci_conf_sb[1][0x2e] = dev->pci_conf_sb[1][0x2f] = 0x00;
dev->pci_conf_sb[1][0x30] = dev->pci_conf_sb[1][0x31] = 0x00;
dev->pci_conf_sb[1][0x32] = dev->pci_conf_sb[1][0x33] = 0x00;
dev->pci_conf_sb[1][0x40] = dev->pci_conf_sb[1][0x41] = 0x00;
dev->pci_conf_sb[1][0x42] = dev->pci_conf_sb[1][0x43] = 0x00;
dev->pci_conf_sb[1][0x44] = dev->pci_conf_sb[1][0x45] = 0x00;
dev->pci_conf_sb[1][0x46] = dev->pci_conf_sb[1][0x47] = 0x00;
dev->pci_conf_sb[1][0x48] = dev->pci_conf_sb[1][0x49] = 0x00;
dev->pci_conf_sb[1][0x4a] = 0x06;
dev->pci_conf_sb[1][0x4b] = 0x00;
dev->pci_conf_sb[1][0x4c] = dev->pci_conf_sb[1][0x4d] = 0x00;
dev->pci_conf_sb[1][0x4e] = dev->pci_conf_sb[1][0x4f] = 0x00;
sis_5513_ide_irq_handler(dev);
sis_5513_ide_handler(dev);
sff_bus_master_reset(dev->bm[0]);
sff_bus_master_reset(dev->bm[1]);
}
static void
sis_5511_close(void *priv)
{
sis_5511_t *dev = (sis_5511_t *) priv;
smram_del(dev->smram);
free(dev);
}
@@ -920,53 +141,18 @@ static void *
sis_5511_init(UNUSED(const device_t *info))
{
sis_5511_t *dev = (sis_5511_t *) calloc(1, sizeof(sis_5511_t));
uint8_t pit_is_fast = (((pit_mode == -1) && is486) || (pit_mode == 1));
/* Device 0: SiS 5511 */
pci_add_card(PCI_ADD_NORTHBRIDGE, sis_5511_read, sis_5511_write, dev, &dev->nb_slot);
/* Device 1: SiS 5513 */
pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_5513_read, sis_5513_write, dev, &dev->sb_slot);
/* SLiC Memory Mapped Registers */
mem_mapping_add(&dev->slic_mapping,
0xffc00000, 0x00001000,
sis_5511_slic_read,
NULL,
NULL,
sis_5511_slic_write,
NULL,
NULL,
NULL, MEM_MAPPING_EXTERNAL,
dev);
dev->sis = device_add(&sis_55xx_common_device);
/* Ports 22h-23h: SiS 5513 ISA */
io_sethandler(0x0022, 0x0002, sis_5513_isa_read, NULL, NULL, sis_5513_isa_write, NULL, NULL, dev);
dev->h2p = device_add_linked(&sis_5511_h2p_device, dev->sis);
/* MIRQ */
pci_enable_mirq(0);
pci_enable_mirq(1);
/* IDEIRQ */
pci_enable_mirq(2);
/* Port 92h */
dev->port_92 = device_add(&port_92_device);
/* SFF IDE */
dev->bm[0] = device_add_inst(&sff8038i_device, 1);
dev->bm[1] = device_add_inst(&sff8038i_device, 2);
/* SMRAM */
dev->smram = smram_add();
/* PIT */
dev->pit = device_find_first_priv(DEVICE_PIT);
dev->pit_read_reg = pit_is_fast ? pitf_read_reg : pit_read_reg;
/* NVR */
dev->nvr = device_add(&at_mb_nvr_device);
sis_5511_reset(dev);
dev->p2i = device_add_linked(&sis_5513_p2i_device, dev->sis);
dev->ide = device_add_linked(&sis_5513_ide_device, dev->sis);
return dev;
}
@@ -978,7 +164,7 @@ const device_t sis_5511_device = {
.local = 0,
.init = sis_5511_init,
.close = sis_5511_close,
.reset = sis_5511_reset,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,

461
src/chipset/sis_5511_h2p.c Normal file
View File

@@ -0,0 +1,461 @@
/*
* 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 SiS 5511 Host to PCI bridge.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2024 Miran Grca.
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/io.h>
#include <86box/timer.h>
#include <86box/dma.h>
#include <86box/mem.h>
#include <86box/nvr.h>
#include <86box/hdd.h>
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
#include <86box/hdc_ide_sff8038i.h>
#include <86box/pci.h>
#include <86box/pic.h>
#include <86box/pit.h>
#include <86box/pit_fast.h>
#include <86box/plat.h>
#include <86box/plat_unused.h>
#include <86box/port_92.h>
#include <86box/smram.h>
#include <86box/spd.h>
#include <86box/apm.h>
#include <86box/ddma.h>
#include <86box/acpi.h>
#include <86box/smbus.h>
#include <86box/spd.h>
#include <86box/sis_55xx.h>
#include <86box/chipset.h>
#include <86box/usb.h>
#include <86box/agpgart.h>
#ifdef ENABLE_SIS_5511_HOST_TO_PCI_LOG
int sis_5511_host_to_pci_do_log = ENABLE_SIS_5511_HOST_TO_PCI_LOG;
static void
sis_5511_host_to_pci_log(const char *fmt, ...)
{
va_list ap;
if (sis_5511_host_to_pci_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define sis_5511_host_to_pci_log(fmt, ...)
#endif
typedef struct sis_5511_host_to_pci_t {
uint8_t pci_conf[256];
uint8_t states[7];
uint8_t slic_regs[4096];
sis_55xx_common_t *sis;
smram_t *smram;
mem_mapping_t slic_mapping;
} sis_5511_host_to_pci_t;
static void
sis_5511_shadow_recalc(sis_5511_host_to_pci_t *dev)
{
int state;
uint32_t base;
for (uint8_t i = 0x80; i <= 0x86; i++) {
if (i == 0x86) {
if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0xa0) {
state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
mem_set_mem_state_both(0xf0000, 0x10000, state);
sis_5511_host_to_pci_log("000F0000-000FFFFF\n");
}
} else {
base = ((i & 0x07) << 15) + 0xc0000;
if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0xa0) {
state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
mem_set_mem_state_both(base, 0x4000, state);
sis_5511_host_to_pci_log("%08X-%08X\n", base, base + 0x3fff);
}
if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0x0a) {
state = (dev->pci_conf[i] & 0x08) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
state |= (dev->pci_conf[i] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
mem_set_mem_state_both(base + 0x4000, 0x4000, state);
sis_5511_host_to_pci_log("%08X-%08X\n", base + 0x4000, base + 0x7fff);
}
}
dev->states[i & 0x0f] = dev->pci_conf[i];
}
flushmmucache_nopc();
}
static void
sis_5511_smram_recalc(sis_5511_host_to_pci_t *dev)
{
smram_disable_all();
switch (dev->pci_conf[0x65] >> 6) {
case 0:
smram_enable(dev->smram, 0x000e0000, 0x000e0000, 0x8000, dev->pci_conf[0x65] & 0x10, 1);
break;
case 1:
smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x8000, dev->pci_conf[0x65] & 0x10, 1);
break;
case 2:
smram_enable(dev->smram, 0x000e0000, 0x000b0000, 0x8000, dev->pci_conf[0x65] & 0x10, 1);
break;
default:
break;
}
flushmmucache();
}
void
sis_5511_host_to_pci_write(int addr, uint8_t val, void *priv)
{
sis_5511_host_to_pci_t *dev = (sis_5511_host_to_pci_t *) priv;
sis_5511_host_to_pci_log("SiS 5511 H2P: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
switch (addr) {
default:
break;
case 0x07: /* Status - High Byte */
dev->pci_conf[addr] &= 0xb0;
break;
case 0x50:
dev->pci_conf[addr] = val;
cpu_cache_ext_enabled = !!(val & 0x40);
cpu_update_waitstates();
break;
case 0x51:
dev->pci_conf[addr] = val & 0xfe;
break;
case 0x52:
dev->pci_conf[addr] = val & 0x3f;
break;
case 0x53:
case 0x54:
dev->pci_conf[addr] = val;
break;
case 0x55:
dev->pci_conf[addr] = val & 0xf8;
break;
case 0x56 ... 0x59:
dev->pci_conf[addr] = val;
break;
case 0x5a:
/* TODO: Fast Gate A20 Emulation and Fast Reset Emulation on the KBC.
The former (bit 7) means the chipset intercepts D1h to 64h and 00h to 60h.
The latter (bit 6) means the chipset intercepts all odd FXh to 64h.
Bit 5 sets fast reset latency. This should be fixed on the other SiS
chipsets as well. */
dev->pci_conf[addr] = val;
break;
case 0x5b:
dev->pci_conf[addr] = val & 0xf7;
break;
case 0x5c:
dev->pci_conf[addr] = val & 0xcf;
break;
case 0x5d:
dev->pci_conf[addr] = val;
break;
case 0x5e:
dev->pci_conf[addr] = val & 0xfe;
break;
case 0x5f:
dev->pci_conf[addr] = val & 0xfe;
break;
case 0x60:
dev->pci_conf[addr] = val & 0x3e;
if ((dev->pci_conf[0x68] & 1) && (val & 2)) {
smi_raise();
dev->pci_conf[0x69] |= 1;
}
break;
case 0x61 ... 0x64:
dev->pci_conf[addr] = val;
break;
case 0x65:
dev->pci_conf[addr] = val & 0xd0;
sis_5511_smram_recalc(dev);
break;
case 0x66:
dev->pci_conf[addr] = val & 0x7f;
break;
case 0x67:
case 0x68:
dev->pci_conf[addr] = val;
break;
case 0x69:
dev->pci_conf[addr] &= val;
break;
case 0x6a ... 0x6e:
dev->pci_conf[addr] = val;
break;
case 0x6f:
dev->pci_conf[addr] = val & 0x3f;
break;
case 0x70: /* DRAM Bank Register 0-0 */
case 0x72: /* DRAM Bank Register 0-1 */
case 0x74: /* DRAM Bank Register 1-0 */
case 0x76: /* DRAM Bank Register 1-1 */
case 0x78: /* DRAM Bank Register 2-0 */
case 0x7a: /* DRAM Bank Register 2-1 */
case 0x7c: /* DRAM Bank Register 3-0 */
case 0x7e: /* DRAM Bank Register 3-1 */
spd_write_drbs(dev->pci_conf, 0x70, 0x7e, 0x82);
break;
case 0x71: /* DRAM Bank Register 0-0 */
dev->pci_conf[addr] = val;
break;
case 0x75: /* DRAM Bank Register 1-0 */
case 0x79: /* DRAM Bank Register 2-0 */
case 0x7d: /* DRAM Bank Register 3-0 */
dev->pci_conf[addr] = val & 0x7f;
break;
case 0x73: /* DRAM Bank Register 0-1 */
case 0x77: /* DRAM Bank Register 1-1 */
case 0x7b: /* DRAM Bank Register 2-1 */
case 0x7f: /* DRAM Bank Register 3-1 */
dev->pci_conf[addr] = val & 0x83;
break;
case 0x80 ... 0x85:
dev->pci_conf[addr] = val & 0xee;
sis_5511_shadow_recalc(dev);
break;
case 0x86:
dev->pci_conf[addr] = val & 0xe8;
sis_5511_shadow_recalc(dev);
break;
case 0x90 ... 0x93: /* 5512 General Purpose Register Index */
dev->pci_conf[addr] = val;
break;
}
}
uint8_t
sis_5511_host_to_pci_read(int addr, void *priv)
{
const sis_5511_host_to_pci_t *dev = (sis_5511_host_to_pci_t *) priv;
uint8_t ret = 0xff;
ret = dev->pci_conf[addr];
sis_5511_host_to_pci_log("SiS 5511 H2P: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
return ret;
}
static void
sis_5511_slic_write(uint32_t addr, uint8_t val, void *priv)
{
sis_5511_host_to_pci_t *dev = (sis_5511_host_to_pci_t *) priv;
addr &= 0x00000fff;
switch (addr) {
case 0x00000000:
case 0x00000008: /* 0x00000008 is a SiS 5512 register. */
dev->slic_regs[addr] = val;
break;
case 0x00000010:
case 0x00000018:
case 0x00000028:
case 0x00000038:
dev->slic_regs[addr] = val & 0x01;
break;
case 0x00000030:
dev->slic_regs[addr] = val & 0x0f;
mem_mapping_set_addr(&dev->slic_mapping,
(((uint32_t) (val & 0x0f)) << 28) | 0x0fc00000, 0x00001000);
break;
}
}
static uint8_t
sis_5511_slic_read(uint32_t addr, void *priv)
{
sis_5511_host_to_pci_t *dev = (sis_5511_host_to_pci_t *) priv;
uint8_t ret = 0xff;
addr &= 0x00000fff;
switch (addr) {
case 0x00000008: /* 0x00000008 is a SiS 5512 register. */
ret = dev->slic_regs[addr];
break;
}
return ret;
}
static void
sis_5511_host_to_pci_reset(void *priv)
{
sis_5511_host_to_pci_t *dev = (sis_5511_host_to_pci_t *) priv;
dev->pci_conf[0x00] = 0x39;
dev->pci_conf[0x01] = 0x10;
dev->pci_conf[0x02] = 0x11;
dev->pci_conf[0x03] = 0x55;
dev->pci_conf[0x04] = 0x07;
dev->pci_conf[0x05] = dev->pci_conf[0x06] = 0x00;
dev->pci_conf[0x07] = 0x02;
dev->pci_conf[0x08] = 0x00;
dev->pci_conf[0x09] = dev->pci_conf[0x0a] = 0x00;
dev->pci_conf[0x0b] = 0x06;
dev->pci_conf[0x50] = dev->pci_conf[0x51] = 0x00;
dev->pci_conf[0x52] = 0x20;
dev->pci_conf[0x53] = dev->pci_conf[0x54] = 0x00;
dev->pci_conf[0x55] = dev->pci_conf[0x56] = 0x00;
dev->pci_conf[0x57] = dev->pci_conf[0x58] = 0x00;
dev->pci_conf[0x59] = dev->pci_conf[0x5a] = 0x00;
dev->pci_conf[0x5b] = dev->pci_conf[0x5c] = 0x00;
dev->pci_conf[0x5d] = dev->pci_conf[0x5e] = 0x00;
dev->pci_conf[0x5f] = dev->pci_conf[0x60] = 0x00;
dev->pci_conf[0x61] = dev->pci_conf[0x62] = 0xff;
dev->pci_conf[0x63] = 0xff;
dev->pci_conf[0x64] = dev->pci_conf[0x65] = 0x00;
dev->pci_conf[0x66] = 0x00;
dev->pci_conf[0x67] = 0xff;
dev->pci_conf[0x68] = dev->pci_conf[0x69] = 0x00;
dev->pci_conf[0x6a] = 0x00;
dev->pci_conf[0x6b] = dev->pci_conf[0x6c] = 0xff;
dev->pci_conf[0x6d] = dev->pci_conf[0x6e] = 0xff;
dev->pci_conf[0x6f] = 0x00;
dev->pci_conf[0x70] = dev->pci_conf[0x72] = 0x04;
dev->pci_conf[0x74] = dev->pci_conf[0x76] = 0x04;
dev->pci_conf[0x78] = dev->pci_conf[0x7a] = 0x04;
dev->pci_conf[0x7c] = dev->pci_conf[0x7e] = 0x04;
dev->pci_conf[0x71] = dev->pci_conf[0x75] = 0x00;
dev->pci_conf[0x73] = dev->pci_conf[0x77] = 0x80;
dev->pci_conf[0x79] = dev->pci_conf[0x7d] = 0x00;
dev->pci_conf[0x7b] = dev->pci_conf[0x7f] = 0x80;
dev->pci_conf[0x80] = dev->pci_conf[0x81] = 0x00;
dev->pci_conf[0x82] = dev->pci_conf[0x83] = 0x00;
dev->pci_conf[0x84] = dev->pci_conf[0x85] = 0x00;
dev->pci_conf[0x86] = 0x00;
cpu_cache_ext_enabled = 0;
cpu_update_waitstates();
sis_5511_smram_recalc(dev);
sis_5511_shadow_recalc(dev);
flushmmucache();
memset(dev->slic_regs, 0x00, 4096 * sizeof(uint8_t));
dev->slic_regs[0x18] = 0x0f;
mem_mapping_set_addr(&dev->slic_mapping, 0xffc00000, 0x00001000);
}
static void
sis_5511_host_to_pci_close(void *priv)
{
sis_5511_host_to_pci_t *dev = (sis_5511_host_to_pci_t *) priv;
smram_del(dev->smram);
free(dev);
}
static void *
sis_5511_host_to_pci_init(UNUSED(const device_t *info))
{
sis_5511_host_to_pci_t *dev = (sis_5511_host_to_pci_t *) calloc(1, sizeof(sis_5511_host_to_pci_t));
dev->sis = device_get_common_priv();
/* SLiC Memory Mapped Registers */
mem_mapping_add(&dev->slic_mapping,
0xffc00000, 0x00001000,
sis_5511_slic_read,
NULL,
NULL,
sis_5511_slic_write,
NULL,
NULL,
NULL, MEM_MAPPING_EXTERNAL,
dev);
/* SMRAM */
dev->smram = smram_add();
sis_5511_host_to_pci_reset(dev);
return dev;
}
const device_t sis_5511_h2p_device = {
.name = "SiS 5511 Host to PCI bridge",
.internal_name = "sis_5511_host_to_pci",
.flags = DEVICE_PCI,
.local = 0x00,
.init = sis_5511_host_to_pci_init,
.close = sis_5511_host_to_pci_close,
.reset = sis_5511_host_to_pci_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

501
src/chipset/sis_5513_ide.c Normal file
View File

@@ -0,0 +1,501 @@
/*
* 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 SiS 5513 IDE controller.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2024 Miran Grca.
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/io.h>
#include <86box/timer.h>
#include <86box/dma.h>
#include <86box/mem.h>
#include <86box/nvr.h>
#include <86box/hdd.h>
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
#include <86box/hdc_ide_sff8038i.h>
#include <86box/pci.h>
#include <86box/pic.h>
#include <86box/pit.h>
#include <86box/pit_fast.h>
#include <86box/plat.h>
#include <86box/plat_unused.h>
#include <86box/port_92.h>
#include <86box/smram.h>
#include <86box/spd.h>
#include <86box/apm.h>
#include <86box/ddma.h>
#include <86box/acpi.h>
#include <86box/smbus.h>
#include <86box/sis_55xx.h>
#include <86box/chipset.h>
#ifdef ENABLE_SIS_5513_IDE_LOG
int sis_5513_ide_do_log = ENABLE_SIS_5513_IDE_LOG;
static void
sis_5513_ide_log(const char *fmt, ...)
{
va_list ap;
if (sis_5513_ide_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define sis_5513_ide_log(fmt, ...)
#endif
typedef struct sis_5513_ide_t {
uint8_t rev;
uint8_t pci_conf[256];
sis_55xx_common_t *sis;
} sis_5513_ide_t;
static void
sis_5513_ide_irq_handler(sis_5513_ide_t *dev)
{
if (dev->pci_conf[0x09] & 0x01) {
/* Primary IDE is native. */
sis_5513_ide_log("Primary IDE IRQ mode: Native, Native\n");
sff_set_irq_mode(dev->sis->bm[0], IRQ_MODE_SIS_551X);
} else {
/* Primary IDE is legacy. */
sis_5513_ide_log("Primary IDE IRQ mode: IRQ14, IRQ15\n");
sff_set_irq_mode(dev->sis->bm[0], IRQ_MODE_LEGACY);
}
if (dev->pci_conf[0x09] & 0x04) {
/* Secondary IDE is native. */
sis_5513_ide_log("Secondary IDE IRQ mode: Native, Native\n");
sff_set_irq_mode(dev->sis->bm[1], IRQ_MODE_SIS_551X);
} else {
/* Secondary IDE is legacy. */
sis_5513_ide_log("Secondary IDE IRQ mode: IRQ14, IRQ15\n");
sff_set_irq_mode(dev->sis->bm[1], IRQ_MODE_LEGACY);
}
}
static void
sis_5513_ide_handler(sis_5513_ide_t *dev)
{
uint8_t ide_io_on = dev->pci_conf[0x04] & 0x01;
uint16_t native_base_pri_addr = (dev->pci_conf[0x11] | dev->pci_conf[0x10] << 8) & 0xfffe;
uint16_t native_side_pri_addr = (dev->pci_conf[0x15] | dev->pci_conf[0x14] << 8) & 0xfffe;
uint16_t native_base_sec_addr = (dev->pci_conf[0x19] | dev->pci_conf[0x18] << 8) & 0xfffe;
uint16_t native_side_sec_addr = (dev->pci_conf[0x1c] | dev->pci_conf[0x1b] << 8) & 0xfffe;
uint16_t current_pri_base;
uint16_t current_pri_side;
uint16_t current_sec_base;
uint16_t current_sec_side;
/* Primary Channel Programming */
current_pri_base = (!(dev->pci_conf[0x09] & 1)) ? 0x01f0 : native_base_pri_addr;
current_pri_side = (!(dev->pci_conf[0x09] & 1)) ? 0x03f6 : native_side_pri_addr;
/* Secondary Channel Programming */
current_sec_base = (!(dev->pci_conf[0x09] & 4)) ? 0x0170 : native_base_sec_addr;
current_sec_side = (!(dev->pci_conf[0x09] & 4)) ? 0x0376 : native_side_sec_addr;
sis_5513_ide_log("sis_5513_ide_handler(): Disabling primary IDE...\n");
ide_pri_disable();
sis_5513_ide_log("sis_5513_ide_handler(): Disabling secondary IDE...\n");
ide_sec_disable();
if (ide_io_on) {
/* Primary Channel Setup */
if (dev->pci_conf[0x4a] & 0x02) {
sis_5513_ide_log("sis_5513_ide_handler(): Primary IDE base now %04X...\n", current_pri_base);
ide_set_base(0, current_pri_base);
sis_5513_ide_log("sis_5513_ide_handler(): Primary IDE side now %04X...\n", current_pri_side);
ide_set_side(0, current_pri_side);
sis_5513_ide_log("sis_5513_ide_handler(): Enabling primary IDE...\n");
ide_pri_enable();
sis_5513_ide_log("SiS 5513 PRI: BASE %04x SIDE %04x\n", current_pri_base, current_pri_side);
}
/* Secondary Channel Setup */
if (dev->pci_conf[0x4a] & 0x04) {
sis_5513_ide_log("sis_5513_ide_handler(): Secondary IDE base now %04X...\n", current_sec_base);
ide_set_base(1, current_sec_base);
sis_5513_ide_log("sis_5513_ide_handler(): Secondary IDE side now %04X...\n", current_sec_side);
ide_set_side(1, current_sec_side);
sis_5513_ide_log("sis_5513_ide_handler(): Enabling secondary IDE...\n");
ide_sec_enable();
sis_5513_ide_log("SiS 5513: BASE %04x SIDE %04x\n", current_sec_base, current_sec_side);
}
}
sff_bus_master_handler(dev->sis->bm[0], ide_io_on,
((dev->pci_conf[0x20] & 0xf0) | (dev->pci_conf[0x21] << 8)) + 0);
sff_bus_master_handler(dev->sis->bm[1], ide_io_on,
((dev->pci_conf[0x20] & 0xf0) | (dev->pci_conf[0x21] << 8)) + 8);
}
void
sis_5513_ide_write(int addr, uint8_t val, void *priv)
{
sis_5513_ide_t *dev = (sis_5513_ide_t *) priv;
sis_5513_ide_log("SiS 5513 IDE: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
switch (addr) {
case 0x04: /* Command low byte */
dev->pci_conf[addr] = val & 0x05;
sis_5513_ide_handler(dev);
break;
case 0x06: /* Status low byte */
dev->pci_conf[addr] = val & 0x20;
break;
case 0x07: /* Status high byte */
dev->pci_conf[addr] = (dev->pci_conf[addr] & 0x06) & ~(val & 0x38);
break;
case 0x09: /* Programming Interface Byte */
switch (dev->rev) {
case 0xd0:
if (dev->sis->ide_bits_1_3_writable)
val |= 0x0a;
fallthrough;
case 0x00:
case 0xd1:
val &= 0xbf;
fallthrough;
case 0xc0:
switch (val & 0x0a) {
case 0x00:
dev->pci_conf[addr] = (dev->pci_conf[addr] & 0x85) | (val & 0x4a);
break;
case 0x02:
dev->pci_conf[addr] = (dev->pci_conf[addr] & 0x84) | (val & 0x4b);
break;
case 0x08:
dev->pci_conf[addr] = (dev->pci_conf[addr] & 0x81) | (val & 0x4e);
break;
case 0x0a:
dev->pci_conf[addr] = (dev->pci_conf[addr] & 0x80) | (val & 0x4f);
break;
}
break;
}
sis_5513_ide_irq_handler(dev);
sis_5513_ide_handler(dev);
break;
case 0x0d: /* Latency Timer */
dev->pci_conf[addr] = val;
break;
/* Primary Base Address */
case 0x10 ... 0x11:
case 0x14 ... 0x15:
fallthrough;
/* Secondary Base Address */
case 0x18 ... 0x19:
case 0x1c ... 0x1d:
fallthrough;
/* Bus Mastering Base Address */
case 0x20 ... 0x21:
if (addr == 0x20)
dev->pci_conf[addr] = (val & 0xe0) | 0x01;
else
dev->pci_conf[addr] = val;
sis_5513_ide_handler(dev);
break;
case 0x2c ... 0x2f:
if (dev->rev >= 0xd0)
dev->pci_conf[addr] = val;
break;
case 0x30 ... 0x33: /* Expansion ROM Base Address */
#ifdef DATASHEET
dev->pci_conf[addr] = val;
#else
if (dev->rev == 0x00)
dev->pci_conf[addr] = val;
#endif
break;
case 0x40: /* IDE Primary Channel/Master Drive Data Recovery Time Control */
if (dev->rev >= 0xd0)
dev->pci_conf[addr] = val & 0xcf;
else
dev->pci_conf[addr] = val & 0x0f;
break;
case 0x42: /* IDE Primary Channel/Slave Drive Data Recovery Time Control */
case 0x44: /* IDE Secondary Channel/Master Drive Data Recovery Time Control */
case 0x46: /* IDE Secondary Channel/Slave Drive Data Recovery Time Control */
case 0x48: /* IDE Command Recovery Time Control */
dev->pci_conf[addr] = val & 0x0f;
break;
case 0x41: /* IDE Primary Channel/Master Drive DataActive Time Control */
case 0x43: /* IDE Primary Channel/Slave Drive Data Active Time Control */
case 0x45: /* IDE Secondary Channel/Master Drive Data Active Time Control */
case 0x47: /* IDE Secondary Channel/Slave Drive Data Active Time Control */
if (dev->rev >= 0xd0)
dev->pci_conf[addr] = val & 0xe7;
else
dev->pci_conf[addr] = val & 0x07;
break;
case 0x49: /* IDE Command Active Time Control */
dev->pci_conf[addr] = val & 0x07;
break;
case 0x4a: /* IDE General Control Register 0 */
switch (dev->rev) {
case 0x00:
dev->pci_conf[addr] = val & 0x9e;
break;
case 0xc0:
dev->pci_conf[addr] = val & 0xaf;
break;
case 0xd0:
dev->pci_conf[addr] = val;
break;
}
sis_5513_ide_handler(dev);
break;
case 0x4b: /* IDE General Control Register 1 */
if (dev->rev >= 0xc0)
dev->pci_conf[addr] = val;
else
dev->pci_conf[addr] = val & 0xef;
break;
case 0x4c: /* Prefetch Count of Primary Channel (Low Byte) */
case 0x4d: /* Prefetch Count of Primary Channel (High Byte) */
case 0x4e: /* Prefetch Count of Secondary Channel (Low Byte) */
case 0x4f: /* Prefetch Count of Secondary Channel (High Byte) */
dev->pci_conf[addr] = val;
break;
case 0x50:
case 0x51:
if (dev->rev >= 0xd0)
dev->pci_conf[addr] = val;
break;
case 0x52:
if (dev->rev >= 0xd0)
dev->pci_conf[addr] = val & 0x0f;
break;
default:
break;
}
}
uint8_t
sis_5513_ide_read(int addr, void *priv)
{
const sis_5513_ide_t *dev = (sis_5513_ide_t *) priv;
uint8_t ret = 0xff;
switch (addr) {
default:
ret = dev->pci_conf[addr];
break;
case 0x09:
ret = dev->pci_conf[addr];
if (dev->rev >= 0xc0) {
if (dev->pci_conf[0x09] & 0x40)
ret |= ((dev->pci_conf[0x4a] & 0x06) << 3);
if ((dev->rev == 0xd0) && dev->sis->ide_bits_1_3_writable)
ret |= 0x0a;
}
break;
case 0x3d:
if (dev->rev >= 0xc0)
ret = (dev->pci_conf[0x09] & 0x05) ? PCI_INTA : 0x00;
else
ret = (((dev->pci_conf[0x4b] & 0xc0) == 0xc0) ||
(dev->pci_conf[0x09] & 0x05)) ? PCI_INTA : 0x00;
break;
}
sis_5513_ide_log("SiS 5513 IDE: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
return ret;
}
static void
sis_5513_ide_reset(void *priv)
{
sis_5513_ide_t *dev = (sis_5513_ide_t *) priv;
dev->pci_conf[0x00] = 0x39;
dev->pci_conf[0x01] = 0x10;
dev->pci_conf[0x02] = 0x13;
dev->pci_conf[0x03] = 0x55;
dev->pci_conf[0x04] = dev->pci_conf[0x05] = 0x00;
dev->pci_conf[0x06] = dev->pci_conf[0x07] = 0x00;
dev->pci_conf[0x08] = (dev->rev == 0xd1) ? 0xd0 : dev->rev;
dev->pci_conf[0x09] = 0x8a;
dev->pci_conf[0x0a] = dev->pci_conf[0x0b] = 0x01;
dev->pci_conf[0x0c] = dev->pci_conf[0x0d] = 0x00;
dev->pci_conf[0x0e] = 0x80;
dev->pci_conf[0x0f] = 0x00;
dev->pci_conf[0x10] = 0xf1;
dev->pci_conf[0x11] = 0x01;
dev->pci_conf[0x14] = 0xf5;
dev->pci_conf[0x15] = 0x03;
dev->pci_conf[0x18] = 0x71;
dev->pci_conf[0x19] = 0x01;
dev->pci_conf[0x1c] = 0x75;
dev->pci_conf[0x1d] = 0x03;
dev->pci_conf[0x20] = 0x01;
dev->pci_conf[0x21] = 0xf0;
dev->pci_conf[0x22] = dev->pci_conf[0x23] = 0x00;
dev->pci_conf[0x24] = dev->pci_conf[0x25] = 0x00;
dev->pci_conf[0x26] = dev->pci_conf[0x27] = 0x00;
dev->pci_conf[0x28] = dev->pci_conf[0x29] = 0x00;
dev->pci_conf[0x2a] = dev->pci_conf[0x2b] = 0x00;
switch (dev->rev) {
case 0x00:
case 0xd0:
case 0xd1:
dev->pci_conf[0x2c] = dev->pci_conf[0x2d] = 0x00;
break;
case 0xc0:
#ifdef DATASHEET
dev->pci_conf[0x2c] = dev->pci_conf[0x2d] = 0x00;
#else
/* The only Linux lspci listing I could find of this chipset,
shows a subsystem of 0058:0000. */
dev->pci_conf[0x2c] = 0x58;
dev->pci_conf[0x2d] = 0x00;
#endif
break;
}
dev->pci_conf[0x2e] = dev->pci_conf[0x2f] = 0x00;
dev->pci_conf[0x30] = dev->pci_conf[0x31] = 0x00;
dev->pci_conf[0x32] = dev->pci_conf[0x33] = 0x00;
dev->pci_conf[0x40] = dev->pci_conf[0x41] = 0x00;
dev->pci_conf[0x42] = dev->pci_conf[0x43] = 0x00;
dev->pci_conf[0x44] = dev->pci_conf[0x45] = 0x00;
dev->pci_conf[0x46] = dev->pci_conf[0x47] = 0x00;
dev->pci_conf[0x48] = dev->pci_conf[0x49] = 0x00;
dev->pci_conf[0x4a] = 0x06;
dev->pci_conf[0x4b] = 0x00;
dev->pci_conf[0x4c] = dev->pci_conf[0x4d] = 0x00;
dev->pci_conf[0x4e] = dev->pci_conf[0x4f] = 0x00;
sis_5513_ide_irq_handler(dev);
sis_5513_ide_handler(dev);
sff_bus_master_reset(dev->sis->bm[0]);
sff_bus_master_reset(dev->sis->bm[1]);
}
static void
sis_5513_ide_close(void *priv)
{
sis_5513_ide_t *dev = (sis_5513_ide_t *) priv;
free(dev);
}
static void *
sis_5513_ide_init(UNUSED(const device_t *info))
{
sis_5513_ide_t *dev = (sis_5513_ide_t *) calloc(1, sizeof(sis_5513_ide_t));
dev->rev = info->local;
dev->sis = device_get_common_priv();
/* SFF IDE */
dev->sis->bm[0] = device_add_inst(&sff8038i_device, 1);
dev->sis->bm[1] = device_add_inst(&sff8038i_device, 2);
sis_5513_ide_reset(dev);
return dev;
}
const device_t sis_5513_ide_device = {
.name = "SiS 5513 IDE controller",
.internal_name = "sis_5513_ide",
.flags = DEVICE_PCI,
.local = 0x00,
.init = sis_5513_ide_init,
.close = sis_5513_ide_close,
.reset = sis_5513_ide_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t sis_5572_ide_device = {
.name = "SiS 5572 IDE controller",
.internal_name = "sis_5572_ide",
.flags = DEVICE_PCI,
.local = 0xc0,
.init = sis_5513_ide_init,
.close = sis_5513_ide_close,
.reset = sis_5513_ide_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t sis_5582_ide_device = {
.name = "SiS 5582 IDE controller",
.internal_name = "sis_5582_ide",
.flags = DEVICE_PCI,
.local = 0xd0,
.init = sis_5513_ide_init,
.close = sis_5513_ide_close,
.reset = sis_5513_ide_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t sis_5591_5600_ide_device = {
.name = "SiS 5591/(5)600 IDE controller",
.internal_name = "sis_5591_5600_ide",
.flags = DEVICE_PCI,
.local = 0xd1, /* D0, but we need to distinguish them. */
.init = sis_5513_ide_init,
.close = sis_5513_ide_close,
.reset = sis_5513_ide_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

1354
src/chipset/sis_5513_p2i.c Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

458
src/chipset/sis_5571_h2p.c Normal file
View File

@@ -0,0 +1,458 @@
/*
* 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 SiS 5571 Host to PCI bridge.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2024 Miran Grca.
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/io.h>
#include <86box/timer.h>
#include <86box/dma.h>
#include <86box/mem.h>
#include <86box/nvr.h>
#include <86box/hdd.h>
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
#include <86box/hdc_ide_sff8038i.h>
#include <86box/pci.h>
#include <86box/pic.h>
#include <86box/pit.h>
#include <86box/pit_fast.h>
#include <86box/plat.h>
#include <86box/plat_unused.h>
#include <86box/port_92.h>
#include <86box/smram.h>
#include <86box/spd.h>
#include <86box/apm.h>
#include <86box/ddma.h>
#include <86box/acpi.h>
#include <86box/smbus.h>
#include <86box/spd.h>
#include <86box/sis_55xx.h>
#include <86box/chipset.h>
#include <86box/usb.h>
#include <86box/agpgart.h>
#ifdef ENABLE_SIS_5571_HOST_TO_PCI_LOG
int sis_5571_host_to_pci_do_log = ENABLE_SIS_5571_HOST_TO_PCI_LOG;
static void
sis_5571_host_to_pci_log(const char *fmt, ...)
{
va_list ap;
if (sis_5571_host_to_pci_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define sis_5571_host_to_pci_log(fmt, ...)
#endif
typedef struct sis_5571_host_to_pci_t {
uint8_t pci_conf[256];
uint8_t states[7];
sis_55xx_common_t *sis;
smram_t *smram;
} sis_5571_host_to_pci_t;
static void
sis_5571_shadow_recalc(sis_5571_host_to_pci_t *dev)
{
int state;
uint32_t base;
for (uint8_t i = 0x70; i <= 0x76; i++) {
if (i == 0x76) {
if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0xa0) {
state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
mem_set_mem_state_both(0xf0000, 0x10000, state);
sis_5571_host_to_pci_log("000F0000-000FFFFF\n");
}
} else {
base = ((i & 0x07) << 15) + 0xc0000;
if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0xa0) {
state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
mem_set_mem_state_both(base, 0x4000, state);
sis_5571_host_to_pci_log("%08X-%08X\n", base, base + 0x3fff);
}
if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0x0a) {
state = (dev->pci_conf[i] & 0x08) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
state |= (dev->pci_conf[i] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
mem_set_mem_state_both(base + 0x4000, 0x4000, state);
sis_5571_host_to_pci_log("%08X-%08X\n", base + 0x4000, base + 0x7fff);
}
}
dev->states[i & 0x0f] = dev->pci_conf[i];
}
flushmmucache_nopc();
}
static void
sis_5571_smram_recalc(sis_5571_host_to_pci_t *dev)
{
smram_disable_all();
switch (dev->pci_conf[0x68] >> 6) {
case 0:
smram_enable(dev->smram, 0x000e0000, 0x000e0000, 0x8000, dev->pci_conf[0x68] & 0x10, 1);
break;
case 1:
smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x8000, dev->pci_conf[0x68] & 0x10, 1);
break;
case 2:
smram_enable(dev->smram, 0x000e0000, 0x000b0000, 0x8000, dev->pci_conf[0x68] & 0x10, 1);
break;
case 3:
smram_enable(dev->smram, 0x000a0000, 0x000a0000, 0x10000, dev->pci_conf[0x68] & 0x10, 1);
break;
default:
break;
}
flushmmucache();
}
void
sis_5571_host_to_pci_write(int addr, uint8_t val, void *priv)
{
sis_5571_host_to_pci_t *dev = (sis_5571_host_to_pci_t *) priv;
sis_5571_host_to_pci_log("SiS 5571 H2P: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
switch (addr) {
default:
break;
case 0x04: /* Command - low byte */
case 0x05: /* Command - high byte */
dev->pci_conf[addr] = (dev->pci_conf[addr] & 0xfd) | (val & 0x02);
break;
case 0x07: /* Status - High Byte */
dev->pci_conf[addr] &= ~(val & 0xb8);
break;
case 0x0d: /* Master latency timer */
dev->pci_conf[addr] = val;
break;
case 0x50: /* Host Interface and DRAM arbiter */
dev->pci_conf[addr] = val & 0xec;
break;
case 0x51: /* CACHE */
dev->pci_conf[addr] = val;
cpu_cache_ext_enabled = !!(val & 0x40);
cpu_update_waitstates();
break;
case 0x52:
dev->pci_conf[addr] = val & 0xd0;
break;
case 0x53: /* DRAM */
dev->pci_conf[addr] = val & 0xfe;
break;
case 0x54: /* FP/EDO */
dev->pci_conf[addr] = val;
break;
case 0x55:
dev->pci_conf[addr] = val & 0xe0;
break;
case 0x56: /* MDLE delay */
dev->pci_conf[addr] = val & 0x07;
break;
case 0x57: /* SDRAM */
dev->pci_conf[addr] = val & 0xf8;
break;
case 0x59: /* Buffer strength and current rating */
dev->pci_conf[addr] = val;
break;
case 0x5a:
dev->pci_conf[addr] = val & 0x03;
break;
/* Undocumented - DRAM bank registers, the exact layout is currently unknown. */
case 0x60 ... 0x6b:
dev->pci_conf[addr] = val;
break;
case 0x70 ... 0x75:
dev->pci_conf[addr] = val & 0xee;
sis_5571_shadow_recalc(dev);
break;
case 0x76:
dev->pci_conf[addr] = val & 0xe8;
sis_5571_shadow_recalc(dev);
break;
case 0x77: /* Characteristics of non-cacheable area */
dev->pci_conf[addr] = val & 0x0f;
break;
case 0x78: /* Allocation of Non-Cacheable area #1 */
case 0x79: /* NCA1REG2 */
case 0x7a: /* Allocation of Non-Cacheable area #2 */
case 0x7b: /* NCA2REG2 */
dev->pci_conf[addr] = val;
break;
case 0x80: /* PCI master characteristics */
dev->pci_conf[addr] = val & 0xfe;
break;
case 0x81:
dev->pci_conf[addr] = val & 0xcc;
break;
case 0x82:
dev->pci_conf[addr] = val;
break;
case 0x83: /* CPU to PCI characteristics */
dev->pci_conf[addr] = val;
/* TODO: Implement Fast A20 and Fast reset stuff on the KBC already! */
break;
case 0x84 ... 0x86:
dev->pci_conf[addr] = val;
break;
case 0x87: /* Miscellanea */
dev->pci_conf[addr] = val & 0xf8;
break;
case 0x90: /* PMU control register */
case 0x91: /* Address trap for green function */
case 0x92:
dev->pci_conf[addr] = val;
break;
case 0x93: /* STPCLK# and APM SMI control */
dev->pci_conf[addr] = val;
if ((dev->pci_conf[0x9b] & 0x01) && (val & 0x02)) {
smi_raise();
dev->pci_conf[0x9d] |= 0x01;
}
break;
case 0x94: /* 6x86 and Green function control */
dev->pci_conf[addr] = val & 0xf8;
break;
case 0x95: /* Test mode control */
case 0x96: /* Time slot and Programmable 10-bit I/O port definition */
dev->pci_conf[addr] = val & 0xfb;
break;
case 0x97: /* programmable 10-bit I/O port address */
case 0x98: /* Programmable 16-bit I/O port */
case 0x99 ... 0x9c:
dev->pci_conf[addr] = val;
break;
case 0x9d:
dev->pci_conf[addr] &= val;
break;
case 0x9e: /* STPCLK# Assertion Timer */
case 0x9f: /* STPCLK# De-assertion Timer */
case 0xa0 ... 0xa2:
dev->pci_conf[addr] = val;
break;
case 0xa3: /* SMRAM access control and Power supply control */
dev->pci_conf[addr] = val & 0xd0;
sis_5571_smram_recalc(dev);
break;
}
}
uint8_t
sis_5571_host_to_pci_read(int addr, void *priv)
{
const sis_5571_host_to_pci_t *dev = (sis_5571_host_to_pci_t *) priv;
uint8_t ret = 0xff;
ret = dev->pci_conf[addr];
sis_5571_host_to_pci_log("SiS 5571 H2P: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
return ret;
}
static void
sis_5571_host_to_pci_reset(void *priv)
{
sis_5571_host_to_pci_t *dev = (sis_5571_host_to_pci_t *) priv;
dev->pci_conf[0x00] = 0x39;
dev->pci_conf[0x01] = 0x10;
dev->pci_conf[0x02] = 0x71;
dev->pci_conf[0x03] = 0x55;
dev->pci_conf[0x04] = 0x05;
dev->pci_conf[0x05] = 0x00;
dev->pci_conf[0x06] = 0x00;
dev->pci_conf[0x07] = 0x02;
dev->pci_conf[0x08] = 0x00;
dev->pci_conf[0x09] = 0x00;
dev->pci_conf[0x0a] = 0x00;
dev->pci_conf[0x0b] = 0x06;
dev->pci_conf[0x0c] = 0x00;
dev->pci_conf[0x0d] = 0x00;
dev->pci_conf[0x0e] = 0x00;
dev->pci_conf[0x0f] = 0x00;
dev->pci_conf[0x50] = 0x00;
dev->pci_conf[0x51] = 0x00;
dev->pci_conf[0x52] = 0x00;
dev->pci_conf[0x53] = 0x00;
dev->pci_conf[0x54] = 0x54;
dev->pci_conf[0x55] = 0x54;
dev->pci_conf[0x56] = 0x03;
dev->pci_conf[0x57] = 0x00;
dev->pci_conf[0x58] = 0x00;
dev->pci_conf[0x59] = 0x00;
dev->pci_conf[0x5a] = 0x00;
/* Undocumented DRAM bank registers. */
dev->pci_conf[0x60] = dev->pci_conf[0x62] = 0x04;
dev->pci_conf[0x64] = dev->pci_conf[0x66] = 0x04;
dev->pci_conf[0x68] = dev->pci_conf[0x6a] = 0x04;
dev->pci_conf[0x61] = dev->pci_conf[0x65] = 0x00;
dev->pci_conf[0x63] = dev->pci_conf[0x67] = 0x80;
dev->pci_conf[0x69] = 0x00;
dev->pci_conf[0x6b] = 0x80;
dev->pci_conf[0x70] = 0x00;
dev->pci_conf[0x71] = 0x00;
dev->pci_conf[0x72] = 0x00;
dev->pci_conf[0x73] = 0x00;
dev->pci_conf[0x74] = 0x00;
dev->pci_conf[0x75] = 0x00;
dev->pci_conf[0x76] = 0x00;
dev->pci_conf[0x77] = 0x00;
dev->pci_conf[0x78] = 0x00;
dev->pci_conf[0x79] = 0x00;
dev->pci_conf[0x7a] = 0x00;
dev->pci_conf[0x7b] = 0x00;
dev->pci_conf[0x80] = 0x00;
dev->pci_conf[0x81] = 0x00;
dev->pci_conf[0x82] = 0x00;
dev->pci_conf[0x83] = 0x00;
dev->pci_conf[0x84] = 0x00;
dev->pci_conf[0x85] = 0x00;
dev->pci_conf[0x86] = 0x00;
dev->pci_conf[0x87] = 0x00;
dev->pci_conf[0x8c] = 0x00;
dev->pci_conf[0x8d] = 0x00;
dev->pci_conf[0x8e] = 0x00;
dev->pci_conf[0x8f] = 0x00;
dev->pci_conf[0x90] = 0x00;
dev->pci_conf[0x91] = 0x00;
dev->pci_conf[0x92] = 0x00;
dev->pci_conf[0x93] = 0x00;
dev->pci_conf[0x93] = 0x00;
dev->pci_conf[0x94] = 0x00;
dev->pci_conf[0x95] = 0x00;
dev->pci_conf[0x96] = 0x00;
dev->pci_conf[0x97] = 0x00;
dev->pci_conf[0x98] = 0x00;
dev->pci_conf[0x99] = 0x00;
dev->pci_conf[0x9a] = 0x00;
dev->pci_conf[0x9b] = 0x00;
dev->pci_conf[0x9c] = 0x00;
dev->pci_conf[0x9d] = 0x00;
dev->pci_conf[0x9e] = 0xff;
dev->pci_conf[0x9f] = 0xff;
dev->pci_conf[0xa0] = 0xff;
dev->pci_conf[0xa1] = 0x00;
dev->pci_conf[0xa2] = 0xff;
dev->pci_conf[0xa3] = 0x00;
cpu_cache_ext_enabled = 0;
cpu_update_waitstates();
sis_5571_smram_recalc(dev);
sis_5571_shadow_recalc(dev);
flushmmucache();
}
static void
sis_5571_host_to_pci_close(void *priv)
{
sis_5571_host_to_pci_t *dev = (sis_5571_host_to_pci_t *) priv;
smram_del(dev->smram);
free(dev);
}
static void *
sis_5571_host_to_pci_init(UNUSED(const device_t *info))
{
sis_5571_host_to_pci_t *dev = (sis_5571_host_to_pci_t *) calloc(1, sizeof(sis_5571_host_to_pci_t));
dev->sis = device_get_common_priv();
/* SMRAM */
dev->smram = smram_add();
sis_5571_host_to_pci_reset(dev);
return dev;
}
const device_t sis_5571_h2p_device = {
.name = "SiS 5571 Host to PCI bridge",
.internal_name = "sis_5571_host_to_pci",
.flags = DEVICE_PCI,
.local = 0x00,
.init = sis_5571_host_to_pci_init,
.close = sis_5571_host_to_pci_close,
.reset = sis_5571_host_to_pci_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

772
src/chipset/sis_5571_old.c Normal file
View File

@@ -0,0 +1,772 @@
/*
* 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 SiS 5571 Chipset.
*
*
*
* Authors: Tiseno100,
*
* Copyright 2021 Tiseno100.
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/io.h>
#include <86box/timer.h>
#include <86box/dma.h>
#include <86box/mem.h>
#include <86box/pci.h>
#include <86box/pic.h>
#include <86box/plat_unused.h>
#include <86box/port_92.h>
#include <86box/hdc_ide.h>
#include <86box/hdc_ide_sff8038i.h>
#include <86box/smram.h>
#include <86box/usb.h>
#include <86box/chipset.h>
/* Shadow RAM */
#define LSB_READ ((dev->pci_conf[0x70 + (cur_reg & 0x07)] & 0x08) ? MEM_READ_INTERNAL : MEM_READ_EXTANY)
#define LSB_WRITE ((dev->pci_conf[0x70 + (cur_reg & 0x07)] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)
#define MSB_READ ((dev->pci_conf[0x70 + (cur_reg & 0x07)] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY)
#define MSB_WRITE ((dev->pci_conf[0x70 + (cur_reg & 0x07)] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)
#define SYSTEM_READ ((dev->pci_conf[0x76] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY)
#define SYSTEM_WRITE ((dev->pci_conf[0x76] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)
/* IDE Flags (1 Native / 0 Compatibility)*/
#define PRIMARY_COMP_NAT_SWITCH (dev->pci_conf_sb[1][9] & 1)
#define SECONDARY_COMP_NAT_SWITCH (dev->pci_conf_sb[1][9] & 4)
#define PRIMARY_NATIVE_BASE (dev->pci_conf_sb[1][0x11] << 8) | (dev->pci_conf_sb[1][0x10] & 0xf8)
#define PRIMARY_NATIVE_SIDE (((dev->pci_conf_sb[1][0x15] << 8) | (dev->pci_conf_sb[1][0x14] & 0xfc)) + 2)
#define SECONDARY_NATIVE_BASE (dev->pci_conf_sb[1][0x19] << 8) | (dev->pci_conf_sb[1][0x18] & 0xf8)
#define SECONDARY_NATIVE_SIDE (((dev->pci_conf_sb[1][0x1d] << 8) | (dev->pci_conf_sb[1][0x1c] & 0xfc)) + 2)
#define BUS_MASTER_BASE ((dev->pci_conf_sb[1][0x20] & 0xf0) | (dev->pci_conf_sb[1][0x21] << 8))
#ifdef ENABLE_SIS_5571_LOG
int sis_5571_do_log = ENABLE_SIS_5571_LOG;
static void
sis_5571_log(const char *fmt, ...)
{
va_list ap;
if (sis_5571_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define sis_5571_log(fmt, ...)
#endif
typedef struct sis_5571_t {
uint8_t nb_slot;
uint8_t sb_slot;
uint8_t pad;
uint8_t usb_irq_state;
uint8_t pci_conf[256];
uint8_t pci_conf_sb[3][256];
port_92_t *port_92;
sff8038i_t *ide_drive[2];
smram_t *smram;
usb_t *usb;
} sis_5571_t;
static void
sis_5571_shadow_recalc(int cur_reg, sis_5571_t *dev)
{
if (cur_reg != 0x76) {
mem_set_mem_state_both(0xc0000 + (0x8000 * (cur_reg & 0x07)), 0x4000, LSB_READ | LSB_WRITE);
mem_set_mem_state_both(0xc4000 + (0x8000 * (cur_reg & 0x07)), 0x4000, MSB_READ | MSB_WRITE);
} else
mem_set_mem_state_both(0xf0000, 0x10000, SYSTEM_READ | SYSTEM_WRITE);
flushmmucache_nopc();
}
static void
sis_5571_smm_recalc(sis_5571_t *dev)
{
smram_disable_all();
switch ((dev->pci_conf[0xa3] & 0xc0) >> 6) {
case 0x00:
smram_enable(dev->smram, 0xe0000, 0xe0000, 0x8000, (dev->pci_conf[0xa3] & 0x10), 1);
break;
case 0x01:
smram_enable(dev->smram, 0xe0000, 0xa0000, 0x8000, (dev->pci_conf[0xa3] & 0x10), 1);
break;
case 0x02:
smram_enable(dev->smram, 0xe0000, 0xb0000, 0x8000, (dev->pci_conf[0xa3] & 0x10), 1);
break;
case 0x03:
smram_enable(dev->smram, 0xa0000, 0xa0000, 0x10000, (dev->pci_conf[0xa3] & 0x10), 1);
break;
default:
break;
}
flushmmucache();
}
void
sis_5571_ide_handler(sis_5571_t *dev)
{
ide_pri_disable();
ide_sec_disable();
if (dev->pci_conf_sb[1][4] & 1) {
if (dev->pci_conf_sb[1][0x4a] & 4) {
ide_set_base(0, PRIMARY_COMP_NAT_SWITCH ? PRIMARY_NATIVE_BASE : 0x1f0);
ide_set_side(0, PRIMARY_COMP_NAT_SWITCH ? PRIMARY_NATIVE_SIDE : 0x3f6);
ide_pri_enable();
}
if (dev->pci_conf_sb[1][0x4a] & 2) {
ide_set_base(1, SECONDARY_COMP_NAT_SWITCH ? SECONDARY_NATIVE_BASE : 0x170);
ide_set_side(1, SECONDARY_COMP_NAT_SWITCH ? SECONDARY_NATIVE_SIDE : 0x376);
ide_sec_enable();
}
}
}
void
sis_5571_bm_handler(sis_5571_t *dev)
{
sff_bus_master_handler(dev->ide_drive[0], dev->pci_conf_sb[1][4] & 4, BUS_MASTER_BASE);
sff_bus_master_handler(dev->ide_drive[1], dev->pci_conf_sb[1][4] & 4, BUS_MASTER_BASE + 8);
}
static void
memory_pci_bridge_write(UNUSED(int func), int addr, uint8_t val, void *priv)
{
sis_5571_t *dev = (sis_5571_t *) priv;
switch (addr) {
case 0x04: /* Command - low byte */
case 0x05: /* Command - high byte */
dev->pci_conf[addr] |= val;
break;
case 0x06: /* Status - Low Byte */
dev->pci_conf[addr] &= val;
break;
case 0x07: /* Status - High Byte */
dev->pci_conf[addr] &= val & 0xbe;
break;
case 0x0d: /* Master latency timer */
dev->pci_conf[addr] = val;
break;
case 0x50: /* Host Interface and DRAM arbiter */
dev->pci_conf[addr] = val & 0xec;
break;
case 0x51: /* CACHE */
dev->pci_conf[addr] = val;
cpu_cache_ext_enabled = !!(val & 0x40);
cpu_update_waitstates();
break;
case 0x52:
dev->pci_conf[addr] = val & 0xd0;
break;
case 0x53: /* DRAM */
dev->pci_conf[addr] = val & 0xfe;
break;
case 0x54: /* FP/EDO */
dev->pci_conf[addr] = val;
break;
case 0x55:
dev->pci_conf[addr] = val & 0xe0;
break;
case 0x56: /* MDLE delay */
case 0x57: /* SDRAM */
dev->pci_conf[addr] = val & 0xf8;
break;
case 0x59: /* Buffer strength and current rating */
dev->pci_conf[addr] = val;
break;
case 0x5a:
dev->pci_conf[addr] = val & 0x03;
break;
case 0x60: /* Undocumented */
case 0x61: /* Undocumented */
case 0x62: /* Undocumented */
case 0x63: /* Undocumented */
case 0x64: /* Undocumented */
case 0x65: /* Undocumented */
case 0x66: /* Undocumented */
case 0x67: /* Undocumented */
case 0x68: /* Undocumented */
case 0x69: /* Undocumented */
case 0x6a: /* Undocumented */
case 0x6b: /* Undocumented */
dev->pci_conf[addr] = val;
break;
case 0x70:
case 0x71:
case 0x72:
case 0x73:
case 0x74:
case 0x75:
case 0x76: /* Attribute of shadow RAM for BIOS area */
dev->pci_conf[addr] = val & ((addr != 0x76) ? 0xee : 0xe8);
sis_5571_shadow_recalc(addr, dev);
sis_5571_smm_recalc(dev);
break;
case 0x77: /* Characteristics of non-cacheable area */
dev->pci_conf[addr] = val & 0x0f;
break;
case 0x78: /* Allocation of Non-Cacheable area #1 */
case 0x79: /* NCA1REG2 */
case 0x7a: /* Allocation of Non-Cacheable area #2 */
case 0x7b: /* NCA2REG2 */
dev->pci_conf[addr] = val;
break;
case 0x80: /* PCI master characteristics */
dev->pci_conf[addr] = val & 0xfe;
break;
case 0x81:
dev->pci_conf[addr] = val & 0xcc;
break;
case 0x82:
dev->pci_conf[addr] = val;
break;
case 0x83: /* CPU to PCI characteristics */
dev->pci_conf[addr] = val;
port_92_set_features(dev->port_92, !!(val & 0x40), !!(val & 0x80));
break;
case 0x84:
case 0x85:
case 0x86:
dev->pci_conf[addr] = val;
break;
case 0x87: /* Miscellanea */
dev->pci_conf[addr] = val & 0xf8;
break;
case 0x90: /* PMU control register */
case 0x91: /* Address trap for green function */
case 0x92:
dev->pci_conf[addr] = val;
break;
case 0x93: /* STPCLK# and APM SMI control */
dev->pci_conf[addr] = val;
if ((dev->pci_conf[0x9b] & 1) && !!(val & 2)) {
smi_raise();
dev->pci_conf[0x9d] |= 1;
}
break;
case 0x94: /* 6x86 and Green function control */
dev->pci_conf[addr] = val & 0xf8;
break;
case 0x95: /* Test mode control */
case 0x96: /* Time slot and Programmable 10-bit I/O port definition */
dev->pci_conf[addr] = val & 0xfb;
break;
case 0x97: /* programmable 10-bit I/O port address */
case 0x98: /* Programmable 16-bit I/O port */
case 0x99:
case 0x9a:
case 0x9b:
case 0x9c:
dev->pci_conf[addr] = val;
break;
case 0x9d:
dev->pci_conf[addr] &= val;
break;
case 0x9e: /* STPCLK# Assertion Timer */
case 0x9f: /* STPCLK# De-assertion Timer */
case 0xa0:
case 0xa1:
case 0xa2:
dev->pci_conf[addr] = val;
break;
case 0xa3: /* SMRAM access control and Power supply control */
dev->pci_conf[addr] = val & 0xd0;
sis_5571_smm_recalc(dev);
break;
default:
break;
}
sis_5571_log("SiS5571: dev->pci_conf[%02x] = %02x\n", addr, val);
}
static uint8_t
memory_pci_bridge_read(UNUSED(int func), int addr, void *priv)
{
const sis_5571_t *dev = (sis_5571_t *) priv;
sis_5571_log("SiS5571: dev->pci_conf[%02x] (%02x)\n", addr, dev->pci_conf[addr]);
return dev->pci_conf[addr];
}
static void
pci_isa_bridge_write(int func, int addr, uint8_t val, void *priv)
{
sis_5571_t *dev = (sis_5571_t *) priv;
switch (func) {
case 0: /* Bridge */
switch (addr) {
case 0x04: /* Command */
dev->pci_conf_sb[0][addr] |= val & 0x0f;
break;
case 0x06: /* Status */
dev->pci_conf_sb[0][addr] &= val;
break;
case 0x40: /* BIOS Control Register */
dev->pci_conf_sb[0][addr] = val & 0x3f;
break;
case 0x41: /* INTA# Remapping Control Register */
case 0x42: /* INTB# Remapping Control Register */
case 0x43: /* INTC# Remapping Control Register */
case 0x44: /* INTD# Remapping Control Register */
dev->pci_conf_sb[0][addr] = val & 0x8f;
pci_set_irq_routing((addr & 0x07), !(val & 0x80) ? (val & 0x0f) : PCI_IRQ_DISABLED);
break;
case 0x45:
dev->pci_conf_sb[0][addr] = val & 0xec;
switch ((val & 0xc0) >> 6) {
case 0:
cpu_set_isa_speed(7159091);
break;
case 1:
cpu_set_isa_pci_div(4);
break;
case 2:
cpu_set_isa_pci_div(3);
break;
default:
break;
}
break;
case 0x46:
dev->pci_conf_sb[0][addr] = val & 0xec;
break;
case 0x47: /* DMA Clock and Wait State Control Register */
dev->pci_conf_sb[0][addr] = val & 0x3e;
break;
case 0x48: /* ISA Master/DMA Memory Cycle Control Register 1 */
case 0x49: /* ISA Master/DMA Memory Cycle Control Register 2 */
case 0x4a: /* ISA Master/DMA Memory Cycle Control Register 3 */
case 0x4b: /* ISA Master/DMA Memory Cycle Control Register 4 */
dev->pci_conf_sb[0][addr] = val;
break;
case 0x4c:
case 0x4d:
case 0x4e:
case 0x4f:
case 0x50:
case 0x51:
case 0x52:
case 0x53:
case 0x54:
case 0x55:
case 0x56:
case 0x57:
case 0x58:
case 0x59:
case 0x5a:
case 0x5b:
case 0x5c:
case 0x5d:
case 0x5e:
dev->pci_conf_sb[0][addr] = val;
break;
case 0x5f:
dev->pci_conf_sb[0][addr] = val & 0x3f;
break;
case 0x60:
dev->pci_conf_sb[0][addr] = val;
break;
case 0x61: /* MIRQ Remapping Control Register */
dev->pci_conf_sb[0][addr] = val;
pci_set_mirq_routing(PCI_MIRQ0, !(val & 0x80) ? (val & 0x0f) : PCI_IRQ_DISABLED);
break;
case 0x62: /* On-board Device DMA Control Register */
dev->pci_conf_sb[0][addr] = val & 0x0f;
dma_set_drq((val & 0x07), 1);
break;
case 0x63: /* IDEIRQ Remapping Control Register */
dev->pci_conf_sb[0][addr] = val & 0x8f;
if (val & 0x80) {
sff_set_irq_line(dev->ide_drive[0], val & 0x0f);
sff_set_irq_line(dev->ide_drive[1], val & 0x0f);
}
break;
case 0x64: /* GPIO Control Register */
dev->pci_conf_sb[0][addr] = val & 0xef;
break;
case 0x65:
dev->pci_conf_sb[0][addr] = val & 0x1b;
break;
case 0x66: /* GPIO Output Mode Control Register */
case 0x67: /* GPIO Output Mode Control Register */
dev->pci_conf_sb[0][addr] = val;
break;
case 0x68: /* USBIRQ Remapping Control Register */
dev->pci_conf_sb[0][addr] = val & 0x1b;
break;
case 0x69:
dev->pci_conf_sb[0][addr] = val;
break;
case 0x6a:
dev->pci_conf_sb[0][addr] = val & 0xfc;
break;
case 0x6b:
dev->pci_conf_sb[0][addr] = val;
break;
case 0x6c:
dev->pci_conf_sb[0][addr] = val & 0x03;
break;
case 0x6e: /* Software-Controlled Interrupt Request, Channels 7-0 */
case 0x6f: /* Software-Controlled Interrupt Request, channels 15-8 */
dev->pci_conf_sb[0][addr] = val;
break;
case 0x70:
dev->pci_conf_sb[0][addr] = val & 0xde;
break;
case 0x71: /* Type-F DMA Control Register */
dev->pci_conf_sb[0][addr] = val & 0xfe;
break;
case 0x72: /* SMI Triggered By IRQ/GPIO Control */
case 0x73: /* SMI Triggered By IRQ/GPIO Control */
dev->pci_conf_sb[0][addr] = (addr == 0x72) ? val & 0xfe : val;
break;
case 0x74: /* System Standby Timer Reload, System Standby State Exit And Throttling State Exit Control */
case 0x75: /* System Standby Timer Reload, System Standby State Exit And Throttling State Exit Control */
case 0x76: /* Monitor Standby Timer Reload And Monitor Standby State ExitControl */
case 0x77: /* Monitor Standby Timer Reload And Monitor Standby State ExitControl */
dev->pci_conf_sb[0][addr] = val;
break;
default:
break;
}
sis_5571_log("SiS5571-SB: dev->pci_conf[%02x] = %02x\n", addr, val);
break;
case 1: /* IDE Controller */
switch (addr) {
case 0x04: /* Command low byte */
dev->pci_conf_sb[1][addr] = val & 0x05;
sis_5571_ide_handler(dev);
sis_5571_bm_handler(dev);
break;
case 0x07: /* Status high byte */
dev->pci_conf_sb[1][addr] &= val;
break;
case 0x09: /* Programming Interface Byte */
dev->pci_conf_sb[1][addr] = val & 0xcf;
sis_5571_ide_handler(dev);
break;
case 0x0d: /* Latency Time */
case 0x10: /* Primary Channel Base Address Register */
case 0x11: /* Primary Channel Base Address Register */
case 0x12: /* Primary Channel Base Address Register */
case 0x13: /* Primary Channel Base Address Register */
case 0x14: /* Primary Channel Base Address Register */
case 0x15: /* Primary Channel Base Address Register */
case 0x16: /* Primary Channel Base Address Register */
case 0x17: /* Primary Channel Base Address Register */
case 0x18: /* Secondary Channel Base Address Register */
case 0x19: /* Secondary Channel Base Address Register */
case 0x1a: /* Secondary Channel Base Address Register */
case 0x1b: /* Secondary Channel Base Address Register */
case 0x1c: /* Secondary Channel Base Address Register */
case 0x1d: /* Secondary Channel Base Address Register */
case 0x1e: /* Secondary Channel Base Address Register */
case 0x1f: /* Secondary Channel Base Address Register */
dev->pci_conf_sb[1][addr] = val;
sis_5571_ide_handler(dev);
break;
case 0x20: /* Bus Master IDE Control Register Base Address */
case 0x21: /* Bus Master IDE Control Register Base Address */
case 0x22: /* Bus Master IDE Control Register Base Address */
case 0x23: /* Bus Master IDE Control Register Base Address */
dev->pci_conf_sb[1][addr] = val;
sis_5571_bm_handler(dev);
break;
case 0x30: /* Expansion ROM Base Address */
case 0x31: /* Expansion ROM Base Address */
case 0x32: /* Expansion ROM Base Address */
case 0x33: /* Expansion ROM Base Address */
case 0x40: /* IDE Primary Channel/Master Drive Data Recovery Time Control */
case 0x41: /* IDE Primary Channel/Master Drive DataActive Time Control */
case 0x42: /* IDE Primary Channel/Slave Drive Data Recovery Time Control */
case 0x43: /* IDE Primary Channel/Slave Drive Data Active Time Control */
case 0x44: /* IDE Secondary Channel/Master Drive Data Recovery Time Control */
case 0x45: /* IDE Secondary Channel/Master Drive Data Active Time Control */
case 0x46: /* IDE Secondary Channel/Slave Drive Data Recovery Time Control */
case 0x47: /* IDE Secondary Channel/Slave Drive Data Active Time Control */
case 0x48: /* IDE Command Recovery Time Control */
case 0x49: /* IDE Command Active Time Control */
dev->pci_conf_sb[1][addr] = val;
break;
case 0x4a: /* IDE General Control Register 0 */
dev->pci_conf_sb[1][addr] = val & 0xaf;
sis_5571_ide_handler(dev);
break;
case 0x4b: /* IDE General Control register 1 */
case 0x4c: /* Prefetch Count of Primary Channel (Low Byte) */
case 0x4d: /* Prefetch Count of Primary Channel (High Byte) */
case 0x4e: /* Prefetch Count of Secondary Channel (Low Byte) */
case 0x4f: /* Prefetch Count of Secondary Channel (High Byte) */
dev->pci_conf_sb[1][addr] = val;
break;
default:
break;
}
sis_5571_log("SiS5571-IDE: dev->pci_conf[%02x] = %02x\n", addr, val);
break;
case 2: /* USB Controller */
switch (addr) {
case 0x04: /* Command - Low Byte */
dev->pci_conf_sb[2][addr] = val;
ohci_update_mem_mapping(dev->usb, dev->pci_conf_sb[2][0x11], dev->pci_conf_sb[2][0x12], dev->pci_conf_sb[2][0x13], dev->pci_conf_sb[2][4] & 1);
break;
case 0x05: /* Command - High Byte */
dev->pci_conf_sb[2][addr] = val & 0x03;
break;
case 0x06: /* Status - Low Byte */
dev->pci_conf_sb[2][addr] &= val & 0xc0;
break;
case 0x07: /* Status - High Byte */
dev->pci_conf_sb[2][addr] &= val;
break;
case 0x10: /* Memory Space Base Address Register */
case 0x11: /* Memory Space Base Address Register */
case 0x12: /* Memory Space Base Address Register */
case 0x13: /* Memory Space Base Address Register */
dev->pci_conf_sb[2][addr] = val & ((addr == 0x11) ? 0x0f : 0xff);
ohci_update_mem_mapping(dev->usb, dev->pci_conf_sb[2][0x11], dev->pci_conf_sb[2][0x12], dev->pci_conf_sb[2][0x13], dev->pci_conf_sb[2][4] & 1);
break;
case 0x14: /* IO Space Base Address Register */
case 0x15: /* IO Space Base Address Register */
case 0x16: /* IO Space Base Address Register */
case 0x17: /* IO Space Base Address Register */
case 0x3c: /* Interrupt Line */
dev->pci_conf_sb[2][addr] = val;
break;
default:
break;
}
sis_5571_log("SiS5571-USB: dev->pci_conf[%02x] = %02x\n", addr, val);
break;
default:
break;
}
}
static uint8_t
pci_isa_bridge_read(int func, int addr, void *priv)
{
const sis_5571_t *dev = (sis_5571_t *) priv;
switch (func) {
case 0:
sis_5571_log("SiS5571-SB: dev->pci_conf[%02x] (%02x)\n", addr, dev->pci_conf_sb[0][addr]);
return dev->pci_conf_sb[0][addr];
case 1:
sis_5571_log("SiS5571-IDE: dev->pci_conf[%02x] (%02x)\n", addr, dev->pci_conf_sb[1][addr]);
return dev->pci_conf_sb[1][addr];
case 2:
sis_5571_log("SiS5571-USB: dev->pci_conf[%02x] (%02x)\n", addr, dev->pci_conf_sb[2][addr]);
return dev->pci_conf_sb[2][addr];
default:
return 0xff;
}
}
static void
sis_5571_reset(void *priv)
{
sis_5571_t *dev = (sis_5571_t *) priv;
/* Memory/PCI Bridge */
dev->pci_conf[0x00] = 0x39;
dev->pci_conf[0x01] = 0x10;
dev->pci_conf[0x02] = 0x71;
dev->pci_conf[0x03] = 0x55;
dev->pci_conf[0x04] = 0xfd;
dev->pci_conf[0x0b] = 0x06;
dev->pci_conf[0x9e] = 0xff;
dev->pci_conf[0x9f] = 0xff;
dev->pci_conf[0xa2] = 0xff;
/* PCI to ISA bridge */
dev->pci_conf_sb[0][0x00] = 0x39;
dev->pci_conf_sb[0][0x01] = 0x10;
dev->pci_conf_sb[0][0x02] = 0x08;
dev->pci_conf_sb[0][0x04] = 0xfd;
dev->pci_conf_sb[0][0x08] = 0x01;
dev->pci_conf_sb[0][0x0a] = 0x01;
dev->pci_conf_sb[0][0x0b] = 0x06;
/* IDE Controller */
dev->pci_conf_sb[1][0x00] = 0x39;
dev->pci_conf_sb[1][0x01] = 0x10;
dev->pci_conf_sb[1][0x02] = 0x13;
dev->pci_conf_sb[1][0x03] = 0x55;
dev->pci_conf_sb[1][0x08] = 0xc0;
dev->pci_conf_sb[1][0x0a] = 0x01;
dev->pci_conf_sb[1][0x0b] = 0x01;
dev->pci_conf_sb[1][0x0e] = 0x80;
dev->pci_conf_sb[1][0x4a] = 0x06;
sff_set_slot(dev->ide_drive[0], dev->sb_slot);
sff_set_slot(dev->ide_drive[1], dev->sb_slot);
sff_bus_master_reset(dev->ide_drive[0]);
sff_bus_master_reset(dev->ide_drive[1]);
/* USB Controller */
dev->pci_conf_sb[2][0x00] = 0x39;
dev->pci_conf_sb[2][0x01] = 0x10;
dev->pci_conf_sb[2][0x02] = 0x01;
dev->pci_conf_sb[2][0x03] = 0x70;
dev->pci_conf_sb[2][0x08] = 0xb0;
dev->pci_conf_sb[2][0x09] = 0x10;
dev->pci_conf_sb[2][0x0a] = 0x03;
dev->pci_conf_sb[2][0x0b] = 0xc0;
dev->pci_conf_sb[2][0x0e] = 0x80;
dev->pci_conf_sb[2][0x14] = 0x01;
dev->pci_conf_sb[2][0x3d] = 0x01;
}
static void
sis_5571_close(void *priv)
{
sis_5571_t *dev = (sis_5571_t *) priv;
smram_del(dev->smram);
free(dev);
}
static void *
sis_5571_init(UNUSED(const device_t *info))
{
sis_5571_t *dev = (sis_5571_t *) malloc(sizeof(sis_5571_t));
memset(dev, 0x00, sizeof(sis_5571_t));
pci_add_card(PCI_ADD_NORTHBRIDGE, memory_pci_bridge_read, memory_pci_bridge_write, dev, &dev->nb_slot);
pci_add_card(PCI_ADD_SOUTHBRIDGE, pci_isa_bridge_read, pci_isa_bridge_write, dev, &dev->sb_slot);
/* MIRQ */
pci_enable_mirq(0);
/* Port 92 & SMRAM */
dev->port_92 = device_add(&port_92_pci_device);
dev->smram = smram_add();
/* SFF IDE */
dev->ide_drive[0] = device_add_inst(&sff8038i_device, 1);
dev->ide_drive[1] = device_add_inst(&sff8038i_device, 2);
/* USB */
dev->usb = device_add(&usb_device);
sis_5571_reset(dev);
return dev;
}
const device_t sis_5571_device = {
.name = "SiS 5571",
.internal_name = "sis_5571",
.flags = DEVICE_PCI,
.local = 0,
.init = sis_5571_init,
.close = sis_5571_close,
.reset = sis_5571_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

323
src/chipset/sis_5572_usb.c Normal file
View File

@@ -0,0 +1,323 @@
/*
* 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 SiS 5572 USB controller.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2024 Miran Grca.
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/io.h>
#include <86box/timer.h>
#include <86box/dma.h>
#include <86box/mem.h>
#include <86box/nvr.h>
#include <86box/hdd.h>
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
#include <86box/hdc_ide_sff8038i.h>
#include <86box/pci.h>
#include <86box/pic.h>
#include <86box/pit.h>
#include <86box/pit_fast.h>
#include <86box/plat.h>
#include <86box/plat_unused.h>
#include <86box/port_92.h>
#include <86box/smram.h>
#include <86box/spd.h>
#include <86box/apm.h>
#include <86box/ddma.h>
#include <86box/acpi.h>
#include <86box/smbus.h>
#include <86box/sis_55xx.h>
#include <86box/chipset.h>
#include <86box/usb.h>
#ifdef ENABLE_SIS_5572_USB_LOG
int sis_5572_usb_do_log = ENABLE_SIS_5572_USB_LOG;
static void
sis_5572_usb_log(const char *fmt, ...)
{
va_list ap;
if (sis_5572_usb_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define sis_5572_usb_log(fmt, ...)
#endif
typedef struct sis_5572_usb_t {
uint8_t rev;
uint8_t usb_unk_regs[256];
uint8_t pci_conf[256];
uint16_t usb_unk_base;
usb_t *usb;
sis_55xx_common_t *sis;
} sis_5572_usb_t;
/* SiS 5572 unknown I/O port (second USB PCI BAR). */
static void
sis_5572_usb_unk_write(uint16_t addr, uint8_t val, void *priv)
{
sis_5572_usb_t *dev = (sis_5572_usb_t *) priv;
addr = (addr - dev->usb_unk_base) & 0x07;
sis_5572_usb_log("SiS 5572 USB UNK: [W] dev->usb_unk_regs[%02X] = %02X\n", addr, val);
dev->usb_unk_regs[addr] = val;
}
static uint8_t
sis_5572_usb_unk_read(uint16_t addr, void *priv)
{
const sis_5572_usb_t *dev = (sis_5572_usb_t *) priv;
uint8_t ret = 0xff;
addr = (addr - dev->usb_unk_base) & 0x07;
ret = dev->usb_unk_regs[addr & 0x07];
sis_5572_usb_log("SiS 5572 USB UNK: [R] dev->usb_unk_regs[%02X] = %02X\n", addr, ret);
return ret;
}
void
sis_5572_usb_write(int addr, uint8_t val, void *priv)
{
sis_5572_usb_t *dev = (sis_5572_usb_t *) priv;
sis_5572_usb_log("SiS 5572 USB: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
if (dev->sis->usb_enabled) switch (addr) {
default:
break;
case 0x04: /* Command - Low Byte */
if (dev->rev == 0xb0)
dev->pci_conf[addr] = val & 0x47;
else
dev->pci_conf[addr] = val & 0x57;
if (dev->usb_unk_base != 0x0000) {
io_removehandler(dev->usb_unk_base, 0x0002,
sis_5572_usb_unk_read, NULL, NULL,
sis_5572_usb_unk_write, NULL, NULL, dev);
if (dev->pci_conf[0x04] & 0x01)
io_sethandler(dev->usb_unk_base, 0x0002,
sis_5572_usb_unk_read, NULL, NULL,
sis_5572_usb_unk_write, NULL, NULL, dev);
}
ohci_update_mem_mapping(dev->usb,
dev->pci_conf[0x11], dev->pci_conf[0x12],
dev->pci_conf[0x13], dev->pci_conf[0x04] & 0x02);
break;
case 0x05: /* Command - High Byte */
dev->pci_conf[addr] = val & 0x01;
break;
case 0x07: /* Status - High Byte */
dev->pci_conf[addr] &= ~(val & 0xf9);
break;
case 0x0d: /* Latency Timer */
dev->pci_conf[addr] = val;
break;
case 0x11 ... 0x13: /* Memory Space Base Address Register */
dev->pci_conf[addr] = val & ((addr == 0x11) ? 0xf0 : 0xff);
ohci_update_mem_mapping(dev->usb,
dev->pci_conf[0x11], dev->pci_conf[0x12],
dev->pci_conf[0x13], dev->pci_conf[4] & 0x02);
break;
case 0x14 ... 0x15: /* IO Space Base Address Register */
if (dev->rev == 0xb0) {
if (dev->usb_unk_base != 0x0000) {
io_removehandler(dev->usb_unk_base, 0x0002,
sis_5572_usb_unk_read, NULL, NULL,
sis_5572_usb_unk_write, NULL, NULL, dev);
}
dev->pci_conf[addr] = val;
dev->usb_unk_base = (dev->pci_conf[0x14] & 0xf8) |
(dev->pci_conf[0x15] << 8);
if (dev->usb_unk_base != 0x0000) {
io_sethandler(dev->usb_unk_base, 0x0002,
sis_5572_usb_unk_read, NULL, NULL,
sis_5572_usb_unk_write, NULL, NULL, dev);
}
}
break;
case 0x2c ... 0x2f:
if (dev->rev == 0x11)
dev->pci_conf[addr] = val;
break;
case 0x3c: /* Interrupt Line */
dev->pci_conf[addr] = val;
break;
}
}
uint8_t
sis_5572_usb_read(int addr, void *priv)
{
const sis_5572_usb_t *dev = (sis_5572_usb_t *) priv;
uint8_t ret = 0xff;
if (dev->sis->usb_enabled) {
ret = dev->pci_conf[addr];
sis_5572_usb_log("SiS 5572 USB: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
}
return ret;
}
static void
sis_5572_usb_reset(void *priv)
{
sis_5572_usb_t *dev = (sis_5572_usb_t *) priv;
dev->pci_conf[0x00] = 0x39;
dev->pci_conf[0x01] = 0x10;
dev->pci_conf[0x02] = 0x01;
dev->pci_conf[0x03] = 0x70;
dev->pci_conf[0x04] = dev->pci_conf[0x05] = 0x00;
dev->pci_conf[0x06] = (dev->rev == 0xb0) ? 0x00 : 0x80;
dev->pci_conf[0x07] = 0x02;
dev->pci_conf[0x08] = dev->rev;
dev->pci_conf[0x09] = 0x10;
dev->pci_conf[0x0a] = 0x03;
dev->pci_conf[0x0b] = 0x0c;
dev->pci_conf[0x0c] = dev->pci_conf[0x0d] = 0x00;
dev->pci_conf[0x0e] = 0x80 /* 0x10 - Datasheet erratum - header type 0x10 is invalid! */;
dev->pci_conf[0x0f] = 0x00;
dev->pci_conf[0x10] = 0x00;
dev->pci_conf[0x11] = 0x00;
dev->pci_conf[0x12] = 0x00;
dev->pci_conf[0x13] = 0x00;
if (dev->rev == 0xb0) {
dev->pci_conf[0x14] = 0x01;
dev->pci_conf[0x15] = 0x00;
dev->pci_conf[0x16] = 0x00;
dev->pci_conf[0x17] = 0x00;
} else if (dev->rev == 0x11) {
dev->pci_conf[0x2c] = 0x00;
dev->pci_conf[0x2d] = 0x00;
dev->pci_conf[0x2e] = 0x00;
dev->pci_conf[0x2f] = 0x00;
}
dev->pci_conf[0x3c] = 0x00;
dev->pci_conf[0x3d] = PCI_INTA;
dev->pci_conf[0x3e] = 0x00;
dev->pci_conf[0x3f] = 0x00;
if (dev->rev == 0xb0) {
ohci_update_mem_mapping(dev->usb,
dev->pci_conf[0x11], dev->pci_conf[0x12],
dev->pci_conf[0x13], dev->pci_conf[0x04] & 0x02);
if (dev->usb_unk_base != 0x0000) {
io_removehandler(dev->usb_unk_base, 0x0002,
sis_5572_usb_unk_read, NULL, NULL,
sis_5572_usb_unk_write, NULL, NULL, dev);
}
dev->usb_unk_base = 0x0000;
memset(dev->usb_unk_regs, 0x00, sizeof(dev->usb_unk_regs));
}
}
static void
sis_5572_usb_close(void *priv)
{
sis_5572_usb_t *dev = (sis_5572_usb_t *) priv;
free(dev);
}
static void *
sis_5572_usb_init(UNUSED(const device_t *info))
{
sis_5572_usb_t *dev = (sis_5572_usb_t *) calloc(1, sizeof(sis_5572_usb_t));
dev->rev = info->local;
dev->sis = device_get_common_priv();
/* USB */
dev->usb = device_add(&usb_device);
sis_5572_usb_reset(dev);
return dev;
}
const device_t sis_5572_usb_device = {
.name = "SiS 5572 USB controller",
.internal_name = "sis_5572_usb",
.flags = DEVICE_PCI,
.local = 0xb0,
.init = sis_5572_usb_init,
.close = sis_5572_usb_close,
.reset = sis_5572_usb_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t sis_5582_usb_device = {
.name = "SiS 5582 USB controller",
.internal_name = "sis_5582_usb",
.flags = DEVICE_PCI,
.local = 0xe0,
.init = sis_5572_usb_init,
.close = sis_5572_usb_close,
.reset = sis_5572_usb_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t sis_5595_usb_device = {
.name = "SiS 5595 USB controller",
.internal_name = "sis_5595_usb",
.flags = DEVICE_PCI,
.local = 0x11,
.init = sis_5572_usb_init,
.close = sis_5572_usb_close,
.reset = sis_5572_usb_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

185
src/chipset/sis_5581.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 SiS 5581/5582 Pentium PCI/ISA Chipset.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2024 Miran Grca.
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/io.h>
#include <86box/timer.h>
#include <86box/mem.h>
#include <86box/nvr.h>
#include <86box/apm.h>
#include <86box/acpi.h>
#include <86box/hdd.h>
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
#include <86box/hdc_ide_sff8038i.h>
#include <86box/pci.h>
#include <86box/pic.h>
#include <86box/pit.h>
#include <86box/pit_fast.h>
#include <86box/plat.h>
#include <86box/plat_unused.h>
#include <86box/port_92.h>
#include <86box/smram.h>
#include <86box/spd.h>
#include <86box/sis_55xx.h>
#include <86box/chipset.h>
#define ENABLE_SIS_5581_LOG 1
#ifdef ENABLE_SIS_5581_LOG
int sis_5581_do_log = ENABLE_SIS_5581_LOG;
static void
sis_5581_log(const char *fmt, ...)
{
va_list ap;
if (sis_5581_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define sis_5581_log(fmt, ...)
#endif
typedef struct sis_5581_t {
uint8_t nb_slot;
uint8_t sb_slot;
void *h2p;
void *p2i;
void *ide;
void *usb;
sis_55xx_common_t *sis;
} sis_5581_t;
static void
sis_5581_write(int func, int addr, uint8_t val, void *priv)
{
const sis_5581_t *dev = (sis_5581_t *) priv;
sis_5581_log("SiS 5581: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
if (func == 0x00)
sis_5581_host_to_pci_write(addr, val, dev->h2p);
}
static uint8_t
sis_5581_read(int func, int addr, void *priv)
{
const sis_5581_t *dev = (sis_5581_t *) priv;
uint8_t ret = 0xff;
if (func == 0x00)
ret = sis_5581_host_to_pci_read(addr, dev->h2p);
sis_5581_log("SiS 5581: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
return ret;
}
static void
sis_5582_write(int func, int addr, uint8_t val, void *priv)
{
const sis_5581_t *dev = (sis_5581_t *) priv;
sis_5581_log("SiS 5582: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
switch (func) {
case 0x00:
sis_5513_pci_to_isa_write(addr, val, dev->p2i);
break;
case 0x01:
sis_5513_ide_write(addr, val, dev->ide);
break;
case 0x02:
sis_5572_usb_write(addr, val, dev->usb);
break;
}
}
static uint8_t
sis_5582_read(int func, int addr, void *priv)
{
const sis_5581_t *dev = (sis_5581_t *) priv;
uint8_t ret = 0xff;
switch (func) {
case 0x00:
ret = sis_5513_pci_to_isa_read(addr, dev->p2i);
break;
case 0x01:
ret = sis_5513_ide_read(addr, dev->ide);
break;
case 0x02:
ret = sis_5572_usb_read(addr, dev->usb);
break;
}
sis_5581_log("SiS 5582: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
return ret;
}
static void
sis_5581_close(void *priv)
{
sis_5581_t *dev = (sis_5581_t *) priv;
free(dev);
}
static void *
sis_5581_init(UNUSED(const device_t *info))
{
sis_5581_t *dev = (sis_5581_t *) calloc(1, sizeof(sis_5581_t));
/* Device 0: SiS 5581 */
pci_add_card(PCI_ADD_NORTHBRIDGE, sis_5581_read, sis_5581_write, dev, &dev->nb_slot);
/* Device 1: SiS 5582 */
pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_5582_read, sis_5582_write, dev, &dev->sb_slot);
dev->sis = device_add(&sis_55xx_common_device);
dev->p2i = device_add_linked(&sis_5582_p2i_device, dev->sis);
dev->h2p = device_add_linked(&sis_5581_h2p_device, dev->sis);
dev->ide = device_add_linked(&sis_5582_ide_device, dev->sis);
dev->usb = device_add_linked(&sis_5582_usb_device, dev->sis);
return dev;
}
const device_t sis_5581_device = {
.name = "SiS 5581",
.internal_name = "sis_5581",
.flags = DEVICE_PCI,
.local = 0,
.init = sis_5581_init,
.close = sis_5581_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

553
src/chipset/sis_5581_h2p.c Normal file
View File

@@ -0,0 +1,553 @@
/*
* 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 SiS 5581 Host to PCI bridge.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2024 Miran Grca.
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/io.h>
#include <86box/timer.h>
#include <86box/dma.h>
#include <86box/mem.h>
#include <86box/nvr.h>
#include <86box/hdd.h>
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
#include <86box/hdc_ide_sff8038i.h>
#include <86box/pci.h>
#include <86box/pic.h>
#include <86box/pit.h>
#include <86box/pit_fast.h>
#include <86box/plat.h>
#include <86box/plat_unused.h>
#include <86box/port_92.h>
#include <86box/smram.h>
#include <86box/spd.h>
#include <86box/apm.h>
#include <86box/ddma.h>
#include <86box/acpi.h>
#include <86box/smbus.h>
#include <86box/sis_55xx.h>
#include <86box/chipset.h>
#include <86box/usb.h>
#ifdef ENABLE_SIS_5581_HOST_TO_PCI_LOG
int sis_5581_host_to_pci_do_log = ENABLE_SIS_5581_HOST_TO_PCI_LOG;
static void
sis_5581_host_to_pci_log(const char *fmt, ...)
{
va_list ap;
if (sis_5581_host_to_pci_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define sis_5581_host_to_pci_log(fmt, ...)
#endif
typedef struct {
uint8_t installed;
uint8_t code;
uint32_t phys_size;
} ram_bank_t;
typedef struct sis_5581_io_trap_t {
void *priv;
void *trap;
uint8_t flags, mask;
uint8_t *sts_reg, sts_mask;
uint16_t addr;
} sis_5581_io_trap_t;
typedef struct sis_5581_host_to_pci_t {
uint8_t pci_conf[256];
uint8_t states[7];
ram_bank_t ram_banks[3];
sis_5581_io_trap_t io_traps[10];
sis_55xx_common_t *sis;
smram_t *smram;
} sis_5581_host_to_pci_t;
static uint8_t bank_codes[7] = { 0x00, 0x20, 0x24, 0x22, 0x26, 0x2a, 0x2b };
static uint32_t bank_sizes[7] = { 0x00800000, /* 8 MB */
0x01000000, /* 16 MB */
0x02000000, /* 32 MB */
0x04000000, /* 64 MB */
0x08000000, /* 128 MB */
0x10000000, /* 256 MB */
0x20000000 }; /* 512 MB */
static void
sis_5581_shadow_recalc(sis_5581_host_to_pci_t *dev)
{
int state;
uint32_t base;
for (uint8_t i = 0x70; i <= 0x76; i++) {
if (i == 0x76) {
if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0xa0) {
state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
mem_set_mem_state_both(0xf0000, 0x10000, state);
sis_5581_host_to_pci_log("000F0000-000FFFFF\n");
}
} else {
base = ((i & 0x07) << 15) + 0xc0000;
if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0xa0) {
state = (dev->pci_conf[i] & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
state |= (dev->pci_conf[i] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
mem_set_mem_state_both(base, 0x4000, state);
sis_5581_host_to_pci_log("%08X-%08X\n", base, base + 0x3fff);
}
if ((dev->states[i & 0x0f] ^ dev->pci_conf[i]) & 0x0a) {
state = (dev->pci_conf[i] & 0x08) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
state |= (dev->pci_conf[i] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
mem_set_mem_state_both(base + 0x4000, 0x4000, state);
sis_5581_host_to_pci_log("%08X-%08X\n", base + 0x4000, base + 0x7fff);
}
}
dev->states[i & 0x0f] = dev->pci_conf[i];
}
flushmmucache_nopc();
}
static void
sis_5581_trap_io(UNUSED(int size), UNUSED(uint16_t addr), UNUSED(uint8_t write), UNUSED(uint8_t val),
void *priv)
{
sis_5581_io_trap_t *trap = (sis_5581_io_trap_t *) priv;
sis_5581_host_to_pci_t *dev = (sis_5581_host_to_pci_t *) trap->priv;
trap->sts_reg[0x04] |= trap->sts_mask;
if (trap->sts_reg[0x00] & trap->sts_mask)
acpi_sis5582_pmu_event(dev->sis->acpi);
}
static void
sis_5581_trap_io_mask(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv)
{
sis_5581_io_trap_t *trap = (sis_5581_io_trap_t *) priv;
if ((addr & trap->mask) == (trap->addr & trap->mask))
sis_5581_trap_io(size, addr, write, val, priv);
}
static void
sis_5581_trap_update_devctl(sis_5581_host_to_pci_t *dev, uint8_t trap_id, uint8_t enable,
uint8_t flags, uint8_t mask, uint8_t *sts_reg, uint8_t sts_mask,
uint16_t addr, uint16_t size)
{
sis_5581_io_trap_t *trap = &dev->io_traps[trap_id];
enable = enable;
/* Set up Device I/O traps dynamically. */
if (enable && !trap->trap) {
trap->priv = (void *) dev;
trap->flags = flags;
trap->mask = mask;
trap->addr = addr;
if (flags & 0x08)
trap->trap = io_trap_add(sis_5581_trap_io_mask, trap);
else
trap->trap = io_trap_add(sis_5581_trap_io, trap);
trap->sts_reg = sts_reg;
trap->sts_mask = sts_mask;
}
/* Remap I/O trap. */
io_trap_remap(trap->trap, enable, addr, size);
}
static void
sis_5581_trap_update(void *priv)
{
sis_5581_host_to_pci_t *dev = (sis_5581_host_to_pci_t *) priv;
uint8_t trap_id = 0;
uint8_t *fregs = dev->pci_conf;
uint16_t temp;
uint8_t mask;
uint8_t on;
on = fregs[0x9a];
temp = ((fregs[0x96] & 0x02) | (fregs[0x97] << 2)) & 0x03ff;
mask = ~((1 << ((fregs[0x96] >> 3) & 0x07)) - 1);
sis_5581_trap_update_devctl(dev, trap_id++,
on & 0x40, 0x08, mask, &(fregs[0x9c]), 0x40, temp, 0x80);
temp = fregs[0x98] | (fregs[0x99] << 8);
mask = 0xff;
sis_5581_trap_update_devctl(dev, trap_id++,
on & 0x20, 0x08, mask, &(fregs[0x9c]), 0x20, temp, 0x80);
sis_5581_trap_update_devctl(dev, trap_id++,
on & 0x10, 0x00, 0xff, &(fregs[0x9c]), 0x10, 0x378, 0x08);
sis_5581_trap_update_devctl(dev, trap_id++,
on & 0x10, 0x00, 0xff, &(fregs[0x9c]), 0x10, 0x278, 0x08);
sis_5581_trap_update_devctl(dev, trap_id++,
on & 0x08, 0x00, 0xff, &(fregs[0x9c]), 0x08, 0x3f8, 0x08);
sis_5581_trap_update_devctl(dev, trap_id++,
on & 0x04, 0x00, 0xff, &(fregs[0x9c]), 0x04, 0x2f8, 0x08);
sis_5581_trap_update_devctl(dev, trap_id++,
on & 0x02, 0x00, 0xff, &(fregs[0x9c]), 0x02, 0x1f0, 0x08);
sis_5581_trap_update_devctl(dev, trap_id++,
on & 0x01, 0x00, 0xff, &(fregs[0x9c]), 0x01, 0x170, 0x08);
on = fregs[0x9b];
sis_5581_trap_update_devctl(dev, trap_id++,
on & 0x08, 0x00, 0xff, &(fregs[0x9d]), 0x08, 0x064, 0x01);
sis_5581_trap_update_devctl(dev, trap_id++,
on & 0x08, 0x00, 0xff, &(fregs[0x9d]), 0x08, 0x060, 0x01);
}
static void
sis_5581_smram_recalc(sis_5581_host_to_pci_t *dev)
{
smram_disable_all();
switch (dev->pci_conf[0xa3] >> 6) {
case 0:
smram_enable(dev->smram, 0x000e0000, 0x000e0000, 0x8000, dev->pci_conf[0xa3] & 0x10, 1);
break;
case 1:
smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x8000, dev->pci_conf[0xa3] & 0x10, 1);
break;
case 2:
smram_enable(dev->smram, 0x000e0000, 0x000b0000, 0x8000, dev->pci_conf[0xa3] & 0x10, 1);
break;
case 3:
smram_enable(dev->smram, 0x000a0000, 0x000a0000, 0x10000, dev->pci_conf[0xa3] & 0x10, 1);
break;
default:
break;
}
flushmmucache();
}
void
sis_5581_host_to_pci_write(int addr, uint8_t val, void *priv)
{
sis_5581_host_to_pci_t *dev = (sis_5581_host_to_pci_t *) priv;
sis_5581_host_to_pci_log("SiS 5581 H2P: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
switch (addr) {
default:
break;
case 0x04: /* Command - Low Byte */
dev->pci_conf[addr] = (dev->pci_conf[addr] & 0xfc) | (val & 0x03);
break;
case 0x05: /* Command - High Byte */
dev->pci_conf[addr] = val & 0x02;
break;
case 0x07: /* Status - High Byte */
dev->pci_conf[addr] &= ~(val & 0xb8);
break;
case 0x0d: /* Master latency timer */
case 0x50:
case 0x54:
case 0x56 ... 0x57:
case 0x59:
dev->pci_conf[addr] = val;
break;
case 0x51:
dev->pci_conf[addr] = val;
cpu_cache_ext_enabled = !!(val & 0x40);
cpu_update_waitstates();
break;
case 0x52:
dev->pci_conf[addr] = val & 0xeb;
break;
case 0x53:
case 0x55:
dev->pci_conf[addr] = val & 0xfe;
break;
case 0x58:
dev->pci_conf[addr] = val & 0xfc;
break;
case 0x5a:
dev->pci_conf[addr] = val & 0x03;
break;
case 0x60 ... 0x62:
dev->pci_conf[addr] = dev->ram_banks[addr & 0x0f].code | 0xc0;
break;
case 0x63:
dev->pci_conf[addr] = dev->ram_banks[0].installed |
(dev->ram_banks[1].installed << 1) |
(dev->ram_banks[2].installed << 2);
break;
case 0x70 ... 0x75:
dev->pci_conf[addr] = val & 0xee;
sis_5581_shadow_recalc(dev);
break;
case 0x76:
dev->pci_conf[addr] = val & 0xe8;
sis_5581_shadow_recalc(dev);
break;
case 0x77: /* Characteristics of non-cacheable area */
dev->pci_conf[addr] = val & 0x0f;
break;
case 0x78: /* Allocation of Non-Cacheable area #1 */
case 0x79: /* NCA1REG2 */
case 0x7a: /* Allocation of Non-Cacheable area #2 */
case 0x7b: /* NCA2REG2 */
dev->pci_conf[addr] = val;
break;
case 0x80: /* PCI master characteristics */
dev->pci_conf[addr] = val & 0xfe;
break;
case 0x81:
dev->pci_conf[addr] = val & 0xde;
break;
case 0x82:
dev->pci_conf[addr] = val;
break;
case 0x83: /* CPU to PCI characteristics */
dev->pci_conf[addr] = val;
/* TODO: Implement Fast A20 and Fast reset stuff on the KBC already! */
break;
case 0x84 ... 0x86:
case 0x88 ... 0x8b:
dev->pci_conf[addr] = val;
break;
case 0x87: /* Miscellanea */
dev->pci_conf[addr] = val & 0xfe;
break;
case 0x8c ... 0x92:
case 0x9e ... 0xa2:
dev->pci_conf[addr] = val;
break;
case 0x93:
dev->pci_conf[addr] = val;
if (val & 0x02) {
dev->pci_conf[0x9d] |= 0x01;
if (dev->pci_conf[0x9b] & 0x01)
acpi_sis5582_pmu_event(dev->sis->acpi);
}
break;
case 0x94:
dev->pci_conf[addr] = val & 0xf8;
break;
case 0x95:
dev->pci_conf[addr] = val & 0xfb;
break;
case 0x96:
dev->pci_conf[addr] = val & 0xfb;
sis_5581_trap_update(dev);
break;
case 0x97 ... 0x9b:
dev->pci_conf[addr] = val;
sis_5581_trap_update(dev);
break;
case 0x9c ... 0x9d:
dev->pci_conf[addr] &= ~val;
break;
case 0xa3:
dev->pci_conf[addr] = val;
sis_5581_smram_recalc(dev);
break;
}
}
uint8_t
sis_5581_host_to_pci_read(int addr, void *priv)
{
const sis_5581_host_to_pci_t *dev = (sis_5581_host_to_pci_t *) priv;
uint8_t ret = 0xff;
ret = dev->pci_conf[addr];
sis_5581_host_to_pci_log("SiS 5581 H2P: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
return ret;
}
static void
sis_5581_host_to_pci_reset(void *priv)
{
sis_5581_host_to_pci_t *dev = (sis_5581_host_to_pci_t *) priv;
dev->pci_conf[0x00] = 0x39;
dev->pci_conf[0x01] = 0x10;
dev->pci_conf[0x02] = 0x97;
dev->pci_conf[0x03] = 0x55;
dev->pci_conf[0x04] = 0x05;
dev->pci_conf[0x05] = dev->pci_conf[0x06] = 0x00;
dev->pci_conf[0x07] = 0x02;
dev->pci_conf[0x08] = 0x02;
dev->pci_conf[0x09] = dev->pci_conf[0x0a] = 0x00;
dev->pci_conf[0x0b] = 0x06;
dev->pci_conf[0x0c] = 0x00;
dev->pci_conf[0x0d] = 0xff;
dev->pci_conf[0x0e] = dev->pci_conf[0x0f] = 0x00;
dev->pci_conf[0x50] = dev->pci_conf[0x51] = 0x00;
dev->pci_conf[0x52] = 0x00;
dev->pci_conf[0x53] = 0x38;
dev->pci_conf[0x54] = 0x54;
dev->pci_conf[0x55] = 0x00;
dev->pci_conf[0x56] = 0x80;
dev->pci_conf[0x57] = dev->pci_conf[0x58] = 0x00;
dev->pci_conf[0x59] = dev->pci_conf[0x5a] = 0x00;
dev->pci_conf[0x60] = dev->pci_conf[0x61] = 0x00;
dev->pci_conf[0x62] = 0x00;
dev->pci_conf[0x63] = 0xff;
dev->pci_conf[0x70] = dev->pci_conf[0x71] = 0x00;
dev->pci_conf[0x72] = dev->pci_conf[0x73] = 0x00;
dev->pci_conf[0x74] = dev->pci_conf[0x75] = 0x00;
dev->pci_conf[0x76] = dev->pci_conf[0x77] = 0x00;
dev->pci_conf[0x78] = dev->pci_conf[0x79] = 0x00;
dev->pci_conf[0x7a] = dev->pci_conf[0x7b] = 0x00;
dev->pci_conf[0x80] = dev->pci_conf[0x81] = 0x00;
dev->pci_conf[0x82] = dev->pci_conf[0x83] = 0x00;
dev->pci_conf[0x84] = dev->pci_conf[0x85] = 0x00;
dev->pci_conf[0x86] = dev->pci_conf[0x87] = 0x00;
dev->pci_conf[0x88] = dev->pci_conf[0x89] = 0x00;
dev->pci_conf[0x8a] = dev->pci_conf[0x8b] = 0x00;
dev->pci_conf[0x90] = dev->pci_conf[0x91] = 0x00;
dev->pci_conf[0x92] = dev->pci_conf[0x93] = 0x00;
dev->pci_conf[0x94] = dev->pci_conf[0x95] = 0x00;
dev->pci_conf[0x96] = dev->pci_conf[0x97] = 0x00;
dev->pci_conf[0x98] = dev->pci_conf[0x99] = 0x00;
dev->pci_conf[0x9a] = dev->pci_conf[0x9b] = 0x00;
dev->pci_conf[0x9c] = dev->pci_conf[0x9d] = 0x00;
dev->pci_conf[0x9e] = dev->pci_conf[0x9f] = 0xff;
dev->pci_conf[0xa0] = 0xff;
dev->pci_conf[0xa1] = 0x00;
dev->pci_conf[0xa2] = 0xff;
dev->pci_conf[0xa3] = 0x00;
cpu_cache_ext_enabled = 0;
cpu_update_waitstates();
sis_5581_shadow_recalc(dev);
sis_5581_trap_update(dev);
sis_5581_smram_recalc(dev);
}
static void
sis_5581_host_to_pci_close(void *priv)
{
sis_5581_host_to_pci_t *dev = (sis_5581_host_to_pci_t *) priv;
smram_del(dev->smram);
free(dev);
}
static void *
sis_5581_host_to_pci_init(UNUSED(const device_t *info))
{
sis_5581_host_to_pci_t *dev = (sis_5581_host_to_pci_t *) calloc(1, sizeof(sis_5581_host_to_pci_t));
uint32_t total_mem = mem_size << 10;
ram_bank_t *rb;
dev->sis = device_get_common_priv();
/* Calculate the physical RAM banks. */
for (uint8_t i = 0; i < 3; i++) {
rb = &(dev->ram_banks[i]);
uint32_t size = 0x00000000;
uint8_t index = 0;
for (int8_t j = 6; j >= 0; j--) {
uint32_t *bs = &(bank_sizes[j]);
if (*bs <= total_mem) {
size = *bs;
index = j;
break;
}
}
if (size != 0x00000000) {
rb->installed = 1;
rb->code = bank_codes[index];
rb->phys_size = size;
total_mem -= size;
} else
rb->installed = 0;
}
/* SMRAM */
dev->smram = smram_add();
sis_5581_host_to_pci_reset(dev);
return dev;
}
const device_t sis_5581_h2p_device = {
.name = "SiS 5581 Host to PCI bridge",
.internal_name = "sis_5581_host_to_pci",
.flags = DEVICE_PCI,
.local = 0x00,
.init = sis_5581_host_to_pci_init,
.close = sis_5581_host_to_pci_close,
.reset = sis_5581_host_to_pci_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

210
src/chipset/sis_5591.c Normal file
View File

@@ -0,0 +1,210 @@
/*
* 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 SiS 5591/5592 Pentium PCI/ISA Chipset.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2024 Miran Grca.
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/io.h>
#include <86box/timer.h>
#include <86box/mem.h>
#include <86box/nvr.h>
#include <86box/apm.h>
#include <86box/acpi.h>
#include <86box/hdd.h>
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
#include <86box/hdc_ide_sff8038i.h>
#include <86box/pci.h>
#include <86box/pic.h>
#include <86box/pit.h>
#include <86box/pit_fast.h>
#include <86box/plat.h>
#include <86box/plat_unused.h>
#include <86box/port_92.h>
#include <86box/smram.h>
#include <86box/spd.h>
#include <86box/sis_55xx.h>
#include <86box/chipset.h>
#ifdef ENABLE_SIS_5591_LOG
int sis_5591_do_log = ENABLE_SIS_5591_LOG;
static void
sis_5591_log(const char *fmt, ...)
{
va_list ap;
if (sis_5591_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define sis_5591_log(fmt, ...)
#endif
typedef struct sis_5591_t {
uint8_t nb_slot;
uint8_t sb_slot;
void *h2p;
void *p2i;
void *ide;
void *usb;
void *pmu;
sis_55xx_common_t *sis;
} sis_5591_t;
static void
sis_5591_write(int func, int addr, uint8_t val, void *priv)
{
const sis_5591_t *dev = (sis_5591_t *) priv;
sis_5591_log("SiS 5591: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
if (func == 0x00)
sis_5591_host_to_pci_write(addr, val, dev->h2p);
else if (func == 0x01)
sis_5513_ide_write(addr, val, dev->ide);
}
static uint8_t
sis_5591_read(int func, int addr, void *priv)
{
const sis_5591_t *dev = (sis_5591_t *) priv;
uint8_t ret = 0xff;
if (func == 0x00)
ret = sis_5591_host_to_pci_read(addr, dev->h2p);
else if (func == 0x01)
ret = sis_5513_ide_read(addr, dev->ide);
sis_5591_log("SiS 5591: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
return ret;
}
static void
sis_5595_write(int func, int addr, uint8_t val, void *priv)
{
const sis_5591_t *dev = (sis_5591_t *) priv;
sis_5591_log("SiS 5595: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
switch (func) {
case 0x00:
sis_5513_pci_to_isa_write(addr, val, dev->p2i);
break;
case 0x01:
sis_5595_pmu_write(addr, val, dev->pmu);
break;
case 0x02:
sis_5572_usb_write(addr, val, dev->usb);
break;
}
}
static uint8_t
sis_5595_read(int func, int addr, void *priv)
{
const sis_5591_t *dev = (sis_5591_t *) priv;
uint8_t ret = 0xff;
switch (func) {
case 0x00:
ret = sis_5513_pci_to_isa_read(addr, dev->p2i);
break;
case 0x01:
ret = sis_5595_pmu_read(addr, dev->pmu);
break;
case 0x02:
ret = sis_5572_usb_read(addr, dev->usb);
break;
}
sis_5591_log("SiS 5592: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
return ret;
}
static void
sis_5591_close(void *priv)
{
sis_5591_t *dev = (sis_5591_t *) priv;
free(dev);
}
static void *
sis_5591_init(UNUSED(const device_t *info))
{
sis_5591_t *dev = (sis_5591_t *) calloc(1, sizeof(sis_5591_t));
/* Device 0: SiS 5591 */
pci_add_card(PCI_ADD_NORTHBRIDGE, sis_5591_read, sis_5591_write, dev, &dev->nb_slot);
/* Device 1: SiS 5595 */
pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_5595_read, sis_5595_write, dev, &dev->sb_slot);
dev->sis = device_add(&sis_55xx_common_device);
dev->ide = device_add_linked(&sis_5591_5600_ide_device, dev->sis);
if (info->local)
dev->p2i = device_add_linked(&sis_5595_1997_p2i_device, dev->sis);
else
dev->p2i = device_add_linked(&sis_5595_p2i_device, dev->sis);
dev->h2p = device_add_linked(&sis_5591_h2p_device, dev->sis);
dev->usb = device_add_linked(&sis_5595_usb_device, dev->sis);
if (info->local)
dev->pmu = device_add_linked(&sis_5595_1997_pmu_device, dev->sis);
else
dev->pmu = device_add_linked(&sis_5595_pmu_device, dev->sis);
return dev;
}
const device_t sis_5591_1997_device = {
.name = "SiS 5591 (1997)",
.internal_name = "sis_5591_1997",
.flags = DEVICE_PCI,
.local = 1,
.init = sis_5591_init,
.close = sis_5591_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t sis_5591_device = {
.name = "SiS 5591",
.internal_name = "sis_5591",
.flags = DEVICE_PCI,
.local = 0,
.init = sis_5591_init,
.close = sis_5591_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

493
src/chipset/sis_5591_h2p.c Normal file
View File

@@ -0,0 +1,493 @@
/*
* 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 SiS 5591 Host to PCI bridge.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2024 Miran Grca.
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/io.h>
#include <86box/timer.h>
#include <86box/dma.h>
#include <86box/mem.h>
#include <86box/nvr.h>
#include <86box/hdd.h>
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
#include <86box/hdc_ide_sff8038i.h>
#include <86box/pci.h>
#include <86box/pic.h>
#include <86box/pit.h>
#include <86box/pit_fast.h>
#include <86box/plat.h>
#include <86box/plat_unused.h>
#include <86box/port_92.h>
#include <86box/smram.h>
#include <86box/spd.h>
#include <86box/apm.h>
#include <86box/ddma.h>
#include <86box/acpi.h>
#include <86box/smbus.h>
#include <86box/sis_55xx.h>
#include <86box/chipset.h>
#include <86box/usb.h>
#include <86box/agpgart.h>
#ifdef ENABLE_SIS_5591_HOST_TO_PCI_LOG
int sis_5591_host_to_pci_do_log = ENABLE_SIS_5591_HOST_TO_PCI_LOG;
static void
sis_5591_host_to_pci_log(const char *fmt, ...)
{
va_list ap;
if (sis_5591_host_to_pci_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define sis_5591_host_to_pci_log(fmt, ...)
#endif
typedef struct {
uint8_t installed;
uint8_t code;
uint32_t phys_size;
} ram_bank_t;
typedef struct sis_5591_host_to_pci_t {
uint8_t pci_conf[256];
uint8_t states[7];
uint8_t states_bus[7];
ram_bank_t ram_banks[3];
sis_55xx_common_t *sis;
smram_t *smram;
agpgart_t *agpgart;
} sis_5591_host_to_pci_t;
static uint8_t bank_codes[6] = { 0x00, 0x20, 0x24, 0x22, 0x26, 0x2a };
static uint32_t bank_sizes[6] = { 0x00800000, /* 8 MB */
0x01000000, /* 16 MB */
0x02000000, /* 32 MB */
0x04000000, /* 64 MB */
0x08000000, /* 128 MB */
0x10000000 }; /* 256 MB */
static void
sis_5591_shadow_recalc(sis_5591_host_to_pci_t *dev)
{
uint32_t base;
uint32_t state;
uint8_t val;
for (uint8_t i = 0x70; i <= 0x76; i++) {
if (i == 0x76) {
val = dev->pci_conf[i];
if ((dev->states[i & 0x0f] ^ val) & 0xa0) {
state = (val & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
state |= (val & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
mem_set_mem_state_cpu_both(0xf0000, 0x10000, state);
sis_5591_host_to_pci_log("000F0000-000FFFFF\n");
dev->states[i & 0x0f] = val;
}
if (!(dev->pci_conf[0x76] & 0x08))
val &= 0x5f;
if ((dev->states_bus[i & 0x0f] ^ val) & 0xa0) {
state = (val & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
state |= (val & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
mem_set_mem_state_bus_both(0xf0000, 0x10000, state);
sis_5591_host_to_pci_log("000F0000-000FFFFF\n");
dev->states_bus[i & 0x0f] = val;
}
} else {
base = ((i & 0x07) << 15) + 0xc0000;
val = dev->pci_conf[i];
if ((dev->states[i & 0x0f] ^ val) & 0xa0) {
state = (val & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
state |= (val & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
mem_set_mem_state_cpu_both(base, 0x4000, state);
sis_5591_host_to_pci_log("%08X-%08X\n", base, base + 0x3fff);
dev->states[i & 0x0f] = (dev->states[i & 0x0f] & 0x0f) | (val & 0xf0);
}
if ((dev->states[i & 0x0f] ^ val) & 0x0a) {
state = (val & 0x08) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
state |= (val & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
mem_set_mem_state_cpu_both(base + 0x4000, 0x4000, state);
sis_5591_host_to_pci_log("%08X-%08X\n", base + 0x4000, base + 0x7fff);
dev->states[i & 0x0f] = (dev->states[i & 0x0f] & 0xf0) | (val & 0x0f);
}
if (!(dev->pci_conf[0x76] & 0x08))
val &= 0x55;
if ((dev->states_bus[i & 0x0f] ^ val) & 0xa0) {
state = (val & 0x80) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
state |= (val & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
mem_set_mem_state_bus_both(base, 0x4000, state);
sis_5591_host_to_pci_log("%08X-%08X\n", base, base + 0x3fff);
dev->states_bus[i & 0x0f] = (dev->states_bus[i & 0x0f] & 0x0f) | (val & 0xf0);
}
if ((dev->states_bus[i & 0x0f] ^ val) & 0x0a) {
state = (val & 0x08) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
state |= (val & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
mem_set_mem_state_bus_both(base + 0x4000, 0x4000, state);
sis_5591_host_to_pci_log("%08X-%08X\n", base + 0x4000, base + 0x7fff);
dev->states_bus[i & 0x0f] = (dev->states_bus[i & 0x0f] & 0xf0) | (val & 0x0f);
}
}
}
flushmmucache_nopc();
}
static void
sis_5591_smram_recalc(sis_5591_host_to_pci_t *dev)
{
smram_disable_all();
switch (dev->pci_conf[0x68] >> 6) {
case 0:
smram_enable(dev->smram, 0x000e0000, 0x000e0000, 0x8000, dev->pci_conf[0x68] & 0x10, 1);
break;
case 1:
smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x8000, dev->pci_conf[0x68] & 0x10, 1);
break;
case 2:
smram_enable(dev->smram, 0x000e0000, 0x000b0000, 0x8000, dev->pci_conf[0x68] & 0x10, 1);
break;
case 3:
smram_enable(dev->smram, 0x000a0000, 0x000a0000, 0x10000, dev->pci_conf[0x68] & 0x10, 1);
break;
default:
break;
}
flushmmucache();
}
static void
sis_5591_mask_bar(uint8_t *regs, void *agpgart)
{
uint32_t bar;
uint32_t sizes[8] = { 0x00400000, 0x00800000, 0x01000000, 0x02000000, 0x04000000, 0x08000000,
0x10000000, 0x00000000 } ;
/* Make sure the aperture's base is aligned to its size. */
bar = (regs[0x13] << 24) | (regs[0x12] << 16);
bar &= (sizes[(regs[0x94] >> 4) & 0x07] | 0xf0000000);
regs[0x12] = (bar >> 16) & 0xff;
regs[0x13] = (bar >> 24) & 0xff;
if (!agpgart)
return;
/* Map aperture and GART. */
agpgart_set_aperture(agpgart,
bar,
sizes[(regs[0x94] >> 4) & 0x07],
!!(regs[0x94] & 0x02));
if (regs[0x94] & 0x01)
agpgart_set_gart(agpgart, (regs[0x91] << 8) | (regs[0x92] << 16) | (regs[0x93] << 24));
else
agpgart_set_gart(agpgart, 0x00000000);
}
void
sis_5591_host_to_pci_write(int addr, uint8_t val, void *priv)
{
sis_5591_host_to_pci_t *dev = (sis_5591_host_to_pci_t *) priv;
sis_5591_host_to_pci_log("SiS 5591 H2P: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
switch (addr) {
default:
break;
case 0x04: /* Command - Low Byte */
dev->pci_conf[addr] = (dev->pci_conf[addr] & 0xfd) | (val & 0x02);
break;
case 0x05: /* Command - High Byte */
dev->pci_conf[addr] = val & 0x03;
break;
case 0x07: /* Status - High Byte */
dev->pci_conf[addr] &= ~(val & 0xf0);
break;
case 0x12:
dev->pci_conf[addr] = val & 0xc0;
sis_5591_mask_bar(dev->pci_conf, dev->agpgart);
break;
case 0x13:
dev->pci_conf[addr] = val;
sis_5591_mask_bar(dev->pci_conf, dev->agpgart);
break;
case 0x51:
dev->pci_conf[addr] = val;
cpu_cache_ext_enabled = !!(val & 0x80);
cpu_update_waitstates();
break;
case 0x60 ... 0x62:
dev->pci_conf[addr] = dev->ram_banks[addr & 0x0f].code | 0xc0;
break;
case 0x63:
dev->pci_conf[addr] = dev->ram_banks[0].installed |
(dev->ram_banks[1].installed << 1) |
(dev->ram_banks[2].installed << 2);
break;
case 0x68:
dev->pci_conf[addr] = val;
sis_5591_smram_recalc(dev);
break;
case 0x70 ... 0x75:
dev->pci_conf[addr] = val & 0xee;
sis_5591_shadow_recalc(dev);
break;
case 0x76:
dev->pci_conf[addr] = val & 0xe8;
sis_5591_shadow_recalc(dev);
break;
case 0x0d: /* Master latency timer */
case 0x50:
case 0x52:
case 0x54 ... 0x5a:
case 0x5c ... 0x5f:
case 0x64 ... 0x65:
case 0x69 ... 0x6c:
case 0x77 ... 0x7b:
case 0x80 ... 0x8d:
case 0x90:
case 0x97 ... 0xab:
case 0xb0:
case 0xc8 ... 0xcb:
case 0xd4 ... 0xda:
case 0xe0 ... 0xe3:
case 0xef:
dev->pci_conf[addr] = val;
break;
case 0x91 ... 0x93:
dev->pci_conf[addr] = val;
sis_5591_mask_bar(dev->pci_conf, dev->agpgart);
break;
case 0x94:
dev->pci_conf[addr] = val & 0x7f;
sis_5591_mask_bar(dev->pci_conf, dev->agpgart);
break;
case 0xb2:
dev->pci_conf[addr] &= ~(val & 0x01);
break;
}
}
uint8_t
sis_5591_host_to_pci_read(int addr, void *priv)
{
const sis_5591_host_to_pci_t *dev = (sis_5591_host_to_pci_t *) priv;
uint8_t ret = 0xff;
ret = dev->pci_conf[addr];
sis_5591_host_to_pci_log("SiS 5591 H2P: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
return ret;
}
static void
sis_5591_host_to_pci_reset(void *priv)
{
sis_5591_host_to_pci_t *dev = (sis_5591_host_to_pci_t *) priv;
dev->pci_conf[0x00] = 0x39;
dev->pci_conf[0x01] = 0x10;
dev->pci_conf[0x02] = 0x91;
dev->pci_conf[0x03] = 0x55;
dev->pci_conf[0x04] = 0x05;
dev->pci_conf[0x05] = 0x00;
dev->pci_conf[0x06] = 0x10;
dev->pci_conf[0x07] = 0x02;
dev->pci_conf[0x08] = 0x02;
dev->pci_conf[0x09] = dev->pci_conf[0x0a] = 0x00;
dev->pci_conf[0x0b] = 0x06;
dev->pci_conf[0x0c] = 0x00;
dev->pci_conf[0x0d] = 0xff;
dev->pci_conf[0x0e] = 0x80;
dev->pci_conf[0x0f] = 0x00;
dev->pci_conf[0x10] = dev->pci_conf[0x11] = 0x00;
dev->pci_conf[0x12] = dev->pci_conf[0x13] = 0x00;
dev->pci_conf[0x34] = 0xc0;
dev->pci_conf[0x50] = 0x00;
dev->pci_conf[0x51] = 0x18;
dev->pci_conf[0x52] = dev->pci_conf[0x54] = 0x00;
dev->pci_conf[0x55] = 0x0e;
dev->pci_conf[0x56] = 0x40;
dev->pci_conf[0x57] = 0x00;
dev->pci_conf[0x58] = 0x50;
dev->pci_conf[0x59] = dev->pci_conf[0x5a] = 0x00;
dev->pci_conf[0x5c] = dev->pci_conf[0x5d] = 0x00;
dev->pci_conf[0x5e] = dev->pci_conf[0x5f] = 0x00;
dev->pci_conf[0x60] = dev->pci_conf[0x61] = 0x00;
dev->pci_conf[0x62] = 0x00;
dev->pci_conf[0x63] = 0xff;
dev->pci_conf[0x64] = dev->pci_conf[0x65] = 0x00;
dev->pci_conf[0x68] = dev->pci_conf[0x69] = 0x00;
dev->pci_conf[0x6a] = dev->pci_conf[0x6b] = 0x00;
dev->pci_conf[0x6c] = 0x00;
dev->pci_conf[0x70] = dev->pci_conf[0x71] = 0x00;
dev->pci_conf[0x72] = dev->pci_conf[0x73] = 0x00;
dev->pci_conf[0x74] = dev->pci_conf[0x75] = 0x00;
dev->pci_conf[0x76] = dev->pci_conf[0x77] = 0x00;
dev->pci_conf[0x78] = dev->pci_conf[0x79] = 0x00;
dev->pci_conf[0x7a] = dev->pci_conf[0x7b] = 0x00;
dev->pci_conf[0x80] = dev->pci_conf[0x81] = 0x00;
dev->pci_conf[0x82] = dev->pci_conf[0x83] = 0x00;
dev->pci_conf[0x84] = dev->pci_conf[0x85] = 0xff;
dev->pci_conf[0x86] = 0xff;
dev->pci_conf[0x87] = 0x00;
dev->pci_conf[0x88] = dev->pci_conf[0x89] = 0x00;
dev->pci_conf[0x8a] = dev->pci_conf[0x8b] = 0x00;
dev->pci_conf[0x8c] = dev->pci_conf[0x8d] = 0x00;
dev->pci_conf[0x90] = dev->pci_conf[0x91] = 0x00;
dev->pci_conf[0x92] = dev->pci_conf[0x93] = 0x00;
dev->pci_conf[0x94] = dev->pci_conf[0x97] = 0x00;
dev->pci_conf[0x98] = dev->pci_conf[0x99] = 0x00;
dev->pci_conf[0x9a] = dev->pci_conf[0x9b] = 0x00;
dev->pci_conf[0x9c] = dev->pci_conf[0x9d] = 0x00;
dev->pci_conf[0x9e] = dev->pci_conf[0x9f] = 0x00;
dev->pci_conf[0xa0] = dev->pci_conf[0xa1] = 0x00;
dev->pci_conf[0xa2] = dev->pci_conf[0xa3] = 0x00;
dev->pci_conf[0xa4] = dev->pci_conf[0xa5] = 0x00;
dev->pci_conf[0xa6] = dev->pci_conf[0xa7] = 0x00;
dev->pci_conf[0xa8] = dev->pci_conf[0xa9] = 0x00;
dev->pci_conf[0xaa] = dev->pci_conf[0xab] = 0x00;
dev->pci_conf[0xb0] = dev->pci_conf[0xb2] = 0x00;
dev->pci_conf[0xc0] = 0x02;
dev->pci_conf[0xc1] = 0x00;
dev->pci_conf[0xc2] = 0x10;
dev->pci_conf[0xc3] = 0x00;
dev->pci_conf[0xc4] = 0x03;
dev->pci_conf[0xc5] = 0x02;
dev->pci_conf[0xc6] = 0x00;
dev->pci_conf[0xc7] = 0x1f;
dev->pci_conf[0xc8] = dev->pci_conf[0xc9] = 0x00;
dev->pci_conf[0xca] = dev->pci_conf[0xcb] = 0x00;
dev->pci_conf[0xd4] = dev->pci_conf[0xd5] = 0x00;
dev->pci_conf[0xd6] = dev->pci_conf[0xd7] = 0x00;
dev->pci_conf[0xd8] = dev->pci_conf[0xd9] = 0x00;
dev->pci_conf[0xda] = 0x00;
dev->pci_conf[0xe0] = dev->pci_conf[0xe1] = 0x00;
dev->pci_conf[0xe2] = dev->pci_conf[0xe3] = 0x00;
dev->pci_conf[0xef] = 0x00;
sis_5591_mask_bar(dev->pci_conf, dev->agpgart);
cpu_cache_ext_enabled = 0;
cpu_update_waitstates();
sis_5591_shadow_recalc(dev);
sis_5591_smram_recalc(dev);
}
static void
sis_5591_host_to_pci_close(void *priv)
{
sis_5591_host_to_pci_t *dev = (sis_5591_host_to_pci_t *) priv;
smram_del(dev->smram);
free(dev);
}
static void *
sis_5591_host_to_pci_init(UNUSED(const device_t *info))
{
sis_5591_host_to_pci_t *dev = (sis_5591_host_to_pci_t *) calloc(1, sizeof(sis_5591_host_to_pci_t));
uint32_t total_mem = mem_size << 10;
ram_bank_t *rb;
dev->sis = device_get_common_priv();
/* Calculate the physical RAM banks. */
for (uint8_t i = 0; i < 3; i++) {
rb = &(dev->ram_banks[i]);
uint32_t size = 0x00000000;
uint8_t index = 0;
for (int8_t j = 5; j >= 0; j--) {
uint32_t *bs = &(bank_sizes[j]);
if (*bs <= total_mem) {
size = *bs;
index = j;
break;
}
}
if (size != 0x00000000) {
rb->installed = 1;
rb->code = bank_codes[index];
rb->phys_size = size;
total_mem -= size;
} else
rb->installed = 0;
}
/* SMRAM */
dev->smram = smram_add();
device_add(&sis_5xxx_agp_device);
dev->agpgart = device_add(&agpgart_device);
sis_5591_host_to_pci_reset(dev);
return dev;
}
const device_t sis_5591_h2p_device = {
.name = "SiS 5591 Host to PCI bridge",
.internal_name = "sis_5591_host_to_pci",
.flags = DEVICE_PCI,
.local = 0x00,
.init = sis_5591_host_to_pci_init,
.close = sis_5591_host_to_pci_close,
.reset = sis_5591_host_to_pci_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

455
src/chipset/sis_5595_pmu.c Normal file
View File

@@ -0,0 +1,455 @@
/*
* 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 SiS 5572 USB controller.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2024 Miran Grca.
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/io.h>
#include <86box/timer.h>
#include <86box/dma.h>
#include <86box/mem.h>
#include <86box/nvr.h>
#include <86box/hdd.h>
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
#include <86box/hdc_ide_sff8038i.h>
#include <86box/pci.h>
#include <86box/pic.h>
#include <86box/pit.h>
#include <86box/pit_fast.h>
#include <86box/plat.h>
#include <86box/plat_unused.h>
#include <86box/port_92.h>
#include <86box/smram.h>
#include <86box/spd.h>
#include <86box/apm.h>
#include <86box/ddma.h>
#include <86box/acpi.h>
#include <86box/smbus.h>
#include <86box/sis_55xx.h>
#include <86box/chipset.h>
#include <86box/usb.h>
#ifdef ENABLE_SIS_5595_PMU_LOG
int sis_5595_pmu_do_log = ENABLE_SIS_5595_PMU_LOG;
static void
sis_5595_pmu_log(const char *fmt, ...)
{
va_list ap;
if (sis_5595_pmu_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define sis_5595_pmu_log(fmt, ...)
#endif
typedef struct sis_5595_pmu_io_trap_t {
void *priv;
void *trap;
uint8_t flags, mask;
uint8_t *sts_reg, sts_mask;
uint16_t addr;
} sis_5595_pmu_io_trap_t;
typedef struct sis_5595_pmu_t {
uint8_t is_1997;
uint8_t pci_conf[256];
sis_5595_pmu_io_trap_t io_traps[22];
sis_55xx_common_t *sis;
} sis_5595_pmu_t;
static void
sis_5595_pmu_trap_io(UNUSED(int size), UNUSED(uint16_t addr), UNUSED(uint8_t write), UNUSED(uint8_t val),
void *priv)
{
sis_5595_pmu_io_trap_t *trap = (sis_5595_pmu_io_trap_t *) priv;
sis_5595_pmu_t *dev = (sis_5595_pmu_t *) trap->priv;
trap->sts_reg[0x04] |= trap->sts_mask;
if (trap->sts_reg[0x00] & trap->sts_mask)
acpi_sis5595_pmu_event(dev->sis->acpi);
if (trap->sts_reg[0x20] & trap->sts_mask)
acpi_update_irq(dev->sis->acpi);
}
static void
sis_5595_pmu_trap_io_ide(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv)
{
sis_5595_pmu_io_trap_t *trap = (sis_5595_pmu_io_trap_t *) priv;
/* IDE traps are per drive, not per channel. */
if (ide_drives[trap->flags & 0x03]->selected)
sis_5595_pmu_trap_io(size, addr, write, val, priv);
}
static void
sis_5595_pmu_trap_io_mask(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv)
{
sis_5595_pmu_io_trap_t *trap = (sis_5595_pmu_io_trap_t *) priv;
if ((addr & trap->mask) == (trap->addr & trap->mask))
sis_5595_pmu_trap_io(size, addr, write, val, priv);
}
static void
sis_5595_pmu_trap_io_ide_bm(int size, uint16_t addr, uint8_t write, uint8_t val, void *priv)
{
sis_5595_pmu_io_trap_t *trap = (sis_5595_pmu_io_trap_t *) priv;
sis_5595_pmu_t *dev = (sis_5595_pmu_t *) trap->priv;
if (trap->flags & 0x01) {
dev->pci_conf[0x67] |= 0x01;
dev->pci_conf[0x64] |= 0x08;
} else {
dev->pci_conf[0x67] |= 0x02;
dev->pci_conf[0x64] |= 0x10;
}
acpi_sis5595_pmu_event(dev->sis->acpi);
}
static void
sis_5595_pmu_trap_update_devctl(sis_5595_pmu_t *dev, uint8_t trap_id, uint8_t enable,
uint8_t flags, uint8_t mask, uint8_t *sts_reg, uint8_t sts_mask,
uint16_t addr, uint16_t size)
{
sis_5595_pmu_io_trap_t *trap = &dev->io_traps[trap_id];
enable = enable;
/* Set up Device I/O traps dynamically. */
if (enable && !trap->trap) {
trap->priv = (void *) dev;
trap->flags = flags;
trap->mask = mask;
trap->addr = addr;
if (flags & 0x10)
trap->trap = io_trap_add(sis_5595_pmu_trap_io_ide_bm, trap);
else if (flags & 0x08)
trap->trap = io_trap_add(sis_5595_pmu_trap_io_mask, trap);
else if (flags & 0x04)
trap->trap = io_trap_add(sis_5595_pmu_trap_io_ide, trap);
else
trap->trap = io_trap_add(sis_5595_pmu_trap_io, trap);
trap->sts_reg = sts_reg;
trap->sts_mask = sts_mask;
}
/* Remap I/O trap. */
io_trap_remap(trap->trap, enable, addr, size);
}
static void
sis_5595_pmu_trap_update(void *priv)
{
sis_5595_pmu_t *dev = (sis_5595_pmu_t *) priv;
uint8_t trap_id = 0;
uint8_t *fregs = dev->pci_conf;
uint16_t temp;
uint8_t mask;
uint8_t on;
temp = (fregs[0x7e] | (fregs[0x7f] << 8)) & 0xffe0;
sis_5595_pmu_trap_update_devctl(dev, trap_id++,
fregs[0x7e] & 0x08, 0x10, 0xff, NULL, 0xff, temp, 0x08);
sis_5595_pmu_trap_update_devctl(dev, trap_id++,
fregs[0x7e] & 0x04, 0x10, 0xff, NULL, 0xff, temp + 8, 0x08);
on = fregs[0x63] | fregs[0x83];
sis_5595_pmu_trap_update_devctl(dev, trap_id++,
on & 0x02, 0x04, 0xff, &(fregs[0x63]), 0x02, 0x1f0, 0x08);
sis_5595_pmu_trap_update_devctl(dev, trap_id++,
on & 0x01, 0x06, 0xff, &(fregs[0x63]), 0x01, 0x170, 0x08);
on = fregs[0x62] | fregs[0x82];
sis_5595_pmu_trap_update_devctl(dev, trap_id++,
on & 0x80, 0x00, 0xff, &(fregs[0x62]), 0x80, 0x064, 0x01);
sis_5595_pmu_trap_update_devctl(dev, trap_id++,
on & 0x80, 0x00, 0xff, &(fregs[0x62]), 0x80, 0x060, 0x01);
sis_5595_pmu_trap_update_devctl(dev, trap_id++,
on & 0x40, 0x00, 0xff, &(fregs[0x62]), 0x40, 0x3f8, 0x08);
sis_5595_pmu_trap_update_devctl(dev, trap_id++,
on & 0x20, 0x00, 0xff, &(fregs[0x62]), 0x20, 0x2f8, 0x08);
sis_5595_pmu_trap_update_devctl(dev, trap_id++,
on & 0x10, 0x00, 0xff, &(fregs[0x62]), 0x10, 0x378, 0x08);
sis_5595_pmu_trap_update_devctl(dev, trap_id++,
on & 0x10, 0x00, 0xff, &(fregs[0x62]), 0x10, 0x278, 0x08);
temp = (fregs[0x5c] | (fregs[0x5d] << 8)) & 0x03ff;
mask = fregs[0x5d] >> 2;
sis_5595_pmu_trap_update_devctl(dev, trap_id++,
on & 0x04, 0x08, mask, &(fregs[0x62]), 0x04, temp, 0x40);
temp = fregs[0x5e] | (fregs[0x5f] << 8);
if (dev->is_1997) {
mask = fregs[0x4d] & 0x1f;
sis_5595_pmu_trap_update_devctl(dev, trap_id++,
on & 0x02, 0x08, mask, &(fregs[0x62]), 0x02, temp, 0x20);
} else {
mask = fregs[0x4d];
sis_5595_pmu_trap_update_devctl(dev, trap_id++,
on & 0x02, 0x08, mask, &(fregs[0x62]), 0x02, temp, 0x100);
}
on = fregs[0x61] | fregs[0x81];
sis_5595_pmu_trap_update_devctl(dev, trap_id++,
on & 0x40, 0x00, 0xff, &(fregs[0x61]), 0x40, 0x3b0, 0x30);
switch ((fregs[0x4c] >> 6) & 0x03) {
case 0x00:
temp = 0xf40;
break;
case 0x01:
temp = 0xe80;
break;
case 0x02:
temp = 0x604;
break;
default:
temp = 0x530;
break;
}
sis_5595_pmu_trap_update_devctl(dev, trap_id++,
on & 0x10, 0x00, 0xff, &(fregs[0x61]), 0x10, temp, 0x08);
switch ((fregs[0x4c] >> 4) & 0x03) {
case 0x00:
temp = 0x280;
break;
case 0x01:
temp = 0x260;
break;
case 0x02:
temp = 0x240;
break;
default:
temp = 0x220;
break;
}
sis_5595_pmu_trap_update_devctl(dev, trap_id++,
on & 0x08, 0x00, 0xff, &(fregs[0x61]), 0x08, temp, 0x14);
switch ((fregs[0x4c] >> 2) & 0x03) {
case 0x00:
temp = 0x330;
break;
case 0x01:
temp = 0x320;
break;
case 0x02:
temp = 0x310;
break;
default:
temp = 0x300;
break;
}
sis_5595_pmu_trap_update_devctl(dev, trap_id++,
on & 0x04, 0x00, 0xff, &(fregs[0x61]), 0x04, temp, 0x04);
sis_5595_pmu_trap_update_devctl(dev, trap_id++,
on & 0x02, 0x00, 0xff, &(fregs[0x61]), 0x02, 0x200, 0x08);
sis_5595_pmu_trap_update_devctl(dev, trap_id++,
on & 0x02, 0x00, 0xff, &(fregs[0x61]), 0x02, 0x388, 0x04);
on = fregs[0x60] | fregs[0x80];
sis_5595_pmu_trap_update_devctl(dev, trap_id++,
on & 0x20, 0x00, 0xff, &(fregs[0x60]), 0x20, 0x3f0, 0x08);
sis_5595_pmu_trap_update_devctl(dev, trap_id++,
on & 0x20, 0x00, 0xff, &(fregs[0x60]), 0x20, 0x370, 0x08);
sis_5595_pmu_trap_update_devctl(dev, trap_id++,
on & 0x10, 0x05, 0xff, &(fregs[0x60]), 0x10, 0x1f0, 0x08);
sis_5595_pmu_trap_update_devctl(dev, trap_id++,
on & 0x08, 0x07, 0xff, &(fregs[0x60]), 0x08, 0x170, 0x08);
}
void
sis_5595_pmu_write(int addr, uint8_t val, void *priv)
{
sis_5595_pmu_t *dev = (sis_5595_pmu_t *) priv;
sis_5595_pmu_log("SiS 5595 PMU: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
if (dev->sis->usb_enabled) switch (addr) {
default:
break;
case 0x40 ... 0x4b:
case 0x50 ... 0x5b:
case 0x68 ... 0x7b:
case 0x7d:
dev->pci_conf[addr] = val;
break;
case 0x4c ... 0x4d:
case 0x5c ... 0x63:
case 0x7e ... 0x7f:
case 0x80 ... 0x83:
dev->pci_conf[addr] = val;
sis_5595_pmu_trap_update(dev);
break;
case 0x64 ... 0x67:
dev->pci_conf[addr] &= ~val;
break;
case 0x7c:
dev->pci_conf[addr] = val;
if (val & 0x02) {
dev->pci_conf[0x64] |= 0x04;
if (dev->pci_conf[0x60] & 0x04)
acpi_sis5595_pmu_event(dev->sis->acpi);
}
break;
}
}
uint8_t
sis_5595_pmu_read(int addr, void *priv)
{
const sis_5595_pmu_t *dev = (sis_5595_pmu_t *) priv;
uint8_t ret = 0xff;
ret = dev->pci_conf[addr];
sis_5595_pmu_log("SiS 5595 PMU: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
return ret;
}
static void
sis_5595_pmu_reset(void *priv)
{
sis_5595_pmu_t *dev = (sis_5595_pmu_t *) priv;
dev->pci_conf[0x00] = 0x39;
dev->pci_conf[0x01] = 0x10;
dev->pci_conf[0x02] = 0x09;
dev->pci_conf[0x03] = 0x00;
dev->pci_conf[0x04] = dev->pci_conf[0x05] = 0x00;
dev->pci_conf[0x06] = 0x00;
dev->pci_conf[0x07] = 0x02;
dev->pci_conf[0x08] = dev->pci_conf[0x09] = 0x00;
dev->pci_conf[0x0a] = 0x00;
dev->pci_conf[0x0b] = 0xff;
dev->pci_conf[0x0c] = dev->pci_conf[0x0d] = 0x00;
dev->pci_conf[0x0e] = 0x80;
dev->pci_conf[0x0f] = 0x00;
dev->pci_conf[0x40] = dev->pci_conf[0x41] = 0x00;
dev->pci_conf[0x42] = dev->pci_conf[0x43] = 0x00;
dev->pci_conf[0x44] = dev->pci_conf[0x45] = 0x00;
dev->pci_conf[0x46] = dev->pci_conf[0x47] = 0x00;
dev->pci_conf[0x48] = dev->pci_conf[0x49] = 0x00;
dev->pci_conf[0x4a] = dev->pci_conf[0x4b] = 0x00;
dev->pci_conf[0x4c] = dev->pci_conf[0x4d] = 0x00;
dev->pci_conf[0x4e] = dev->pci_conf[0x4f] = 0x00;
dev->pci_conf[0x50] = dev->pci_conf[0x51] = 0x00;
dev->pci_conf[0x52] = dev->pci_conf[0x53] = 0x00;
dev->pci_conf[0x54] = dev->pci_conf[0x55] = 0x00;
dev->pci_conf[0x56] = dev->pci_conf[0x57] = 0x00;
dev->pci_conf[0x58] = dev->pci_conf[0x59] = 0x00;
dev->pci_conf[0x5a] = dev->pci_conf[0x5b] = 0x00;
dev->pci_conf[0x5c] = dev->pci_conf[0x5d] = 0x00;
dev->pci_conf[0x5e] = dev->pci_conf[0x5f] = 0x00;
dev->pci_conf[0x60] = dev->pci_conf[0x61] = 0x00;
dev->pci_conf[0x62] = dev->pci_conf[0x63] = 0x00;
dev->pci_conf[0x64] = dev->pci_conf[0x65] = 0x00;
dev->pci_conf[0x66] = dev->pci_conf[0x67] = 0x00;
dev->pci_conf[0x68] = dev->pci_conf[0x69] = 0x00;
dev->pci_conf[0x6a] = dev->pci_conf[0x6b] = 0x00;
dev->pci_conf[0x6c] = dev->pci_conf[0x6d] = 0x00;
dev->pci_conf[0x6e] = dev->pci_conf[0x6f] = 0x00;
dev->pci_conf[0x70] = dev->pci_conf[0x71] = 0x00;
dev->pci_conf[0x72] = dev->pci_conf[0x73] = 0x00;
dev->pci_conf[0x74] = dev->pci_conf[0x75] = 0x00;
dev->pci_conf[0x76] = dev->pci_conf[0x77] = 0x00;
dev->pci_conf[0x78] = dev->pci_conf[0x79] = 0x00;
dev->pci_conf[0x7a] = dev->pci_conf[0x7b] = 0x00;
dev->pci_conf[0x7c] = dev->pci_conf[0x7d] = 0x00;
dev->pci_conf[0x7e] = dev->pci_conf[0x7f] = 0x00;
dev->pci_conf[0x80] = dev->pci_conf[0x81] = 0x00;
dev->pci_conf[0x82] = dev->pci_conf[0x83] = 0x00;
sis_5595_pmu_trap_update(dev);
acpi_update_irq(dev->sis->acpi);
}
static void
sis_5595_pmu_close(void *priv)
{
sis_5595_pmu_t *dev = (sis_5595_pmu_t *) priv;
free(dev);
}
static void *
sis_5595_pmu_init(UNUSED(const device_t *info))
{
sis_5595_pmu_t *dev = (sis_5595_pmu_t *) calloc(1, sizeof(sis_5595_pmu_t));
dev->sis = device_get_common_priv();
dev->sis->pmu_regs = dev->pci_conf;
dev->is_1997 = info->local;
sis_5595_pmu_reset(dev);
return dev;
}
const device_t sis_5595_1997_pmu_device = {
.name = "SiS 5595 (1997) PMU",
.internal_name = "sis_5595_1997_pmu",
.flags = DEVICE_PCI,
.local = 0x01,
.init = sis_5595_pmu_init,
.close = sis_5595_pmu_close,
.reset = sis_5595_pmu_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t sis_5595_pmu_device = {
.name = "SiS 5595 PMU",
.internal_name = "sis_5595_pmu",
.flags = DEVICE_PCI,
.local = 0x00,
.init = sis_5595_pmu_init,
.close = sis_5595_pmu_close,
.reset = sis_5595_pmu_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

96
src/chipset/sis_55xx.c Normal file
View File

@@ -0,0 +1,96 @@
/*
* 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 SiS 55xx common structure.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2024 Miran Grca.
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/io.h>
#include <86box/timer.h>
#include <86box/dma.h>
#include <86box/mem.h>
#include <86box/nvr.h>
#include <86box/hdd.h>
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
#include <86box/hdc_ide_sff8038i.h>
#include <86box/pci.h>
#include <86box/pic.h>
#include <86box/pit.h>
#include <86box/pit_fast.h>
#include <86box/plat.h>
#include <86box/plat_unused.h>
#include <86box/port_92.h>
#include <86box/smram.h>
#include <86box/spd.h>
#include <86box/apm.h>
#include <86box/ddma.h>
#include <86box/acpi.h>
#include <86box/smbus.h>
#include <86box/sis_55xx.h>
#include <86box/chipset.h>
#include <86box/usb.h>
#ifdef ENABLE_SIS_55XX_COMMON_LOG
int sis_55xx_common_do_log = ENABLE_SIS_55XX_COMMON_LOG;
static void
sis_55xx_common_log(const char *fmt, ...)
{
va_list ap;
if (sis_55xx_common_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define sis_55xx_common_log(fmt, ...)
#endif
static void
sis_55xx_common_close(void *priv)
{
sis_55xx_common_t *dev = (sis_55xx_common_t *) priv;
free(dev);
}
static void *
sis_55xx_common_init(UNUSED(const device_t *info))
{
sis_55xx_common_t *dev = (sis_55xx_common_t *) calloc(1, sizeof(sis_55xx_common_t));
return dev;
}
const device_t sis_55xx_common_device = {
.name = "SiS 55xx Common Structure",
.internal_name = "sis_55xx_common",
.flags = DEVICE_PCI,
.local = 0x00,
.init = sis_55xx_common_init,
.close = sis_55xx_common_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

210
src/chipset/sis_5600.c Normal file
View File

@@ -0,0 +1,210 @@
/*
* 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 SiS (5)600 Pentium PCI/ISA Chipset.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2024 Miran Grca.
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/io.h>
#include <86box/timer.h>
#include <86box/mem.h>
#include <86box/nvr.h>
#include <86box/apm.h>
#include <86box/acpi.h>
#include <86box/hdd.h>
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
#include <86box/hdc_ide_sff8038i.h>
#include <86box/pci.h>
#include <86box/pic.h>
#include <86box/pit.h>
#include <86box/pit_fast.h>
#include <86box/plat.h>
#include <86box/plat_unused.h>
#include <86box/port_92.h>
#include <86box/smram.h>
#include <86box/spd.h>
#include <86box/sis_55xx.h>
#include <86box/chipset.h>
#ifdef ENABLE_SIS_5600_LOG
int sis_5600_do_log = ENABLE_SIS_5600_LOG;
static void
sis_5600_log(const char *fmt, ...)
{
va_list ap;
if (sis_5600_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define sis_5600_log(fmt, ...)
#endif
typedef struct sis_5600_t {
uint8_t nb_slot;
uint8_t sb_slot;
void *h2p;
void *p2i;
void *ide;
void *usb;
void *pmu;
sis_55xx_common_t *sis;
} sis_5600_t;
static void
sis_5600_write(int func, int addr, uint8_t val, void *priv)
{
const sis_5600_t *dev = (sis_5600_t *) priv;
sis_5600_log("SiS 5600: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
if (func == 0x00)
sis_5600_host_to_pci_write(addr, val, dev->h2p);
else if (func == 0x01)
sis_5513_ide_write(addr, val, dev->ide);
}
static uint8_t
sis_5600_read(int func, int addr, void *priv)
{
const sis_5600_t *dev = (sis_5600_t *) priv;
uint8_t ret = 0xff;
if (func == 0x00)
ret = sis_5600_host_to_pci_read(addr, dev->h2p);
else if (func == 0x01)
ret = sis_5513_ide_read(addr, dev->ide);
sis_5600_log("SiS 5600: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
return ret;
}
static void
sis_5595_write(int func, int addr, uint8_t val, void *priv)
{
const sis_5600_t *dev = (sis_5600_t *) priv;
sis_5600_log("SiS 5595: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
switch (func) {
case 0x00:
sis_5513_pci_to_isa_write(addr, val, dev->p2i);
break;
case 0x01:
sis_5595_pmu_write(addr, val, dev->pmu);
break;
case 0x02:
sis_5572_usb_write(addr, val, dev->usb);
break;
}
}
static uint8_t
sis_5595_read(int func, int addr, void *priv)
{
const sis_5600_t *dev = (sis_5600_t *) priv;
uint8_t ret = 0xff;
switch (func) {
case 0x00:
ret = sis_5513_pci_to_isa_read(addr, dev->p2i);
break;
case 0x01:
ret = sis_5595_pmu_read(addr, dev->pmu);
break;
case 0x02:
ret = sis_5572_usb_read(addr, dev->usb);
break;
}
sis_5600_log("SiS 5602: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
return ret;
}
static void
sis_5600_close(void *priv)
{
sis_5600_t *dev = (sis_5600_t *) priv;
free(dev);
}
static void *
sis_5600_init(UNUSED(const device_t *info))
{
sis_5600_t *dev = (sis_5600_t *) calloc(1, sizeof(sis_5600_t));
/* Device 0: SiS 5600 */
pci_add_card(PCI_ADD_NORTHBRIDGE, sis_5600_read, sis_5600_write, dev, &dev->nb_slot);
/* Device 1: SiS 5595 */
pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_5595_read, sis_5595_write, dev, &dev->sb_slot);
dev->sis = device_add(&sis_55xx_common_device);
dev->ide = device_add_linked(&sis_5591_5600_ide_device, dev->sis);
if (info->local)
dev->p2i = device_add_linked(&sis_5595_1997_p2i_device, dev->sis);
else
dev->p2i = device_add_linked(&sis_5595_p2i_device, dev->sis);
dev->h2p = device_add_linked(&sis_5600_h2p_device, dev->sis);
dev->usb = device_add_linked(&sis_5595_usb_device, dev->sis);
if (info->local)
dev->pmu = device_add_linked(&sis_5595_1997_pmu_device, dev->sis);
else
dev->pmu = device_add_linked(&sis_5595_pmu_device, dev->sis);
return dev;
}
const device_t sis_5600_1997_device = {
.name = "SiS (5)600 (1997)",
.internal_name = "sis_5600_1997",
.flags = DEVICE_PCI,
.local = 1,
.init = sis_5600_init,
.close = sis_5600_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t sis_5600_device = {
.name = "SiS (5)600",
.internal_name = "sis_5600",
.flags = DEVICE_PCI,
.local = 0,
.init = sis_5600_init,
.close = sis_5600_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

434
src/chipset/sis_5600_h2p.c Normal file
View File

@@ -0,0 +1,434 @@
/*
* 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 SiS (5)600 Host to PCI bridge.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2024 Miran Grca.
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/io.h>
#include <86box/timer.h>
#include <86box/dma.h>
#include <86box/mem.h>
#include <86box/nvr.h>
#include <86box/hdd.h>
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
#include <86box/hdc_ide_sff8038i.h>
#include <86box/pci.h>
#include <86box/pic.h>
#include <86box/pit.h>
#include <86box/pit_fast.h>
#include <86box/plat.h>
#include <86box/plat_unused.h>
#include <86box/port_92.h>
#include <86box/smram.h>
#include <86box/spd.h>
#include <86box/apm.h>
#include <86box/ddma.h>
#include <86box/acpi.h>
#include <86box/smbus.h>
#include <86box/sis_55xx.h>
#include <86box/chipset.h>
#include <86box/usb.h>
#include <86box/agpgart.h>
#ifdef ENABLE_SIS_5600_HOST_TO_PCI_LOG
int sis_5600_host_to_pci_do_log = ENABLE_SIS_5600_HOST_TO_PCI_LOG;
static void
sis_5600_host_to_pci_log(const char *fmt, ...)
{
va_list ap;
if (sis_5600_host_to_pci_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define sis_5600_host_to_pci_log(fmt, ...)
#endif
typedef struct {
uint8_t installed;
uint8_t code;
uint32_t phys_size;
} ram_bank_t;
typedef struct sis_5600_host_to_pci_t {
uint8_t pci_conf[256];
uint8_t states[7];
ram_bank_t ram_banks[3];
sis_55xx_common_t *sis;
smram_t *smram;
agpgart_t *agpgart;
} sis_5600_host_to_pci_t;
static uint8_t bank_codes[7] = { 0x00, 0x20, 0x24, 0x22, 0x26, 0x2a, 0x2b };
static uint32_t bank_sizes[7] = { 0x00800000, /* 8 MB */
0x01000000, /* 16 MB */
0x02000000, /* 32 MB */
0x04000000, /* 64 MB */
0x08000000, /* 128 MB */
0x10000000, /* 256 MB */
0x20000000 }; /* 512 MB */
static void
sis_5600_shadow_recalc(sis_5600_host_to_pci_t *dev)
{
int state;
uint32_t base;
for (uint8_t i = 0; i < 8; i++) {
base = 0x000c0000 + (i << 14);
state = (dev->pci_conf[0x70] & (1 << i)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
state |= (dev->pci_conf[0x72] & (1 << i)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
if (((dev->pci_conf[0x70] ^ dev->states[0]) & (1 << i)) ||
((dev->pci_conf[0x72] ^ dev->states[2]) & (1 << i))) {
mem_set_mem_state_both(base, 0x4000, state);
sis_5600_host_to_pci_log("%08X-%08X\n", base, base + 0x3fff);
}
}
for (uint8_t i = 0; i < 4; i++) {
base = 0x000e0000 + (i << 14);
state = (dev->pci_conf[0x71] & (1 << i)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
state |= (dev->pci_conf[0x73] & (1 << i)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
if (((dev->pci_conf[0x71] ^ dev->states[1]) & (1 << i)) ||
((dev->pci_conf[0x73] ^ dev->states[3]) & (1 << i))) {
mem_set_mem_state_both(base, 0x4000, state);
sis_5600_host_to_pci_log("%08X-%08X\n", base, base + 0x3fff);
}
}
base = 0x000f0000;
state = (dev->pci_conf[0x71] & (1 << 4)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
state |= (dev->pci_conf[0x73] & (1 << 4)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
if (((dev->pci_conf[0x71] ^ dev->states[1]) & (1 << 4)) ||
((dev->pci_conf[0x73] ^ dev->states[3]) & (1 << 4))) {
mem_set_mem_state_both(base, 0x10000, state);
sis_5600_host_to_pci_log("%08X-%08X\n", base, base + 0xffff);
}
for (uint8_t i = 0; i < 4; i++)
dev->states[i] = dev->pci_conf[0x70 + i];
flushmmucache_nopc();
}
static void
sis_5600_smram_recalc(sis_5600_host_to_pci_t *dev)
{
smram_disable_all();
switch (dev->pci_conf[0x6a] >> 6) {
case 0:
smram_enable(dev->smram, 0x000e0000, 0x000e0000, 0x8000, dev->pci_conf[0x6a] & 0x10, 1);
break;
case 1:
smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x8000, dev->pci_conf[0x6a] & 0x10, 1);
break;
case 2:
smram_enable(dev->smram, 0x000e0000, 0x000b0000, 0x8000, dev->pci_conf[0x6a] & 0x10, 1);
break;
case 3:
smram_enable(dev->smram, 0x000a0000, 0x000a0000, 0x10000, dev->pci_conf[0x6a] & 0x10, 1);
break;
default:
break;
}
flushmmucache();
}
static void
sis_5600_mask_bar(uint8_t *regs, void *agpgart)
{
uint32_t bar;
uint32_t sizes[8] = { 0x00400000, 0x00800000, 0x01000000, 0x02000000, 0x04000000, 0x08000000,
0x10000000, 0x00000000 } ;
/* Make sure the aperture's base is aligned to its size. */
bar = (regs[0x13] << 24) | (regs[0x12] << 16);
bar &= (sizes[(regs[0x94] >> 4) & 0x07] | 0xf0000000);
regs[0x12] = (bar >> 16) & 0xff;
regs[0x13] = (bar >> 24) & 0xff;
if (!agpgart)
return;
/* Map aperture and GART. */
agpgart_set_aperture(agpgart,
bar,
sizes[(regs[0x94] >> 4) & 0x07],
!!(regs[0x94] & 0x02));
if (regs[0x94] & 0x01)
agpgart_set_gart(agpgart, (regs[0x91] << 8) | (regs[0x92] << 16) | (regs[0x93] << 24));
else
agpgart_set_gart(agpgart, 0x00000000);
}
void
sis_5600_host_to_pci_write(int addr, uint8_t val, void *priv)
{
sis_5600_host_to_pci_t *dev = (sis_5600_host_to_pci_t *) priv;
sis_5600_host_to_pci_log("SiS 5600 H2P: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
switch (addr) {
default:
break;
case 0x04: /* Command - Low Byte */
dev->pci_conf[addr] = (dev->pci_conf[addr] & 0xfd) | (val & 0x02);
break;
case 0x05: /* Command - High Byte */
dev->pci_conf[addr] = val & 0x03;
break;
case 0x07: /* Status - High Byte */
dev->pci_conf[addr] = (dev->pci_conf[addr] & ~(val & 0x70)) | (val & 0x01);
break;
case 0x0d: /* Master latency timer */
case 0x50 ... 0x5a:
case 0x64 ... 0x69:
case 0x6b ... 0x6c:
case 0x74 ... 0x75:
case 0x77 ... 0x80:
case 0x82 ... 0x8f:
case 0x97 ... 0x9b:
case 0xc8 ... 0xcb:
case 0xd4 ... 0xd8:
case 0xda:
case 0xe0:
case 0xe2 ... 0xe3:
dev->pci_conf[addr] = val;
break;
case 0x12:
dev->pci_conf[addr] = val & 0xc0;
sis_5600_mask_bar(dev->pci_conf, dev->agpgart);
break;
case 0x13:
dev->pci_conf[addr] = val;
sis_5600_mask_bar(dev->pci_conf, dev->agpgart);
break;
case 0x60 ... 0x62:
dev->pci_conf[addr] = dev->ram_banks[addr & 0x0f].code | 0xc0;
break;
case 0x63:
dev->pci_conf[addr] = dev->ram_banks[0].installed |
(dev->ram_banks[1].installed << 1) |
(dev->ram_banks[2].installed << 2);
break;
case 0x6a:
dev->pci_conf[addr] = val;
sis_5600_smram_recalc(dev);
break;
case 0x70 ... 0x73:
dev->pci_conf[addr] = val;
sis_5600_shadow_recalc(dev);
break;
case 0x91 ... 0x93:
dev->pci_conf[addr] = val;
sis_5600_mask_bar(dev->pci_conf, dev->agpgart);
break;
case 0x94:
dev->pci_conf[addr] = val & 0x7f;
sis_5600_mask_bar(dev->pci_conf, dev->agpgart);
break;
}
}
uint8_t
sis_5600_host_to_pci_read(int addr, void *priv)
{
const sis_5600_host_to_pci_t *dev = (sis_5600_host_to_pci_t *) priv;
uint8_t ret = 0xff;
ret = dev->pci_conf[addr];
sis_5600_host_to_pci_log("SiS 5600 H2P: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
return ret;
}
static void
sis_5600_host_to_pci_reset(void *priv)
{
sis_5600_host_to_pci_t *dev = (sis_5600_host_to_pci_t *) priv;
dev->pci_conf[0x00] = 0x39;
dev->pci_conf[0x01] = 0x10;
dev->pci_conf[0x02] = 0x00;
dev->pci_conf[0x03] = 0x56;
dev->pci_conf[0x04] = 0x05;
dev->pci_conf[0x05] = 0x00;
dev->pci_conf[0x06] = 0x10;
dev->pci_conf[0x07] = 0x02;
dev->pci_conf[0x08] = 0x10;
dev->pci_conf[0x09] = dev->pci_conf[0x0a] = 0x00;
dev->pci_conf[0x0b] = 0x06;
dev->pci_conf[0x0c] = 0x00;
dev->pci_conf[0x0d] = 0xff;
dev->pci_conf[0x0e] = 0x80;
dev->pci_conf[0x0f] = 0x00;
dev->pci_conf[0x10] = dev->pci_conf[0x11] = 0x00;
dev->pci_conf[0x12] = dev->pci_conf[0x13] = 0x00;
dev->pci_conf[0x34] = 0xc0;
dev->pci_conf[0x50] = dev->pci_conf[0x51] = 0x02;
dev->pci_conf[0x52] = dev->pci_conf[0x53] = 0x00;
dev->pci_conf[0x54] = dev->pci_conf[0x55] = 0x00;
dev->pci_conf[0x56] = dev->pci_conf[0x57] = 0x00;
dev->pci_conf[0x58] = dev->pci_conf[0x59] = 0x00;
dev->pci_conf[0x5a] = 0x00;
dev->pci_conf[0x60] = dev->pci_conf[0x61] = 0x00;
dev->pci_conf[0x62] = 0x00;
dev->pci_conf[0x63] = 0xff;
dev->pci_conf[0x64] = dev->pci_conf[0x65] = 0x00;
dev->pci_conf[0x66] = dev->pci_conf[0x67] = 0x00;
dev->pci_conf[0x68] = dev->pci_conf[0x69] = 0x00;
dev->pci_conf[0x6a] = dev->pci_conf[0x6b] = 0x00;
dev->pci_conf[0x6c] = 0x00;
dev->pci_conf[0x70] = dev->pci_conf[0x71] = 0x00;
dev->pci_conf[0x72] = dev->pci_conf[0x73] = 0x00;
dev->pci_conf[0x74] = dev->pci_conf[0x75] = 0x00;
dev->pci_conf[0x77] = 0x00;
dev->pci_conf[0x78] = dev->pci_conf[0x79] = 0x00;
dev->pci_conf[0x7a] = dev->pci_conf[0x7b] = 0x00;
dev->pci_conf[0x7c] = dev->pci_conf[0x7d] = 0x00;
dev->pci_conf[0x7e] = dev->pci_conf[0x7f] = 0x00;
dev->pci_conf[0x80] = 0x00;
dev->pci_conf[0x82] = dev->pci_conf[0x83] = 0x00;
dev->pci_conf[0x84] = dev->pci_conf[0x85] = 0xff;
dev->pci_conf[0x86] = 0xff;
dev->pci_conf[0x87] = 0x00;
dev->pci_conf[0x88] = dev->pci_conf[0x89] = 0x00;
dev->pci_conf[0x8a] = dev->pci_conf[0x8b] = 0x00;
dev->pci_conf[0x8c] = 0x00;
dev->pci_conf[0x8d] = 0x62;
dev->pci_conf[0x8e] = dev->pci_conf[0x8f] = 0x00;
dev->pci_conf[0x90] = dev->pci_conf[0x91] = 0x00;
dev->pci_conf[0x92] = dev->pci_conf[0x93] = 0x00;
dev->pci_conf[0x94] = dev->pci_conf[0x97] = 0x00;
dev->pci_conf[0x98] = dev->pci_conf[0x99] = 0x00;
dev->pci_conf[0x9a] = dev->pci_conf[0x9b] = 0x00;
dev->pci_conf[0xc0] = 0x02;
dev->pci_conf[0xc1] = 0x00;
dev->pci_conf[0xc2] = 0x10;
dev->pci_conf[0xc3] = 0x00;
dev->pci_conf[0xc4] = 0x03;
dev->pci_conf[0xc5] = 0x02;
dev->pci_conf[0xc6] = 0x00;
dev->pci_conf[0xc7] = 0x1f;
dev->pci_conf[0xc8] = dev->pci_conf[0xc9] = 0x00;
dev->pci_conf[0xca] = dev->pci_conf[0xcb] = 0x00;
dev->pci_conf[0xd4] = dev->pci_conf[0xd5] = 0x00;
dev->pci_conf[0xd6] = dev->pci_conf[0xd7] = 0x00;
dev->pci_conf[0xd8] = dev->pci_conf[0xda] = 0x00;
dev->pci_conf[0xe0] = 0x00;
dev->pci_conf[0xe2] = dev->pci_conf[0xe3] = 0x00;
sis_5600_mask_bar(dev->pci_conf, dev->agpgart);
cpu_cache_ext_enabled = 1;
cpu_update_waitstates();
sis_5600_shadow_recalc(dev);
sis_5600_smram_recalc(dev);
}
static void
sis_5600_host_to_pci_close(void *priv)
{
sis_5600_host_to_pci_t *dev = (sis_5600_host_to_pci_t *) priv;
smram_del(dev->smram);
free(dev);
}
static void *
sis_5600_host_to_pci_init(UNUSED(const device_t *info))
{
sis_5600_host_to_pci_t *dev = (sis_5600_host_to_pci_t *) calloc(1, sizeof(sis_5600_host_to_pci_t));
uint32_t total_mem = mem_size << 10;
ram_bank_t *rb;
dev->sis = device_get_common_priv();
/* Calculate the physical RAM banks. */
for (uint8_t i = 0; i < 3; i++) {
rb = &(dev->ram_banks[i]);
uint32_t size = 0x00000000;
uint8_t index = 0;
for (int8_t j = 6; j >= 0; j--) {
uint32_t *bs = &(bank_sizes[j]);
if (*bs <= total_mem) {
size = *bs;
index = j;
break;
}
}
if (size != 0x00000000) {
rb->installed = 1;
rb->code = bank_codes[index];
rb->phys_size = size;
total_mem -= size;
} else
rb->installed = 0;
}
/* SMRAM */
dev->smram = smram_add();
device_add(&sis_5xxx_agp_device);
dev->agpgart = device_add(&agpgart_device);
sis_5600_host_to_pci_reset(dev);
return dev;
}
const device_t sis_5600_h2p_device = {
.name = "SiS (5)600 Host to PCI bridge",
.internal_name = "sis_5600_host_to_pci",
.flags = DEVICE_PCI,
.local = 0x00,
.init = sis_5600_host_to_pci_init,
.close = sis_5600_host_to_pci_close,
.reset = sis_5600_host_to_pci_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -123,7 +123,7 @@ sis_85c497_isa_read(uint16_t port, void *priv)
const sis_85c496_t *dev = (sis_85c496_t *) priv;
uint8_t ret = 0xff;
if (port == 0x23)
if ((port == 0x23) && (dev->cur_reg < 0xc0))
ret = dev->regs[dev->cur_reg];
else if (port == 0x33)
ret = 0x3c /*random_generate()*/;

View File

@@ -6,15 +6,13 @@
*
* This file is part of the 86Box distribution.
*
* Implementation of the SiS 85C50x Chipset.
* Implementation of the SiS 85C50x and 550x Chipsets.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Tiseno100,
*
*
* Authors: Tiseno100,
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2020-2021 Tiseno100.
* Copyright 2020-2021 Miran Grca.
* Copyright 2020-2024 Miran Grca.
* Copyright 2020-2024 Tiseno100.
*/
#include <stdarg.h>
#include <stdio.h>
@@ -27,16 +25,20 @@
#include <86box/device.h>
#include <86box/io.h>
#include <86box/timer.h>
#include <86box/apm.h>
#include <86box/machine.h>
#include <86box/pic.h>
#include <86box/pit.h>
#include <86box/pit_fast.h>
#include <86box/plat_unused.h>
#include <86box/mem.h>
#include <86box/nvr.h>
#include <86box/smram.h>
#include <86box/pci.h>
#include <86box/port_92.h>
#include <86box/spd.h>
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
#include <86box/chipset.h>
#ifdef ENABLE_SIS_85C50X_LOG
@@ -58,17 +60,23 @@ sis_85c50x_log(const char *fmt, ...)
#endif
typedef struct sis_85c50x_t {
uint8_t index;
uint8_t nb_slot;
uint8_t sb_slot;
uint8_t pad;
uint8_t index;
uint8_t nb_slot;
uint8_t sb_slot;
uint8_t type;
uint8_t pci_conf[256];
uint8_t pci_conf_sb[256];
uint8_t regs[256];
uint8_t pci_conf[256];
uint8_t pci_conf_sb[256];
uint8_t pci_conf_ide[256];
uint8_t regs[256];
uint32_t states[13];
smram_t *smram[2];
port_92_t *port_92;
void *pit;
nvr_t *nvr;
uint8_t (*pit_read_reg)(void *priv, uint8_t reg);
} sis_85c50x_t;
static void
@@ -77,23 +85,59 @@ sis_85c50x_shadow_recalc(sis_85c50x_t *dev)
uint32_t base;
uint32_t can_read;
uint32_t can_write;
uint32_t state;
can_read = (dev->pci_conf[0x53] & 0x40) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
can_write = (dev->pci_conf[0x53] & 0x20) ? MEM_WRITE_EXTANY : MEM_WRITE_INTERNAL;
if (!can_read)
can_write = MEM_WRITE_EXTANY;
mem_set_mem_state_both(0xf0000, 0x10000, can_read | can_write);
shadowbios = 1;
shadowbios_write = 1;
state = can_read | can_write;
if (dev->states[12] != state) {
mem_set_mem_state_both(0x000f0000, 0x00010000, state);
sis_85c50x_log("F0000-FFFFF: R%c, W%c\n",
(dev->pci_conf[0x53] & 0x40) ? 'I' : 'E',
(dev->pci_conf[0x53] & 0x20) ? 'P' : 'I');
dev->states[12] = state;
}
for (uint8_t i = 0; i < 4; i++) {
base = 0xe0000 + (i << 14);
mem_set_mem_state_both(base, 0x4000, (dev->pci_conf[0x54] & (1 << (7 - i))) ? (can_read | can_write) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY));
base = 0xd0000 + (i << 14);
mem_set_mem_state_both(base, 0x4000, (dev->pci_conf[0x55] & (1 << (7 - i))) ? (can_read | can_write) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY));
base = 0xc0000 + (i << 14);
mem_set_mem_state_both(base, 0x4000, (dev->pci_conf[0x56] & (1 << (7 - i))) ? (can_read | can_write) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY));
base = 0x000e0000 + (i << 14);
state = (dev->pci_conf[0x54] & (0x80 >> i)) ?
(can_read | can_write) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY);
if (dev->states[8 + i] != state) {
mem_set_mem_state_both(base, 0x00004000, state);
sis_85c50x_log("%05X-%05X: R%c, W%c\n", base, base + 0x3fff,
(dev->pci_conf[0x543 & (0x80 >> i)) ?
((dev->pci_conf[0x54] & 0x40) ? 'I' : 'D') : 'E',
(dev->pci_conf[0x54] & (0x80 >> i)) ?
((dev->pci_conf[0x53] & 0x20) ? 'P' : 'I') : 'E');
dev->states[8 + i] = state;
}
base = 0x000d0000 + (i << 14);
state = (dev->pci_conf[0x55] & (0x80 >> i)) ?
(can_read | can_write) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY);
if (dev->states[4 + i] != state) {
mem_set_mem_state_both(base, 0x00004000, state);
sis_85c50x_log("%05X-%05X: R%c, W%c\n", base, base + 0x3fff,
(dev->pci_conf[0x55] & (0x80 >> i)) ?
((dev->pci_conf[0x53] & 0x40) ? 'I' : 'D') : 'E',
(dev->pci_conf[0x55] & (0x80 >> i)) ?
((dev->pci_conf[0x53] & 0x20) ? 'P' : 'I') : 'E');
dev->states[4 + i] = state;
}
base = 0x000c0000 + (i << 14);
state = (dev->pci_conf[0x56] & (0x80 >> i)) ?
(can_read | can_write) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY);
if (dev->states[i] != state) {
mem_set_mem_state_both(base, 0x00004000, state);
sis_85c50x_log("%05X-%05X: R%c, W%c\n", base, base + 0x3fff,
(dev->pci_conf[0x56] & (0x80 >> i)) ?
((dev->pci_conf[0x53] & 0x40) ? 'I' : 'D') : 'E',
(dev->pci_conf[0x56] & (0x80 >> i)) ?
((dev->pci_conf[0x53] & 0x20) ? 'P' : 'I') : 'E');
dev->states[i] = state;
}
}
flushmmucache_nopc();
@@ -117,27 +161,35 @@ sis_85c50x_smm_recalc(sis_85c50x_t *dev)
break;
case 0x01:
host_base |= 0x000b0000;
sis_85c50x_log("SiS 50x SMRAM: %08X-%08X -> 000B0000-000BFFFF\n", host_base, host_base + 0x10000 - 1);
sis_85c50x_log("SiS 50x SMRAM: %08X-%08X -> 000B0000-000BFFFF\n",
host_base, host_base + 0x10000 - 1);
smram_enable(dev->smram[0], host_base, 0xb0000, 0x10000, (dev->pci_conf[0x65] & 0x10), 1);
smram_enable(dev->smram[1], host_base ^ 0x00100000, 0xb0000, 0x10000, (dev->pci_conf[0x65] & 0x10), 1);
smram_enable(dev->smram[1], host_base ^ 0x00100000, 0xb0000,
0x10000, (dev->pci_conf[0x65] & 0x10), 1);
break;
case 0x02:
host_base |= 0x000a0000;
sis_85c50x_log("SiS 50x SMRAM: %08X-%08X -> 000A0000-000AFFFF\n", host_base, host_base + 0x10000 - 1);
sis_85c50x_log("SiS 50x SMRAM: %08X-%08X -> 000A0000-000AFFFF\n",
host_base, host_base + 0x10000 - 1);
smram_enable(dev->smram[0], host_base, 0xa0000, 0x10000, (dev->pci_conf[0x65] & 0x10), 1);
smram_enable(dev->smram[1], host_base ^ 0x00100000, 0xa0000, 0x10000, (dev->pci_conf[0x65] & 0x10), 1);
smram_enable(dev->smram[1], host_base ^ 0x00100000, 0xa0000,
0x10000, (dev->pci_conf[0x65] & 0x10), 1);
break;
case 0x04:
host_base |= 0x000a0000;
sis_85c50x_log("SiS 50x SMRAM: %08X-%08X -> 000A0000-000AFFFF\n", host_base, host_base + 0x8000 - 1);
sis_85c50x_log("SiS 50x SMRAM: %08X-%08X -> 000A0000-000AFFFF\n",
host_base, host_base + 0x8000 - 1);
smram_enable(dev->smram[0], host_base, 0xa0000, 0x8000, (dev->pci_conf[0x65] & 0x10), 1);
smram_enable(dev->smram[1], host_base ^ 0x00100000, 0xa0000, 0x8000, (dev->pci_conf[0x65] & 0x10), 1);
smram_enable(dev->smram[1], host_base ^ 0x00100000, 0xa0000,
0x8000, (dev->pci_conf[0x65] & 0x10), 1);
break;
case 0x06:
host_base |= 0x000b0000;
sis_85c50x_log("SiS 50x SMRAM: %08X-%08X -> 000B0000-000BFFFF\n", host_base, host_base + 0x8000 - 1);
sis_85c50x_log("SiS 50x SMRAM: %08X-%08X -> 000B0000-000BFFFF\n",
host_base, host_base + 0x8000 - 1);
smram_enable(dev->smram[0], host_base, 0xb0000, 0x8000, (dev->pci_conf[0x65] & 0x10), 1);
smram_enable(dev->smram[1], host_base ^ 0x00100000, 0xa0000, 0x8000, (dev->pci_conf[0x65] & 0x10), 1);
smram_enable(dev->smram[1], host_base ^ 0x00100000, 0xa0000,
0x8000, (dev->pci_conf[0x65] & 0x10), 1);
break;
default:
break;
@@ -160,7 +212,10 @@ sis_85c50x_write(int func, int addr, uint8_t val, void *priv)
dev->pci_conf[addr] = ((dev->pci_conf[addr] & 0xf9) & ~(val & 0xf8)) | (val & 0x06);
break;
case 0x50:
dev->pci_conf[addr] = val;
if (dev->type & 1)
dev->pci_conf[addr] = val & 0xf7;
else
dev->pci_conf[addr] = val;
break;
case 0x51: /* Cache */
dev->pci_conf[addr] = val;
@@ -176,8 +231,6 @@ sis_85c50x_write(int func, int addr, uint8_t val, void *priv)
case 0x56:
dev->pci_conf[addr] = val;
sis_85c50x_shadow_recalc(dev);
if (addr == 0x54)
sis_85c50x_smm_recalc(dev);
break;
case 0x57:
case 0x58:
@@ -223,6 +276,31 @@ sis_85c50x_write(int func, int addr, uint8_t val, void *priv)
case 0x69:
dev->pci_conf[addr] &= ~val;
break;
case 0x70 ... 0x77:
if (dev->type & 1)
spd_write_drbs(dev->pci_conf, 0x70, 0x77, 2);
break;
case 0x78:
case 0x7c ... 0x7e:
if (dev->type & 1)
dev->pci_conf[addr] = val;
break;
case 0x79:
if (dev->type & 1) {
spd_write_drbs(dev->pci_conf, 0xf8, 0xff, 4);
dev->pci_conf[addr] = 0x00;
for (uint8_t i = 0; i < 8; i++)
if (dev->pci_conf[0xf8 + i] & 0x80) dev->pci_conf[addr] |= (1 << i);
}
break;
case 0x7a:
if (dev->type & 1)
dev->pci_conf[addr] = val & 0xfe;
break;
case 0x7b:
if (dev->type & 1)
dev->pci_conf[addr] = val & 0xe0;
break;
default:
break;
@@ -235,14 +313,33 @@ sis_85c50x_read(int func, int addr, void *priv)
const sis_85c50x_t *dev = (sis_85c50x_t *) priv;
uint8_t ret = 0xff;
if (func == 0x00)
ret = dev->pci_conf[addr];
if (func == 0x00) {
if (addr >= 0xf8)
ret = 0x00;
else
ret = dev->pci_conf[addr];
}
sis_85c50x_log("85C501: [R] (%02X, %02X) = %02X\n", func, addr, ret);
return ret;
}
static void
sis_85c50x_ide_recalc(sis_85c50x_t *dev)
{
ide_pri_disable();
ide_set_base(0, (dev->pci_conf_ide[0x40] & 0x80) ? 0x0170 : 0x01f0);
ide_set_side(0, (dev->pci_conf_ide[0x40] & 0x80) ? 0x0376 : 0x03f6);
ide_pri_enable();
ide_sec_disable();
ide_set_base(1, (dev->pci_conf_ide[0x40] & 0x80) ? 0x01f0 : 0x0170);
ide_set_side(1, (dev->pci_conf_ide[0x40] & 0x80) ? 0x03f6 : 0x0376);
if (dev->pci_conf_ide[0x41] & 0x01)
ide_sec_enable();
}
static void
sis_85c50x_sb_write(int func, int addr, uint8_t val, void *priv)
{
@@ -250,38 +347,46 @@ sis_85c50x_sb_write(int func, int addr, uint8_t val, void *priv)
sis_85c50x_log("85C503: [W] (%02X, %02X) = %02X\n", func, addr, val);
if (func == 0x00)
switch (addr) {
case 0x04: /* Command */
dev->pci_conf_sb[addr] = val & 0x0f;
break;
case 0x07: /* Status */
dev->pci_conf_sb[addr] &= ~(val & 0x30);
break;
case 0x40: /* BIOS Control Register */
dev->pci_conf_sb[addr] = val & 0x3f;
break;
case 0x41:
case 0x42:
case 0x43:
case 0x44:
/* INTA/B/C/D# Remapping Control Register */
dev->pci_conf_sb[addr] = val & 0x8f;
if (val & 0x80)
pci_set_irq_routing(PCI_INTA + (addr - 0x41), PCI_IRQ_DISABLED);
else
pci_set_irq_routing(PCI_INTA + (addr - 0x41), val & 0xf);
break;
case 0x48: /* ISA Master/DMA Memory Cycle Control Register 1 */
case 0x49: /* ISA Master/DMA Memory Cycle Control Register 2 */
case 0x4a: /* ISA Master/DMA Memory Cycle Control Register 3 */
case 0x4b: /* ISA Master/DMA Memory Cycle Control Register 4 */
dev->pci_conf_sb[addr] = val;
break;
if (func == 0x00) switch (addr) {
case 0x04: /* Command */
dev->pci_conf_sb[addr] = val & 0x0f;
break;
case 0x07: /* Status */
dev->pci_conf_sb[addr] &= ~(val & 0x30);
break;
case 0x40: /* BIOS Control Register */
dev->pci_conf_sb[addr] = val & 0x3f;
break;
case 0x41:
case 0x42:
case 0x43:
case 0x44:
/* INTA/B/C/D# Remapping Control Register */
dev->pci_conf_sb[addr] = val & 0x8f;
if (val & 0x80)
pci_set_irq_routing(PCI_INTA + (addr - 0x41), PCI_IRQ_DISABLED);
else
pci_set_irq_routing(PCI_INTA + (addr - 0x41), val & 0xf);
break;
case 0x48: /* ISA Master/DMA Memory Cycle Control Register 1 */
case 0x49: /* ISA Master/DMA Memory Cycle Control Register 2 */
case 0x4a: /* ISA Master/DMA Memory Cycle Control Register 3 */
case 0x4b: /* ISA Master/DMA Memory Cycle Control Register 4 */
dev->pci_conf_sb[addr] = val;
break;
default:
break;
}
default:
break;
} else if ((dev->type & 2) && !(dev->regs[0x81] & 0x02) && (func == 0x01)) switch (addr) {
case 0x40:
case 0x41:
dev->pci_conf_ide[addr] = val;
sis_85c50x_ide_recalc(dev);
break;
default:
break;
}
}
static uint8_t
@@ -290,8 +395,42 @@ sis_85c50x_sb_read(int func, int addr, void *priv)
const sis_85c50x_t *dev = (sis_85c50x_t *) priv;
uint8_t ret = 0xff;
if (func == 0x00)
ret = dev->pci_conf_sb[addr];
if (func == 0x00) switch (addr) {
default:
ret = dev->pci_conf_sb[addr];
break;
case 0x4c ... 0x4f:
if (dev->type & 2)
ret = pic_read_icw(0, addr & 0x03);
else
ret = dev->pci_conf_sb[addr];
break;
case 0x50 ... 0x53:
if (dev->type & 2)
ret = pic_read_icw(1, addr & 0x03);
else
ret = dev->pci_conf_sb[addr];
break;
case 0x54 ... 0x55:
if (dev->type & 2)
ret = pic_read_ocw(0, addr & 0x01);
else
ret = dev->pci_conf_sb[addr];
break;
case 0x56 ... 0x57:
if (dev->type & 2)
ret = pic_read_ocw(1, addr & 0x01);
else
ret = dev->pci_conf_sb[addr];
break;
case 0x58 ... 0x5f:
if (dev->type & 2)
ret = dev->pit_read_reg(dev->pit, addr & 0x07);
else
ret = dev->pci_conf_sb[addr];
break;
} else if ((dev->type & 2) && !(dev->regs[0x81] & 0x02) && (func == 0x01))
ret = dev->pci_conf_ide[addr];
sis_85c50x_log("85C503: [W] (%02X, %02X) = %02X\n", func, addr, ret);
@@ -313,10 +452,39 @@ sis_85c50x_isa_write(uint16_t addr, uint8_t val, void *priv)
case 0x23:
switch (dev->index) {
case 0x80:
dev->regs[dev->index] = val & 0xe7;
if (dev->type & 2) {
dev->regs[dev->index] = val;
nvr_bank_set(0, !!(val & 0x08), dev->nvr);
} else
dev->regs[dev->index] = val & 0xe7;
switch (val >> 6) {
case 0:
cpu_set_isa_speed(7159091);
break;
case 1:
cpu_set_isa_pci_div(4);
break;
case 2:
cpu_set_isa_pci_div(3);
break;
default:
break;
}
break;
case 0x81:
dev->regs[dev->index] = val & 0xf4;
if (dev->type & 2)
dev->regs[dev->index] = val & 0xf6;
else
dev->regs[dev->index] = val & 0xf4;
break;
case 0x82:
if (dev->type & 2)
dev->regs[dev->index] = val;
break;
case 0x83:
if (dev->type & 2)
dev->regs[dev->index] = val & 0x03;
break;
case 0x84:
case 0x88:
@@ -394,6 +562,12 @@ sis_85c50x_reset(void *priv)
sis_85c50x_write(0, 0x68, 0x00, dev);
sis_85c50x_write(0, 0x69, 0xff, dev);
if (dev->type & 1) {
for (uint8_t i = 0; i < 8; i++)
dev->pci_conf[0x70 + i] = 0x00;
dev->pci_conf[0x79] = 0x00;
}
/* South Bridge (SiS 85C503) */
dev->pci_conf_sb[0x00] = 0x39;
dev->pci_conf_sb[0x01] = 0x10;
@@ -407,10 +581,51 @@ sis_85c50x_reset(void *priv)
dev->pci_conf_sb[0x09] = 0x00;
dev->pci_conf_sb[0x0a] = 0x01;
dev->pci_conf_sb[0x0b] = 0x06;
if (dev->type & 2)
dev->pci_conf_sb[0x0e] = 0x80;
sis_85c50x_sb_write(0, 0x41, 0x80, dev);
sis_85c50x_sb_write(0, 0x42, 0x80, dev);
sis_85c50x_sb_write(0, 0x43, 0x80, dev);
sis_85c50x_sb_write(0, 0x44, 0x80, dev);
if (dev->type & 2) {
/* IDE (SiS 5503) */
dev->pci_conf_ide[0x00] = 0x39;
dev->pci_conf_ide[0x01] = 0x10;
dev->pci_conf_ide[0x02] = 0x01;
dev->pci_conf_ide[0x03] = 0x06;
dev->pci_conf_ide[0x04] = 0x89;
dev->pci_conf_ide[0x05] = 0x00;
dev->pci_conf_ide[0x06] = 0x00;
dev->pci_conf_ide[0x07] = 0x00;
dev->pci_conf_ide[0x08] = 0x00;
dev->pci_conf_ide[0x09] = 0x00;
dev->pci_conf_ide[0x0a] = 0x01;
dev->pci_conf_ide[0x0b] = 0x01;
dev->pci_conf_ide[0x0c] = 0x00;
dev->pci_conf_ide[0x0d] = 0x00;
dev->pci_conf_ide[0x0e] = 0x80;
dev->pci_conf_ide[0x0f] = 0x00;
dev->pci_conf_ide[0x10] = 0x71;
dev->pci_conf_ide[0x11] = 0x01;
dev->pci_conf_ide[0x14] = 0xf1;
dev->pci_conf_ide[0x15] = 0x01;
dev->pci_conf_ide[0x18] = 0x71;
dev->pci_conf_ide[0x19] = 0x03;
dev->pci_conf_ide[0x1c] = 0xf1;
dev->pci_conf_ide[0x1d] = 0x03;
dev->pci_conf_ide[0x20] = 0x01;
dev->pci_conf_ide[0x24] = 0x01;
dev->pci_conf_ide[0x40] = 0x00;
dev->pci_conf_ide[0x41] = 0x40;
sis_85c50x_ide_recalc(dev);
}
cpu_set_isa_speed(7159091);
if (dev->type & 2)
nvr_bank_set(0, 0, dev->nvr);
}
static void
@@ -426,8 +641,10 @@ sis_85c50x_close(void *priv)
static void *
sis_85c50x_init(UNUSED(const device_t *info))
{
sis_85c50x_t *dev = (sis_85c50x_t *) malloc(sizeof(sis_85c50x_t));
memset(dev, 0x00, sizeof(sis_85c50x_t));
sis_85c50x_t *dev = (sis_85c50x_t *) calloc(1, sizeof(sis_85c50x_t));
uint8_t pit_is_fast = (((pit_mode == -1) && is486) || (pit_mode == 1));
dev->type = info->local;
/* 501/502 (Northbridge) */
pci_add_card(PCI_ADD_NORTHBRIDGE, sis_85c50x_read, sis_85c50x_write, dev, &dev->nb_slot);
@@ -441,6 +658,17 @@ sis_85c50x_init(UNUSED(const device_t *info))
dev->port_92 = device_add(&port_92_device);
if (dev->type & 2) {
/* PIT */
dev->pit = device_find_first_priv(DEVICE_PIT);
dev->pit_read_reg = pit_is_fast ? pitf_read_reg : pit_read_reg;
/* NVR */
dev->nvr = device_add(&at_mb_nvr_device);
device_add(&ide_pci_2ch_device);
}
sis_85c50x_reset(dev);
return dev;
@@ -459,3 +687,45 @@ const device_t sis_85c50x_device = {
.force_redraw = NULL,
.config = NULL
};
const device_t sis_550x_85c503_device = {
.name = "SiS 550x",
.internal_name = "sis_550x",
.flags = DEVICE_PCI,
.local = 1,
.init = sis_85c50x_init,
.close = sis_85c50x_close,
.reset = sis_85c50x_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t sis_85c50x_5503_device = {
.name = "SiS 85C50x",
.internal_name = "sis_85c50x",
.flags = DEVICE_PCI,
.local = 2,
.init = sis_85c50x_init,
.close = sis_85c50x_close,
.reset = sis_85c50x_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t sis_550x_device = {
.name = "SiS 550x",
.internal_name = "sis_550x",
.flags = DEVICE_PCI,
.local = 3,
.init = sis_85c50x_init,
.close = sis_85c50x_close,
.reset = sis_85c50x_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -79,17 +79,14 @@
#include <86box/timer.h>
#include <86box/io.h>
#include <86box/device.h>
#include <86box/hdd.h>
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
#include <86box/pic.h>
#include <86box/pci.h>
#include <86box/port_92.h>
#include <86box/chipset.h>
#define IDE_BIT 0x01
#ifdef ENABLE_UMC_8886_LOG
int umc_8886_do_log = ENABLE_UMC_8886_LOG;
@@ -108,18 +105,6 @@ umc_8886_log(const char *fmt, ...)
# define umc_8886_log(fmt, ...)
#endif
/* PCI IRQ Flags */
#define INTA (PCI_INTA + (2 * !(addr & 1)))
#define INTB (PCI_INTB + (2 * !(addr & 1)))
#define IRQRECALCA (((val & 0xf0) != 0) ? ((val & 0xf0) >> 4) : PCI_IRQ_DISABLED)
#define IRQRECALCB (((val & 0x0f) != 0) ? (val & 0x0f) : PCI_IRQ_DISABLED)
/* Disable Internal IDE Flag needed for the AF or BF Southbridge variant */
#define HAS_IDE dev->has_ide
/* Southbridge Revision */
#define SB_ID dev->sb_id
typedef struct umc_8886_t {
uint8_t max_func; /* Last function number */
uint8_t pci_slot;
@@ -128,19 +113,24 @@ typedef struct umc_8886_t {
uint8_t pci_conf_sb[2][256]; /* PCI Registers */
uint16_t sb_id; /* Southbridge Revision */
int has_ide; /* Check if Southbridge Revision is AF or F */
uint16_t sb_id; /* Southbridge Revision */
uint16_t ide_id; /* IDE Revision */
int has_ide; /* Check if Southbridge Revision is F, AF, or BF */
} umc_8886_t;
static void
umc_8886_ide_handler(int status)
umc_8886_ide_handler(umc_8886_t *dev)
{
ide_pri_disable();
ide_sec_disable();
if (status) {
ide_pri_enable();
ide_sec_enable();
if (dev->pci_conf_sb[1][0x04] & 0x01) {
if (dev->pci_conf_sb[1][0x40] & 0x80)
ide_pri_enable();
if (dev->pci_conf_sb[1][0x40] & 0x40)
ide_sec_enable();
}
}
@@ -148,6 +138,7 @@ static void
umc_8886_write(int func, int addr, uint8_t val, void *priv)
{
umc_8886_t *dev = (umc_8886_t *) priv;
int irq_routing;
if (func <= dev->max_func)
switch (func) {
@@ -155,8 +146,17 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv)
umc_8886_log("UM8886: dev->regs[%02x] = %02x POST %02x\n", addr, val, inb(0x80));
switch (addr) {
case 0x04:
case 0x05:
case 0x04 ... 0x05:
case 0x0c ... 0x0d:
case 0x40 ... 0x42:
case 0x45:
case 0x50 ... 0x55:
case 0x57:
case 0x70 ... 0x76:
case 0x80 ... 0x82:
case 0x90 ... 0x92:
case 0xa0 ... 0xa1:
case 0xa5 ... 0xa8:
dev->pci_conf_sb[func][addr] = val;
break;
@@ -164,46 +164,31 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv)
dev->pci_conf_sb[func][addr] &= ~(val & 0xf9);
break;
case 0x0c:
case 0x0d:
dev->pci_conf_sb[func][addr] = val;
break;
case 0x40:
case 0x41:
case 0x42:
dev->pci_conf_sb[func][addr] = val;
break;
case 0x43:
dev->pci_conf_sb[func][addr] = val;
irq_routing = (dev->pci_conf_sb[func][0x46] & 0x01) ? (val >> 8) :
PCI_IRQ_DISABLED;
pci_set_irq_routing(PCI_INTA, irq_routing);
irq_routing = (dev->pci_conf_sb[func][0x46] & 0x02) ? (val & 0x0f) :
PCI_IRQ_DISABLED;
pci_set_irq_routing(PCI_INTB, irq_routing);
break;
case 0x44:
dev->pci_conf_sb[func][addr] = val;
pci_set_irq_routing(INTA, IRQRECALCA);
pci_set_irq_routing(INTB, IRQRECALCB);
irq_routing = (dev->pci_conf_sb[func][0x46] & 0x04) ? (val >> 8) :
PCI_IRQ_DISABLED;
pci_set_irq_routing(PCI_INTC, irq_routing);
irq_routing = (dev->pci_conf_sb[func][0x46] & 0x08) ? (val & 0x0f) :
PCI_IRQ_DISABLED;
pci_set_irq_routing(PCI_INTD, irq_routing);
break;
case 0x45:
dev->pci_conf_sb[func][addr] = val;
break;
case 0x46:
case 0x46: /* Bits 3-0 = 0 = IRQ disabled, 1 = IRQ enabled. */
case 0x47: /* Bits 3-0 = 0 = IRQ edge-triggered, 1 = IRQ level-triggered. */
/* Bit 6 seems to be the IRQ/SMI# toggle, 1 = IRQ, 0 = SMI#. */
dev->pci_conf_sb[func][addr] = val;
break;
case 0x47:
dev->pci_conf_sb[func][addr] = val;
break;
case 0x50:
case 0x51:
case 0x52:
case 0x53:
case 0x54:
case 0x55:
dev->pci_conf_sb[func][addr] = val;
break;
case 0x56:
dev->pci_conf_sb[func][addr] = val;
@@ -220,16 +205,6 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv)
default:
break;
}
break;
case 0x57:
case 0x70 ... 0x76:
case 0x80:
case 0x81:
case 0x90 ... 0x92:
case 0xa0 ... 0xa1:
dev->pci_conf_sb[func][addr] = val;
break;
case 0xa2:
@@ -243,7 +218,6 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv)
picint(1 << ((dev->pci_conf_sb[0][0x46] & 0x80) ? 15 : 10));
else
smi_raise();
dev->pci_conf_sb[0][0xa3] |= 0x04;
}
dev->pci_conf_sb[func][addr] = val;
@@ -254,10 +228,6 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv)
cpu_set_pci_speed(cpu_busspeed / ((val & 1) ? 1 : 2));
break;
case 0xa5 ... 0xa8:
dev->pci_conf_sb[func][addr] = val;
break;
default:
break;
}
@@ -269,7 +239,8 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv)
switch (addr) {
case 0x04:
dev->pci_conf_sb[func][addr] = val;
umc_8886_ide_handler(val & 1);
if (dev->ide_id == 0x673a)
umc_8886_ide_handler(dev);
break;
case 0x07:
@@ -277,9 +248,17 @@ umc_8886_write(int func, int addr, uint8_t val, void *priv)
break;
case 0x3c:
case 0x41 ... 0x4b:
case 0x54 ... 0x59:
if (dev->ide_id == 0x673a)
dev->pci_conf_sb[func][addr] = val;
break;
case 0x40:
case 0x41:
dev->pci_conf_sb[func][addr] = val;
if (dev->ide_id == 0x673a) {
dev->pci_conf_sb[func][addr] = val;
umc_8886_ide_handler(dev);
}
break;
default:
@@ -311,47 +290,73 @@ umc_8886_reset(void *priv)
memset(dev->pci_conf_sb[0], 0x00, sizeof(dev->pci_conf_sb[0]));
memset(dev->pci_conf_sb[1], 0x00, sizeof(dev->pci_conf_sb[1]));
dev->pci_conf_sb[0][0] = 0x60; /* UMC */
dev->pci_conf_sb[0][1] = 0x10;
dev->pci_conf_sb[0][2] = (SB_ID & 0xff); /* 8886xx */
dev->pci_conf_sb[0][3] = ((SB_ID >> 8) & 0xff);
dev->pci_conf_sb[0][4] = 0x0f;
dev->pci_conf_sb[0][7] = 2;
dev->pci_conf_sb[0][8] = 0x0e;
dev->pci_conf_sb[0][0x00] = 0x60; /* UMC */
dev->pci_conf_sb[0][0x01] = 0x10;
dev->pci_conf_sb[0][0x02] = (dev->sb_id & 0xff); /* 8886xx */
dev->pci_conf_sb[0][0x03] = ((dev->sb_id >> 8) & 0xff);
dev->pci_conf_sb[0][0x04] = 0x0f;
dev->pci_conf_sb[0][0x07] = 0x02;
dev->pci_conf_sb[0][0x08] = 0x0e;
dev->pci_conf_sb[0][0x09] = 0x00;
dev->pci_conf_sb[0][0x0a] = 0x01;
dev->pci_conf_sb[0][0x0b] = 0x06;
dev->pci_conf_sb[0][0x40] = 1;
dev->pci_conf_sb[0][0x41] = 6;
dev->pci_conf_sb[0][0x42] = 8;
dev->pci_conf_sb[0][0x43] = 0x9a;
dev->pci_conf_sb[0][0x44] = 0xbc;
dev->pci_conf_sb[0][0x45] = 4;
dev->pci_conf_sb[0][0x40] = 0x01;
dev->pci_conf_sb[0][0x41] = 0x06;
dev->pci_conf_sb[0][0x42] = 0x08;
dev->pci_conf_sb[0][0x43] = 0x00;
dev->pci_conf_sb[0][0x44] = 0x00;
dev->pci_conf_sb[0][0x45] = 0x04;
dev->pci_conf_sb[0][0x46] = 0x00;
dev->pci_conf_sb[0][0x47] = 0x40;
dev->pci_conf_sb[0][0x50] = 1;
dev->pci_conf_sb[0][0x51] = 3;
dev->pci_conf_sb[0][0x50] = 0x01;
dev->pci_conf_sb[0][0x51] = 0x03;
dev->pci_conf_sb[0][0x56] = dev->pci_conf_sb[0][0x57] = 0x00;
dev->pci_conf_sb[0][0x70] = dev->pci_conf_sb[0][0x71] = 0x00;
dev->pci_conf_sb[0][0x72] = dev->pci_conf_sb[0][0x73] = 0x00;
dev->pci_conf_sb[0][0x74] = dev->pci_conf_sb[0][0x76] = 0x00;
dev->pci_conf_sb[0][0x82] = 0x00;
dev->pci_conf_sb[0][0x90] = dev->pci_conf_sb[0][0x91] = 0x00;
dev->pci_conf_sb[0][0xa0] = dev->pci_conf_sb[0][0xa2] = 0x00;
dev->pci_conf_sb[0][0xa4] = 0x00;
dev->pci_conf_sb[0][0xa8] = 0x20;
if (HAS_IDE) {
dev->pci_conf_sb[1][0] = 0x60; /* UMC */
dev->pci_conf_sb[1][1] = 0x10;
if (dev->has_ide) {
dev->pci_conf_sb[1][0x00] = 0x60; /* UMC */
dev->pci_conf_sb[1][0x01] = 0x10;
dev->pci_conf_sb[1][0x02] = (dev->ide_id & 0xff); /* 8886xx IDE */
dev->pci_conf_sb[1][0x03] = ((dev->ide_id >> 8) & 0xff);
dev->pci_conf_sb[1][0x04] = 0x05; /* Start with Internal IDE Enabled */
dev->pci_conf_sb[1][0x08] = 0x10;
dev->pci_conf_sb[1][0x09] = 0x8f;
dev->pci_conf_sb[1][0x0a] = dev->pci_conf_sb[1][0x0b] = 0x01;
dev->pci_conf_sb[1][0x10] = 0xf1;
dev->pci_conf_sb[1][0x11] = 0x01;
dev->pci_conf_sb[1][0x14] = 0xf5;
dev->pci_conf_sb[1][0x15] = 0x03;
dev->pci_conf_sb[1][0x18] = 0x71;
dev->pci_conf_sb[1][0x19] = 0x01;
dev->pci_conf_sb[1][0x1c] = 0x75;
dev->pci_conf_sb[1][0x1d] = 0x03;
dev->pci_conf_sb[1][0x20] = 0x01;
dev->pci_conf_sb[1][0x21] = 0x10;
dev->pci_conf_sb[1][2] = 0x3a; /* 8886BF IDE */
dev->pci_conf_sb[1][3] = 0x67;
if (dev->ide_id == 0x673a) {
dev->pci_conf_sb[1][0x40] = 0xc0;
dev->pci_conf_sb[1][0x41] = 0x00;
dev->pci_conf_sb[1][0x42] = dev->pci_conf_sb[1][0x43] = 0x00;
dev->pci_conf_sb[1][0x44] = dev->pci_conf_sb[1][0x45] = 0x00;
dev->pci_conf_sb[1][0x46] = dev->pci_conf_sb[1][0x47] = 0x00;
dev->pci_conf_sb[1][0x48] = dev->pci_conf_sb[1][0x49] = 0x00;
dev->pci_conf_sb[1][0x4a] = dev->pci_conf_sb[1][0x4b] = 0x00;
dev->pci_conf_sb[1][0x54] = dev->pci_conf_sb[1][0x55] = 0x00;
dev->pci_conf_sb[1][0x56] = dev->pci_conf_sb[1][0x57] = 0x00;
dev->pci_conf_sb[1][0x58] = dev->pci_conf_sb[1][0x59] = 0x00;
dev->pci_conf_sb[1][4] = 1; /* Start with Internal IDE Enabled */
umc_8886_ide_handler(dev);
dev->pci_conf_sb[1][8] = 0x10;
dev->pci_conf_sb[1][0x09] = 0x0f;
dev->pci_conf_sb[1][0x0a] = dev->pci_conf_sb[1][0x0b] = 1;
umc_8886_ide_handler(1);
picintc(1 << 14);
picintc(1 << 15);
}
}
for (uint8_t i = 1; i < 5; i++) /* Disable all IRQ interrupts */
@@ -375,17 +380,28 @@ umc_8886_init(const device_t *info)
umc_8886_t *dev = (umc_8886_t *) malloc(sizeof(umc_8886_t));
memset(dev, 0, sizeof(umc_8886_t));
dev->has_ide = !!(info->local == 0x886a);
pci_add_card(PCI_ADD_SOUTHBRIDGE, umc_8886_read, umc_8886_write, dev, &dev->pci_slot); /* Device 12: UMC 8886xx */
/* Add IDE if UM8886AF variant */
if (HAS_IDE)
device_add(&ide_pci_2ch_device);
dev->max_func = (HAS_IDE) ? 1 : 0;
/* Device 12: UMC 8886xx */
pci_add_card(PCI_ADD_SOUTHBRIDGE, umc_8886_read, umc_8886_write, dev, &dev->pci_slot);
/* Get the Southbridge Revision */
SB_ID = info->local;
dev->sb_id = info->local & 0xffff;
/* IDE Revision */
dev->ide_id = info->local >> 16;
dev->has_ide = (dev->ide_id != 0x0000);
dev->max_func = 0;
/* Add IDE if this is the UM8886AF or UM8886BF. */
if (dev->ide_id == 0x673a) {
/* UM8886BF */
device_add(&ide_pci_2ch_device);
dev->max_func = 1;
} else if (dev->ide_id == 0x1001) {
/* UM8886AF */
device_add(&ide_um8673f_device);
}
umc_8886_reset(dev);
@@ -396,7 +412,7 @@ const device_t umc_8886f_device = {
.name = "UMC 8886F",
.internal_name = "umc_8886f",
.flags = DEVICE_PCI,
.local = 0x8886,
.local = 0x00008886,
.init = umc_8886_init,
.close = umc_8886_close,
.reset = umc_8886_reset,
@@ -407,10 +423,24 @@ const device_t umc_8886f_device = {
};
const device_t umc_8886af_device = {
.name = "UMC 8886AF/8886BF",
.name = "UMC 8886AF",
.internal_name = "umc_8886af",
.flags = DEVICE_PCI,
.local = 0x886a,
.local = 0x1001886a,
.init = umc_8886_init,
.close = umc_8886_close,
.reset = umc_8886_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t umc_8886bf_device = {
.name = "UMC 8886BF",
.internal_name = "umc_8886bf",
.flags = DEVICE_PCI,
.local = 0x673a888a,
.init = umc_8886_init,
.close = umc_8886_close,
.reset = umc_8886_reset,

241
src/chipset/umc_8890.c Normal file
View File

@@ -0,0 +1,241 @@
/*
* 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 UMC 8890 Chipset.
*
* Note: This chipset has no datasheet, everything were done via
* reverse engineering the BIOS of various machines using it.
*
* Authors: Tiseno100,
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2021 Tiseno100.
* Copyright 2021-2024 Miran Grca.
*/
#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/apm.h>
#include <86box/mem.h>
#include <86box/pci.h>
#include <86box/port_92.h>
#include <86box/smram.h>
#include <86box/chipset.h>
#ifdef ENABLE_UMC_8890_LOG
int umc_8890_do_log = ENABLE_UMC_8890_LOG;
static void
umc_8890_log(const char *fmt, ...)
{
va_list ap;
if (umc_8890_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define umc_8890_log(fmt, ...)
#endif
typedef struct umc_8890_t {
uint8_t pci_slot;
uint8_t pci_conf[256]; /* PCI Registers */
int mem_state[2];
uint32_t smram_base;
smram_t *smram; /* SMRAM Handler */
} umc_8890_t;
static void
um8890_shadow(umc_8890_t *dev)
{
uint8_t flag;
uint16_t state;
flag = (dev->pci_conf[0x5f] & 0x0c) >> 2;
state = (flag & 1) ? (MEM_READ_INTERNAL | ((flag & 2) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL)) :
(MEM_READ_EXTANY | MEM_WRITE_EXTANY);
if ((dev->mem_state[1] ^ dev->pci_conf[0x5f]) & 0x0c) {
mem_set_mem_state_both(0xe0000, 0x10000, state);
dev->mem_state[1] = (dev->mem_state[1] & 0xf0) | (dev->pci_conf[0x5f] & 0x0f);
}
flag = (dev->pci_conf[0x5f] & 0xc0) >> 6;
state = (flag & 1) ? (MEM_READ_INTERNAL | ((flag & 2) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL)) :
(MEM_READ_EXTANY | MEM_WRITE_EXTANY);
if ((dev->mem_state[1] ^ dev->pci_conf[0x5f]) & 0xc0) {
mem_set_mem_state_both(0xf0000, 0x10000, state);
dev->mem_state[1] = (dev->mem_state[1] & 0x0f) | (dev->pci_conf[0x5f] & 0xf0);
}
for (uint8_t i = 0; i < 8; i++) {
state = (dev->pci_conf[0x5d] & (1 << i)) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) :
(MEM_READ_EXTANY | MEM_WRITE_EXTANY);
if ((dev->mem_state[0] ^ dev->pci_conf[0x5d]) & (1 << i)) {
mem_set_mem_state_both(0xc0000 + (i << 14), 0x4000, state);
dev->mem_state[0] = (dev->mem_state[0] & ~(1 << i)) | (dev->pci_conf[0x5d] & (1 << i));
}
}
flushmmucache_nopc();
}
static void
um8890_smram(umc_8890_t *dev)
{
smram_disable_all();
/* Bit 4, if set, enables SMRAM access outside SMM. SMRAM appears to be always enabled
in SMM, and is always set to A0000-BFFFF. */
smram_enable(dev->smram, 0x000a0000, 0x000a0000, 0x20000, dev->pci_conf[0x65] & 0x10, 1);
}
static void
um8890_write(int func, int addr, uint8_t val, void *priv)
{
umc_8890_t *dev = (umc_8890_t *)priv;
if (func == 0) switch (addr) {
case 0x04 ... 0x05:
case 0x0c ... 0x0d:
case 0x40 ... 0x5b:
case 0x60 ... 0x63:
case 0x66 ... 0xff:
dev->pci_conf[addr] = val;
break;
case 0x07:
dev->pci_conf[addr] &= ~(val & 0xf9);
break;
case 0x5c ... 0x5f:
dev->pci_conf[addr] = val;
um8890_shadow(dev);
break;
/* Register 64h, 16-bit:
Bit 12: SMRAM enabled outside SMM (1 = yes, 0 = no);
Bit 10: ???? (set by Award BIOS);
Bits 7- 0: SMM handler offset to SMBASE, shifted to the right by 14.
*/
case 0x64: case 0x65:
dev->pci_conf[addr] = val;
if (addr == 0x65)
um8890_smram(dev);
break;
}
umc_8890_log("UM8890: dev->regs[%02x] = %02x POST: %02x\n", addr, dev->pci_conf[addr], inb(0x80));
}
static uint8_t
um8890_read(int func, int addr, void *priv)
{
umc_8890_t *dev = (umc_8890_t *)priv;
uint8_t ret = 0xff;
if (func == 0)
ret = dev->pci_conf[addr];
return ret;
}
static void
umc_8890_reset(void *priv)
{
umc_8890_t *dev = (umc_8890_t *)priv;
memset(dev->pci_conf, 0x00, sizeof(dev->pci_conf));
/* Defaults */
dev->pci_conf[0x00] = 0x60; /* UMC */
dev->pci_conf[0x01] = 0x10;
dev->pci_conf[0x02] = 0x91; /* 8891F */
dev->pci_conf[0x03] = 0x88;
dev->pci_conf[0x07] = 0x02;
dev->pci_conf[0x08] = 0x01;
dev->pci_conf[0x09] = 0x00;
dev->pci_conf[0x0a] = 0x00;
dev->pci_conf[0x0b] = 0x06;
dev->pci_conf[0x5c] = 0x00;
dev->pci_conf[0x5d] = 0x00;
dev->pci_conf[0x5e] = 0x00;
dev->pci_conf[0x5f] = 0x00;
dev->pci_conf[0x64] = 0x00;
dev->pci_conf[0x65] = 0x00;
um8890_shadow(dev);
um8890_smram(dev);
}
static void
umc_8890_close(void *priv)
{
umc_8890_t *dev = (umc_8890_t *)priv;
smram_del(dev->smram);
free(dev);
}
static void *
umc_8890_init(const device_t *info)
{
umc_8890_t *dev = (umc_8890_t *) calloc(1, sizeof(umc_8890_t));
/* Device 0: UMC 8890 */
pci_add_card(PCI_ADD_NORTHBRIDGE, um8890_read, um8890_write, dev, &dev->pci_slot);
/* Port 92 */
device_add(&port_92_pci_device);
dev->smram = smram_add();
umc_8890_reset(dev);
return dev;
}
const device_t umc_8890_device = {
.name = "UMC 8890(8891BF/8892BF)",
.internal_name = "umc_8890",
.flags = DEVICE_PCI,
.local = 0x886a,
.init = umc_8890_init,
.close = umc_8890_close,
.reset = umc_8890_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -14,13 +14,11 @@
* Note 2: Additional information were also used from all
* around the web.
*
*
*
* Authors: Tiseno100,
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2021 Tiseno100.
* Copyright 2021 Miran Grca.
* Copyright 2021-2024 Miran Grca.
*/
/*
@@ -75,15 +73,24 @@
Bit 3: CC000-CFFFF Read Enable
Bit 2: C8000-CBFFF Read Enable
Bit 1: C0000-C7FFF Read Enable
Bit 0: Enable C0000-DFFFF Shadow Segment Bits
Bit 0: E0000-EFFFF Read Enable
Register 55:
Bit 7: E0000-FFFF Read Enable
Bit 7: F0000-FFFF Read Enable
Bit 6: Shadow Write Status (1: Write Protect/0: Write)
Register 56h & 57h: DRAM Bank 0 Configuration
Register 58h & 59h: DRAM Bank 1 Configuration
Register 5A:
Bit 2: Detrubo
Register 5C:
Bits 7-0: SMRAM base A27-A20
Register 5D:
Bits 3-0: SMRAM base A31-A28
Register 60:
Bit 5: If set and SMRAM is enabled, data cycles go to PCI and code cycles go to DRAM
Bit 0: SMRAM Local Access Enable - if set, SMRAM is also enabled outside SMM
@@ -129,14 +136,15 @@ hb4_log(const char *fmt, ...)
#endif
typedef struct hb4_t {
uint8_t shadow;
uint8_t shadow_read;
uint8_t shadow_write;
uint8_t pci_slot;
uint8_t pci_conf[256]; /* PCI Registers */
int mem_state[9];
smram_t *smram[3]; /* SMRAM Handlers */
uint32_t smram_base;
smram_t *smram; /* SMRAM Handler */
} hb4_t;
static int shadow_bios[4] = { (MEM_READ_EXTANY | MEM_WRITE_INTERNAL), (MEM_READ_EXTANY | MEM_WRITE_EXTANY),
@@ -167,7 +175,8 @@ hb4_shadow_bios_low(hb4_t *dev)
{
int state;
state = shadow_bios[(dev->pci_conf[0x55] >> 6) & (dev->shadow | 0x01)];
/* Erratum in Vogons' datasheet: Register 55h bit 7 in fact controls E0000-FFFFF. */
state = shadow_bios[dev->pci_conf[0x55] >> 6];
if (state != dev->mem_state[7]) {
mem_set_mem_state_both(0xe0000, 0x10000, state);
@@ -185,7 +194,8 @@ hb4_shadow_main(hb4_t *dev)
int n = 0;
for (uint8_t i = 0; i < 6; i++) {
state = shadow_read[dev->shadow && ((dev->pci_conf[0x54] >> (i + 2)) & 0x01)] | shadow_write[(dev->pci_conf[0x55] >> 6) & 0x01];
state = shadow_read[(dev->pci_conf[0x54] >> (i + 2)) & 0x01] |
shadow_write[(dev->pci_conf[0x55] >> 6) & 0x01];
if (state != dev->mem_state[i + 1]) {
n++;
@@ -202,7 +212,8 @@ hb4_shadow_video(hb4_t *dev)
{
int state;
state = shadow_read[dev->shadow && ((dev->pci_conf[0x54] >> 1) & 0x01)] | shadow_write[(dev->pci_conf[0x55] >> 6) & 0x01];
state = shadow_read[(dev->pci_conf[0x54] >> 1) & 0x01] |
shadow_write[(dev->pci_conf[0x55] >> 6) & 0x01];
if (state != dev->mem_state[0]) {
mem_set_mem_state_both(0xc0000, 0x8000, state);
@@ -232,22 +243,26 @@ static void
hb4_smram(hb4_t *dev)
{
smram_disable_all();
if (dev->smram_base != 0x00000000)
umc_smram_recalc(dev->smram_base >> 12, 0);
dev->smram_base = ((uint32_t) dev->pci_conf[0x5c]) << 20;
dev->smram_base |= ((uint32_t) (dev->pci_conf[0x5d] & 0x0f)) << 28;
dev->smram_base |= 0x000a0000;
/* Bit 0, if set, enables SMRAM access outside SMM. SMRAM appears to be always enabled
in SMM, and is always set to A0000-BFFFF. */
smram_enable(dev->smram[0], 0x000a0000, 0x000a0000, 0x20000, dev->pci_conf[0x60] & 0x01, 1);
/* There's a mirror of the SMRAM at 0E0A0000, mapped to A0000. */
smram_enable(dev->smram[1], 0x0e0a0000, 0x000a0000, 0x20000, dev->pci_conf[0x60] & 0x01, 1);
/* There's another mirror of the SMRAM at 4E0A0000, mapped to A0000. */
smram_enable(dev->smram[2], 0x4e0a0000, 0x000a0000, 0x20000, dev->pci_conf[0x60] & 0x01, 1);
smram_enable(dev->smram, dev->smram_base, 0x000a0000, 0x20000, dev->pci_conf[0x60] & 0x01, 1);
/* Bit 5 seems to set data to go to PCI and code to DRAM. The Samsung SPC7700P-LW uses
this. */
if (dev->pci_conf[0x60] & 0x20) {
if (dev->pci_conf[0x60] & 0x01)
mem_set_mem_state_smram_ex(0, 0x000a0000, 0x20000, 0x02);
mem_set_mem_state_smram_ex(1, 0x000a0000, 0x20000, 0x02);
mem_set_mem_state_smram_ex(0, dev->smram_base, 0x20000, 0x02);
mem_set_mem_state_smram_ex(1, dev->smram_base, 0x20000, 0x02);
}
umc_smram_recalc(dev->smram_base >> 12, 1);
}
static void
@@ -278,38 +293,27 @@ hb4_write(UNUSED(int func), int addr, uint8_t val, void *priv)
cpu_update_waitstates();
break;
case 0x51:
case 0x52:
case 0x51 ... 0x53:
dev->pci_conf[addr] = val;
break;
case 0x53:
dev->pci_conf[addr] = val;
hb4_log("HB53: %02X\n", val);
break;
case 0x55:
dev->shadow_read = (val & 0x80);
dev->shadow_write = (val & 0x40);
dev->pci_conf[addr] = val;
hb4_shadow(dev);
break;
case 0x54:
dev->shadow = (val & 0x01) << 1;
case 0x54 ... 0x55:
dev->pci_conf[addr] = val;
hb4_shadow(dev);
break;
case 0x56 ... 0x5f:
case 0x56 ... 0x5b:
case 0x5e ... 0x5f:
dev->pci_conf[addr] = val;
break;
case 0x5c ... 0x5d:
case 0x60:
dev->pci_conf[addr] = val;
hb4_smram(dev);
break;
case 0x61:
case 0x61 ... 0x62:
dev->pci_conf[addr] = val;
break;
@@ -336,30 +340,35 @@ hb4_reset(void *priv)
hb4_t *dev = (hb4_t *) priv;
memset(dev->pci_conf, 0x00, sizeof(dev->pci_conf));
dev->pci_conf[0] = 0x60; /* UMC */
dev->pci_conf[1] = 0x10;
dev->pci_conf[2] = 0x81; /* 8881x */
dev->pci_conf[3] = 0x88;
dev->pci_conf[7] = 2;
dev->pci_conf[8] = 4;
dev->pci_conf[0x00] = 0x60; /* UMC */
dev->pci_conf[0x01] = 0x10;
dev->pci_conf[0x02] = 0x81; /* 8881x */
dev->pci_conf[0x03] = 0x88;
dev->pci_conf[0x07] = 0x02;
dev->pci_conf[0x08] = 0x04;
dev->pci_conf[0x09] = 0x00;
dev->pci_conf[0x0a] = 0x00;
dev->pci_conf[0x0b] = 0x06;
dev->pci_conf[0x51] = 1;
dev->pci_conf[0x52] = 1;
dev->pci_conf[0x5a] = 4;
dev->pci_conf[0x5c] = 0xc0;
dev->pci_conf[0x50] = 0x00;
dev->pci_conf[0x51] = 0x00;
dev->pci_conf[0x52] = 0x01;
dev->pci_conf[0x53] = 0x00;
dev->pci_conf[0x54] = 0x00;
dev->pci_conf[0x55] = 0x00;
dev->pci_conf[0x56] = 0x00;
dev->pci_conf[0x57] = 0x00;
dev->pci_conf[0x58] = 0x00;
dev->pci_conf[0x59] = 0x00;
dev->pci_conf[0x5a] = 0x04;
dev->pci_conf[0x5c] = 0x00;
dev->pci_conf[0x5d] = 0x20;
dev->pci_conf[0x5f] = 0xff;
dev->pci_conf[0x60] = 0x00;
dev->pci_conf[0x61] = 0x00;
dev->pci_conf[0x62] = 0x00;
hb4_write(0, 0x54, 0x00, dev);
hb4_write(0, 0x55, 0x00, dev);
hb4_write(0, 0x60, 0x80, dev);
hb4_shadow(dev);
hb4_smram(dev);
cpu_cache_ext_enabled = 0;
cpu_update_waitstates();
@@ -372,6 +381,7 @@ hb4_close(void *priv)
{
hb4_t *dev = (hb4_t *) priv;
smram_del(dev->smram);
free(dev);
}
@@ -387,10 +397,9 @@ hb4_init(UNUSED(const device_t *info))
device_add(&port_92_pci_device);
/* SMRAM */
dev->smram[0] = smram_add();
dev->smram[1] = smram_add();
dev->smram[2] = smram_add();
dev->smram = smram_add();
dev->smram_base = 0x000a0000;
hb4_reset(dev);
return dev;

File diff suppressed because it is too large Load Diff

View File

@@ -139,8 +139,6 @@ load_general(void)
rctrl_is_lalt = ini_section_get_int(cat, "rctrl_is_lalt", 0);
update_icons = ini_section_get_int(cat, "update_icons", 1);
status_icons_fullscreen = !!ini_section_get_int(cat, "status_icons_fullscreen", 0);
window_remember = ini_section_get_int(cat, "window_remember", 0);
if (!window_remember && !(vid_resize & 2))
@@ -244,25 +242,81 @@ load_machine(void)
{
ini_section_t cat = ini_find_section(config, "Machine");
const char *p;
const char *migrate_from = NULL;
int c;
int i;
int j;
int speed;
double multi;
p = ini_section_get_string(cat, "machine", NULL);
if (p != NULL)
machine = machine_get_machine_from_internal_name(p);
else
if (p != NULL) {
migrate_from = p;
/* Migrate renamed machines. */
if (!strcmp(p, "430nx"))
machine = machine_get_machine_from_internal_name("586ip");
else if (!strcmp(p, "586mc1"))
machine = machine_get_machine_from_internal_name("586is");
else {
machine = machine_get_machine_from_internal_name(p);
migrate_from = NULL;
}
} else
machine = 0;
if (machine >= machine_count())
machine = machine_count() - 1;
/* Copy NVR files when migrating a machine to a new internal name. */
if (migrate_from) {
char old_fn[256];
strcpy(old_fn, migrate_from);
strcat(old_fn, ".");
c = strlen(old_fn);
char new_fn[256];
strcpy(new_fn, machines[machine].internal_name);
strcat(new_fn, ".");
i = strlen(new_fn);
/* Iterate through NVR files. */
DIR *dirp = opendir(nvr_path("."));
if (dirp) {
struct dirent *entry;
while ((entry = readdir(dirp))) {
/* Check if this file corresponds to the old name. */
if (strncmp(entry->d_name, old_fn, c))
continue;
/* Add extension to the new name. */
strcpy(&new_fn[i], &entry->d_name[c]);
/* Only copy if a file with the new name doesn't already exist. */
FILE *g = nvr_fopen(new_fn, "rb");
if (!g) {
FILE *f = nvr_fopen(entry->d_name, "rb");
g = nvr_fopen(new_fn, "wb");
uint8_t buf[4096];
while ((j = fread(buf, 1, sizeof(buf), f)))
fwrite(buf, 1, j, g);
fclose(f);
}
fclose(g);
}
}
}
cpu_override = ini_section_get_int(cat, "cpu_override", 0);
cpu_f = NULL;
p = ini_section_get_string(cat, "cpu_family", NULL);
if (p) {
cpu_f = cpu_get_family(p);
/* Migrate CPU family changes. */
if ((!strcmp(machines[machine].internal_name, "deskpro386") ||
!strcmp(machines[machine].internal_name, "deskpro386_05_1988")))
cpu_f = cpu_get_family("i386dx_deskpro386");
else
cpu_f = cpu_get_family(p);
if (cpu_f && !cpu_family_is_eligible(cpu_f, machine)) /* only honor eligible families */
cpu_f = NULL;
@@ -721,6 +775,7 @@ static void
load_storage_controllers(void)
{
ini_section_t cat = ini_find_section(config, "Storage controllers");
ini_section_t migration_cat;
char *p;
char temp[512];
int c;
@@ -754,17 +809,16 @@ load_storage_controllers(void)
}
free_p = 1;
}
if (!strcmp(p, "mfm_xt"))
hdc_current = hdc_get_from_internal_name("st506_xt");
else if (!strcmp(p, "mfm_xt_dtc5150x"))
hdc_current = hdc_get_from_internal_name("st506_xt_dtc5150x");
else if (!strcmp(p, "mfm_at"))
hdc_current = hdc_get_from_internal_name("st506_at");
else if (!strcmp(p, "vlb_isa"))
hdc_current = hdc_get_from_internal_name("ide_vlb");
else if (!strcmp(p, "vlb_isa_2ch"))
hdc_current = hdc_get_from_internal_name("ide_vlb_2ch");
else
/* Migrate renamed and merged cards. */
if (!strcmp(p, "xtide_plus")) {
hdc_current = hdc_get_from_internal_name("xtide");
migration_cat = ini_find_or_create_section(config, "PC/XT XTIDE");
ini_section_set_string(migration_cat, "bios", "xt_plus");
} else if (!strcmp(p, "xtide_at_386")) {
hdc_current = hdc_get_from_internal_name("xtide_at");
migration_cat = ini_find_or_create_section(config, "PC/AT XTIDE");
ini_section_set_string(migration_cat, "bios", "at_386");
} else
hdc_current = hdc_get_from_internal_name(p);
if (free_p) {
@@ -1533,7 +1587,8 @@ load_other_peripherals(void)
void
config_load(void)
{
int i;
int i;
ini_section_t c;
config_log("Loading config file '%s'..\n", cfg_path);
@@ -1623,6 +1678,23 @@ config_load(void)
load_other_removable_devices(); /* Other removable devices */
load_other_peripherals(); /* Other peripherals */
/* Migrate renamed device configurations. */
c = ini_find_section(config, "MDA");
if (c != NULL)
ini_rename_section(c, "IBM MDA");
c = ini_find_section(config, "CGA");
if (c != NULL)
ini_rename_section(c, "IBM CGA");
c = ini_find_section(config, "EGA");
if (c != NULL)
ini_rename_section(c, "IBM EGA");
c = ini_find_section(config, "3DFX Voodoo Graphics");
if (c != NULL)
ini_rename_section(c, "3Dfx Voodoo Graphics");
c = ini_find_section(config, "3dfx Voodoo Banshee");
if (c != NULL)
ini_rename_section(c, "3Dfx Voodoo Banshee");
/* Mark the configuration as changed. */
config_changed = 1;
@@ -1785,11 +1857,6 @@ save_general(void)
else
ini_section_delete_var(cat, "open_dir_usr_path");
if (status_icons_fullscreen)
ini_section_set_int(cat, "status_icons_fullscreen", status_icons_fullscreen);
else
ini_section_delete_var(cat, "status_icons_fullscreen");
if (video_framerate != -1)
ini_section_set_int(cat, "video_gl_framerate", video_framerate);
else
@@ -1846,11 +1913,6 @@ save_machine(void)
{
ini_section_t cat = ini_find_or_create_section(config, "Machine");
const char *p;
int c;
int i = 0;
int legacy_mfg;
int legacy_cpu = -1;
int closest_legacy_cpu = -1;
p = machine_get_internal_name();
ini_section_set_string(cat, "machine", p);
@@ -1867,57 +1929,6 @@ save_machine(void)
ini_section_delete_var(cat, "cpu_manufacturer");
ini_section_delete_var(cat, "cpu");
/* Look for a machine entry on the legacy table. */
c = 0;
while (cpu_legacy_table[c].machine) {
if (!strcmp(p, cpu_legacy_table[c].machine))
break;
c++;
}
if (cpu_legacy_table[c].machine) {
/* Look for a corresponding CPU entry. */
const cpu_legacy_table_t *legacy_table_entry;
for (legacy_mfg = 0; legacy_mfg < 4; legacy_mfg++) {
if (!cpu_legacy_table[c].tables[legacy_mfg])
continue;
i = 0;
while (cpu_legacy_table[c].tables[legacy_mfg][i].family) {
legacy_table_entry = &cpu_legacy_table[c].tables[legacy_mfg][i];
/* Match the family name, speed and multiplier. */
if (!strcmp(cpu_f->internal_name, legacy_table_entry->family)) {
if ((legacy_table_entry->rspeed == cpu_f->cpus[cpu].rspeed) &&
(legacy_table_entry->multi == cpu_f->cpus[cpu].multi)) {
/* Exact speed/multiplier match. */
legacy_cpu = i;
break;
} else if ((legacy_table_entry->rspeed >= cpu_f->cpus[cpu].rspeed) &&
(closest_legacy_cpu == -1))
/* Closest speed match. */
closest_legacy_cpu = i;
}
i++;
}
/* Use the closest speed match if no exact match was found. */
if ((legacy_cpu == -1) && (closest_legacy_cpu > -1)) {
legacy_cpu = closest_legacy_cpu;
break;
} else if (legacy_cpu > -1) /* exact match found */
break;
}
/* Set legacy values if a match was found. */
if (legacy_cpu > -1) {
if (legacy_mfg)
ini_section_set_int(cat, "cpu_manufacturer", legacy_mfg);
if (legacy_cpu)
ini_section_set_int(cat, "cpu", legacy_cpu);
}
}
if (cpu_waitstates == 0)
ini_section_delete_var(cat, "cpu_waitstates");
else

View File

@@ -25,6 +25,7 @@
#include <86box/fdd.h>
#include <86box/fdc.h>
#include <86box/machine.h>
#include <86box/plat_fallthrough.h>
#include <86box/gdbstub.h>
#ifndef OPS_286_386
# define OPS_286_386
@@ -240,6 +241,7 @@ exec386_2386(int32_t cycs)
cycdiff = 0;
oldcyc = cycles;
while (cycdiff < cycle_period) {
int ins_fetch_fault = 0;
ins_cycles = cycles;
#ifndef USE_NEW_DYNAREC
@@ -259,6 +261,13 @@ exec386_2386(int32_t cycs)
fetchdat = fastreadl_fetch(cs + cpu_state.pc);
ol = opcode_length[fetchdat & 0xff];
CHECK_READ_CS(MIN(ol, 4));
ins_fetch_fault = cpu_386_check_instruction_fault();
/* Breakpoint fault has priority over other faults. */
if (ins_fetch_fault) {
ins_fetch_fault = 0;
cpu_state.abrt = 1;
}
if (!cpu_state.abrt) {
#ifdef ENABLE_386_LOG
@@ -267,10 +276,11 @@ exec386_2386(int32_t cycs)
#endif
opcode = fetchdat & 0xFF;
fetchdat >>= 8;
trap = cpu_state.flags & T_FLAG;
trap |= !!(cpu_state.flags & T_FLAG);
cpu_state.pc++;
x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
cpu_state.eflags &= ~(RF_FLAG);
x86_2386_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
if (x86_was_reset)
break;
}
@@ -311,7 +321,8 @@ exec386_2386(int32_t cycs)
}
} else if (trap) {
flags_rebuild();
dr[6] |= (trap == 2) ? 0x8000 : 0x4000;
if (trap & 2) dr[6] |= 0x8000;
if (trap & 1) dr[6] |= 0x4000;
trap = 0;
#ifndef USE_NEW_DYNAREC
oldcs = CS;

View File

@@ -80,6 +80,7 @@ int smm_in_hlt = 0;
int smi_block = 0;
int prefetch_prefixes = 0;
int rf_flag_no_clear = 0;
int tempc;
int oldcpl;
@@ -119,6 +120,53 @@ int opcode_length[256] = { 3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 3, /*
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 2, 1, 1, 1, 1, /* 0xex */
1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 3, 3 }; /* 0xfx */
/* 0 = no, 1 = always, 2 = depends on second opcode, 3 = depends on mod/rm */
int lock_legal[256] = { 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 2, /* 0x0x */
1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, /* 0x1x */
1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, /* 0x2x */
1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x3x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x4x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x5x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x6x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x7x */
3, 3, 3, 3, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x8x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x9x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xax */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xbx */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xcx */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xdx */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xex */
0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 3, 3 }; /* 0xfx */
int lock_legal_0f[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x0x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x1x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x2x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x3x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x4x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x5x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x6x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x7x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x8x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x9x */
0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, /* 0xax */
0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, /* 0xbx */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xcx */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xdx */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xex */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* 0xfx */
/* (modrm >> 3) & 0x07 */
int lock_legal_ba[8] = { 0, 0, 0, 0, 1, 1, 1, 1 };
/* Also applies to 81, 82, and 83 */
int lock_legal_80[8] = { 1, 1, 1, 1, 1, 1, 1, 0 };
/* Also applies to F7 */
int lock_legal_f6[8] = { 0, 0, 1, 1, 0, 0, 0, 0 };
/* Also applies to FF */
int lock_legal_fe[8] = { 1, 1, 0, 0, 0, 0, 0, 0 };
uint32_t addr64;
uint32_t addr64_2;
uint32_t addr64a[8];
@@ -127,9 +175,9 @@ uint32_t addr64a_2[8];
static pc_timer_t *cpu_fast_off_timer = NULL;
static double cpu_fast_off_period = 0.0;
#define AMD_SYSCALL_EIP (msr.star & 0xFFFFFFFF)
#define AMD_SYSCALL_SB ((msr.star >> 32) & 0xFFFF)
#define AMD_SYSRET_SB ((msr.star >> 48) & 0xFFFF)
#define AMD_SYSCALL_EIP (msr.amd_star & 0xFFFFFFFF)
#define AMD_SYSCALL_SB ((msr.amd_star >> 32) & 0xFFFF)
#define AMD_SYSRET_SB ((msr.amd_star >> 48) & 0xFFFF)
/* These #define's and enum have been borrowed from Bochs. */
/* SMM feature masks */
@@ -1411,7 +1459,7 @@ x86_int(int num)
cpu_state.pc = cpu_state.oldpc;
if (msw & 1)
is486 ? pmodeint(num, 0) : pmodeint_2386(num, 0);
cpu_use_exec ? pmodeint(num, 0) : pmodeint_2386(num, 0);
else {
addr = (num << 2) + idt.base;
@@ -1444,7 +1492,7 @@ x86_int(int num)
oxpc = cpu_state.pc;
#endif
cpu_state.pc = readmemw(0, addr);
is486 ? loadcs(readmemw(0, addr + 2)) : loadcs_2386(readmemw(0, addr + 2));
cpu_use_exec ? loadcs(readmemw(0, addr + 2)) : loadcs_2386(readmemw(0, addr + 2));
}
}
@@ -1461,7 +1509,7 @@ x86_int_sw(int num)
cycles -= timing_int;
if (msw & 1)
is486 ? pmodeint(num, 1) : pmodeint_2386(num, 1);
cpu_use_exec ? pmodeint(num, 1) : pmodeint_2386(num, 1);
else {
addr = (num << 2) + idt.base;
@@ -1486,12 +1534,15 @@ x86_int_sw(int num)
oxpc = cpu_state.pc;
#endif
cpu_state.pc = readmemw(0, addr);
is486 ? loadcs(readmemw(0, addr + 2)) : loadcs_2386(readmemw(0, addr + 2));
cpu_use_exec ? loadcs(readmemw(0, addr + 2)) : loadcs_2386(readmemw(0, addr + 2));
cycles -= timing_int_rm;
}
}
trap = 0;
if (cpu_use_exec)
trap = 0;
else
trap &= ~1;
CPU_BLOCK_END();
}
@@ -1528,13 +1579,16 @@ x86_int_sw_rm(int num)
cpu_state.eflags &= ~VIF_FLAG;
cpu_state.flags &= ~T_FLAG;
cpu_state.pc = new_pc;
is486 ? loadcs(new_cs) : loadcs_2386(new_cs);
cpu_use_exec ? loadcs(new_cs) : loadcs_2386(new_cs);
#ifndef USE_NEW_DYNAREC
oxpc = cpu_state.pc;
#endif
cycles -= timing_int_rm;
trap = 0;
if (cpu_use_exec)
trap = 0;
else
trap &= ~1;
CPU_BLOCK_END();
return 0;
@@ -1551,6 +1605,13 @@ checkio(uint32_t port, int mask)
{
uint32_t t;
if (!(tr.access & 0x08)) {
if ((CPL) > (IOPL))
return 1;
return 0;
}
cpl_override = 1;
t = readmemw(tr.base, 0x66);
@@ -1655,6 +1716,37 @@ cpu_386_flags_rebuild(void)
flags_rebuild();
}
extern uint64_t mmutranslate_noabrt_2386(uint32_t addr, int rw);
int
cpu_386_check_instruction_fault(void)
{
int i = 0;
int fault = 0;
/* Report no fault if RF is set. */
if (cpu_state.eflags & RF_FLAG)
return 0;
/* Make sure breakpoints are enabled. */
if (!(dr[7] & 0xFF))
return 0;
for (i = 0; i < 4; i++) {
int breakpoint_enabled = !!(dr[7] & (0x3 << (2 * i))) && !(dr[7] & (0x30000 << (4 * i)));
uint32_t translated_addr = 0xffffffff;
if (!breakpoint_enabled)
continue;
translated_addr = dr[i];
if ((cs + cpu_state.pc) == (uint32_t)translated_addr) {
dr[6] |= (1 << i);
fault = 1;
}
}
return fault;
}
int
sysenter(uint32_t fetchdat)
{

View File

@@ -225,19 +225,37 @@ int checkio(uint32_t port, int mask);
static __inline uint8_t
fastreadb(uint32_t a)
{
return readmembl_2386(a);
uint8_t ret;
read_type = 1;
ret = readmembl_2386(a);
read_type = 4;
if (cpu_state.abrt)
return 0;
return ret;
}
static __inline uint16_t
fastreadw(uint32_t a)
{
return readmemwl_2386(a);
uint16_t ret;
read_type = 1;
ret = readmemwl_2386(a);
read_type = 4;
if (cpu_state.abrt)
return 0;
return ret;
}
static __inline uint32_t
fastreadl(uint32_t a)
{
return readmemll_2386(a);
uint32_t ret;
read_type = 1;
ret = readmemll_2386(a);
read_type = 4;
if (cpu_state.abrt)
return 0;
return ret;
}
#else
static __inline uint8_t
@@ -342,31 +360,41 @@ extern int opcode_length[256];
static __inline uint16_t
fastreadw_fetch(uint32_t a)
{
uint16_t val;
uint16_t ret;
if ((a & 0xFFF) > 0xFFE) {
val = fastreadb(a);
if (opcode_length[val & 0xff] > 1)
val |= ((uint16_t) fastreadb(a + 1) << 8);
return val;
ret = fastreadb(a);
if (!cpu_state.abrt && (opcode_length[ret & 0xff] > 1))
ret |= ((uint16_t) fastreadb(a + 1) << 8);
} else if (cpu_state.abrt)
ret = 0;
else {
read_type = 1;
ret = readmemwl_2386(a);
read_type = 4;
}
return readmemwl_2386(a);
return ret;
}
static __inline uint32_t
fastreadl_fetch(uint32_t a)
{
uint32_t val;
uint32_t ret;
if (cpu_16bitbus || ((a & 0xFFF) > 0xFFC)) {
val = fastreadw_fetch(a);
if (opcode_length[val & 0xff] > 2)
val |= ((uint32_t) fastreadw(a + 2) << 16);
return val;
ret = fastreadw_fetch(a);
if (!cpu_state.abrt && (opcode_length[ret & 0xff] > 2))
ret |= ((uint32_t) fastreadw(a + 2) << 16);
} else if (cpu_state.abrt)
ret = 0;
else {
read_type = 1;
ret = readmemll_2386(a);
read_type = 4;
}
return readmemll_2386(a);
return ret;
}
#else
static __inline uint16_t
@@ -674,3 +702,8 @@ seteaq(uint64_t v)
cpu_state.pc += 2
#endif
/* Resume Flag handling. */
extern int rf_flag_no_clear;
int cpu_386_check_instruction_fault(void);

View File

@@ -48,6 +48,7 @@
#define CPU_BLOCK_END() cpu_block_end = 1
int cpu_override_dynarec = 0;
int inrecomp = 0;
int cpu_block_end = 0;
int cpu_end_block_after_ins = 0;
@@ -718,7 +719,7 @@ exec386_dynarec(int32_t cycs)
cycles_old = cycles;
oldtsc = tsc;
tsc_old = tsc;
if (!CACHE_ON()) /*Interpret block*/
if ((!CACHE_ON()) || cpu_override_dynarec) /*Interpret block*/
{
exec386_dynarec_int();
} else {

View File

@@ -181,8 +181,16 @@ extern void x386_dynarec_log(const char *fmt, ...);
#ifndef OPS_286_386
# include "x86_ops_cyrix.h"
#endif
#include "x86_ops_flag.h"
#include "x86_ops_fpu.h"
#ifdef OPS_286_386
# include "x86_ops_flag_2386.h"
#else
# include "x86_ops_flag.h"
#endif
#ifdef OPS_286_386
# include "x86_ops_fpu_2386.h"
#else
# include "x86_ops_fpu.h"
#endif
#include "x86_ops_inc_dec.h"
#include "x86_ops_int.h"
#include "x86_ops_io.h"
@@ -200,7 +208,11 @@ extern void x386_dynarec_log(const char *fmt, ...);
# include "x86_ops_mmx_shift.h"
#endif
#include "x86_ops_mov.h"
#include "x86_ops_mov_ctrl.h"
#ifdef OPS_286_386
# include "x86_ops_mov_ctrl_2386.h"
#else
# include "x86_ops_mov_ctrl.h"
#endif
#include "x86_ops_mov_seg.h"
#include "x86_ops_movx.h"
#ifndef OPS_286_386
@@ -208,7 +220,11 @@ extern void x386_dynarec_log(const char *fmt, ...);
#endif
#include "x86_ops_mul.h"
#include "x86_ops_pmode.h"
#include "x86_ops_prefix.h"
#ifdef OPS_286_386
# include "x86_ops_prefix_2386.h"
#else
# include "x86_ops_prefix.h"
#endif
#ifdef IS_DYNAREC
# include "x86_ops_rep_dyn.h"
#else
@@ -218,7 +234,11 @@ extern void x386_dynarec_log(const char *fmt, ...);
# include "x86_ops_rep.h"
# endif
#endif
#include "x86_ops_ret.h"
#ifdef OPS_286_386
# include "x86_ops_ret_2386.h"
#else
# include "x86_ops_ret.h"
#endif
#include "x86_ops_set.h"
#include "x86_ops_stack.h"
#ifdef OPS_286_386
@@ -629,7 +649,7 @@ const OpFn OP_TABLE(386_0f)[1024] = {
// clang-format off
/*16-bit data, 16-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*10*/ opMOV_b_r_a16, opMOV_w_r_a16, opMOV_r_b_a16, opMOV_r_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
@@ -644,14 +664,14 @@ const OpFn OP_TABLE(386_0f)[1024] = {
/*a0*/ opPUSH_FS_w, opPOP_FS_w, ILLEGAL, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16,
/*b0*/ ILLEGAL, ILLEGAL, opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL,
/*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*32-bit data, 16-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*10*/ opMOV_b_r_a16, opMOV_l_r_a16, opMOV_r_b_a16, opMOV_r_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
@@ -666,14 +686,14 @@ const OpFn OP_TABLE(386_0f)[1024] = {
/*a0*/ opPUSH_FS_l, opPOP_FS_l, ILLEGAL, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16,
/*b0*/ ILLEGAL, ILLEGAL, opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16,
/*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*16-bit data, 32-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*10*/ opMOV_b_r_a32, opMOV_w_r_a32, opMOV_r_b_a32, opMOV_r_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
@@ -688,14 +708,14 @@ const OpFn OP_TABLE(386_0f)[1024] = {
/*a0*/ opPUSH_FS_w, opPOP_FS_w, ILLEGAL, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32,
/*b0*/ ILLEGAL, ILLEGAL, opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL,
/*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*32-bit data, 32-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*10*/ opMOV_b_r_a32, opMOV_l_r_a32, opMOV_r_b_a32, opMOV_r_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
@@ -710,7 +730,7 @@ const OpFn OP_TABLE(386_0f)[1024] = {
/*a0*/ opPUSH_FS_l, opPOP_FS_l, ILLEGAL, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32,
/*b0*/ ILLEGAL, ILLEGAL, opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32,
/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,

View File

@@ -563,9 +563,10 @@ reset_808x(int hard)
_opseg[3] = &cpu_state.seg_ds;
pfq_size = (is8086) ? 6 : 4;
pfq_clear();
}
pfq_clear();
load_cs(0xFFFF);
cpu_state.pc = 0;
if (is_nec)
@@ -1222,34 +1223,48 @@ static void
add(int bits)
{
int size_mask = (1 << bits) - 1;
int special_case = 0;
uint32_t temp_src = cpu_src;
if ((cpu_alu_op == 2) && !(cpu_src & size_mask) && (cpu_state.flags & C_FLAG))
special_case = 1;
cpu_data = cpu_dest + cpu_src;
if ((cpu_alu_op == 2) && (cpu_state.flags & C_FLAG))
cpu_src--;
set_apzs(bits);
set_of_add(bits);
/* Anything - FF with carry on is basically anything + 0x100: value stays
unchanged but carry goes on. */
if ((cpu_alu_op == 2) && !(cpu_src & size_mask) && (cpu_state.flags & C_FLAG))
if (special_case)
cpu_state.flags |= C_FLAG;
else
set_cf((cpu_src & size_mask) > (cpu_data & size_mask));
set_cf((temp_src & size_mask) > (cpu_data & size_mask));
}
static void
sub(int bits)
{
int size_mask = (1 << bits) - 1;
int special_case = 0;
uint32_t temp_src = cpu_src;
if ((cpu_alu_op == 3) && !(cpu_src & size_mask) && (cpu_state.flags & C_FLAG))
special_case = 1;
cpu_data = cpu_dest - cpu_src;
if ((cpu_alu_op == 3) && (cpu_state.flags & C_FLAG))
cpu_src--;
set_apzs(bits);
set_of_sub(bits);
/* Anything - FF with carry on is basically anything - 0x100: value stays
unchanged but carry goes on. */
if ((cpu_alu_op == 3) && !(cpu_src & size_mask) && (cpu_state.flags & C_FLAG))
if (special_case)
cpu_state.flags |= C_FLAG;
else
set_cf((cpu_src & size_mask) > (cpu_dest & size_mask));
set_cf((temp_src & size_mask) > (cpu_dest & size_mask));
}
static void

File diff suppressed because it is too large Load Diff

View File

@@ -86,42 +86,33 @@ enum {
};
enum {
CPU_PKG_8088 = (1 << 0),
CPU_PKG_8088_EUROPC = (1 << 1),
CPU_PKG_8086 = (1 << 2),
CPU_PKG_188 = (1 << 3),
CPU_PKG_186 = (1 << 4),
CPU_PKG_286 = (1 << 5),
CPU_PKG_386SX = (1 << 6),
CPU_PKG_386DX = (1 << 7),
CPU_PKG_M6117 = (1 << 8),
CPU_PKG_386SLC_IBM = (1 << 9),
CPU_PKG_486SLC = (1 << 10),
CPU_PKG_486SLC_IBM = (1 << 11),
CPU_PKG_486BL = (1 << 12),
CPU_PKG_486DLC = (1 << 13),
CPU_PKG_SOCKET1 = (1 << 14),
CPU_PKG_SOCKET3 = (1 << 15),
CPU_PKG_SOCKET3_PC330 = (1 << 16),
CPU_PKG_STPC = (1 << 17),
CPU_PKG_SOCKET4 = (1 << 18),
CPU_PKG_SOCKET5_7 = (1 << 19),
CPU_PKG_SOCKET8 = (1 << 20),
CPU_PKG_SLOT1 = (1 << 21),
CPU_PKG_SLOT2 = (1 << 22),
CPU_PKG_SLOTA = (1 << 23),
CPU_PKG_SOCKET370 = (1 << 24),
CPU_PKG_SOCKETA = (1 << 25),
CPU_PKG_EBGA368 = (1 << 26)
CPU_PKG_8088 = (1 << 0),
CPU_PKG_8088_EUROPC = (1 << 1),
CPU_PKG_8086 = (1 << 2),
CPU_PKG_188 = (1 << 3),
CPU_PKG_186 = (1 << 4),
CPU_PKG_286 = (1 << 5),
CPU_PKG_386SX = (1 << 6),
CPU_PKG_386DX = (1 << 7),
CPU_PKG_386DX_DESKPRO386 = (1 << 8),
CPU_PKG_M6117 = (1 << 9),
CPU_PKG_386SLC_IBM = (1 << 10),
CPU_PKG_486SLC = (1 << 11),
CPU_PKG_486SLC_IBM = (1 << 12),
CPU_PKG_486BL = (1 << 13),
CPU_PKG_486DLC = (1 << 14),
CPU_PKG_SOCKET1 = (1 << 15),
CPU_PKG_SOCKET3 = (1 << 16),
CPU_PKG_SOCKET3_PC330 = (1 << 17),
CPU_PKG_STPC = (1 << 18),
CPU_PKG_SOCKET4 = (1 << 19),
CPU_PKG_SOCKET5_7 = (1 << 20),
CPU_PKG_SOCKET8 = (1 << 21),
CPU_PKG_SLOT1 = (1 << 22),
CPU_PKG_SLOT2 = (1 << 23),
CPU_PKG_SOCKET370 = (1 << 24)
};
#define MANU_INTEL 0
#define MANU_AMD 1
#define MANU_CYRIX 2
#define MANU_IDT 3
#define MANU_NEC 4
#define MANU_IBM 5
#define CPU_SUPPORTS_DYNAREC 1
#define CPU_REQUIRES_DYNAREC 2
#define CPU_ALTERNATE_XTAL 4
@@ -165,17 +156,6 @@ typedef struct {
const CPU *cpus;
} cpu_family_t;
typedef struct {
const char *family;
const uint32_t rspeed;
const double multi;
} cpu_legacy_table_t;
typedef struct {
const char *machine;
const cpu_legacy_table_t **tables;
} cpu_legacy_machine_t;
#define C_FLAG 0x0001
#define P_FLAG 0x0004
#define A_FLAG 0x0010
@@ -194,6 +174,7 @@ typedef struct {
#define VIP_FLAG 0x0010 /* in EFLAGS */
#define VID_FLAG 0x0020 /* in EFLAGS */
#define EM_FLAG 0x00004 /* in CR0 */
#define WP_FLAG 0x10000 /* in CR0 */
#define CR4_VME (1 << 0) /* Virtual 8086 Mode Extensions */
@@ -246,58 +227,92 @@ typedef union {
} MMX_REG;
typedef struct {
/* IDT WinChip and WinChip 2 MSR's */
uint32_t tr1; /* 0x00000002, 0x0000000e */
uint32_t tr12; /* 0x00000002, 0x0000000e */
uint32_t cesr; /* 0x00000011 */
/* IBM 386SLC/486SLC/486BL MSRs */
uint64_t ibm_por; /* 0x00001000 - 386SLC and later */
uint64_t ibm_crcr; /* 0x00001001 - 386SLC and later */
uint64_t ibm_por2; /* 0x00001002 - 486SLC and later */
uint64_t ibm_pcr; /* 0x00001004 - 486BL3 */
/* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */
uint64_t apic_base; /* 0x0000001b - Should the Pentium not also have this? */
uint64_t ecx79; /* 0x00000079 */
/* IDT WinChip C6/2/VIA Cyrix III MSRs */
uint32_t fcr; /* 0x00000107 (IDT), 0x00001107 (VIA) */
uint64_t fcr2; /* 0x00000108 (IDT), 0x00001108 (VIA) */
uint64_t fcr3; /* 0x00000108 (IDT), 0x00001108 (VIA) */
uint64_t mcr[8]; /* 0x00000110 - 0x00000117 (IDT) */
uint32_t mcr_ctrl; /* 0x00000120 (IDT) */
/* AMD K5, 5k86, K6, K6-2, K6-2C, K6-3, K6-2P, and K6-3P MSR's */
uint64_t ecx83; /* 0x00000083 - AMD K5 and K6 MSR's. */
/* AMD K5/K6 MSRs */
uint64_t amd_aar; /* 0x00000082 - all K5 */
uint64_t amd_hwcr; /* 0x00000083 - all K5 and all K6 */
uint64_t amd_watmcr; /* 0x00000085 - K5 Model 1 and later */
uint64_t amd_wapmrr; /* 0x00000086 - K5 Model 1 and later */
/* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */
uint64_t ecx8x[4]; /* 0x00000088 - 0x0000008b */
uint64_t ia32_pmc[8]; /* 0x000000c1 - 0x000000c8 */
uint64_t mtrr_cap; /* 0x000000fe */
uint64_t amd_efer; /* 0xc0000080 - all K5 and all K6 */
uint64_t amd_star; /* 0xc0000081 - K6-2 and later */
uint64_t amd_whcr; /* 0xc0000082 - all K5 and all K6 */
uint64_t amd_uwccr; /* 0xc0000085 - K6-2C and later */
uint64_t amd_epmr; /* 0xc0000086 - K6-III+/2+ only */
uint64_t amd_psor; /* 0xc0000087 - K6-2C and later */
uint64_t amd_pfir; /* 0xc0000088 - K6-2C and later */
uint64_t amd_l2aar; /* 0xc0000089 - K6-III and later */
/* IDT WinChip and WinChip 2 MSR's that are also on the VIA Cyrix III */
uint32_t fcr; /* 0x00000107 (IDT), 0x00001107 (VIA) */
uint64_t fcr2; /* 0x00000108 (IDT), 0x00001108 (VIA) */
uint64_t fcr3; /* 0x00000108 (IDT), 0x00001108 (VIA) */
/* Pentium/Pentium MMX MSRs */
uint64_t mcar; /* 0x00000000 - also on K5 and (R/W) K6 */
uint64_t mctr; /* 0x00000001 - also on K5 and (R/W) K6 */
uint32_t tr1; /* 0x00000002 - also on WinChip C6/2 */
uint32_t tr2; /* 0x00000004 - reserved on PMMX */
uint32_t tr3; /* 0x00000005 */
uint32_t tr4; /* 0x00000006 */
uint32_t tr5; /* 0x00000007 */
uint32_t tr6; /* 0x00000008 */
uint32_t tr7; /* 0x00000009 */
uint32_t tr9; /* 0x0000000b */
uint32_t tr10; /* 0x0000000c */
uint32_t tr11; /* 0x0000000d */
uint32_t tr12; /* 0x0000000e - also on WinChip C6/2 and K6 */
uint32_t cesr; /* 0x00000011 - also on WinChip C6/2 and Cx6x86MX */
uint64_t pmc[2]; /* 0x00000012, 0x00000013 - also on WinChip C6/2 and Cx6x86MX */
uint32_t fp_last_xcpt; /* 0x8000001b - undocumented */
uint32_t probe_ctl; /* 0x8000001d - undocumented */
uint32_t ecx8000001e; /* 0x8000001e - undocumented */
uint32_t ecx8000001f; /* 0x8000001f - undocumented */
/* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */
uint64_t ecx116; /* 0x00000116 */
uint64_t ecx11x[4]; /* 0x00000118 - 0x0000011b */
uint64_t ecx11e; /* 0x0000011e */
/* Pentium Pro/II MSRs */
uint64_t apic_base; /* 0x0000001b */
uint32_t test_ctl; /* 0x00000033 */
uint64_t bios_updt; /* 0x00000079 */
/* Pentium II Klamath and Pentium II Deschutes MSR's */
uint16_t sysenter_cs; /* 0x00000174 - SYSENTER/SYSEXIT MSR's */
uint32_t sysenter_esp; /* 0x00000175 - SYSENTER/SYSEXIT MSR's */
uint32_t sysenter_eip; /* 0x00000176 - SYSENTER/SYSEXIT MSR's */
uint64_t bbl_cr_dx[4]; /* 0x00000088 - 0x0000008b */
uint64_t perfctr[2]; /* 0x000000c1, 0x000000c2 */
uint64_t mtrr_cap; /* 0x000000fe */
/* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */
uint64_t mcg_ctl; /* 0x0000017b - Machine Check Architecture */
uint64_t ecx186; /* 0x00000186, 0x00000187 */
uint64_t ecx187; /* 0x00000186, 0x00000187 */
uint64_t bbl_cr_addr; /* 0x00000116 */
uint64_t bbl_cr_decc; /* 0x00000118 */
uint64_t bbl_cr_ctl; /* 0x00000119 */
uint64_t bbl_cr_trig; /* 0x0000011a */
uint64_t bbl_cr_busy; /* 0x0000011b */
uint64_t bbl_cr_ctl3; /* 0x0000011e */
/* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */
uint64_t debug_ctl; /* 0x000001d9 - Debug Registers Control */
uint64_t ecx1e0; /* 0x000001e0 */
uint16_t sysenter_cs; /* 0x00000174 - Pentium II and later */
uint32_t sysenter_esp; /* 0x00000175 - Pentium II and later */
uint32_t sysenter_eip; /* 0x00000176 - Pentium II and later */
/* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's that are also
on the VIA Cyrix III */
uint64_t mtrr_physbase[8]; /* 0x00000200 - 0x0000020f */
uint64_t mcg_ctl; /* 0x0000017b */
uint64_t evntsel[2]; /* 0x00000186, 0x00000187 */
uint32_t debug_ctl; /* 0x000001d9 */
uint32_t rob_cr_bkuptmpdr6; /* 0x000001e0 */
/* MTTR-related MSRs also present on the VIA Cyrix III */
uint64_t mtrr_physbase[8]; /* 0x00000200 - 0x0000020f (ECX & 0) */
uint64_t mtrr_physmask[8]; /* 0x00000200 - 0x0000020f (ECX & 1) */
uint64_t mtrr_fix64k_8000; /* 0x00000250 */
uint64_t mtrr_fix16k_8000; /* 0x00000258 */
uint64_t mtrr_fix16k_a000; /* 0x00000259 */
uint64_t mtrr_fix4k[8]; /* 0x00000268 - 0x0000026f */
uint64_t mtrr_deftype; /* 0x000002ff */
/* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */
uint64_t pat; /* 0x00000277 */
uint64_t pat; /* 0x00000277 - Pentium II Deschutes and later */
/* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's that are also
on the VIA Cyrix III */
@@ -310,48 +325,12 @@ typedef struct {
uint64_t ecx19d; /* 0x0000019d */
/* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */
uint64_t mca_ctl[5]; /* 0x00000400, 0x00000404, 0x00000408, 0x0000040c, 0x00000410 - Machine Check Architecture */
uint64_t mca_ctl[5]; /* 0x00000400, 0x00000404, 0x00000408, 0x0000040c, 0x00000410 */
uint64_t ecx570; /* 0x00000570 */
/* IBM 386SLC, 486SLC, and 486BL MSR's */
uint64_t ibm_por; /* 0x00001000 - Processor Operation Register */
uint64_t ibm_crcr; /* 0x00001001 - Cache Region Control Register */
/* IBM 486SLC and 486BL MSR's */
uint64_t ibm_por2; /* 0x00001002 - Processor Operation Register */
/* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */
uint64_t ecx1002ff; /* 0x001002ff - MSR used by some Intel AMI boards */
/* AMD K5, 5k86, K6, K6-2, K6-2C, K6-3, K6-2P, and K6-3P MSR's */
uint64_t amd_efer; /* 0xc0000080 */
/* AMD K6-2, K6-2C, K6-3, K6-2P, and K6-3P MSR's */
uint64_t star; /* 0xc0000081 */
/* AMD K5, 5k86, K6, K6-2, K6-2C, K6-3, K6-2P, and K6-3P MSR's */
uint64_t amd_whcr; /* 0xc0000082 */
/* AMD K6-2C, K6-3, K6-2P, and K6-3P MSR's */
uint64_t amd_uwccr; /* 0xc0000085 */
/* AMD K6-2P and K6-3P MSR's */
uint64_t amd_epmr; /* 0xc0000086 */
/* AMD K6-2C, K6-3, K6-2P, and K6-3P MSR's */
uint64_t amd_psor; /* 0xc0000087, 0xc0000088 */
uint64_t amd_pfir; /* 0xc0000087, 0xc0000088 */
/* K6-3, K6-2P, and K6-3P MSR's */
uint64_t amd_l2aar; /* 0xc0000089 */
/* Weird long MSR's used by the Hyper-V BIOS. */
uint64_t ecx40000020; /* 0x40000020 */
/* Pentium Pro, Pentium II Klamath, and Pentium II Deschutes MSR's */
uint64_t ecxf0f00250; /* 0xf0f00250 - Some weird long MSR's used by i686 AMI & some Phoenix BIOSes */
uint64_t ecxf0f00258; /* 0xf0f00258 */
uint64_t ecxf0f00259; /* 0xf0f00259 */
/* Other/Unclassified MSRs */
uint64_t ecx20; /* 0x00000020, really 0x40000020, but we filter out the top 18 bits
like a real Deschutes does. */
} msr_t;
typedef struct {
@@ -539,7 +518,6 @@ extern cpu_state_t cpu_state;
extern fpu_state_t fpu_state;
extern const cpu_family_t cpu_families[];
extern const cpu_legacy_machine_t cpu_legacy_table[];
extern cpu_family_t *cpu_f;
extern CPU *cpu_s;
extern int cpu_override;
@@ -618,7 +596,6 @@ extern double bus_timing;
extern double isa_timing;
extern double pci_timing;
extern double agp_timing;
extern uint64_t pmc[2];
extern uint16_t temp_seg_data[4];
extern uint16_t cs_msr;
extern uint32_t esp_msr;
@@ -799,6 +776,11 @@ void cyrix_write_seg_descriptor(uint32_t addr, x86seg *seg);
#define SMHR_VALID (1 << 0)
#define SMHR_ADDR_MASK (0xfffffffc)
typedef union {
uint32_t fd;
uint8_t b[4];
} fetch_dat_t;
typedef struct {
struct {
uint32_t base;
@@ -820,6 +802,7 @@ extern int hlt_reset_pending;
extern cyrix_t cyrix;
extern int prefetch_prefixes;
extern int cpu_use_exec;
extern uint8_t use_custom_nmi_vector;
extern uint32_t custom_nmi_vector;
@@ -844,9 +827,19 @@ extern void nmi_raise(void);
extern MMX_REG *MMP[8];
extern uint16_t *MMEP[8];
extern int cpu_block_end;
extern int cpu_override_dynarec;
extern void mmx_init(void);
extern void prefetch_flush(void);
extern void prefetch_run(int instr_cycles, int bytes, int modrm, int reads, int reads_l, int writes, int writes_l, int ea32);
extern int lock_legal[256];
extern int lock_legal_0f[256];
extern int lock_legal_ba[8];
extern int lock_legal_80[8];
extern int lock_legal_f6[8];
extern int lock_legal_fe[8];
#endif /*EMU_CPU_H*/

File diff suppressed because it is too large Load Diff

View File

@@ -270,11 +270,19 @@ reset_common(int hard)
cr0 = 1 << 30;
else
cr0 = 0;
if (is386 && !is486 && (fpu_type == FPU_387))
cr0 |= 0x10;
cpu_cache_int_enabled = 0;
cpu_update_waitstates();
cr4 = 0;
cpu_state.eflags = 0;
cgate32 = 0;
if (is386 && !is486) {
for (uint8_t i = 0; i < 4; i++)
dr[i] = 0x00000000;
dr[6] = 0xffff1ff0;
dr[7] = 0x00000400;
}
if (is286) {
if (is486)
loadcs(0xF000);

323
src/cpu/x86_ops_flag_2386.h Normal file
View File

@@ -0,0 +1,323 @@
static int
opCMC(uint32_t fetchdat)
{
flags_rebuild();
cpu_state.flags ^= C_FLAG;
CLOCK_CYCLES(2);
PREFETCH_RUN(2, 1, -1, 0, 0, 0, 0, 0);
return 0;
}
static int
opCLC(uint32_t fetchdat)
{
flags_rebuild();
cpu_state.flags &= ~C_FLAG;
CLOCK_CYCLES(2);
PREFETCH_RUN(2, 1, -1, 0, 0, 0, 0, 0);
return 0;
}
static int
opCLD(uint32_t fetchdat)
{
cpu_state.flags &= ~D_FLAG;
CLOCK_CYCLES(2);
PREFETCH_RUN(2, 1, -1, 0, 0, 0, 0, 0);
return 0;
}
static int
opCLI(uint32_t fetchdat)
{
if (!IOPLp) {
if ((!(cpu_state.eflags & VM_FLAG) && (cr4 & CR4_PVI)) || ((cpu_state.eflags & VM_FLAG) && (cr4 & CR4_VME))) {
cpu_state.eflags &= ~VIF_FLAG;
} else {
x86gpf(NULL, 0);
return 1;
}
} else
cpu_state.flags &= ~I_FLAG;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0);
return 0;
}
static int
opSTC(uint32_t fetchdat)
{
flags_rebuild();
cpu_state.flags |= C_FLAG;
CLOCK_CYCLES(2);
PREFETCH_RUN(2, 1, -1, 0, 0, 0, 0, 0);
return 0;
}
static int
opSTD(uint32_t fetchdat)
{
cpu_state.flags |= D_FLAG;
CLOCK_CYCLES(2);
PREFETCH_RUN(2, 1, -1, 0, 0, 0, 0, 0);
return 0;
}
static int
opSTI(uint32_t fetchdat)
{
if (!IOPLp) {
if ((!(cpu_state.eflags & VM_FLAG) && (cr4 & CR4_PVI)) || ((cpu_state.eflags & VM_FLAG) && (cr4 & CR4_VME))) {
if (cpu_state.eflags & VIP_FLAG) {
x86gpf(NULL, 0);
return 1;
} else
cpu_state.eflags |= VIF_FLAG;
} else {
x86gpf(NULL, 0);
return 1;
}
} else
cpu_state.flags |= I_FLAG;
/*First instruction after STI will always execute, regardless of whether
there is a pending interrupt*/
cpu_end_block_after_ins = 2;
CLOCK_CYCLES(2);
PREFETCH_RUN(2, 1, -1, 0, 0, 0, 0, 0);
return 0;
}
static int
opSAHF(uint32_t fetchdat)
{
flags_rebuild();
cpu_state.flags = (cpu_state.flags & 0xff00) | (AH & 0xd5) | 2;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0);
#if (defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC))
codegen_flags_changed = 0;
#endif
return 0;
}
static int
opLAHF(uint32_t fetchdat)
{
flags_rebuild();
AH = cpu_state.flags & 0xff;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 1, -1, 0, 0, 0, 0, 0);
return 0;
}
static int
opPUSHF(uint32_t fetchdat)
{
if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) {
if (cr4 & CR4_VME) {
uint16_t temp;
flags_rebuild();
temp = (cpu_state.flags & ~I_FLAG) | 0x3000;
if (cpu_state.eflags & VIF_FLAG)
temp |= I_FLAG;
PUSH_W(temp);
} else {
x86gpf(NULL, 0);
return 1;
}
} else {
flags_rebuild();
PUSH_W(cpu_state.flags);
}
CLOCK_CYCLES(4);
PREFETCH_RUN(4, 1, -1, 0, 0, 1, 0, 0);
return cpu_state.abrt;
}
static int
opPUSHFD(uint32_t fetchdat)
{
uint16_t tempw;
if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) {
x86gpf(NULL, 0);
return 1;
}
if (cpu_CR4_mask & CR4_VME)
tempw = cpu_state.eflags & 0x3c;
else if (CPUID)
tempw = cpu_state.eflags & 0x24;
else
tempw = cpu_state.eflags & 4;
flags_rebuild();
PUSH_L(cpu_state.flags | (tempw << 16));
CLOCK_CYCLES(4);
PREFETCH_RUN(4, 1, -1, 0, 0, 0, 1, 0);
return cpu_state.abrt;
}
static int
opPOPF_186(uint32_t fetchdat)
{
uint16_t tempw;
if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) {
x86gpf(NULL, 0);
return 1;
}
tempw = POP_W();
if (cpu_state.abrt)
return 1;
if (!(msw & 1))
cpu_state.flags = (cpu_state.flags & 0x7000) | (tempw & 0x0fd5) | 2;
else if (!(CPL))
cpu_state.flags = (tempw & 0x7fd5) | 2;
else if (IOPLp)
cpu_state.flags = (cpu_state.flags & 0x3000) | (tempw & 0x4fd5) | 2;
else
cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2;
flags_extract();
rf_flag_no_clear = 1;
CLOCK_CYCLES(5);
PREFETCH_RUN(5, 1, -1, 1, 0, 0, 0, 0);
#if (defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC))
codegen_flags_changed = 0;
#endif
return 0;
}
static int
opPOPF_286(uint32_t fetchdat)
{
uint16_t tempw;
if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) {
x86gpf(NULL, 0);
return 1;
}
tempw = POP_W();
if (cpu_state.abrt)
return 1;
if (!(msw & 1))
cpu_state.flags = (cpu_state.flags & 0x7000) | (tempw & 0x0fd5) | 2;
else if (!(CPL))
cpu_state.flags = (tempw & 0x7fd5) | 2;
else if (IOPLp)
cpu_state.flags = (cpu_state.flags & 0x3000) | (tempw & 0x4fd5) | 2;
else
cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2;
flags_extract();
rf_flag_no_clear = 1;
CLOCK_CYCLES(5);
PREFETCH_RUN(5, 1, -1, 1, 0, 0, 0, 0);
#if (defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC))
codegen_flags_changed = 0;
#endif
return 0;
}
static int
opPOPF(uint32_t fetchdat)
{
uint16_t tempw;
if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) {
if (cr4 & CR4_VME) {
uint32_t old_esp = ESP;
tempw = POP_W();
if (cpu_state.abrt) {
ESP = old_esp;
return 1;
}
if ((tempw & T_FLAG) || ((tempw & I_FLAG) && (cpu_state.eflags & VIP_FLAG))) {
ESP = old_esp;
x86gpf(NULL, 0);
return 1;
}
if (tempw & I_FLAG)
cpu_state.eflags |= VIF_FLAG;
else
cpu_state.eflags &= ~VIF_FLAG;
cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2;
} else {
x86gpf(NULL, 0);
return 1;
}
} else {
tempw = POP_W();
if (cpu_state.abrt)
return 1;
if (!(CPL) || !(msw & 1))
cpu_state.flags = (tempw & 0x7fd5) | 2;
else if (IOPLp)
cpu_state.flags = (cpu_state.flags & 0x3000) | (tempw & 0x4fd5) | 2;
else
cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2;
}
flags_extract();
rf_flag_no_clear = 1;
CLOCK_CYCLES(5);
PREFETCH_RUN(5, 1, -1, 1, 0, 0, 0, 0);
#if (defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC))
codegen_flags_changed = 0;
#endif
return 0;
}
static int
opPOPFD(uint32_t fetchdat)
{
uint32_t templ;
if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) {
x86gpf(NULL, 0);
return 1;
}
templ = POP_L();
if (cpu_state.abrt)
return 1;
if (!(CPL) || !(msw & 1))
cpu_state.flags = (templ & 0x7fd5) | 2;
else if (IOPLp)
cpu_state.flags = (cpu_state.flags & 0x3000) | (templ & 0x4fd5) | 2;
else
cpu_state.flags = (cpu_state.flags & 0x3200) | (templ & 0x4dd5) | 2;
templ &= (is486 || isibm486) ? 0x3c0000 : 0;
templ |= ((cpu_state.eflags & 3) << 16);
if (cpu_CR4_mask & CR4_VME)
cpu_state.eflags = (templ >> 16) & 0x3f;
else if (CPUID)
cpu_state.eflags = (templ >> 16) & 0x27;
else if (is486 || isibm486)
cpu_state.eflags = (templ >> 16) & 7;
else
cpu_state.eflags = (templ >> 16) & 3;
flags_extract();
rf_flag_no_clear = 1;
CLOCK_CYCLES(5);
PREFETCH_RUN(5, 1, -1, 0, 1, 0, 0, 0);
#if (defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC))
codegen_flags_changed = 0;
#endif
return 0;
}

113
src/cpu/x86_ops_fpu_2386.h Normal file
View File

@@ -0,0 +1,113 @@
/* Copyright holders: Sarah Walker
see COPYING for more details
*/
static int
opESCAPE_d8_a16(uint32_t fetchdat)
{
return x86_2386_opcodes_d8_a16[(fetchdat >> 3) & 0x1f](fetchdat);
}
static int
opESCAPE_d8_a32(uint32_t fetchdat)
{
return x86_2386_opcodes_d8_a32[(fetchdat >> 3) & 0x1f](fetchdat);
}
static int
opESCAPE_d9_a16(uint32_t fetchdat)
{
return x86_2386_opcodes_d9_a16[fetchdat & 0xff](fetchdat);
}
static int
opESCAPE_d9_a32(uint32_t fetchdat)
{
return x86_2386_opcodes_d9_a32[fetchdat & 0xff](fetchdat);
}
static int
opESCAPE_da_a16(uint32_t fetchdat)
{
return x86_2386_opcodes_da_a16[fetchdat & 0xff](fetchdat);
}
static int
opESCAPE_da_a32(uint32_t fetchdat)
{
return x86_2386_opcodes_da_a32[fetchdat & 0xff](fetchdat);
}
static int
opESCAPE_db_a16(uint32_t fetchdat)
{
return x86_2386_opcodes_db_a16[fetchdat & 0xff](fetchdat);
}
static int
opESCAPE_db_a32(uint32_t fetchdat)
{
return x86_2386_opcodes_db_a32[fetchdat & 0xff](fetchdat);
}
static int
opESCAPE_dc_a16(uint32_t fetchdat)
{
return x86_2386_opcodes_dc_a16[(fetchdat >> 3) & 0x1f](fetchdat);
}
static int
opESCAPE_dc_a32(uint32_t fetchdat)
{
return x86_2386_opcodes_dc_a32[(fetchdat >> 3) & 0x1f](fetchdat);
}
static int
opESCAPE_dd_a16(uint32_t fetchdat)
{
return x86_2386_opcodes_dd_a16[fetchdat & 0xff](fetchdat);
}
static int
opESCAPE_dd_a32(uint32_t fetchdat)
{
return x86_2386_opcodes_dd_a32[fetchdat & 0xff](fetchdat);
}
static int
opESCAPE_de_a16(uint32_t fetchdat)
{
return x86_2386_opcodes_de_a16[fetchdat & 0xff](fetchdat);
}
static int
opESCAPE_de_a32(uint32_t fetchdat)
{
return x86_2386_opcodes_de_a32[fetchdat & 0xff](fetchdat);
}
static int
opESCAPE_df_a16(uint32_t fetchdat)
{
return x86_2386_opcodes_df_a16[fetchdat & 0xff](fetchdat);
}
static int
opESCAPE_df_a32(uint32_t fetchdat)
{
return x86_2386_opcodes_df_a32[fetchdat & 0xff](fetchdat);
}
static int
opWAIT(uint32_t fetchdat)
{
if ((cr0 & 0xa) == 0xa) {
x86_int(7);
return 1;
}
#if 0
if (!cpu_use_dynarec && fpu_softfloat) {
#endif
if (fpu_softfloat) {
if (fpu_state.swd & FPU_SW_Summary) {
if (cr0 & 0x20) {
x86_int(16);
return 1;
}
}
}
CLOCK_CYCLES(4);
return 0;
}

View File

@@ -129,7 +129,7 @@ opF6_a16(uint32_t fetchdat)
if (dst && !(tempw & 0xff00)) {
AH = src16 % dst;
AL = (src16 / dst) & 0xff;
if (!cpu_iscyrix) {
if (!cpu_iscyrix && !is6117) {
flags_rebuild();
cpu_state.flags |= 0x8D5; /*Not a Cyrix*/
cpu_state.flags &= ~1;
@@ -149,7 +149,7 @@ opF6_a16(uint32_t fetchdat)
if (dst && ((int) temps == tempws2)) {
AH = (tempws % (int) ((int8_t) dst)) & 0xff;
AL = tempws2 & 0xff;
if (!cpu_iscyrix) {
if (!cpu_iscyrix && !is6117) {
flags_rebuild();
cpu_state.flags |= 0x8D5; /*Not a Cyrix*/
cpu_state.flags &= ~1;
@@ -246,7 +246,7 @@ opF6_a32(uint32_t fetchdat)
if (dst && !(tempw & 0xff00)) {
AH = src16 % dst;
AL = (src16 / dst) & 0xff;
if (!cpu_iscyrix) {
if (!cpu_iscyrix && !is6117) {
flags_rebuild();
cpu_state.flags |= 0x8D5; /*Not a Cyrix*/
cpu_state.flags &= ~1;
@@ -266,7 +266,7 @@ opF6_a32(uint32_t fetchdat)
if (dst && ((int) temps == tempws2)) {
AH = (tempws % (int) ((int8_t) dst)) & 0xff;
AL = tempws2 & 0xff;
if (!cpu_iscyrix) {
if (!cpu_iscyrix && !is6117) {
flags_rebuild();
cpu_state.flags |= 0x8D5; /*Not a Cyrix*/
cpu_state.flags &= ~1;
@@ -366,7 +366,7 @@ opF7_w_a16(uint32_t fetchdat)
if (dst && !(templ2 & 0xffff0000)) {
DX = templ % dst;
AX = (templ / dst) & 0xffff;
if (!cpu_iscyrix)
if (!cpu_iscyrix && !is6117)
setznp16(AX); /*Not a Cyrix*/
} else {
x86_int(0);
@@ -383,7 +383,7 @@ opF7_w_a16(uint32_t fetchdat)
if ((dst != 0) && ((int) temps16 == tempws2)) {
DX = tempws % (int) ((int16_t) dst);
AX = tempws2 & 0xffff;
if (!cpu_iscyrix)
if (!cpu_iscyrix && !is6117)
setznp16(AX); /*Not a Cyrix*/
} else {
x86_int(0);
@@ -479,7 +479,7 @@ opF7_w_a32(uint32_t fetchdat)
if (dst && !(templ2 & 0xffff0000)) {
DX = templ % dst;
AX = (templ / dst) & 0xffff;
if (!cpu_iscyrix)
if (!cpu_iscyrix && !is6117)
setznp16(AX); /*Not a Cyrix*/
} else {
// fatal("DIVw BY 0 %04X:%04X %i\n",cs>>4,pc,ins);
@@ -497,7 +497,7 @@ opF7_w_a32(uint32_t fetchdat)
if ((dst != 0) && ((int) temps16 == tempws2)) {
DX = tempws % (int) ((int16_t) dst);
AX = tempws2 & 0xffff;
if (!cpu_iscyrix)
if (!cpu_iscyrix && !is6117)
setznp16(AX); /*Not a Cyrix*/
} else {
x86_int(0);
@@ -587,7 +587,7 @@ opF7_l_a16(uint32_t fetchdat)
case 0x30: /*DIV EAX,l*/
if (divl(dst))
return 1;
if (!cpu_iscyrix)
if (!cpu_iscyrix && !is6117)
setznp32(EAX); /*Not a Cyrix*/
CLOCK_CYCLES((is486) ? 40 : 38);
PREFETCH_RUN(is486 ? 40 : 38, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 0);
@@ -595,7 +595,7 @@ opF7_l_a16(uint32_t fetchdat)
case 0x38: /*IDIV EAX,l*/
if (idivl((int32_t) dst))
return 1;
if (!cpu_iscyrix)
if (!cpu_iscyrix && !is6117)
setznp32(EAX); /*Not a Cyrix*/
CLOCK_CYCLES(43);
PREFETCH_RUN(43, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 0);
@@ -680,7 +680,7 @@ opF7_l_a32(uint32_t fetchdat)
case 0x30: /*DIV EAX,l*/
if (divl(dst))
return 1;
if (!cpu_iscyrix)
if (!cpu_iscyrix && !is6117)
setznp32(EAX); /*Not a Cyrix*/
CLOCK_CYCLES((is486) ? 40 : 38);
PREFETCH_RUN(is486 ? 40 : 38, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 1);
@@ -688,7 +688,7 @@ opF7_l_a32(uint32_t fetchdat)
case 0x38: /*IDIV EAX,l*/
if (idivl((int32_t) dst))
return 1;
if (!cpu_iscyrix)
if (!cpu_iscyrix && !is6117)
setznp32(EAX); /*Not a Cyrix*/
CLOCK_CYCLES(43);
PREFETCH_RUN(43, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1, 0, 0, 1);
@@ -726,6 +726,59 @@ opHLT(uint32_t fetchdat)
return 0;
}
#ifdef OPS_286_386
static int
opLOCK(uint32_t fetchdat)
{
int legal;
fetch_dat_t fetch_dat;
fetchdat = fastreadl_fetch(cs + cpu_state.pc);
if (cpu_state.abrt)
return 0;
cpu_state.pc++;
fetch_dat.fd = fetchdat;
legal = lock_legal[fetch_dat.b[0]];
if (legal == 1)
legal = ((fetch_dat.b[1] >> 6) != 0x03); /* reg is illegal */
else if (legal == 2) {
legal = lock_legal_0f[fetch_dat.b[1]];
if (legal == 1)
legal = ((fetch_dat.b[2] >> 6) != 0x03); /* reg,reg is illegal */
else if (legal == 3) {
legal = lock_legal_ba[(fetch_dat.b[2] >> 3) & 0x07];
if (legal == 1)
legal = ((fetch_dat.b[2] >> 6) != 0x03); /* reg,imm is illegal */
}
} else if (legal == 3) switch(fetch_dat.b[0]) {
case 0x80 ... 0x83:
legal = lock_legal_80[(fetch_dat.b[1] >> 3) & 0x07];
if (legal == 1)
legal = ((fetch_dat.b[1] >> 6) != 0x03); /* reg is illegal */
break;
case 0xf6 ... 0xf7:
legal = lock_legal_f6[(fetch_dat.b[1] >> 3) & 0x07];
if (legal == 1)
legal = ((fetch_dat.b[1] >> 6) != 0x03); /* reg is illegal */
break;
case 0xfe ... 0xff:
legal = lock_legal_fe[(fetch_dat.b[1] >> 3) & 0x07];
if (legal == 1)
legal = ((fetch_dat.b[1] >> 6) != 0x03); /* reg is illegal */
break;
default:
legal = 0;
break;
}
ILLEGAL_ON(legal == 0);
CLOCK_CYCLES(4);
PREFETCH_PREFIX();
return x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
}
#else
static int
opLOCK(uint32_t fetchdat)
{
@@ -740,6 +793,7 @@ opLOCK(uint32_t fetchdat)
PREFETCH_PREFIX();
return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
}
#endif
static int
opBOUND_w_a16(uint32_t fetchdat)

View File

@@ -0,0 +1,500 @@
static int
opMOV_r_CRx_a16(uint32_t fetchdat)
{
if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) {
x86gpf(NULL, 0);
return 1;
}
fetch_ea_16(fetchdat);
switch (cpu_reg) {
case 0:
cpu_state.regs[cpu_rm].l = cr0;
if (is486 || isibm486)
cpu_state.regs[cpu_rm].l |= 0x10; /*ET hardwired on 486*/
else {
if (is386)
cpu_state.regs[cpu_rm].l |= 0x7fffffe0;
else
cpu_state.regs[cpu_rm].l |= 0x7ffffff0;
}
break;
case 2:
cpu_state.regs[cpu_rm].l = cr2;
break;
case 3:
cpu_state.regs[cpu_rm].l = cr3;
break;
case 4:
if (cpu_has_feature(CPU_FEATURE_CR4)) {
cpu_state.regs[cpu_rm].l = cr4;
break;
}
default:
cpu_state.pc = cpu_state.oldpc;
x86illegal();
break;
}
CLOCK_CYCLES(6);
PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 0);
return 0;
}
static int
opMOV_r_CRx_a32(uint32_t fetchdat)
{
if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) {
x86gpf(NULL, 0);
return 1;
}
fetch_ea_32(fetchdat);
switch (cpu_reg) {
case 0:
cpu_state.regs[cpu_rm].l = cr0;
if (is486 || isibm486)
cpu_state.regs[cpu_rm].l |= 0x10; /*ET hardwired on 486*/
else {
if (is386)
cpu_state.regs[cpu_rm].l |= 0x7fffffe0;
else
cpu_state.regs[cpu_rm].l |= 0x7ffffff0;
}
break;
case 2:
cpu_state.regs[cpu_rm].l = cr2;
break;
case 3:
cpu_state.regs[cpu_rm].l = cr3;
break;
case 4:
if (cpu_has_feature(CPU_FEATURE_CR4)) {
cpu_state.regs[cpu_rm].l = cr4;
break;
}
default:
cpu_state.pc = cpu_state.oldpc;
x86illegal();
break;
}
CLOCK_CYCLES(6);
PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 1);
return 0;
}
static int
opMOV_r_DRx_a16(uint32_t fetchdat)
{
if ((CPL > 0) && (cr0 & 1)) {
x86gpf(NULL, 0);
return 1;
}
if ((dr[7] & 0x2000) && !(cpu_state.eflags & RF_FLAG)) {
trap |= 1;
return 1;
}
fetch_ea_16(fetchdat);
switch (cpu_reg) {
case 0 ... 3:
cpu_state.regs[cpu_rm].l = dr[cpu_reg];
break;
case 4:
if (cr4 & 0x8) {
x86illegal();
return 1;
}
fallthrough;
case 6:
cpu_state.regs[cpu_rm].l = dr[6];
break;
case 5:
if (cr4 & 0x8) {
x86illegal();
return 1;
}
fallthrough;
case 7:
cpu_state.regs[cpu_rm].l = dr[7];
break;
default:
x86illegal();
return 1;
}
CLOCK_CYCLES(6);
PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 0);
return 0;
}
static int
opMOV_r_DRx_a32(uint32_t fetchdat)
{
if ((CPL > 0) && (cr0 & 1)) {
x86gpf(NULL, 0);
return 1;
}
if ((dr[7] & 0x2000) && !(cpu_state.eflags & RF_FLAG)) {
trap |= 1;
return 1;
}
fetch_ea_32(fetchdat);
switch (cpu_reg) {
case 0 ... 3:
cpu_state.regs[cpu_rm].l = dr[cpu_reg];
break;
case 4:
if (cr4 & 0x8) {
x86illegal();
return 1;
}
fallthrough;
case 6:
cpu_state.regs[cpu_rm].l = dr[6];
break;
case 5:
if (cr4 & 0x8) {
x86illegal();
return 1;
}
fallthrough;
case 7:
cpu_state.regs[cpu_rm].l = dr[7];
break;
default:
x86illegal();
return 1;
}
CLOCK_CYCLES(6);
PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 1);
return 0;
}
static int
opMOV_CRx_r_a16(uint32_t fetchdat)
{
uint32_t old_cr0 = cr0;
if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) {
x86gpf(NULL, 0);
return 1;
}
fetch_ea_16(fetchdat);
switch (cpu_reg) {
case 0:
if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000001)
flushmmucache();
/* Make sure CPL = 0 when switching from real mode to protected mode. */
if ((cpu_state.regs[cpu_rm].l & 0x01) && !(cr0 & 0x01))
cpu_state.seg_cs.access &= 0x9f;
cr0 = cpu_state.regs[cpu_rm].l;
if (cpu_16bitbus)
cr0 |= 0x10;
if (!(cr0 & 0x80000000))
mmu_perm = 4;
if (hascache && !(cr0 & (1 << 30)))
cpu_cache_int_enabled = 1;
else
cpu_cache_int_enabled = 0;
if (hascache && ((cr0 ^ old_cr0) & (1 << 30)))
cpu_update_waitstates();
if (cr0 & 1)
cpu_cur_status |= CPU_STATUS_PMODE;
else
cpu_cur_status &= ~CPU_STATUS_PMODE;
break;
case 2:
cr2 = cpu_state.regs[cpu_rm].l;
break;
case 3:
cr3 = cpu_state.regs[cpu_rm].l;
flushmmucache();
break;
case 4:
if (cpu_has_feature(CPU_FEATURE_CR4)) {
if (((cpu_state.regs[cpu_rm].l ^ cr4) & cpu_CR4_mask) & (CR4_PAE | CR4_PGE))
flushmmucache();
cr4 = cpu_state.regs[cpu_rm].l & cpu_CR4_mask;
break;
}
default:
cpu_state.pc = cpu_state.oldpc;
x86illegal();
break;
}
CLOCK_CYCLES(10);
PREFETCH_RUN(10, 2, rmdat, 0, 0, 0, 0, 0);
return 0;
}
static int
opMOV_CRx_r_a32(uint32_t fetchdat)
{
uint32_t old_cr0 = cr0;
if ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1)) {
x86gpf(NULL, 0);
return 1;
}
fetch_ea_32(fetchdat);
switch (cpu_reg) {
case 0:
if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000001)
flushmmucache();
/* Make sure CPL = 0 when switching from real mode to protected mode. */
if ((cpu_state.regs[cpu_rm].l & 0x01) && !(cr0 & 0x01))
cpu_state.seg_cs.access &= 0x9f;
cr0 = cpu_state.regs[cpu_rm].l;
if (cpu_16bitbus)
cr0 |= 0x10;
if (!(cr0 & 0x80000000))
mmu_perm = 4;
if (hascache && !(cr0 & (1 << 30)))
cpu_cache_int_enabled = 1;
else
cpu_cache_int_enabled = 0;
if (hascache && ((cr0 ^ old_cr0) & (1 << 30)))
cpu_update_waitstates();
if (cr0 & 1)
cpu_cur_status |= CPU_STATUS_PMODE;
else
cpu_cur_status &= ~CPU_STATUS_PMODE;
break;
case 2:
cr2 = cpu_state.regs[cpu_rm].l;
break;
case 3:
cr3 = cpu_state.regs[cpu_rm].l;
flushmmucache();
break;
case 4:
if (cpu_has_feature(CPU_FEATURE_CR4)) {
if (((cpu_state.regs[cpu_rm].l ^ cr4) & cpu_CR4_mask) & (CR4_PAE | CR4_PGE))
flushmmucache();
cr4 = cpu_state.regs[cpu_rm].l & cpu_CR4_mask;
break;
}
default:
cpu_state.pc = cpu_state.oldpc;
x86illegal();
break;
}
CLOCK_CYCLES(10);
PREFETCH_RUN(10, 2, rmdat, 0, 0, 0, 0, 1);
return 0;
}
static int
opMOV_DRx_r_a16(uint32_t fetchdat)
{
if ((CPL > 0) && (cr0 & 1)) {
x86gpf(NULL, 0);
return 1;
}
if ((dr[7] & 0x2000) && !(cpu_state.eflags & RF_FLAG)) {
trap |= 1;
return 1;
}
fetch_ea_16(fetchdat);
switch (cpu_reg) {
case 0 ... 3:
dr[cpu_reg] = cpu_state.regs[cpu_rm].l;
break;
case 4:
if (cr4 & 0x8) {
x86illegal();
return 1;
}
fallthrough;
case 6:
dr[6] = (dr[6] & 0xffff0ff0) | (cpu_state.regs[cpu_rm].l & 0x0000f00f);
break;
case 5:
if (cr4 & 0x8) {
x86illegal();
return 1;
}
fallthrough;
case 7:
dr[7] = cpu_state.regs[cpu_rm].l | 0x00000400;
break;
default:
x86illegal();
return 1;
}
CLOCK_CYCLES(6);
PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 0);
CPU_BLOCK_END();
return 0;
}
static int
opMOV_DRx_r_a32(uint32_t fetchdat)
{
if ((CPL > 0) && (cr0 & 1)) {
x86gpf(NULL, 0);
return 1;
}
if ((dr[7] & 0x2000) && !(cpu_state.eflags & RF_FLAG)) {
trap |= 1;
return 1;
}
fetch_ea_32(fetchdat);
switch (cpu_reg) {
case 0 ... 3:
dr[cpu_reg] = cpu_state.regs[cpu_rm].l;
break;
case 4:
if (cr4 & 0x8) {
x86illegal();
return 1;
}
fallthrough;
case 6:
dr[6] = (dr[6] & 0xffff0ff0) | (cpu_state.regs[cpu_rm].l & 0x0000f00f);
break;
case 5:
if (cr4 & 0x8) {
x86illegal();
return 1;
}
fallthrough;
case 7:
dr[7] = cpu_state.regs[cpu_rm].l | 0x00000400;
break;
default:
x86illegal();
return 1;
}
CLOCK_CYCLES(6);
PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 1);
CPU_BLOCK_END();
return 0;
}
static void
opMOV_r_TRx(void)
{
#if 0
uint32_t base;
base = _tr[4] & 0xfffff800;
#endif
switch (cpu_reg) {
case 3:
#if 0
pclog("[R] %08X cache = %08X\n", base + cache_index, _tr[3]);
#endif
_tr[3] = *(uint32_t *) &(_cache[cache_index]);
cache_index = (cache_index + 4) & 0xf;
break;
}
cpu_state.regs[cpu_rm].l = _tr[cpu_reg];
CLOCK_CYCLES(6);
}
static int
opMOV_r_TRx_a16(uint32_t fetchdat)
{
if ((cpu_s->cpu_type == CPU_PENTIUM) || ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1))) {
x86gpf(NULL, 0);
return 1;
}
fetch_ea_16(fetchdat);
opMOV_r_TRx();
PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 0);
return 0;
}
static int
opMOV_r_TRx_a32(uint32_t fetchdat)
{
if ((cpu_s->cpu_type == CPU_PENTIUM) || ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1))) {
x86gpf(NULL, 0);
return 1;
}
fetch_ea_32(fetchdat);
opMOV_r_TRx();
PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 1);
return 0;
}
static void
opMOV_TRx_r(void)
{
uint32_t base;
int i;
int ctl;
_tr[cpu_reg] = cpu_state.regs[cpu_rm].l;
base = _tr[4] & 0xfffff800;
ctl = _tr[5] & 3;
switch (cpu_reg) {
case 3:
#if 0
pclog("[W] %08X cache = %08X\n", base + cache_index, _tr[3]);
#endif
*(uint32_t *) &(_cache[cache_index]) = _tr[3];
cache_index = (cache_index + 4) & 0xf;
break;
case 4:
#if 0
if (!(cr0 & 1) && !(_tr[5] & (1 << 19)))
pclog("TAG = %08X, DEST = %08X\n", base, base + cache_index - 16);
#endif
break;
case 5:
#if 0
pclog("[16] EXT = %i (%i), SET = %04X\n", !!(_tr[5] & (1 << 19)), _tr[5] & 0x03, _tr[5] & 0x7f0);
#endif
if (!(_tr[5] & (1 << 19))) {
switch (ctl) {
case 0:
#if 0
pclog(" Cache fill or read...\n", base);
#endif
break;
case 1:
base += (_tr[5] & 0x7f0);
#if 0
pclog(" Writing 16 bytes to %08X...\n", base);
#endif
for (i = 0; i < 16; i += 4)
mem_writel_phys(base + i, *(uint32_t *) &(_cache[i]));
break;
case 2:
base += (_tr[5] & 0x7f0);
#if 0
pclog(" Reading 16 bytes from %08X...\n", base);
#endif
for (i = 0; i < 16; i += 4)
*(uint32_t *) &(_cache[i]) = mem_readl_phys(base + i);
break;
case 3:
#if 0
pclog(" Cache invalidate/flush...\n", base);
#endif
break;
}
}
break;
}
CLOCK_CYCLES(6);
}
static int
opMOV_TRx_r_a16(uint32_t fetchdat)
{
if ((cpu_s->cpu_type == CPU_PENTIUM) || ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1))) {
x86gpf(NULL, 0);
return 1;
}
fetch_ea_16(fetchdat);
opMOV_TRx_r();
PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 0);
return 0;
}
static int
opMOV_TRx_r_a32(uint32_t fetchdat)
{
if ((cpu_s->cpu_type == CPU_PENTIUM) || ((CPL || (cpu_state.eflags & VM_FLAG)) && (cr0 & 1))) {
x86gpf(NULL, 0);
return 1;
}
fetch_ea_32(fetchdat);
opMOV_TRx_r();
PREFETCH_RUN(6, 2, rmdat, 0, 0, 0, 0, 1);
return 0;
}

View File

@@ -195,7 +195,11 @@ opMOV_seg_w_a16(uint32_t fetchdat)
cpu_state.pc++;
if (cpu_state.abrt)
return 1;
#ifdef OPS_286_386
x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
#else
x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
#endif
return 1;
case 0x20: /*FS*/
op_loadseg(new_seg, &cpu_state.seg_fs);
@@ -240,7 +244,11 @@ opMOV_seg_w_a32(uint32_t fetchdat)
cpu_state.pc++;
if (cpu_state.abrt)
return 1;
#ifdef OPS_286_386
x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
#else
x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
#endif
return 1;
case 0x20: /*FS*/
op_loadseg(new_seg, &cpu_state.seg_fs);

View File

@@ -367,6 +367,7 @@ op0F01_common(uint32_t fetchdat, int is32, int is286, int ea32)
switch (rmdat & 0x38) {
case 0x00: /*SGDT*/
ILLEGAL_ON(cpu_mod == 3);
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
seteaw(gdt.limit);
@@ -389,6 +390,7 @@ op0F01_common(uint32_t fetchdat, int is32, int is286, int ea32)
PREFETCH_RUN(7, 2, rmdat, 0, 0, 1, 1, ea32);
break;
case 0x10: /*LGDT*/
ILLEGAL_ON(cpu_mod == 3);
if ((CPL || cpu_state.eflags & VM_FLAG) && (cr0 & 1)) {
x86gpf(NULL, 0);
break;

View File

@@ -0,0 +1,179 @@
#define op_seg(name, seg, opcode_table, normal_opcode_table) \
static int op##name##_w_a16(uint32_t fetchdat) \
{ \
fetchdat = fastreadl(cs + cpu_state.pc); \
if (cpu_state.abrt) \
return 1; \
cpu_state.pc++; \
\
cpu_state.ea_seg = &seg; \
cpu_state.ssegs = 1; \
CLOCK_CYCLES(4); \
PREFETCH_PREFIX(); \
\
if (opcode_table[fetchdat & 0xff]) \
return opcode_table[fetchdat & 0xff](fetchdat >> 8); \
return normal_opcode_table[fetchdat & 0xff](fetchdat >> 8); \
} \
\
static int op##name##_l_a16(uint32_t fetchdat) \
{ \
fetchdat = fastreadl(cs + cpu_state.pc); \
if (cpu_state.abrt) \
return 1; \
cpu_state.pc++; \
\
cpu_state.ea_seg = &seg; \
cpu_state.ssegs = 1; \
CLOCK_CYCLES(4); \
PREFETCH_PREFIX(); \
\
if (opcode_table[(fetchdat & 0xff) | 0x100]) \
return opcode_table[(fetchdat & 0xff) | 0x100](fetchdat >> 8); \
return normal_opcode_table[(fetchdat & 0xff) | 0x100](fetchdat >> 8); \
} \
\
static int op##name##_w_a32(uint32_t fetchdat) \
{ \
fetchdat = fastreadl(cs + cpu_state.pc); \
if (cpu_state.abrt) \
return 1; \
cpu_state.pc++; \
\
cpu_state.ea_seg = &seg; \
cpu_state.ssegs = 1; \
CLOCK_CYCLES(4); \
PREFETCH_PREFIX(); \
\
if (opcode_table[(fetchdat & 0xff) | 0x200]) \
return opcode_table[(fetchdat & 0xff) | 0x200](fetchdat >> 8); \
return normal_opcode_table[(fetchdat & 0xff) | 0x200](fetchdat >> 8); \
} \
\
static int op##name##_l_a32(uint32_t fetchdat) \
{ \
fetchdat = fastreadl(cs + cpu_state.pc); \
if (cpu_state.abrt) \
return 1; \
cpu_state.pc++; \
\
cpu_state.ea_seg = &seg; \
cpu_state.ssegs = 1; \
CLOCK_CYCLES(4); \
PREFETCH_PREFIX(); \
\
if (opcode_table[(fetchdat & 0xff) | 0x300]) \
return opcode_table[(fetchdat & 0xff) | 0x300](fetchdat >> 8); \
return normal_opcode_table[(fetchdat & 0xff) | 0x300](fetchdat >> 8); \
}
// clang-format off
op_seg(CS, cpu_state.seg_cs, x86_2386_opcodes, x86_2386_opcodes)
op_seg(DS, cpu_state.seg_ds, x86_2386_opcodes, x86_2386_opcodes)
op_seg(ES, cpu_state.seg_es, x86_2386_opcodes, x86_2386_opcodes)
op_seg(FS, cpu_state.seg_fs, x86_2386_opcodes, x86_2386_opcodes)
op_seg(GS, cpu_state.seg_gs, x86_2386_opcodes, x86_2386_opcodes)
op_seg(SS, cpu_state.seg_ss, x86_2386_opcodes, x86_2386_opcodes)
op_seg(CS_REPE, cpu_state.seg_cs, x86_2386_opcodes_REPE, x86_2386_opcodes)
op_seg(DS_REPE, cpu_state.seg_ds, x86_2386_opcodes_REPE, x86_2386_opcodes)
op_seg(ES_REPE, cpu_state.seg_es, x86_2386_opcodes_REPE, x86_2386_opcodes)
op_seg(FS_REPE, cpu_state.seg_fs, x86_2386_opcodes_REPE, x86_2386_opcodes)
op_seg(GS_REPE, cpu_state.seg_gs, x86_2386_opcodes_REPE, x86_2386_opcodes)
op_seg(SS_REPE, cpu_state.seg_ss, x86_2386_opcodes_REPE, x86_2386_opcodes)
op_seg(CS_REPNE, cpu_state.seg_cs, x86_2386_opcodes_REPNE, x86_2386_opcodes)
op_seg(DS_REPNE, cpu_state.seg_ds, x86_2386_opcodes_REPNE, x86_2386_opcodes)
op_seg(ES_REPNE, cpu_state.seg_es, x86_2386_opcodes_REPNE, x86_2386_opcodes)
op_seg(FS_REPNE, cpu_state.seg_fs, x86_2386_opcodes_REPNE, x86_2386_opcodes)
op_seg(GS_REPNE, cpu_state.seg_gs, x86_2386_opcodes_REPNE, x86_2386_opcodes)
op_seg(SS_REPNE, cpu_state.seg_ss, x86_2386_opcodes_REPNE, x86_2386_opcodes)
// clang-format on
static int
op_66(uint32_t fetchdat) /*Data size select*/
{
fetchdat = fastreadl(cs + cpu_state.pc);
if (cpu_state.abrt)
return 1;
cpu_state.pc++;
cpu_state.op32 = ((use32 & 0x100) ^ 0x100) | (cpu_state.op32 & 0x200);
CLOCK_CYCLES(2);
PREFETCH_PREFIX();
return x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
}
static int
op_67(uint32_t fetchdat) /*Address size select*/
{
fetchdat = fastreadl(cs + cpu_state.pc);
if (cpu_state.abrt)
return 1;
cpu_state.pc++;
cpu_state.op32 = ((use32 & 0x200) ^ 0x200) | (cpu_state.op32 & 0x100);
CLOCK_CYCLES(2);
PREFETCH_PREFIX();
return x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
}
static int
op_66_REPE(uint32_t fetchdat) /*Data size select*/
{
fetchdat = fastreadl(cs + cpu_state.pc);
if (cpu_state.abrt)
return 1;
cpu_state.pc++;
cpu_state.op32 = ((use32 & 0x100) ^ 0x100) | (cpu_state.op32 & 0x200);
CLOCK_CYCLES(2);
PREFETCH_PREFIX();
if (x86_2386_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32])
return x86_2386_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
return x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
}
static int
op_67_REPE(uint32_t fetchdat) /*Address size select*/
{
fetchdat = fastreadl(cs + cpu_state.pc);
if (cpu_state.abrt)
return 1;
cpu_state.pc++;
cpu_state.op32 = ((use32 & 0x200) ^ 0x200) | (cpu_state.op32 & 0x100);
CLOCK_CYCLES(2);
PREFETCH_PREFIX();
if (x86_2386_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32])
return x86_2386_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
return x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
}
static int
op_66_REPNE(uint32_t fetchdat) /*Data size select*/
{
fetchdat = fastreadl(cs + cpu_state.pc);
if (cpu_state.abrt)
return 1;
cpu_state.pc++;
cpu_state.op32 = ((use32 & 0x100) ^ 0x100) | (cpu_state.op32 & 0x200);
CLOCK_CYCLES(2);
PREFETCH_PREFIX();
if (x86_2386_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32])
return x86_2386_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
return x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
}
static int
op_67_REPNE(uint32_t fetchdat) /*Address size select*/
{
fetchdat = fastreadl(cs + cpu_state.pc);
if (cpu_state.abrt)
return 1;
cpu_state.pc++;
cpu_state.op32 = ((use32 & 0x200) ^ 0x200) | (cpu_state.op32 & 0x100);
CLOCK_CYCLES(2);
PREFETCH_PREFIX();
if (x86_2386_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32])
return x86_2386_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
return x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
}

View File

@@ -836,7 +836,7 @@ REP_OPS_CMPS_SCAS(a32_E, ECX, ESI, EDI, 1)
static int
opREPNE(uint32_t fetchdat)
{
fetchdat = fastreadl(cs + cpu_state.pc);
fetchdat = fastreadl_fetch(cs + cpu_state.pc);
if (cpu_state.abrt)
return 1;
cpu_state.pc++;
@@ -850,7 +850,7 @@ opREPNE(uint32_t fetchdat)
static int
opREPE(uint32_t fetchdat)
{
fetchdat = fastreadl(cs + cpu_state.pc);
fetchdat = fastreadl_fetch(cs + cpu_state.pc);
if (cpu_state.abrt)
return 1;
cpu_state.pc++;

297
src/cpu/x86_ops_ret_2386.h Normal file
View File

@@ -0,0 +1,297 @@
#ifdef USE_NEW_DYNAREC
# define CPU_SET_OXPC
#else
# define CPU_SET_OXPC oxpc = cpu_state.pc;
#endif
#define RETF_a16(stack_offset) \
if ((msw & 1) && !(cpu_state.eflags & VM_FLAG)) { \
op_pmoderetf(0, stack_offset); \
return 1; \
} \
CPU_SET_OXPC \
if (stack32) { \
cpu_state.pc = readmemw(ss, ESP); \
op_loadcs(readmemw(ss, ESP + 2)); \
} else { \
cpu_state.pc = readmemw(ss, SP); \
op_loadcs(readmemw(ss, SP + 2)); \
} \
if (cpu_state.abrt) \
return 1; \
if (stack32) \
ESP += 4 + stack_offset; \
else \
SP += 4 + stack_offset; \
cycles -= timing_retf_rm;
#define RETF_a32(stack_offset) \
if ((msw & 1) && !(cpu_state.eflags & VM_FLAG)) { \
op_pmoderetf(1, stack_offset); \
return 1; \
} \
CPU_SET_OXPC \
if (stack32) { \
cpu_state.pc = readmeml(ss, ESP); \
op_loadcs(readmeml(ss, ESP + 4) & 0xffff); \
} else { \
cpu_state.pc = readmeml(ss, SP); \
op_loadcs(readmeml(ss, SP + 4) & 0xffff); \
} \
if (cpu_state.abrt) \
return 1; \
if (stack32) \
ESP += 8 + stack_offset; \
else \
SP += 8 + stack_offset; \
cycles -= timing_retf_rm;
static int
opRETF_a16(uint32_t fetchdat)
{
int cycles_old = cycles;
UN_USED(cycles_old);
CPU_BLOCK_END();
RETF_a16(0);
PREFETCH_RUN(cycles_old - cycles, 1, -1, 2, 0, 0, 0, 0);
PREFETCH_FLUSH();
return 0;
}
static int
opRETF_a32(uint32_t fetchdat)
{
int cycles_old = cycles;
UN_USED(cycles_old);
CPU_BLOCK_END();
RETF_a32(0);
PREFETCH_RUN(cycles_old - cycles, 1, -1, 0, 2, 0, 0, 1);
PREFETCH_FLUSH();
return 0;
}
static int
opRETF_a16_imm(uint32_t fetchdat)
{
uint16_t offset = getwordf();
int cycles_old = cycles;
UN_USED(cycles_old);
CPU_BLOCK_END();
RETF_a16(offset);
PREFETCH_RUN(cycles_old - cycles, 3, -1, 2, 0, 0, 0, 0);
PREFETCH_FLUSH();
return 0;
}
static int
opRETF_a32_imm(uint32_t fetchdat)
{
uint16_t offset = getwordf();
int cycles_old = cycles;
UN_USED(cycles_old);
CPU_BLOCK_END();
RETF_a32(offset);
PREFETCH_RUN(cycles_old - cycles, 3, -1, 0, 2, 0, 0, 1);
PREFETCH_FLUSH();
return 0;
}
static int
opIRET_186(uint32_t fetchdat)
{
int cycles_old = cycles;
UN_USED(cycles_old);
if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) {
x86gpf(NULL, 0);
return 1;
}
if (msw & 1) {
optype = IRET;
op_pmodeiret(0);
optype = 0;
} else {
uint16_t new_cs;
CPU_SET_OXPC
if (stack32) {
cpu_state.pc = readmemw(ss, ESP);
new_cs = readmemw(ss, ESP + 2);
cpu_state.flags = (cpu_state.flags & 0x7000) | (readmemw(ss, ESP + 4) & 0xffd5) | 2;
ESP += 6;
} else {
cpu_state.pc = readmemw(ss, SP);
new_cs = readmemw(ss, ((SP + 2) & 0xffff));
cpu_state.flags = (cpu_state.flags & 0x7000) | (readmemw(ss, ((SP + 4) & 0xffff)) & 0x0fd5) | 2;
SP += 6;
}
op_loadcs(new_cs);
cycles -= timing_iret_rm;
}
flags_extract();
nmi_enable = 1;
rf_flag_no_clear = 1;
CPU_BLOCK_END();
PREFETCH_RUN(cycles_old - cycles, 1, -1, 2, 0, 0, 0, 0);
PREFETCH_FLUSH();
return cpu_state.abrt;
}
static int
opIRET_286(uint32_t fetchdat)
{
int cycles_old = cycles;
UN_USED(cycles_old);
if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) {
x86gpf(NULL, 0);
return 1;
}
if (msw & 1) {
optype = IRET;
op_pmodeiret(0);
optype = 0;
} else {
uint16_t new_cs;
CPU_SET_OXPC
if (stack32) {
cpu_state.pc = readmemw(ss, ESP);
new_cs = readmemw(ss, ESP + 2);
cpu_state.flags = (cpu_state.flags & 0x7000) | (readmemw(ss, ESP + 4) & 0xffd5) | 2;
ESP += 6;
} else {
cpu_state.pc = readmemw(ss, SP);
new_cs = readmemw(ss, ((SP + 2) & 0xffff));
cpu_state.flags = (cpu_state.flags & 0x7000) | (readmemw(ss, ((SP + 4) & 0xffff)) & 0x0fd5) | 2;
SP += 6;
}
op_loadcs(new_cs);
cycles -= timing_iret_rm;
}
flags_extract();
nmi_enable = 1;
rf_flag_no_clear = 1;
CPU_BLOCK_END();
PREFETCH_RUN(cycles_old - cycles, 1, -1, 2, 0, 0, 0, 0);
PREFETCH_FLUSH();
return cpu_state.abrt;
}
static int
opIRET(uint32_t fetchdat)
{
int cycles_old = cycles;
UN_USED(cycles_old);
if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) {
if (cr4 & CR4_VME) {
uint16_t new_pc;
uint16_t new_cs;
uint16_t new_flags;
new_pc = readmemw(ss, SP);
new_cs = readmemw(ss, ((SP + 2) & 0xffff));
new_flags = readmemw(ss, ((SP + 4) & 0xffff));
if (cpu_state.abrt)
return 1;
if ((new_flags & T_FLAG) || ((new_flags & I_FLAG) && (cpu_state.eflags & VIP_FLAG))) {
x86gpf(NULL, 0);
return 1;
}
SP += 6;
if (new_flags & I_FLAG)
cpu_state.eflags |= VIF_FLAG;
else
cpu_state.eflags &= ~VIF_FLAG;
cpu_state.flags = (cpu_state.flags & 0x3300) | (new_flags & 0x4cd5) | 2;
op_loadcs(new_cs);
cpu_state.pc = new_pc;
cycles -= timing_iret_rm;
} else {
x86gpf_expected(NULL, 0);
return 1;
}
} else {
if (msw & 1) {
optype = IRET;
op_pmodeiret(0);
optype = 0;
} else {
uint16_t new_cs;
CPU_SET_OXPC
if (stack32) {
cpu_state.pc = readmemw(ss, ESP);
new_cs = readmemw(ss, ESP + 2);
cpu_state.flags = (readmemw(ss, ESP + 4) & 0xffd5) | 2;
ESP += 6;
} else {
cpu_state.pc = readmemw(ss, SP);
new_cs = readmemw(ss, ((SP + 2) & 0xffff));
cpu_state.flags = (readmemw(ss, ((SP + 4) & 0xffff)) & 0xffd5) | 2;
SP += 6;
}
op_loadcs(new_cs);
cycles -= timing_iret_rm;
}
}
flags_extract();
nmi_enable = 1;
rf_flag_no_clear = 1;
CPU_BLOCK_END();
PREFETCH_RUN(cycles_old - cycles, 1, -1, 2, 0, 0, 0, 0);
PREFETCH_FLUSH();
return cpu_state.abrt;
}
static int
opIRETD(uint32_t fetchdat)
{
int cycles_old = cycles;
UN_USED(cycles_old);
if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) {
x86gpf_expected(NULL, 0);
return 1;
}
if (msw & 1) {
optype = IRET;
op_pmodeiret(1);
optype = 0;
} else {
uint16_t new_cs;
CPU_SET_OXPC
if (stack32) {
cpu_state.pc = readmeml(ss, ESP);
new_cs = readmemw(ss, ESP + 4);
cpu_state.flags = (readmemw(ss, ESP + 8) & 0xffd5) | 2;
cpu_state.eflags = readmemw(ss, ESP + 10);
ESP += 12;
} else {
cpu_state.pc = readmeml(ss, SP);
new_cs = readmemw(ss, ((SP + 4) & 0xffff));
cpu_state.flags = (readmemw(ss, (SP + 8) & 0xffff) & 0xffd5) | 2;
cpu_state.eflags = readmemw(ss, (SP + 10) & 0xffff);
SP += 12;
}
op_loadcs(new_cs);
cycles -= timing_iret_rm;
}
flags_extract();
nmi_enable = 1;
rf_flag_no_clear = 1;
CPU_BLOCK_END();
PREFETCH_RUN(cycles_old - cycles, 1, -1, 0, 2, 0, 0, 1);
PREFETCH_FLUSH();
return cpu_state.abrt;
}

View File

@@ -667,7 +667,11 @@ opPOP_SS_w(uint32_t fetchdat)
cpu_state.pc++;
if (cpu_state.abrt)
return 1;
#ifdef OPS_286_386
x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
#else
x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
#endif
return 1;
}
@@ -695,7 +699,11 @@ opPOP_SS_l(uint32_t fetchdat)
cpu_state.pc++;
if (cpu_state.abrt)
return 1;
#ifdef OPS_286_386
x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
#else
x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
#endif
return 1;
}

View File

@@ -2286,8 +2286,14 @@ taskswitch286(uint16_t seg, uint16_t *segdat, int is32)
op_loadseg(new_fs, &cpu_state.seg_fs);
op_loadseg(new_gs, &cpu_state.seg_gs);
if (!cpu_use_exec)
rf_flag_no_clear = 1;
if (t_bit) {
trap = 2;
if (cpu_use_exec)
trap = 2;
else
trap |= 2;
#ifdef USE_DYNAREC
cpu_block_end = 1;
#endif
@@ -2467,6 +2473,8 @@ taskswitch286(uint16_t seg, uint16_t *segdat, int is32)
tr.limit = limit;
tr.access = segdat[2] >> 8;
tr.ar_high = segdat[3] & 0xff;
if (!cpu_use_exec)
dr[7] &= 0xFFFFFFAA;
}
void

View File

@@ -87,6 +87,12 @@ x86de(UNUSED(char *s), UNUSED(uint16_t error))
#endif
}
void
x86gen(void)
{
x86_int(1);
}
void
x86gpf(UNUSED(char *s), uint16_t error)
{

View File

@@ -41,6 +41,7 @@ extern int cgate32;
extern int intgatesize;
extern void x86seg_reset(void);
extern void x86gen(void);
extern void x86de(char *s, uint16_t error);
extern void x86gpf(char *s, uint16_t error);
extern void x86gpf_expected(char *s, uint16_t error);

View File

@@ -1,22 +0,0 @@
/*
* 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.
*
* x86 CPU segment emulation for the 286/386 interpreter.
*
*
*
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2018 Sarah Walker.
* Copyright 2016-2018 Miran Grca.
*/
#ifndef OPS_286_386
# define OPS_286_386
#endif
#include "x86seg.c"

View File

@@ -62,6 +62,7 @@ static device_t *devices[DEVICE_MAX];
static void *device_priv[DEVICE_MAX];
static device_context_t device_current;
static device_context_t device_prev;
static void *device_common_priv;
#ifdef ENABLE_DEVICE_LOG
int device_do_log = ENABLE_DEVICE_LOG;
@@ -209,6 +210,16 @@ device_add(const device_t *dev)
return device_add_common(dev, dev, NULL, NULL, 0);
}
void *
device_add_linked(const device_t *dev, void *priv)
{
void *ret;
device_common_priv = priv;
ret = device_add_common(dev, dev, NULL, NULL, 0);
device_common_priv = NULL;
return ret;
}
void *
device_add_parameters(const device_t *dev, void *params)
{
@@ -305,6 +316,12 @@ device_cadd_inst_ex_parameters(const device_t *dev, const device_t *cd, void *pr
device_add_common(dev, cd, priv, params, inst);
}
void *
device_get_common_priv(void)
{
return device_common_priv;
}
void
device_close_all(void)
{

View File

@@ -19,7 +19,7 @@ add_library(dev OBJECT bugger.c cassette.c cartridge.c hasp.c hwm.c hwm_lm75.c h
hwm_vt82c686.c ibm_5161.c intel_ich2_gpio.c intel_ich2_trap.c
isamem.c isartc.c ../lpt.c pci_bridge.c
postcard.c serial.c unittester.c clock_ics9xxx.c isapnp.c i2c.c i2c_gpio.c
smbus_piix4.c smbus_ali7101.c keyboard.c keyboard_xt.c
smbus_piix4.c smbus_ali7101.c smbus_sis5595.c keyboard.c keyboard_xt.c
kbc_at.c kbc_at_dev.c
keyboard_at.c
mouse.c mouse_bus.c mouse_serial.c mouse_ps2.c nec_mate_unk.c phoenix_486_jumper.c

View File

@@ -73,8 +73,8 @@ ibm_5161_in(uint16_t port, void *priv)
02-03 = not used
04-07 = switch position
1 = Off
0 =On */
ret = dev->regs[3] & 0x01;
0 = On */
ret = (dev->regs[3] & 0x01) | (((~(0xf - ((mem_size + isa_mem_size) >> 6))) & 0xf) << 4);
break;
default:
@@ -95,8 +95,7 @@ ibm_5161_close(void *priv)
static void *
ibm_5161_init(UNUSED(const device_t *info))
{
ibm_5161_t *dev = (ibm_5161_t *) malloc(sizeof(ibm_5161_t));
memset(dev, 0, sizeof(ibm_5161_t));
ibm_5161_t *dev = (ibm_5161_t *) calloc(1, sizeof(ibm_5161_t));
/* Extender Card Registers */
io_sethandler(0x0210, 0x0004,

View File

@@ -1787,6 +1787,9 @@ kbc_at_process_cmd(void *priv)
if (dev->ib == 0xbb)
break;
if (strstr(machine_get_internal_name(), "pb") != NULL)
cpu_override_dynarec = 1;
if (dev->misc_flags & FLAG_PS2) {
set_enable_aux(dev, 1);
if ((dev->ports[1] != NULL) && (dev->ports[1]->priv != NULL)) {
@@ -1891,6 +1894,8 @@ kbc_at_read(uint16_t port, void *priv)
This also means that in AT mode, the IRQ is level-triggered. */
if (!(dev->misc_flags & FLAG_PS2))
picintclevel(1 << 1, &dev->irq_state);
if ((strstr(machine_get_internal_name(), "pb") != NULL) && (cpu_override_dynarec == 1))
cpu_override_dynarec = 0;
break;
case 0x64:

View File

@@ -119,12 +119,13 @@ kbc_at_dev_poll(void *priv)
break;
case DEV_STATE_MAIN_2:
/* Output from scan queue if needed and then return to main loop #1. */
if (*dev->scan && (dev->port->out_new == -1) && (dev->queue_start != dev->queue_end)) {
if (!dev->ignore && *dev->scan && (dev->port->out_new == -1) &&
(dev->queue_start != dev->queue_end)) {
kbc_at_dev_log("%s: %02X (DATA) on channel 1\n", dev->name, dev->queue[dev->queue_start]);
dev->port->out_new = dev->queue[dev->queue_start];
dev->queue_start = (dev->queue_start + 1) & dev->fifo_mask;
}
if (!(*dev->scan) || dev->port->wantcmd)
if (dev->ignore || !(*dev->scan) || dev->port->wantcmd)
dev->state = DEV_STATE_MAIN_1;
break;
case DEV_STATE_MAIN_OUT:
@@ -199,8 +200,7 @@ kbc_at_dev_init(uint8_t inst)
{
atkbc_dev_t *dev;
dev = (atkbc_dev_t *) malloc(sizeof(atkbc_dev_t));
memset(dev, 0x00, sizeof(atkbc_dev_t));
dev = (atkbc_dev_t *) calloc(1, sizeof(atkbc_dev_t));
dev->port = kbc_at_ports[inst];

View File

@@ -523,10 +523,12 @@ static void
add_data_kbd(uint16_t val)
{
atkbc_dev_t *dev = SavedKbd;
uint8_t fake_shift[4];
uint8_t fake_shift[4] = { 0 };
uint8_t num_lock = 0;
uint8_t shift_states = 0;
dev->ignore = 1;
keyboard_get_states(NULL, &num_lock, NULL);
shift_states = keyboard_get_shift() & STATE_SHIFT_MASK;
@@ -541,12 +543,14 @@ add_data_kbd(uint16_t val)
/* Num lock on and no shifts are pressed, send non-inverted fake shift. */
switch (keyboard_mode & 0x02) {
case 1:
keyboard_at_log("E0 2A\n");
fake_shift[0] = 0xe0;
fake_shift[1] = 0x2a;
add_data_vals(dev, fake_shift, 2);
break;
case 2:
keyboard_at_log("E0 12\n");
fake_shift[0] = 0xe0;
fake_shift[1] = 0x12;
add_data_vals(dev, fake_shift, 2);
@@ -562,12 +566,14 @@ add_data_kbd(uint16_t val)
/* Num lock off and left shift pressed. */
switch (keyboard_mode & 0x02) {
case 1:
keyboard_at_log("E0 AA\n");
fake_shift[0] = 0xe0;
fake_shift[1] = 0xaa;
add_data_vals(dev, fake_shift, 2);
break;
case 2:
keyboard_at_log("E0 F0 12\n");
fake_shift[0] = 0xe0;
fake_shift[1] = 0xf0;
fake_shift[2] = 0x12;
@@ -583,12 +589,14 @@ add_data_kbd(uint16_t val)
/* Num lock off and right shift pressed. */
switch (keyboard_mode & 0x02) {
case 1:
keyboard_at_log("E0 B6\n");
fake_shift[0] = 0xe0;
fake_shift[1] = 0xb6;
add_data_vals(dev, fake_shift, 2);
break;
case 2:
keyboard_at_log("E0 F0 59\n");
fake_shift[0] = 0xe0;
fake_shift[1] = 0xf0;
fake_shift[2] = 0x59;
@@ -614,12 +622,14 @@ add_data_kbd(uint16_t val)
/* Num lock on and no shifts are pressed, send non-inverted fake shift. */
switch (keyboard_mode & 0x02) {
case 1:
keyboard_at_log("E0 AA\n");
fake_shift[0] = 0xe0;
fake_shift[1] = 0xaa;
add_data_vals(dev, fake_shift, 2);
break;
case 2:
keyboard_at_log("E0 F0 12\n");
fake_shift[0] = 0xe0;
fake_shift[1] = 0xf0;
fake_shift[2] = 0x12;
@@ -636,12 +646,14 @@ add_data_kbd(uint16_t val)
/* Num lock off and left shift pressed. */
switch (keyboard_mode & 0x02) {
case 1:
keyboard_at_log("E0 2A\n");
fake_shift[0] = 0xe0;
fake_shift[1] = 0x2a;
add_data_vals(dev, fake_shift, 2);
break;
case 2:
keyboard_at_log("E0 12\n");
fake_shift[0] = 0xe0;
fake_shift[1] = 0x12;
add_data_vals(dev, fake_shift, 2);
@@ -656,12 +668,14 @@ add_data_kbd(uint16_t val)
/* Num lock off and right shift pressed. */
switch (keyboard_mode & 0x02) {
case 1:
keyboard_at_log("E0 36\n");
fake_shift[0] = 0xe0;
fake_shift[1] = 0x36;
add_data_vals(dev, fake_shift, 2);
break;
case 2:
keyboard_at_log("E0 59\n");
fake_shift[0] = 0xe0;
fake_shift[1] = 0x59;
add_data_vals(dev, fake_shift, 2);
@@ -680,6 +694,8 @@ add_data_kbd(uint16_t val)
kbc_at_dev_queue_add(dev, val, 1);
break;
}
dev->ignore = 0;
}
void
@@ -860,7 +876,8 @@ keyboard_at_write(void *priv)
case 0xf5: /* set defaults and disable keyboard */
case 0xf6: /* set defaults */
keyboard_at_log("%s: set defaults%s\n", (val == 0xf6) ? "" : " and disable keyboard");
keyboard_at_log("%s: set defaults%s\n",
dev->name, (val == 0xf6) ? "" : " and disable keyboard");
keyboard_scan = !(val & 0x01);
keyboard_at_log("%s: val = %02X, keyboard_scan = %i\n",
dev->name, val, keyboard_scan);

View File

@@ -454,6 +454,15 @@ mouse_scale(int x, int y)
mouse_scale_y(y);
}
void
mouse_scale_axis(int axis, int val)
{
if (axis == 1)
mouse_scale_y(val);
else if (axis == 0)
mouse_scale_x(val);
}
void
mouse_set_z(int z)
{

View File

@@ -21,6 +21,7 @@
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include "cpu.h"
#include <86box/device.h>
#include <86box/keyboard.h>
#include <86box/mouse.h>
@@ -276,6 +277,7 @@ ps2_write(void *priv)
break;
default:
mouse_ps2_log("%s: Bad command: %02X\n", dev->name, val);
kbc_at_dev_queue_add(dev, 0xfe, 0);
}
}

View File

@@ -43,11 +43,14 @@
#define AGP_BRIDGE_VIA_598 0x11068598
#define AGP_BRIDGE_VIA_691 0x11068691
#define AGP_BRIDGE_VIA_8601 0x11068601
#define AGP_BRIDGE_SIS_5XXX 0x10390001
#define AGP_BRIDGE_ALI(x) (((x) >> 16) == 0x10b9)
#define AGP_BRIDGE_INTEL(x) ((((x) >> 16) == 0x8086) && ((x) != PCI_BRIDGE_INTEL_ICH2))
#define AGP_BRIDGE_VIA(x) (((x) >> 16) == 0x1106)
#define AGP_BRIDGE(x) (((x) >= AGP_BRIDGE_ALI_M5243) && ((x) != PCI_BRIDGE_INTEL_ICH2))
#define AGP_BRIDGE_SIS(x) (((x) >> 16) == 0x1039)
//#define AGP_BRIDGE(x) (((x) >= AGP_BRIDGE_ALI_M5243) && ((x) != PCI_BRIDGE_INTEL_ICH2))
#define AGP_BRIDGE(x) ((x) >= AGP_BRIDGE_SIS_5XXX)
typedef struct pci_bridge_t {
uint32_t local;
@@ -140,6 +143,8 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv)
val |= 0x02;
else if (dev->local == AGP_BRIDGE_ALI_M5247)
val &= 0xc3;
else if (AGP_BRIDGE_SIS(dev->local))
val &= 0x27;
else
val &= 0x67;
break;
@@ -211,7 +216,8 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv)
case 0x22:
case 0x24:
case 0x26:
val &= 0xf0;
val &= 0xf0; /* SiS datasheets say 0Fh for 1Ch but that's clearly an erratum since the
definition of the bits is identical to the other vendors' AGP bridges. */
break;
case 0x3c:
@@ -222,6 +228,8 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv)
case 0x3e:
if (AGP_BRIDGE_VIA(dev->local))
val &= 0x0c;
else if (AGP_BRIDGE_SIS(dev->local))
val &= 0x0e;
else if (dev->local == AGP_BRIDGE_ALI_M5247)
val &= 0x0f;
else if (dev->local == AGP_BRIDGE_ALI_M5243)
@@ -758,3 +766,17 @@ const device_t via_vt8601_agp_device = {
.force_redraw = NULL,
.config = NULL
};
const device_t sis_5xxx_agp_device = {
.name = "SiS 5591/(5)600 AGP Bridge",
.internal_name = "via_5xxx_agp",
.flags = DEVICE_PCI,
.local = AGP_BRIDGE_SIS_5XXX,
.init = pci_bridge_init,
.close = NULL,
.reset = pci_bridge_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

386
src/device/smbus_sis5595.c Normal file
View File

@@ -0,0 +1,386 @@
/*
* 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 a generic SiS 5595-compatible SMBus host
* controller.
*
* Authors: RichardG, <richardg867@gmail.com>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2020-2021 RichardG.
* Copyright 2021 Miran Grca.
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/io.h>
#include <86box/device.h>
#include <86box/timer.h>
#include <86box/i2c.h>
#include <86box/pci.h>
#include <86box/smbus.h>
#include <86box/plat_fallthrough.h>
#ifdef ENABLE_SMBUS_SIS5595_LOG
int smbus_sis5595_do_log = ENABLE_SMBUS_SIS5595_LOG;
static void
smbus_sis5595_log(const char *fmt, ...)
{
va_list ap;
if (smbus_sis5595_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define smbus_sis5595_log(fmt, ...)
#endif
static void
smbus_sis5595_irq(smbus_sis5595_t *dev, int raise)
{
if (dev->irq_enable) {
if (raise)
pci_set_mirq(6, 1, &dev->irq_state);
else
pci_clear_mirq(6, 1, &dev->irq_state);
}
}
void
smbus_sis5595_irq_enable(void *priv, uint8_t enable)
{
smbus_sis5595_t *dev = (smbus_sis5595_t *) priv;
if (!enable && dev->irq_enable)
pci_clear_mirq(6, 1, &dev->irq_state);
dev->irq_enable = enable;
}
uint8_t
smbus_sis5595_read_index(void *priv)
{
smbus_sis5595_t *dev = (smbus_sis5595_t *) priv;
return dev->index;
}
uint8_t
smbus_sis5595_read_data(void *priv)
{
smbus_sis5595_t *dev = (smbus_sis5595_t *) priv;
uint8_t ret = 0x00;
switch (dev->index) {
case 0x00:
ret = dev->stat & 0xff;
break;
case 0x01:
ret = dev->stat >> 8;
break;
case 0x02:
ret = dev->ctl & 0xff;
break;
case 0x03:
ret = dev->ctl >> 8;
break;
case 0x04:
ret = dev->addr;
break;
case 0x05:
ret = dev->cmd;
break;
case 0x06:
ret = dev->block_ptr;
break;
case 0x07:
ret = dev->count;
break;
case 0x08 ... 0x0f:
ret = dev->data[(dev->index & 0x07) + (dev->block_ptr << 3)];
if (dev->index == 0x0f) {
dev->block_ptr = (dev->block_ptr + 1) & 3;
smbus_sis5595_irq(dev, dev->block_ptr != 0x00);
}
break;
case 0x10:
ret = dev->saved_addr;
break;
case 0x11:
ret = dev->data0;
break;
case 0x12:
ret = dev->data1;
break;
case 0x13:
ret = dev->alias;
break;
case 0xff:
ret = dev->reg_ff & 0xc0;
break;
default:
break;
}
smbus_sis5595_log("SMBus SIS5595: read(%02X) = %02x\n", addr, ret);
return ret;
}
void
smbus_sis5595_write_index(void *priv, uint8_t val)
{
smbus_sis5595_t *dev = (smbus_sis5595_t *) priv;
dev->index = val;
}
void
smbus_sis5595_write_data(void *priv, uint8_t val)
{
smbus_sis5595_t *dev = (smbus_sis5595_t *) priv;
uint8_t smbus_addr;
uint8_t cmd;
uint8_t read;
uint16_t prev_stat;
uint16_t timer_bytes = 0;
smbus_sis5595_log("SMBus SIS5595: write(%02X, %02X)\n", addr, val);
prev_stat = dev->next_stat;
dev->next_stat = 0x0000;
switch (dev->index) {
case 0x00:
dev->stat &= ~(val & 0xf0);
/* Make sure IDLE is set if we're not busy or errored. */
if (dev->stat == 0x04)
dev->stat = 0x00;
break;
case 0x01:
dev->stat &= ~(val & 0x07);
break;
case 0x02:
dev->ctl = (dev->ctl & 0xff00) | val;
if (val & 0x20) { /* cancel an in-progress command if KILL is set */
if (prev_stat) { /* cancel only if a command is in progress */
timer_disable(&dev->response_timer);
dev->stat = 0x80; /* raise FAILED */
}
} else if (val & 0x10) {
/* dispatch command if START is set */
timer_bytes++; /* address */
smbus_addr = (dev->addr >> 1);
read = dev->addr & 0x01;
cmd = (dev->ctl >> 1) & 0x7;
smbus_sis5595_log("SMBus SIS5595: addr=%02X read=%d protocol=%X cmd=%02X "
"data0=%02X data1=%02X\n", smbus_addr, read, cmd, dev->cmd,
dev->data0, dev->data1);
/* Raise DEV_ERR if no device is at this address, or if the device returned
NAK when starting the transfer. */
if (!i2c_start(i2c_smbus, smbus_addr, read)) {
dev->next_stat = 0x0020;
break;
}
dev->next_stat = 0x0040; /* raise INTER (command completed) by default */
/* Decode the command protocol. */
dev->block_ptr = 0x01;
switch (cmd) {
case 0x0: /* quick R/W */
break;
case 0x1: /* byte R/W */
if (read) /* byte read */
dev->data[0] = i2c_read(i2c_smbus, smbus_addr);
else /* byte write */
i2c_write(i2c_smbus, smbus_addr, dev->data[0]);
timer_bytes++;
break;
case 0x2: /* byte data R/W */
/* command write */
i2c_write(i2c_smbus, smbus_addr, dev->cmd);
timer_bytes++;
if (read) /* byte read */
dev->data[0] = i2c_read(i2c_smbus, smbus_addr);
else /* byte write */
i2c_write(i2c_smbus, smbus_addr, dev->data[0]);
timer_bytes++;
break;
case 0x3: /* word data R/W */
/* command write */
i2c_write(i2c_smbus, smbus_addr, dev->cmd);
timer_bytes++;
if (read) { /* word read */
dev->data[0] = i2c_read(i2c_smbus, smbus_addr);
dev->data[1] = i2c_read(i2c_smbus, smbus_addr);
} else { /* word write */
i2c_write(i2c_smbus, smbus_addr, dev->data[0]);
i2c_write(i2c_smbus, smbus_addr, dev->data[1]);
}
timer_bytes += 2;
break;
case 0x5: /* block R/W */
dev->block_ptr = 0x00;
timer_bytes++; /* count the SMBus length byte now */
fallthrough;
default: /* unknown */
dev->next_stat = 0x0010; /* raise DEV_ERR */
timer_bytes = 0;
break;
}
/* Finish transfer. */
i2c_stop(i2c_smbus, smbus_addr);
}
break;
case 0x03:
dev->ctl = (dev->ctl & 0x00ff) | (val << 8);
break;
case 0x04:
dev->addr = val;
break;
case 0x05:
dev->cmd = val;
break;
case 0x08 ... 0x0f:
dev->data[dev->index & 0x07] = val;
break;
case 0x10:
dev->saved_addr = val;
break;
case 0x11:
dev->data0 = val;
break;
case 0x12:
dev->data1 = val;
break;
case 0x13:
dev->alias = val & 0xfe;
break;
case 0xff:
dev->reg_ff = val & 0x3f;
break;
default:
break;
}
if (dev->next_stat != 0x04) { /* schedule dispatch of any pending status register update */
dev->stat = 0x08; /* raise HOST_BUSY while waiting */
timer_disable(&dev->response_timer);
/* delay = ((half clock for start + half clock for stop) + (bytes * (8 bits + ack))) * 60us period measured on real VIA 686B */
timer_set_delay_u64(&dev->response_timer, (1 + (timer_bytes * 9)) * 60 * TIMER_USEC);
}
}
static void
smbus_sis5595_response(void *priv)
{
smbus_sis5595_t *dev = (smbus_sis5595_t *) priv;
/* Dispatch the status register update. */
dev->stat = dev->next_stat;
}
static void
smbus_sis5595_reset(void *priv)
{
smbus_sis5595_t *dev = (smbus_sis5595_t *) priv;
timer_disable(&dev->response_timer);
dev->stat = 0x0000;
dev->block_ptr = 0x01;
}
static void *
smbus_sis5595_init(const device_t *info)
{
smbus_sis5595_t *dev = (smbus_sis5595_t *) malloc(sizeof(smbus_sis5595_t));
memset(dev, 0, sizeof(smbus_sis5595_t));
dev->local = info->local;
/* We save the I2C bus handle on dev but use i2c_smbus for all operations because
dev and therefore dev->i2c will be invalidated if a device triggers a hard reset. */
i2c_smbus = dev->i2c = i2c_addbus("smbus_sis5595");
timer_add(&dev->response_timer, smbus_sis5595_response, dev, 0);
smbus_sis5595_reset(dev);
return dev;
}
static void
smbus_sis5595_close(void *priv)
{
smbus_sis5595_t *dev = (smbus_sis5595_t *) priv;
if (i2c_smbus == dev->i2c)
i2c_smbus = NULL;
i2c_removebus(dev->i2c);
free(dev);
}
const device_t sis5595_smbus_device = {
.name = "SiS 5595-compatible SMBus Host Controller",
.internal_name = "sis5595_smbus",
.flags = DEVICE_AT,
.local = 0,
.init = smbus_sis5595_init,
.close = smbus_sis5595_close,
.reset = smbus_sis5595_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -16,7 +16,7 @@
add_library(hdd OBJECT hdd.c hdd_image.c hdd_table.c hdc.c hdc_st506_xt.c
hdc_st506_at.c hdc_xta.c hdc_esdi_at.c hdc_esdi_mca.c hdc_xtide.c
hdc_ide.c hdc_ide_ali5213.c hdc_ide_opti611.c hdc_ide_cmd640.c hdc_ide_cmd646.c
hdc_ide_sff8038i.c)
hdc_ide_sff8038i.c hdc_ide_um8673f.c hdc_ide_w83769f.c)
add_library(zip OBJECT zip.c)

View File

@@ -100,12 +100,10 @@ static const struct {
{ &ide_isa_device },
{ &ide_isa_2ch_device },
{ &xtide_at_device },
{ &xtide_at_386_device },
{ &xtide_at_ps2_device },
{ &xta_wdxt150_device },
{ &xtide_acculogic_device },
{ &xtide_device },
{ &xtide_plus_device },
{ &esdi_ps2_device },
{ &ide_pci_device },
{ &ide_pci_2ch_device },

View File

@@ -436,9 +436,9 @@ sff_bus_master_set_irq(uint8_t status, void *priv)
case IRQ_MODE_SIS_551X:
/* SiS 551x mode. */
if (irq)
pci_set_mirq(2, 1, &dev->irq_state);
pci_set_mirq(dev->mirq, 1, &dev->irq_state);
else
pci_clear_mirq(2, 1, &dev->irq_state);
pci_clear_mirq(dev->mirq, 1, &dev->irq_state);
break;
}
}
@@ -554,6 +554,12 @@ sff_set_irq_pin(sff8038i_t *dev, int irq_pin)
dev->irq_pin = irq_pin;
}
void
sff_set_mirq(sff8038i_t *dev, uint8_t mirq)
{
dev->mirq = mirq;
}
static void
sff_close(void *priv)
{
@@ -586,6 +592,7 @@ sff_init(UNUSED(const device_t *info))
dev->pci_irq_line = 14;
dev->irq_level = 0;
dev->irq_state = 0;
dev->mirq = 2;
dev->channel = next_id;
next_id++;

212
src/disk/hdc_ide_um8673f.c Normal file
View File

@@ -0,0 +1,212 @@
/*
* 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 UMC UMF8673F IDE controller.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2024 Miran Grca.
*/
#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/hdc_ide.h>
#include <86box/hdc.h>
#include <86box/mem.h>
#include <86box/nmi.h>
#include <86box/pic.h>
#include <86box/pci.h>
#include <86box/plat_unused.h>
#include <86box/port_92.h>
#include <86box/smram.h>
#include <86box/chipset.h>
#ifdef ENABLE_UM8673F_LOG
int um8673f_do_log = ENABLE_UM8673F_LOG;
static void
um8673f_log(const char *fmt, ...)
{
va_list ap;
if (um8673f_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define um8673f_log(fmt, ...)
#endif
typedef struct um8673f_t {
uint8_t index;
uint8_t tries;
uint8_t unlocked;
uint8_t regs[256];
} um8673f_t;
static void
um8673f_ide_handler(um8673f_t *dev)
{
ide_pri_disable();
ide_sec_disable();
if (dev->regs[0xb0] & 0x80)
ide_pri_enable();
if (dev->regs[0xb0] & 0x40)
ide_sec_enable();
}
static void
um8673f_write(uint16_t addr, uint8_t val, void *priv)
{
um8673f_t *dev = (um8673f_t *) priv;
um8673f_log("[%04X:%08X] [W] %02X = %02X (%i)\n", CS, cpu_state.pc, port, val, dev->tries);
switch (addr) {
case 0x108:
if (dev->unlocked) {
if (dev->index == 0x34) {
dev->unlocked = 0;
dev->tries = 0;
} else
dev->index = val;
} else if (((dev->tries == 0) && (val == 0x4a)) ||
((dev->tries == 1) && (val == 0x6c))) {
dev->tries++;
if (dev->tries == 2)
dev->unlocked = 1;
} else
dev->tries = 0;
break;
case 0x109:
switch (dev->index) {
case 0xb0:
dev->regs[dev->index] = val;
um8673f_ide_handler(dev);
break;
case 0xb1 ... 0xb8:
dev->regs[dev->index] = val;
break;
default:
break;
}
break;
default:
break;
}
}
static uint8_t
um8673f_read(uint16_t addr, void *priv)
{
um8673f_t *dev = (um8673f_t *) priv;
uint8_t ret = 0xff;
switch (addr) {
case 0x108:
if (dev->unlocked)
ret = dev->index;
else
dev->tries = 0;
break;
case 0x109:
if ((dev->index >= 0xb0) && (dev->index <= 0xb8))
ret = dev->regs[dev->index];
break;
default:
break;
}
um8673f_log("[%04X:%08X] [R] %02X = %02X\n", CS, cpu_state.pc, port, ret);
return ret;
}
static void
um8673f_reset(void *priv)
{
um8673f_t *dev = (um8673f_t *) priv;
memset(dev->regs, 0x00, 256);
ide_pri_disable();
ide_sec_disable();
/* IDE registers */
dev->regs[0xb0] = 0xc0;
um8673f_ide_handler(dev);
}
static void
um8673f_close(void *priv)
{
um8673f_t *dev = (um8673f_t *) priv;
free(dev);
}
static void *
um8673f_init(UNUSED(const device_t *info))
{
um8673f_t *dev = (um8673f_t *) calloc(1, sizeof(um8673f_t));
io_sethandler(0x0108, 0x0002, um8673f_read, NULL, NULL, um8673f_write, NULL, NULL, dev);
device_add(info->local ? &ide_pci_2ch_device : &ide_vlb_2ch_device);
um8673f_reset(dev);
return dev;
}
const device_t ide_um8886af_device = {
.name = "UMC UM8886F IDE",
.internal_name = "um8886af_ide",
.flags = 0,
.local = 1,
.init = um8673f_init,
.close = um8673f_close,
.reset = um8673f_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t ide_um8673f_device = {
.name = "UMC UM8673F",
.internal_name = "um8673f",
.flags = 0,
.local = 0,
.init = um8673f_init,
.close = um8673f_close,
.reset = um8673f_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

460
src/disk/hdc_ide_w83769f.c Normal file
View File

@@ -0,0 +1,460 @@
/*
* 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 Winbond W83769F controller.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2020 Miran Grca.
*/
#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/cdrom.h>
#include <86box/scsi_device.h>
#include <86box/scsi_cdrom.h>
#include <86box/dma.h>
#include <86box/io.h>
#include <86box/device.h>
#include <86box/keyboard.h>
#include <86box/mem.h>
#include <86box/pci.h>
#include <86box/pic.h>
#include <86box/timer.h>
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
#include <86box/hdc_ide_sff8038i.h>
#include <86box/zip.h>
#include <86box/mo.h>
typedef struct w83769f_t {
uint8_t vlb_idx;
uint8_t id;
uint8_t in_cfg;
uint8_t channels;
uint8_t pci;
uint8_t pci_slot;
uint8_t pad;
uint8_t pad0;
uint8_t regs[256];
} w83769f_t;
static int next_id = 0;
#ifdef ENABLE_W83769F_LOG
int w83769f_do_log = ENABLE_W83769F_LOG;
static void
w83769f_log(const char *fmt, ...)
{
va_list ap;
if (cmd640_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define w83769f_log(fmt, ...)
#endif
void
w83769f_set_irq_0(uint8_t status, void *priv)
{
w83769f_t *dev = (w83769f_t *) priv;
int irq = !!(status & 0x04);
if (!(dev->regs[0x50] & 0x04) || (status & 0x04))
dev->regs[0x50] = (dev->regs[0x50] & ~0x04) | status;
if (!(dev->channels & 1))
return;
if (irq)
picint(1 << 14);
else
picintc(1 << 14);
}
void
w83769f_set_irq_1(uint8_t status, void *priv)
{
w83769f_t *dev = (w83769f_t *) priv;
int irq = !!(status & 0x04);
if (!(dev->regs[0x50] & 0x04) || (status & 0x04))
dev->regs[0x50] = (dev->regs[0x50] & ~0x04) | status;
if (!(dev->channels & 2))
return;
if (irq)
picint(1 << 15);
else
picintc(1 << 15);
}
static void
w83769f_ide_handlers(w83769f_t *dev)
{
if (dev->channels & 0x01) {
ide_pri_disable();
if (!dev->pci || (dev->regs[0x04] & 0x01))
ide_pri_enable();
}
if (dev->channels & 0x02) {
ide_sec_disable();
if ((!dev->pci || (dev->regs[0x04] & 0x01)) && (dev->regs[0x57] & 0x01))
ide_sec_enable();
}
}
static void
w83769f_common_write(int addr, uint8_t val, w83769f_t *dev)
{
switch (addr) {
case 0x50:
case 0x57:
dev->regs[0x57] = val & 0x01;
w83769f_ide_handlers(dev);
break;
case 0x51:
dev->regs[addr] = val & 0x7f;
break;
case 0x52:
case 0x54:
case 0x56:
case 0x58 ... 0x59:
dev->regs[addr] = val;
break;
case 0x53:
case 0x55:
dev->regs[addr] = val & 0xcf;
break;
default:
break;
}
}
static void
w83769f_vlb_write(uint16_t addr, uint8_t val, void *priv)
{
w83769f_t *dev = (w83769f_t *) priv;
switch (addr) {
case 0x0034:
case 0x00b4:
dev->vlb_idx = val;
break;
case 0x0038:
case 0x00b8:
w83769f_common_write(dev->vlb_idx, val, dev);
break;
default:
break;
}
}
static void
w83769f_vlb_writew(uint16_t addr, uint16_t val, void *priv)
{
w83769f_vlb_write(addr, val & 0xff, priv);
w83769f_vlb_write(addr + 1, val >> 8, priv);
}
static void
w83769f_vlb_writel(uint16_t addr, uint32_t val, void *priv)
{
w83769f_vlb_writew(addr, val & 0xffff, priv);
w83769f_vlb_writew(addr + 2, val >> 16, priv);
}
static uint8_t
w83769f_vlb_read(uint16_t addr, void *priv)
{
uint8_t ret = 0xff;
w83769f_t *dev = (w83769f_t *) priv;
switch (addr) {
case 0x0034:
case 0x00b4:
ret = dev->vlb_idx;
break;
case 0x0038:
case 0x00b8:
ret = dev->regs[dev->vlb_idx];
if (dev->vlb_idx == 0x50)
dev->regs[0x50] &= ~0x04;
break;
default:
break;
}
return ret;
}
static uint16_t
w83769f_vlb_readw(uint16_t addr, void *priv)
{
uint16_t ret = 0xffff;
ret = w83769f_vlb_read(addr, priv);
ret |= (w83769f_vlb_read(addr + 1, priv) << 8);
return ret;
}
static uint32_t
w83769f_vlb_readl(uint16_t addr, void *priv)
{
uint32_t ret = 0xffffffff;
ret = w83769f_vlb_readw(addr, priv);
ret |= (w83769f_vlb_readw(addr + 2, priv) << 16);
return ret;
}
static void
w83769f_pci_write(int func, int addr, uint8_t val, void *priv)
{
w83769f_t *dev = (w83769f_t *) priv;
w83769f_log("w83769f_pci_write(%i, %02X, %02X)\n", func, addr, val);
if (func == 0x00)
switch (addr) {
case 0x04:
dev->regs[addr] = (dev->regs[addr] & 0xbf) | (val & 0x40);
w83769f_ide_handlers(dev);
break;
case 0x07:
dev->regs[addr] &= ~(val & 0x80);
break;
}
}
static uint8_t
w83769f_pci_read(int func, int addr, void *priv)
{
w83769f_t *dev = (w83769f_t *) priv;
uint8_t ret = 0xff;
if (func == 0x00)
ret = dev->regs[addr];
w83769f_log("w83769f_pci_read(%i, %02X, %02X)\n", func, addr, ret);
return ret;
}
static void
w83769f_reset(void *priv)
{
w83769f_t *dev = (w83769f_t *) priv;
int i = 0;
int min_channel;
int max_channel;
switch (dev->channels) {
default:
case 0x00:
min_channel = max_channel = 0;
break;
case 0x01:
min_channel = 0;
max_channel = 1;
break;
case 0x02:
min_channel = 2;
max_channel = 3;
break;
case 0x03:
min_channel = 0;
max_channel = 3;
break;
}
for (i = 0; i < CDROM_NUM; i++) {
if ((cdrom[i].bus_type == CDROM_BUS_ATAPI) && (cdrom[i].ide_channel >= min_channel) &&
(cdrom[i].ide_channel <= max_channel) && cdrom[i].priv)
scsi_cdrom_reset((scsi_common_t *) cdrom[i].priv);
}
for (i = 0; i < ZIP_NUM; i++) {
if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI) && (zip_drives[i].ide_channel >= min_channel) &&
(zip_drives[i].ide_channel <= max_channel) && zip_drives[i].priv)
zip_reset((scsi_common_t *) zip_drives[i].priv);
}
for (i = 0; i < MO_NUM; i++) {
if ((mo_drives[i].bus_type == MO_BUS_ATAPI) && (mo_drives[i].ide_channel >= min_channel) &&
(mo_drives[i].ide_channel <= max_channel) && mo_drives[i].priv)
mo_reset((scsi_common_t *) mo_drives[i].priv);
}
if (dev->channels & 0x01)
w83769f_set_irq_0(0x00, priv);
if (dev->channels & 0x02)
w83769f_set_irq_1(0x00, priv);
memset(dev->regs, 0x00, sizeof(dev->regs));
dev->regs[0x50] = (dev->id << 3); /* Device ID: 00 = 60h, 01 = 61h, 10 = 62h, 11 = 63h */
dev->regs[0x51] = 0x40;
dev->regs[0x57] = 0x01; /* Required by the MSI MS-5109 */
dev->regs[0x59] = 0x40;
if (dev->pci) {
dev->regs[0x00] = 0xad; /* Winbond */
dev->regs[0x01] = 0x10;
dev->regs[0x02] = 0x01; /* W83769 */
dev->regs[0x03] = 0x00;
dev->regs[0x04] = 0x01;
dev->regs[0x07] = 0x02; /* DEVSEL timing: 01 medium */
dev->regs[0x08] = 0x02; /* 00h for Rev BB, 02h for Rev A3C */
dev->regs[0x09] = 0x00; /* Programming interface */
dev->regs[0x0a] = 0x01; /* IDE controller */
dev->regs[0x0b] = 0x01; /* Mass storage controller */
dev->regs[0x3c] = 0x0e; /* IRQ 14 */
dev->regs[0x3d] = 0x01; /* INTA */
} else
dev->regs[0x04] = 0x01; /* To make sure the two channels get enabled. */
w83769f_ide_handlers(dev);
}
static void
w83769f_close(void *priv)
{
w83769f_t *dev = (w83769f_t *) priv;
free(dev);
next_id = 0;
}
static void *
w83769f_init(const device_t *info)
{
w83769f_t *dev = (w83769f_t *) malloc(sizeof(w83769f_t));
memset(dev, 0x00, sizeof(w83769f_t));
dev->id = next_id | 0x60;
dev->pci = !!(info->flags & DEVICE_PCI);
dev->channels = ((info->local & 0x60000) >> 17) & 0x03;
if (info->flags & DEVICE_PCI) {
device_add(&ide_pci_2ch_device);
if (info->local & 0x80000)
pci_add_card(PCI_ADD_NORMAL, w83769f_pci_read, w83769f_pci_write, dev, &dev->pci_slot);
else
pci_add_card(PCI_ADD_IDE, w83769f_pci_read, w83769f_pci_write, dev, &dev->pci_slot);
} else if (info->flags & DEVICE_VLB)
device_add(&ide_vlb_2ch_device);
if (dev->channels & 0x01)
ide_set_bus_master(0, NULL, w83769f_set_irq_0, dev);
if (dev->channels & 0x02)
ide_set_bus_master(1, NULL, w83769f_set_irq_1, dev);
/* The CMD PCI-0640B IDE controller has no DMA capability,
so set our devices IDE devices to force ATA-3 (no DMA). */
if (dev->channels & 0x01)
ide_board_set_force_ata3(0, 1);
if (dev->channels & 0x02)
ide_board_set_force_ata3(1, 1);
io_sethandler(info->local & 0xffff, 0x0001,
w83769f_vlb_read, w83769f_vlb_readw, w83769f_vlb_readl,
w83769f_vlb_write, w83769f_vlb_writew, w83769f_vlb_writel,
dev);
io_sethandler((info->local & 0xffff) + 0x0004, 0x0001,
w83769f_vlb_read, w83769f_vlb_readw, w83769f_vlb_readl,
w83769f_vlb_write, w83769f_vlb_writew, w83769f_vlb_writel,
dev);
next_id++;
w83769f_reset(dev);
return dev;
}
const device_t ide_w83769f_vlb_device = {
.name = "Winbond W83769F VLB",
.internal_name = "ide_w83769f_vlb",
.flags = DEVICE_VLB,
.local = 0x600b4,
.init = w83769f_init,
.close = w83769f_close,
.reset = w83769f_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t ide_w83769f_vlb_34_device = {
.name = "Winbond W83769F VLB (Port 34h)",
.internal_name = "ide_w83769f_vlb_34",
.flags = DEVICE_VLB,
.local = 0x60034,
.init = w83769f_init,
.close = w83769f_close,
.reset = w83769f_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t ide_w83769f_pci_device = {
.name = "Winbond W83769F PCI",
.internal_name = "ide_w83769f_pci",
.flags = DEVICE_PCI,
.local = 0x600b4,
.init = w83769f_init,
.close = w83769f_close,
.reset = w83769f_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t ide_w83769f_pci_34_device = {
.name = "Winbond W83769F PCI (Port 34h)",
.internal_name = "ide_w83769f_pci_34",
.flags = DEVICE_PCI,
.local = 0x60034,
.init = w83769f_init,
.close = w83769f_close,
.reset = w83769f_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -107,7 +107,7 @@
#define ST11_BIOS_FILE_OLD "roms/hdd/st506/st11_bios_vers_1.7.bin"
#define ST11_BIOS_FILE_NEW "roms/hdd/st506/st11_bios_vers_2.0.bin"
#define WD1002A_WX1_BIOS_FILE "roms/hdd/st506/wd1002a_wx1-62-000094-032.bin"
#define WD1004A_WX1_BIOS_FILE "roms/hdd/st506/wd1002a_wx1-62-000094-032.bin"
#define WD1004A_WX1_BIOS_FILE "roms/hdd/st506/western_digital_WD1004A-27X.bin"
/* SuperBIOS was for both the WX1 and 27X, users jumpers readout to determine
if to use 26 sectors per track, 26 -> 17 sectors per track translation, or
17 sectors per track. */
@@ -1667,7 +1667,7 @@ st506_init(const device_t *info)
fn = WD1004A_WX1_BIOS_FILE;
/* The switches are read in reverse: 0 = closed, 1 = open.
Both open means MFM, 17 sectors per track. */
dev->switches = 0x10; /* autobios */
dev->switches = 0x30; /* autobios */
dev->base = device_get_config_hex16("base");
dev->irq = device_get_config_int("irq");
if (dev->irq == 2)

View File

@@ -49,9 +49,9 @@
#define ROM_PATH_XT "roms/hdd/xtide/ide_xt.bin"
#define ROM_PATH_XTP "roms/hdd/xtide/ide_xtp.bin"
#define ROM_PATH_AT "roms/hdd/xtide/ide_at.bin"
#define ROM_PATH_AT_386 "roms/hdd/xtide/ide_386.bin"
#define ROM_PATH_PS2 "roms/hdd/xtide/SIDE1V12.BIN"
#define ROM_PATH_PS2AT "roms/hdd/xtide/ide_at_1_1_5.bin"
#define ROM_PATH_AT_386 "roms/hdd/xtide/ide_386.bin"
typedef struct xtide_t {
void *ide_board;
@@ -136,13 +136,9 @@ xtide_init(const device_t *info)
memset(xtide, 0x00, sizeof(xtide_t));
if (info->local == 1) {
rom_init(&xtide->bios_rom, ROM_PATH_XTP,
rom_init(&xtide->bios_rom,
device_get_bios_file(info, device_get_config_bios("bios"), 0),
0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL);
} else {
rom_init(&xtide->bios_rom, ROM_PATH_XT,
0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL);
}
xtide->ide_board = ide_xtide_init();
@@ -153,18 +149,6 @@ xtide_init(const device_t *info)
return xtide;
}
static int
xtide_available(void)
{
return (rom_present(ROM_PATH_XT));
}
static int
xtide_plus_available(void)
{
return (rom_present(ROM_PATH_XTP));
}
static void *
xtide_at_init(const device_t *info)
{
@@ -172,31 +156,15 @@ xtide_at_init(const device_t *info)
memset(xtide, 0x00, sizeof(xtide_t));
if (info->local == 1) {
rom_init(&xtide->bios_rom, ROM_PATH_AT_386,
rom_init(&xtide->bios_rom,
device_get_bios_file(info, device_get_config_bios("bios"), 0),
0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL);
} else {
rom_init(&xtide->bios_rom, ROM_PATH_AT,
0xc8000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL);
}
device_add(&ide_isa_2ch_device);
return xtide;
}
static int
xtide_at_available(void)
{
return (rom_present(ROM_PATH_AT));
}
static int
xtide_at_386_available(void)
{
return (rom_present(ROM_PATH_AT_386));
}
static void *
xtide_acculogic_init(UNUSED(const device_t *info))
{
@@ -261,6 +229,50 @@ xtide_at_close(void *priv)
free(xtide);
}
static const device_config_t xtide_config[] = {
// clang-format off
{
.name = "bios",
.description = "BIOS",
.type = CONFIG_BIOS,
.default_string = "xt",
.default_int = 0,
.file_filter = "",
.spinner = { 0 }, /*W1*/
.bios = {
{ .name = "Regular XT", .internal_name = "xt", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 8192, .files = { ROM_PATH_XT, "" } },
{ .name = "XT+ (V20/V30/8018x)", .internal_name = "xt_plus", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 8192, .files = { ROM_PATH_XTP, "" } },
{ .files_no = 0 }
},
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format on
};
static const device_config_t xtide_at_config[] = {
// clang-format off
{
.name = "bios",
.description = "BIOS",
.type = CONFIG_BIOS,
.default_string = "at",
.default_int = 0,
.file_filter = "",
.spinner = { 0 }, /*W1*/
.bios = {
{ .name = "Regular AT", .internal_name = "at", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 8192, .files = { ROM_PATH_AT, "" } },
{ .name = "386", .internal_name = "at_386", .bios_type = BIOS_NORMAL,
.files_no = 1, .local = 0, .size = 8192, .files = { ROM_PATH_AT_386, "" } },
{ .files_no = 0 }
},
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format on
};
const device_t xtide_device = {
.name = "PC/XT XTIDE",
.internal_name = "xtide",
@@ -269,24 +281,10 @@ const device_t xtide_device = {
.init = xtide_init,
.close = xtide_close,
.reset = NULL,
{ .available = xtide_available },
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t xtide_plus_device = {
.name = "PC/XT XTIDE (V20/V30/8018x)",
.internal_name = "xtide_plus",
.flags = DEVICE_ISA,
.local = 1,
.init = xtide_init,
.close = xtide_close,
.reset = NULL,
{ .available = xtide_plus_available },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.config = xtide_config
};
const device_t xtide_at_device = {
@@ -297,24 +295,10 @@ const device_t xtide_at_device = {
.init = xtide_at_init,
.close = xtide_at_close,
.reset = NULL,
{ .available = xtide_at_available },
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t xtide_at_386_device = {
.name = "PC/AT XTIDE (386)",
.internal_name = "xtide_at_386",
.flags = DEVICE_ISA | DEVICE_AT,
.local = 1,
.init = xtide_at_init,
.close = xtide_at_close,
.reset = NULL,
{ .available = xtide_at_386_available },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.config = xtide_at_config
};
const device_t xtide_acculogic_device = {

View File

@@ -950,16 +950,47 @@ dma_page_read(uint16_t addr, UNUSED(void *priv))
uint8_t convert[8] = CHANNELS;
uint8_t ret = 0xff;
addr &= 0x0f;
ret = dmaregs[2][addr];
if (((addr & 0xfffc) == 0x80) && (CS == 0xf000) &&
((cpu_state.pc & 0xfffffff8) == 0x00007278) &&
!strcmp(machine_get_internal_name(), "megapc")) switch (addr) {
/* The Amstrad MegaPC Quadtel BIOS times a sequence of:
mov ax,di
div bx
And expects this value to be at least 0x06e0 for 20 MHz,
and at least 0x0898 for 25 MHz, everything below 0x06e0
is assumed to be 16 MHz. Given that for some reason, this
does not occur on 86Box, we have to work around it here,
we return 0x0580 for 16 MHz, because it logically follows
in the sequence (0x06e0 = 0x0898 * (20 / 25), and
0x0580 = 0x06e0 * (16 / 20)). */
case 0x0081:
if (cpu_busspeed >= 25000000)
ret = 0x98;
else if (cpu_busspeed >= 20000000)
ret = 0xe0;
else
ret = 0x80;
break;
case 0x0082:
if (cpu_busspeed >= 25000000)
ret = 0x08;
else if (cpu_busspeed >= 20000000)
ret = 0x06;
else
ret = 0x05;
break;
} else {
addr &= 0x0f;
ret = dmaregs[2][addr];
if (addr >= 8)
addr = convert[addr & 0x07] | 4;
else
addr = convert[addr & 0x07];
if (addr >= 8)
addr = convert[addr & 0x07] | 4;
else
addr = convert[addr & 0x07];
if (addr < 8)
ret = dma[addr].page_l;
if (addr < 8)
ret = dma[addr].page_l;
}
return ret;
}

View File

@@ -31,10 +31,6 @@
#include <86box/timer.h>
#include <86box/isapnp.h>
#include <86box/gameport.h>
#include <86box/joystick_ch_flightstick_pro.h>
#include <86box/joystick_standard.h>
#include <86box/joystick_sw_pad.h>
#include <86box/joystick_tm_fcs.h>
#include <86box/plat_unused.h>
typedef struct g_axis_t {

View File

@@ -43,7 +43,6 @@
#include <86box/device.h>
#include <86box/timer.h>
#include <86box/gameport.h>
#include <86box/joystick_standard.h>
#include <86box/plat_unused.h>
static void *

View File

@@ -43,7 +43,6 @@
#include <86box/device.h>
#include <86box/timer.h>
#include <86box/gameport.h>
#include <86box/joystick_standard.h>
#include <86box/plat_unused.h>
static void *

View File

@@ -64,7 +64,6 @@
#include <86box/device.h>
#include <86box/timer.h>
#include <86box/gameport.h>
#include <86box/joystick_sw_pad.h>
#include <86box/plat_unused.h>
typedef struct sw_data {

View File

@@ -43,7 +43,6 @@
#include <86box/device.h>
#include <86box/timer.h>
#include <86box/gameport.h>
#include <86box/joystick_standard.h>
#include <86box/plat_unused.h>
static void *

View File

@@ -54,13 +54,15 @@ extern "C" {
#define ACPI_ENABLE 0xf1
#define ACPI_DISABLE 0xf0
#define VEN_ALI 0x010b9
#define VEN_INTEL 0x08086
#define VEN_INTEL_ICH2 0x18086
#define VEN_SIS 0x01039
#define VEN_SMC 0x01055
#define VEN_VIA 0x01106
#define VEN_VIA_596B 0x11106
#define VEN_ALI 0x010b9
#define VEN_INTEL 0x08086
#define VEN_INTEL_ICH2 0x18086
#define VEN_SIS_5582 0x01039
#define VEN_SIS_5595_1997 0x11039
#define VEN_SIS_5595 0x21039
#define VEN_SMC 0x01055
#define VEN_VIA 0x01106
#define VEN_VIA_596B 0x11106
typedef struct acpi_regs_t {
uint8_t acpitst;
@@ -80,6 +82,25 @@ typedef struct acpi_regs_t {
uint8_t gporeg[4];
uint8_t extiotrapsts;
uint8_t extiotrapen;
uint8_t enter_c2_ps;
uint8_t enter_c3_ps;
uint8_t reg_12;
uint8_t reg_13;
uint8_t smi_cmd;
uint8_t reg_24;
uint8_t reg_25;
uint8_t reg_26;
uint8_t smi_en_val;
uint8_t smi_dis_val;
uint8_t mail_box;
uint8_t reg_2b;
uint8_t gp_tmr;
uint8_t leg_sts;
uint8_t leg_en;
uint8_t tst_ctl;
uint8_t reg_34;
uint8_t index;
uint8_t reg_ff;
uint16_t pmsts;
uint16_t pmen;
uint16_t pmcntrl;
@@ -99,6 +120,15 @@ typedef struct acpi_regs_t {
uint16_t pscntrl;
uint16_t gpscists;
uint16_t mon_smi;
uint16_t reg_14;
uint16_t reg_16;
uint16_t reg_18;
uint16_t reg_1a;
uint16_t reg_1c;
uint16_t gpe_mul;
uint16_t gpe_ctl;
uint16_t gpe_smi;
uint16_t gpe_rl;
int smi_lock;
int smi_active;
uint32_t pcntrl;
@@ -118,6 +148,12 @@ typedef struct acpi_regs_t {
uint32_t smi_en;
uint32_t smi_sts;
uint32_t pad0;
uint32_t reg_0c;
uint32_t gpe_sts;
uint32_t gpe_en;
uint32_t gpe_pin;
uint32_t gpe_io;
uint32_t gpe_pol;
} acpi_regs_t;
typedef struct acpi_t {
@@ -138,12 +174,16 @@ typedef struct acpi_t {
pc_timer_t timer;
pc_timer_t resume_timer;
pc_timer_t pwrbtn_timer;
pc_timer_t gp_timer;
pc_timer_t per_timer;
nvr_t *nvr;
apm_t *apm;
tco_t *tco;
void *i2c;
void (*trap_update)(void *priv);
void *trap_priv;
void *smbus;
void *priv;
} acpi_t;
/* Global variables. */
@@ -157,6 +197,9 @@ extern const device_t acpi_intel_ich2_device;
extern const device_t acpi_smc_device;
extern const device_t acpi_via_device;
extern const device_t acpi_via_596b_device;
extern const device_t acpi_sis_5582_device;
extern const device_t acpi_sis_5595_1997_device;
extern const device_t acpi_sis_5595_device;
/* Functions */
extern void acpi_update_irq(acpi_t *dev);
@@ -176,6 +219,12 @@ extern void acpi_set_tco(acpi_t *dev, tco_t *tco);
extern void acpi_set_trap_update(acpi_t *dev, void (*update)(void *priv), void *priv);
extern uint8_t acpi_ali_soft_smi_status_read(acpi_t *dev);
extern void acpi_ali_soft_smi_status_write(acpi_t *dev, uint8_t soft_smi);
extern void * acpi_get_smbus(void *priv);
extern void acpi_sis5582_pmu_event(void *priv);
extern void acpi_sis5595_smi_raise(void *priv);
extern void acpi_sis5595_pmu_event(void *priv);
extern void acpi_sis5595_smbus_event(void *priv);
extern void acpi_sis5595_software_smi(void *priv);
#ifdef __cplusplus
}

View File

@@ -244,6 +244,7 @@ typedef struct cdrom {
int prev_host_drive;
int cd_buflen;
int audio_op;
int audio_muted_soft;
int sony_msf;
const cdrom_ops_t *ops;

View File

@@ -134,8 +134,16 @@ extern const device_t sis_85c471_device;
extern const device_t sis_85c496_device;
extern const device_t sis_85c496_ls486e_device;
extern const device_t sis_85c50x_device;
extern const device_t sis_550x_85c503_device;
extern const device_t sis_85c50x_5503_device;
extern const device_t sis_550x_device;
extern const device_t sis_5511_device;
extern const device_t sis_5571_device;
extern const device_t sis_5581_device;
extern const device_t sis_5591_1997_device;
extern const device_t sis_5591_device;
extern const device_t sis_5600_1997_device;
extern const device_t sis_5600_device;
/* ST */
extern const device_t stpc_client_device;
@@ -148,6 +156,8 @@ extern const device_t stpc_lpt_device;
/* UMC */
extern const device_t umc_8886f_device;
extern const device_t umc_8886af_device;
extern const device_t umc_8886bf_device;
extern const device_t umc_8890_device;
extern const device_t umc_hb4_device;
/* VIA */

View File

@@ -41,23 +41,41 @@
#ifndef EMU_DEVICE_H
#define EMU_DEVICE_H
#define CONFIG_END -1
#define CONFIG_STRING 0
#define CONFIG_INT 1
#define CONFIG_BINARY 2
#define CONFIG_SELECTION 3
#define CONFIG_MIDI_OUT 4
#define CONFIG_FNAME 5
#define CONFIG_SPINNER 6
#define CONFIG_HEX16 7
#define CONFIG_HEX20 8
#define CONFIG_MAC 9
#define CONFIG_MIDI_IN 10
#define CONFIG_BIOS 11
#define CONFIG_SERPORT 12
#define CONFIG_END -1 /* N/A */
#define CONFIG_ONBOARD 256 /* only avaialble on the on-board variant */
#define CONFIG_STANDALONE 257 /* not available on the on-board variant */
#define CONFIG_SHIFT 4
#define CONFIG_TYPE_INT (0 << CONFIG_SHIFT)
#define CONFIG_TYPE_STRING (1 << CONFIG_SHIFT)
#define CONFIG_TYPE_HEX16 (2 << CONFIG_SHIFT)
#define CONFIG_TYPE_HEX20 (3 << CONFIG_SHIFT)
#define CONFIG_TYPE_MAC (4 << CONFIG_SHIFT)
#define CONFIG_INT (0 | CONFIG_TYPE_INT) /* config_get_int() */
#define CONFIG_BINARY (1 | CONFIG_TYPE_INT) /* config_get_int() */
#define CONFIG_SELECTION (2 | CONFIG_TYPE_INT) /* config_get_int() */
#define CONFIG_MIDI_OUT (3 | CONFIG_TYPE_INT) /* config_get_int() */
#define CONFIG_SPINNER (4 | CONFIG_TYPE_INT) /* config_get_int() */
#define CONFIG_MIDI_IN (5 | CONFIG_TYPE_INT) /* config_get_int() */
#define CONFIG_STRING (0 | CONFIG_TYPE_STRING) /* config_get_string() */
#define CONFIG_FNAME (1 | CONFIG_TYPE_STRING) /* config_get_string() */
#define CONFIG_SERPORT (2 | CONFIG_TYPE_STRING) /* config_get_string() */
#define CONFIG_BIOS (3 | CONFIG_TYPE_STRING) /* config_get_string() */
#define CONFIG_HEX16 (0 | CONFIG_TYPE_HEX16) /* config_get_hex16() */
#define CONFIG_HEX20 (0 | CONFIG_TYPE_HEX20) /* config_get_hex20() */
#define CONFIG_MAC (0 | CONFIG_TYPE_MAC) /* N/A */
#define CONFIG_SUBTYPE_MASK (CONFIG_IS_STRING - 1)
#define CONFIG_DEP (16 << CONFIG_SHIFT)
#define CONFIG_TYPE_MASK (CONFIG_DEP - 1)
// #define CONFIG_ONBOARD 256 /* only avaialble on the on-board variant */
// #define CONFIG_STANDALONE 257 /* not available on the on-board variant */
enum {
DEVICE_PCJR = 2, /* requires an IBM PCjr */
@@ -100,38 +118,49 @@ enum {
#define BIOS_INTERLEAVED_INVERT 8
#define BIOS_HIGH_BIT_INVERT 16
#define device_common_config_t \
const char *name; \
const char *description; \
int type; \
const char *default_string; \
int default_int; \
const char *file_filter; \
const device_config_spinner_t spinner; \
const device_config_selection_t selection[32]
typedef struct device_config_selection_t {
const char *description;
int value;
} device_config_selection_t;
typedef struct device_config_bios_t {
const char *name;
const char *internal_name;
int bios_type;
int files_no;
uint32_t local;
uint32_t size;
void *dev1;
void *dev2;
const char *files[9];
} device_config_bios_t;
typedef struct device_config_spinner_t {
int16_t min;
int16_t max;
int16_t step;
} device_config_spinner_t;
typedef struct device_config_t {
const char *name;
const char *description;
int type;
const char *default_string;
int default_int;
const char *file_filter;
const device_config_spinner_t spinner;
const device_config_selection_t selection[32];
typedef struct _device_dep_config_ {
device_common_config_t;
} device_dep_config_t;
typedef struct device_config_bios_t {
const char *name;
const char *internal_name;
int bios_type;
int files_no;
uint32_t local;
uint32_t size;
void *dev1;
void *dev2;
const char *files[9];
/* Configuration options that depend on the device variant.
To prevent excessive nesting, there is no CONFIG_BIOS
option a dep_config struct */
const device_dep_config_t *dep_config;
} device_config_bios_t;
typedef struct _device_config_ {
device_common_config_t;
const device_config_bios_t bios[32];
} device_config_t;
@@ -173,6 +202,7 @@ extern void device_context(const device_t *dev);
extern void device_context_inst(const device_t *dev, int inst);
extern void device_context_restore(void);
extern void *device_add(const device_t *d);
extern void *device_add_linked(const device_t *d, void *priv);
extern void *device_add_parameters(const device_t *dev, void *params);
extern void device_add_ex(const device_t *dev, void *priv);
extern void device_add_ex_parameters(const device_t *dev, void *priv, void *params);
@@ -188,6 +218,7 @@ extern void *device_cadd_inst(const device_t *dev, const device_t *cd, int inst)
extern void *device_cadd_inst_parameters(const device_t *dev, const device_t *cd, int inst, void *params);
extern void device_cadd_inst_ex(const device_t *dev, const device_t *cd, void *priv, int inst);
extern void device_cadd_inst_ex_parameters(const device_t *dev, const device_t *cd, void *priv, int inst, void *params);
extern void *device_get_common_priv(void);
extern void device_close_all(void);
extern void device_reset_all(uint32_t match_flags);
extern void *device_find_first_priv(uint32_t match_flags);

View File

@@ -60,4 +60,6 @@ extern const device_t sst_flash_49lf080_device;
extern const device_t sst_flash_49lf016_device;
extern const device_t sst_flash_49lf160_device;
extern const device_t amd_flash_29f020a_device;
#endif /*EMU_FLASH_H*/

View File

@@ -24,6 +24,10 @@
#define MAX_PLAT_JOYSTICKS 8
#define MAX_JOYSTICKS 4
#define MAX_JOY_AXES 16
#define MAX_JOY_BUTTONS 32
#define MAX_JOY_POVS 4
#define JS_TYPE_NONE 0
#define JS_TYPE_2AXIS_4BUTTON 1
#define JS_TYPE_2AXIS_6BUTTON 2
@@ -36,7 +40,6 @@
#define POV_X 0x80000000
#define POV_Y 0x40000000
#define SLIDER 0x20000000
#define AXIS_NOT_PRESENT -99999
@@ -47,46 +50,39 @@
typedef struct plat_joystick_t {
char name[260];
int a[8];
int b[32];
int p[4];
int s[2];
int a[MAX_JOY_AXES];
int b[MAX_JOY_BUTTONS];
int p[MAX_JOY_POVS];
struct {
char name[260];
int id;
} axis[8];
} axis[MAX_JOY_AXES];
struct {
char name[260];
int id;
} button[32];
} button[MAX_JOY_BUTTONS];
struct {
char name[260];
int id;
} pov[4];
struct {
char name[260];
int id;
} slider[2];
} pov[MAX_JOY_POVS];
int nr_axes;
int nr_buttons;
int nr_povs;
int nr_sliders;
} plat_joystick_t;
typedef struct joystick_t {
int axis[8];
int button[32];
int pov[4];
int axis[MAX_JOY_AXES];
int button[MAX_JOY_BUTTONS];
int pov[MAX_JOY_POVS];
int plat_joystick_nr;
int axis_mapping[8];
int button_mapping[32];
int pov_mapping[4][2];
int axis_mapping[MAX_JOY_AXES];
int button_mapping[MAX_JOY_BUTTONS];
int pov_mapping[MAX_JOY_POVS][2];
} joystick_t;
typedef struct joystick_if_t {
@@ -104,9 +100,9 @@ typedef struct joystick_if_t {
int button_count;
int pov_count;
int max_joysticks;
const char *axis_names[8];
const char *button_names[32];
const char *pov_names[4];
const char *axis_names[MAX_JOY_AXES];
const char *button_names[MAX_JOY_BUTTONS];
const char *pov_names[MAX_JOY_POVS];
} joystick_if_t;
#ifdef __cplusplus
@@ -158,6 +154,19 @@ extern void gameport_update_joystick_type(void);
extern void gameport_remap(void *priv, uint16_t address);
extern void *gameport_add(const device_t *gameport_type);
extern const joystick_if_t joystick_2axis_2button;
extern const joystick_if_t joystick_2axis_4button;
extern const joystick_if_t joystick_3axis_2button;
extern const joystick_if_t joystick_3axis_4button;
extern const joystick_if_t joystick_4axis_4button;
extern const joystick_if_t joystick_2axis_6button;
extern const joystick_if_t joystick_2axis_8button;
extern const joystick_if_t joystick_ch_flightstick_pro;
extern const joystick_if_t joystick_sw_pad;
extern const joystick_if_t joystick_tm_fcs;
#ifdef __cplusplus
}
#endif

View File

@@ -77,8 +77,16 @@ extern const device_t ide_cmd646_device; /* CMD PCI-646 *
extern const device_t ide_cmd646_legacy_only_device; /* CMD PCI-646 (Legacy Mode Only) */
extern const device_t ide_cmd646_single_channel_device; /* CMD PCI-646 (Only primary channel) */
extern const device_t ide_opti611_vlb_device; /* OPTi 82c611/611A VLB */
extern const device_t ide_opti611_vlb_sec_device; /* OPTi 82c611/611A VLB (Secondary channel) */
extern const device_t ide_opti611_vlb_device; /* OPTi 82c611/611A VLB */
extern const device_t ide_opti611_vlb_sec_device; /* OPTi 82c611/611A VLB (Secondary channel) */
extern const device_t ide_um8673f_device; /* UMC UM8673F */
extern const device_t ide_um8886af_device; /* UMC UM8886AF */
extern const device_t ide_w83769f_vlb_device; /* Winbond W83769F VLB */
extern const device_t ide_w83769f_vlb_34_device; /* Winbond W83769F VLB (Port 34h) */
extern const device_t ide_w83769f_pci_device; /* Winbond W83769F PCI */
extern const device_t ide_w83769f_pci_34_device; /* Winbond W83769F PCI (Port 34h) */
extern const device_t ide_ter_device;
extern const device_t ide_ter_pnp_device;
@@ -89,9 +97,7 @@ extern const device_t xta_wdxt150_device; /* xta_wdxt150 */
extern const device_t xta_hd20_device; /* EuroPC internal */
extern const device_t xtide_device; /* xtide_xt */
extern const device_t xtide_plus_device; /* xtide_xt_plus */
extern const device_t xtide_at_device; /* xtide_at */
extern const device_t xtide_at_386_device; /* xtide_at_386 */
extern const device_t xtide_acculogic_device; /* xtide_ps2 */
extern const device_t xtide_at_ps2_device; /* xtide_at_ps2 */

View File

@@ -43,6 +43,7 @@ typedef struct sff8038i_t
uint8_t irq_state;
uint8_t channel;
uint8_t irq_line;
uint8_t mirq;
uint16_t base;
uint16_t pad;
uint32_t ptr;
@@ -72,10 +73,9 @@ extern void sff_bus_master_reset(sff8038i_t *dev);
extern void sff_set_slot(sff8038i_t *dev, int slot);
extern void sff_set_irq_line(sff8038i_t *dev, int irq_line);
extern void sff_set_irq_mode(sff8038i_t *dev, int irq_mode);
extern void sff_set_irq_pin(sff8038i_t *dev, int irq_pin);
extern void sff_set_irq_level(sff8038i_t *dev, int irq_level);
extern void sff_set_mirq(sff8038i_t *dev, uint8_t mirq);
#endif /*EMU_HDC_IDE_SFF8038I_H*/

View File

@@ -1,43 +0,0 @@
/*
* 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.
*
* Definitions for the Flight Stick Pro driver.
*
*
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Sarah Walker, <https://pcem-emulator.co.uk/>
*
* Copyright 2016-2018 Miran Grca.
* Copyright 2008-2018 Sarah Walker.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the:
*
* Free Software Foundation, Inc.
* 59 Temple Place - Suite 330
* Boston, MA 02111-1307
* USA.
*/
#ifndef EMU_JOYSTICK_CH_FLIGHTSTICK_PRO_H
#define EMU_JOYSTICK_CH_FLIGHTSTICK_PRO_H
extern const joystick_if_t joystick_ch_flightstick_pro;
#endif /*EMU_JOYSTICK_CH_FLIGHTSTICK_PRO_H*/

View File

@@ -1,49 +0,0 @@
/*
* 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.
*
* Definitions for the joystick driver.
*
*
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Sarah Walker, <https://pcem-emulator.co.uk/>
*
* Copyright 2016-2018 Miran Grca.
* Copyright 2008-2018 Sarah Walker.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the:
*
* Free Software Foundation, Inc.
* 59 Temple Place - Suite 330
* Boston, MA 02111-1307
* USA.
*/
#ifndef EMU_JOYSTICK_STANDARD_H
#define EMU_JOYSTICK_STANDARD_H
extern const joystick_if_t joystick_2axis_2button;
extern const joystick_if_t joystick_2axis_4button;
extern const joystick_if_t joystick_3axis_2button;
extern const joystick_if_t joystick_3axis_4button;
extern const joystick_if_t joystick_4axis_4button;
extern const joystick_if_t joystick_2axis_6button;
extern const joystick_if_t joystick_2axis_8button;
#endif /*EMU_JOYSTICK_STANDARD_H*/

View File

@@ -1,43 +0,0 @@
/*
* 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.
*
* Definitions for the Sidewinder Pro driver.
*
*
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Sarah Walker, <https://pcem-emulator.co.uk/>
*
* Copyright 2016-2018 Miran Grca.
* Copyright 2008-2018 Sarah Walker.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the:
*
* Free Software Foundation, Inc.
* 59 Temple Place - Suite 330
* Boston, MA 02111-1307
* USA.
*/
#ifndef EMU_JOYSTICK_SW_PAD_H
#define EMU_JOYSTICK_SW_PAD_H
extern const joystick_if_t joystick_sw_pad;
#endif /*EMU_JOYSTICK_SW_PAD_H*/

View File

@@ -1,43 +0,0 @@
/*
* 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.
*
* Definitions for the Flight Control System driver.
*
*
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Sarah Walker, <https://pcem-emulator.co.uk/>
*
* Copyright 2016-2018 Miran Grca.
* Copyright 2008-2018 Sarah Walker.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the:
*
* Free Software Foundation, Inc.
* 59 Temple Place - Suite 330
* Boston, MA 02111-1307
* USA.
*/
#ifndef EMU_JOYSTICK_TM_FCS_H
#define EMU_JOYSTICK_TM_FCS_H
extern const joystick_if_t joystick_tm_fcs;
#endif /*EMU_JOYSTICK_TM_FCS_H*/

View File

@@ -79,6 +79,7 @@ typedef struct atkbc_dev_t {
int y;
int z;
int b;
int ignore;
int *scan;

View File

@@ -97,7 +97,6 @@
#define IDS_2108 2108 // "%u MB (CHS: %i, %i, %i)"
#define IDS_2109 2109 // "Floppy %i (%s): %ls"
#define IDS_2110 2110 // "All floppy images (*.0??;*.."
#define IDS_2112 2112 // "Unable to initialize SDL..."
#define IDS_2113 2113 // "Are you sure you want to..."
#define IDS_2114 2114 // "Are you sure you want to..."
#define IDS_2115 2115 // "Unable to initialize Ghostscript..."

Some files were not shown because too many files have changed in this diff Show More