mirror of
https://github.com/86Box/86Box.git
synced 2026-02-24 02:18:20 -07:00
Merge branch 'master' of ssh://github.com/86Box/86Box into feature/mtrr
# Conflicts: # src/include/86box/machine.h # src/machine/machine_table.c # src/mem/mem.c
This commit is contained in:
@@ -10,8 +10,6 @@
|
||||
# settings, so we can avoid changing the main one for all of
|
||||
# our local setups.
|
||||
#
|
||||
# Version: @(#)Makefile.local 1.0.22 2019/10/20
|
||||
#
|
||||
# Author: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
#
|
||||
|
||||
@@ -35,15 +33,21 @@ STUFF :=
|
||||
# -DENABLE_VRAM_DUMP enables Video Ram dumping.
|
||||
# -DENABLE_LOG_BREAKPOINT enables extra logging.
|
||||
# Root logging:
|
||||
# -DENABLE_ACPI_LOG=N sets logging level at N.
|
||||
# -DENABLE_APM_LOG=N sets logging level at N.
|
||||
# -DENABLE_BUGGER_LOG=N sets logging level at N.
|
||||
# -DENABLE_CONFIG_LOG=N sets logging level at N.
|
||||
# -DENABLE_DDMA_LOG=N sets logging level at N.
|
||||
# -DENABLE_DEVICE_LOG=N sets logging level at N.
|
||||
# -DENABLE_DMA_LOG=N sets logging level at N.
|
||||
# -DENABLE_IO_LOG=N sets logging level at N.
|
||||
# -DENABLE_PIIX_LOG=N sets logging level at N.
|
||||
# -DENABLE_IOAPIC_LOG=N sets logging level at N.
|
||||
# -DENABLE_ISAMEM_LOG=N sets logging level at N.
|
||||
# -DENABLE_ISARTC_LOG=N sets logging level at N.
|
||||
# -DENABLE_KEYBOARD_AT_LOG=N sets logging level at N.
|
||||
# -DENABLE_KEYBOARD_XT_LOG=N sets logging level at N.
|
||||
# -DENABLE_LM75_LOG=N sets logging level at N.
|
||||
# -DENABLE_LM78_LOG=N sets logging level at N.
|
||||
# -DENABLE_MEM_LOG=N sets logging level at N.
|
||||
# -DENABLE_MOUSE_LOG=N sets logging level at N.
|
||||
# -DENABLE_MOUSE_BUS_LOG=N sets logging level at N.
|
||||
@@ -53,30 +57,41 @@ STUFF :=
|
||||
# -DENABLE_PC_LOG=N sets logging level at N.
|
||||
# -DENABLE_PCI_LOG=N sets logging level at N.
|
||||
# -DENABLE_PIC_LOG=N sets logging level at N.
|
||||
# -DENABLE_PIT_LOG=N sets logging level at N.
|
||||
# -DENABLE_POSTCARD_LOG=N sets logging level at N.
|
||||
# -DENABLE_ROM_LOG=N sets logging level at N.
|
||||
# -DENABLE_SERIAL_LOG=N sets logging level at N.
|
||||
# -DENABLE_SMBUS_LOG=N sets logging level at N.
|
||||
# -DENABLE_SMBUS_PIIX4_LOG=N sets logging level at N.
|
||||
# -DENABLE_SPD_LOG=N sets logging level at N.
|
||||
# -DENABLE_USB_LOG=N sets logging level at N.
|
||||
# -DENABLE_VNC_LOG=N sets logging level at N.
|
||||
# -DENABLE_VNC_KEYMAP_LOG=N sets logging level at N.
|
||||
# cdrom/ logging:
|
||||
# -DENABLE_CDROM_LOG=N sets logging level at N.
|
||||
# -DENABLE_CDROM_DOSBOX_LOG=N sets logging level at N.
|
||||
# -DENABLE_CDROM_IMAGE_LOG=N sets logging level at N.
|
||||
# -DENABLE_CDROM_IMAGE_BACKEND_LOG=N sets logging level at N.
|
||||
# chipset/ logging:
|
||||
# -DENABLE_I420EX_LOG=N sets logging level at N.
|
||||
# -DENABLE_NEAT_LOG=N sets logging level at N.
|
||||
# -DENABLE_PIIX_LOG=N sets logging level at N.
|
||||
# -DENABLE_SIO_LOG=N sets logging level at N.
|
||||
# codegen/, codegen_new/, cpu/ logging:
|
||||
# -DENABLE_X86SEG_LOG=N sets logging level at N.
|
||||
# cpu/ logging:
|
||||
# -DENABLE_386_LOG=N sets logging level at N.
|
||||
# -DENABLE_386_COMMON_LOG=N sets logging level at N.
|
||||
# -DENABLE_386_DYNAREC_LOG=N sets logging level at N.
|
||||
# -DENABLE_808X_LOG=N sets logging level at N.
|
||||
# -DENABLE_CPU_LOG=N sets logging level at N.
|
||||
# -DENABLE_FPU_LOG=N sets logging level at N.
|
||||
# -DENABLE_X86SEG_LOG=N sets logging level at N.
|
||||
# cpu_new/ logging:
|
||||
# -DENABLE_386_COMMON_LOG=N sets logging level at N.
|
||||
# chipset/ logging:
|
||||
# -DENABLE_NEAT_LOG=N sets logging level at N.
|
||||
# disk/ logging:
|
||||
# -DENABLE_ESDI_AT_LOG=N sets logging level at N.
|
||||
# -DENABLE_ESDI_MCA_LOG=N sets logging level at N.
|
||||
# -DENABLE_HDC_LOG=N sets logging level at N.
|
||||
# -DENABLE_HDD_IMAGE_LOG=N sets logging level at N.
|
||||
# -DENABLE_IDE_LOG=N sets logging level at N.
|
||||
# -DENABLE_MO_LOG=N sets logging level at N.
|
||||
# -DENABLE_SFF_LOG=N sets logging level at N.
|
||||
# -DENABLE_ST506_AT_LOG=N sets logging level at N.
|
||||
# -DENABLE_ST506_XT_LOG=N sets logging level at N.
|
||||
@@ -109,15 +124,19 @@ STUFF :=
|
||||
# -DENABLE_NETWORK_LOG=N sets logging level at N.
|
||||
# -DENABLE_NIC_LOG=N sets logging level at N.
|
||||
# -DENABLE_PCAP_LOG=N sets logging level at N.
|
||||
# -DENABLE_PCNET_LOG=N sets logging level at N.
|
||||
# -DENABLE_SLIRP_LOG=N sets logging level at N.
|
||||
# -DENABLE_WD_LOG=N sets logging level at N.
|
||||
# printer/ logging:
|
||||
# -DENABLE_ESCP_LOG=N sets logging level at N.
|
||||
# scsi/ logging:
|
||||
# -DENABLE_AHA154X_LOG=N sets logging level at N.
|
||||
# -DENABLE_BUSLOGIC_LOG=N sets logging level at N.
|
||||
# -DENABLE_SCSI_CDROM_LOG=N sets logging level at N.
|
||||
# -DENABLE_SCSI_DISK_LOG=N sets logging level at N.
|
||||
# -DENABLE_NCR5380_LOG=N sets logging level at N.
|
||||
# -DENABLE_NCR53C8XX_LOG=N sets logging level at N.
|
||||
# -DENABLE_SCSI_CDROM_LOG=N sets logging level at N.
|
||||
# -DENABLE_SCSI_DISK_LOG=N sets logging level at N.
|
||||
# -DENABLE_SPOCK_LOG=N sets logging level at N.
|
||||
# -DENABLE_X54X_LOG=N sets logging level at N.
|
||||
# sound/ logging:
|
||||
# -DENABLE_ADLIB_LOG=N sets logging level at N.
|
||||
@@ -139,15 +158,13 @@ STUFF :=
|
||||
# -DENABLE_PGC_LOG=N sets logging level at N.
|
||||
# -DENABLE_S3_VIRGE_LOG=N sets logging level at N.
|
||||
# -DENABLE_VID_TABLE_LOG=N sets logging level at N.
|
||||
# -DENABLE_VIDEO_LOG=N sets logging level at N.
|
||||
# -DENABLE_VOODOO_LOG=N sets logging level at N.
|
||||
# -DENABLE_VRAM_DUMP=N sets logging level at N.
|
||||
# win/ logging:
|
||||
# -DENABLE_WIN_LOG=N sets logging level at N.
|
||||
# -DENABLE_D2D_LOG=N sets logging level at N.
|
||||
# -DENABLE_DDRAW_LOG=N sets logging level at N.
|
||||
# -DENABLE_DISCORD_LOG=N sets logging level at N.
|
||||
# -DENABLE_DYNLD_LOG=N sets logging level at N.
|
||||
# -DENABLE_JOYSTICK_LOG=N sets logging level at N.
|
||||
# -DENABLE_LOG_BREAKPOINT=N sets logging level at N.
|
||||
# -DENABLE_LOG_TOGGLES=N sets logging level at N.
|
||||
# -DENABLE_SDL_LOG=N sets logging level at N.
|
||||
# -DENABLE_SETTINGS_LOG=N sets logging level at N.
|
||||
|
||||
@@ -125,8 +125,10 @@ acpi_reg_read_intel(int size, uint16_t addr, void *p)
|
||||
case 0x08: case 0x09: case 0x0a: case 0x0b:
|
||||
/* PMTMR - Power Management Timer Register (IO) */
|
||||
ret = (dev->regs.timer_val >> shift32) & 0xff;
|
||||
#ifdef USE_DYNAREC
|
||||
if (cpu_use_dynarec)
|
||||
update_tsc();
|
||||
#endif
|
||||
break;
|
||||
case 0x0c: case 0x0d:
|
||||
/* GPSTS - General Purpose Status Register (IO) */
|
||||
@@ -213,8 +215,10 @@ acpi_reg_read_via(int size, uint16_t addr, void *p)
|
||||
case 0x08: case 0x09: case 0x0a: case 0x0b:
|
||||
/* PMTMR - Power Management Timer Register (IO) */
|
||||
ret = (dev->regs.timer_val >> shift32) & 0xff;
|
||||
#ifdef USE_DYNAREC
|
||||
if (cpu_use_dynarec)
|
||||
update_tsc();
|
||||
#endif
|
||||
break;
|
||||
case 0x10: case 0x11: case 0x12: case 0x13:
|
||||
/* PCNTRL - Processor Control Register (IO) */
|
||||
|
||||
@@ -27,12 +27,14 @@
|
||||
#include <86box/cdrom.h>
|
||||
#include <86box/cdrom_image.h>
|
||||
#include <86box/plat.h>
|
||||
#include <86box/scsi_device.h>
|
||||
#include <86box/sound.h>
|
||||
|
||||
|
||||
/* The addresses sent from the guest are absolute, ie. a LBA of 0 corresponds to a MSF of 00:00:00. Otherwise, the counter displayed by the guest is wrong:
|
||||
there is a seeming 2 seconds in which audio plays but counter does not move, while a data track before audio jumps to 2 seconds before the actual start
|
||||
of the audio while audio still plays. With an absolute conversion, the counter is fine. */
|
||||
#undef MSFtoLBA
|
||||
#define MSFtoLBA(m,s,f) ((((m*60)+s)*75)+f)
|
||||
|
||||
#define RAW_SECTOR_SIZE 2352
|
||||
@@ -1171,6 +1173,9 @@ cdrom_close(void)
|
||||
for (i = 0; i < CDROM_NUM; i++) {
|
||||
dev = &cdrom[i];
|
||||
|
||||
if (dev->bus_type == CDROM_BUS_SCSI)
|
||||
memset(&scsi_devices[dev->scsi_device_id], 0x00, sizeof(scsi_device_t));
|
||||
|
||||
if (dev->close)
|
||||
dev->close(dev->priv);
|
||||
|
||||
|
||||
@@ -83,14 +83,14 @@ bin_read(void *p, uint8_t *buffer, uint64_t seek, size_t count)
|
||||
return 0;
|
||||
|
||||
if (fseeko64(tf->file, seek, SEEK_SET) == -1) {
|
||||
#ifdef ENABLE_cdrom_image_backend_log
|
||||
#ifdef ENABLE_CDROM_IMAGE_BACKEND_LOG
|
||||
cdrom_image_backend_log("CDROM: binary_read failed during seek!\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (fread(buffer, count, 1, tf->file) != 1) {
|
||||
#ifdef ENABLE_cdrom_image_backend_log
|
||||
#ifdef ENABLE_CDROM_IMAGE_BACKEND_LOG
|
||||
cdrom_image_backend_log("CDROM: binary_read failed during read!\n");
|
||||
#endif
|
||||
return 0;
|
||||
@@ -953,7 +953,7 @@ cdi_load_cue(cd_img_t *cdi, const wchar_t *cuefile)
|
||||
trk.file = track_file_init(filename, &error);
|
||||
}
|
||||
if (error) {
|
||||
#ifdef ENABLE_cdrom_image_backend_log
|
||||
#ifdef ENABLE_CDROM_IMAGE_BACKEND_LOG
|
||||
cdrom_image_backend_log("CUE: cannot open fille '%ls' in cue sheet!\n",
|
||||
filename);
|
||||
#endif
|
||||
@@ -971,7 +971,7 @@ cdi_load_cue(cd_img_t *cdi, const wchar_t *cuefile)
|
||||
/* Ignored commands. */
|
||||
success = 1;
|
||||
} else {
|
||||
#ifdef ENABLE_cdrom_image_backend_log
|
||||
#ifdef ENABLE_CDROM_IMAGE_BACKEND_LOG
|
||||
cdrom_image_backend_log("CUE: unsupported command '%s' in cue sheet!\n",
|
||||
command.c_str());
|
||||
#endif
|
||||
|
||||
@@ -142,6 +142,11 @@ static void
|
||||
cs8230_write, NULL, NULL,
|
||||
cs8230);
|
||||
|
||||
if (mem_size > 768) {
|
||||
mem_mapping_set_addr(&ram_mid_mapping, 0xa0000, mem_size > 1024 ? 0x60000 : 0x20000 + (mem_size - 768) * 1024);
|
||||
mem_mapping_set_exec(&ram_mid_mapping, ram + 0xa0000);
|
||||
}
|
||||
|
||||
return cs8230;
|
||||
}
|
||||
|
||||
|
||||
573
src/chipset/intel_420ex.c
Normal file
573
src/chipset/intel_420ex.c
Normal file
@@ -0,0 +1,573 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Emulation of Intel 82420EX chipset that acts as both the
|
||||
* northbridge and the southbridge.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2020 Miran Grca.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/apm.h>
|
||||
#include <86box/dma.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/pci.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/pit.h>
|
||||
#include <86box/port_92.h>
|
||||
#include <86box/hdc_ide.h>
|
||||
#include <86box/hdc.h>
|
||||
#include <86box/machine.h>
|
||||
#include <86box/chipset.h>
|
||||
|
||||
|
||||
#define MEM_STATE_SHADOW_R 0x01
|
||||
#define MEM_STATE_SHADOW_W 0x02
|
||||
#define MEM_STATE_SMRAM 0x04
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t id, smram_locked,
|
||||
regs[256];
|
||||
|
||||
uint16_t timer_base,
|
||||
timer_latch;
|
||||
|
||||
double fast_off_period;
|
||||
|
||||
pc_timer_t timer, fast_off_timer;
|
||||
|
||||
apm_t * apm;
|
||||
port_92_t * port_92;
|
||||
} i420ex_t;
|
||||
|
||||
|
||||
#ifdef ENABLE_I420EX_LOG
|
||||
int i420ex_do_log = ENABLE_I420EX_LOG;
|
||||
|
||||
|
||||
static void
|
||||
i420ex_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (i420ex_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define i420ex_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
i420ex_map(uint32_t addr, uint32_t size, int state)
|
||||
{
|
||||
switch (state & 3) {
|
||||
case 0:
|
||||
mem_set_mem_state_both(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
|
||||
break;
|
||||
case 1:
|
||||
mem_set_mem_state_both(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY);
|
||||
break;
|
||||
case 2:
|
||||
mem_set_mem_state_both(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
|
||||
break;
|
||||
case 3:
|
||||
mem_set_mem_state_both(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
|
||||
break;
|
||||
}
|
||||
flushmmucache_nopc();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
i420ex_smram_map(int smm, uint32_t addr, uint32_t size, int is_smram)
|
||||
{
|
||||
mem_set_mem_state_smram(smm, addr, size, is_smram);
|
||||
flushmmucache();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
i420ex_smram_handler_phase0(void)
|
||||
{
|
||||
/* Disable low extended SMRAM. */
|
||||
if (smram[0].size != 0x00000000) {
|
||||
i420ex_smram_map(0, smram[0].host_base, smram[0].size, 0);
|
||||
i420ex_smram_map(1, smram[0].host_base, smram[0].size, 0);
|
||||
|
||||
memset(&smram[0], 0x00, sizeof(smram_t));
|
||||
mem_mapping_disable(&ram_smram_mapping[0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
i420ex_smram_handler_phase1(i420ex_t *dev)
|
||||
{
|
||||
uint8_t *regs = (uint8_t *) dev->regs;
|
||||
|
||||
uint32_t base = 0x000a0000;
|
||||
uint32_t size = 0x00010000;
|
||||
|
||||
switch (regs[0x70] & 0x07) {
|
||||
case 0: case 1:
|
||||
default:
|
||||
base = size = 0x00000000;
|
||||
break;
|
||||
case 2:
|
||||
base = 0x000a0000;
|
||||
smram[0].host_base = 0x000a0000;
|
||||
smram[0].ram_base = 0x000a0000;
|
||||
break;
|
||||
case 3:
|
||||
base = 0x000b0000;
|
||||
smram[0].host_base = 0x000b0000;
|
||||
smram[0].ram_base = 0x000b0000;
|
||||
break;
|
||||
case 4:
|
||||
base = 0x000c0000;
|
||||
smram[0].host_base = 0x000c0000;
|
||||
smram[0].ram_base = 0x000a0000;
|
||||
break;
|
||||
case 5:
|
||||
base = 0x000d0000;
|
||||
smram[0].host_base = 0x000d0000;
|
||||
smram[0].ram_base = 0x000a0000;
|
||||
break;
|
||||
case 6:
|
||||
base = 0x000e0000;
|
||||
smram[0].host_base = 0x000e0000;
|
||||
smram[0].ram_base = 0x000a0000;
|
||||
break;
|
||||
case 7:
|
||||
base = 0x000f0000;
|
||||
smram[0].host_base = 0x000f0000;
|
||||
smram[0].ram_base = 0x000a0000;
|
||||
break;
|
||||
}
|
||||
|
||||
smram[0].size = size;
|
||||
|
||||
if (size != 0x00000000) {
|
||||
mem_mapping_set_addr(&ram_smram_mapping[0], smram[0].host_base, 0x00010000);
|
||||
mem_mapping_set_exec(&ram_smram_mapping[0], ram + smram[0].ram_base);
|
||||
|
||||
/* If OSS = 1 and LSS = 0, extended SMRAM is visible outside SMM. */
|
||||
i420ex_smram_map(0, base, size, (regs[0x70] & 0x70) == 0x40);
|
||||
|
||||
/* If the register is set accordingly, disable the mapping also in SMM. */
|
||||
i420ex_smram_map(1, base, size, !(regs[0x70] & 0x20));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
i420ex_write(int func, int addr, uint8_t val, void *priv)
|
||||
{
|
||||
i420ex_t *dev = (i420ex_t *) priv;
|
||||
|
||||
if (func > 0)
|
||||
return;
|
||||
|
||||
if (((addr >= 0x0f) && (addr < 0x4c)) && (addr != 0x40))
|
||||
return;
|
||||
|
||||
/* The IB (original) variant of the I420EX has no PCI IRQ steering. */
|
||||
if ((addr >= 0x60) && (addr <= 0x63) && (dev->id < 0x03))
|
||||
return;
|
||||
|
||||
switch (addr) {
|
||||
case 0x05:
|
||||
dev->regs[addr] = (val & 0x01);
|
||||
break;
|
||||
|
||||
case 0x07:
|
||||
dev->regs[addr] &= ~(val & 0xf0);
|
||||
break;
|
||||
|
||||
case 0x40:
|
||||
dev->regs[addr] = (val & 0x7f);
|
||||
break;
|
||||
case 0x44:
|
||||
dev->regs[addr] = (val & 0x07);
|
||||
break;
|
||||
case 0x48:
|
||||
dev->regs[addr] = (val & 0x3f);
|
||||
#ifdef USE_420EX_IDE
|
||||
ide_pri_disable();
|
||||
switch (val & 0x03) {
|
||||
case 0x01:
|
||||
ide_set_base(0, 0x01f0);
|
||||
ide_set_side(0, 0x03f6);
|
||||
ide_pri_enable();
|
||||
break;
|
||||
case 0x02:
|
||||
ide_set_base(0, 0x0170);
|
||||
ide_set_side(0, 0x0376);
|
||||
ide_pri_enable();
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case 0x49: case 0x53:
|
||||
dev->regs[addr] = (val & 0x1f);
|
||||
break;
|
||||
case 0x4c: case 0x51:
|
||||
case 0x57:
|
||||
case 0x60: case 0x61: case 0x62: case 0x63:
|
||||
case 0x64:
|
||||
case 0x68: case 0x69:
|
||||
dev->regs[addr] = val;
|
||||
if (addr == 0x4c) {
|
||||
dma_alias_remove();
|
||||
if (!(val & 0x80))
|
||||
dma_alias_set();
|
||||
}
|
||||
break;
|
||||
case 0x4d:
|
||||
dev->regs[addr] = (dev->regs[addr] & 0xef) | (val & 0x10);
|
||||
break;
|
||||
case 0x4e:
|
||||
dev->regs[addr] = (val & 0xf7);
|
||||
break;
|
||||
case 0x50:
|
||||
dev->regs[addr] = (val & 0x0f);
|
||||
break;
|
||||
case 0x52:
|
||||
dev->regs[addr] = (val & 0x7f);
|
||||
break;
|
||||
case 0x56:
|
||||
dev->regs[addr] = (val & 0x3e);
|
||||
break;
|
||||
case 0x59: /* PAM0 */
|
||||
if ((dev->regs[0x59] ^ val) & 0xf0) {
|
||||
i420ex_map(0xf0000, 0x10000, val >> 4);
|
||||
shadowbios = (val & 0x10);
|
||||
}
|
||||
dev->regs[0x59] = val & 0xf0;
|
||||
break;
|
||||
case 0x5a: /* PAM1 */
|
||||
if ((dev->regs[0x5a] ^ val) & 0x0f)
|
||||
i420ex_map(0xc0000, 0x04000, val & 0xf);
|
||||
if ((dev->regs[0x5a] ^ val) & 0xf0)
|
||||
i420ex_map(0xc4000, 0x04000, val >> 4);
|
||||
dev->regs[0x5a] = val;
|
||||
break;
|
||||
case 0x5b: /*PAM2 */
|
||||
if ((dev->regs[0x5b] ^ val) & 0x0f)
|
||||
i420ex_map(0xc8000, 0x04000, val & 0xf);
|
||||
if ((dev->regs[0x5b] ^ val) & 0xf0)
|
||||
i420ex_map(0xcc000, 0x04000, val >> 4);
|
||||
dev->regs[0x5b] = val;
|
||||
break;
|
||||
case 0x5c: /*PAM3 */
|
||||
if ((dev->regs[0x5c] ^ val) & 0x0f)
|
||||
i420ex_map(0xd0000, 0x04000, val & 0xf);
|
||||
if ((dev->regs[0x5c] ^ val) & 0xf0)
|
||||
i420ex_map(0xd4000, 0x04000, val >> 4);
|
||||
dev->regs[0x5c] = val;
|
||||
break;
|
||||
case 0x5d: /* PAM4 */
|
||||
if ((dev->regs[0x5d] ^ val) & 0x0f)
|
||||
i420ex_map(0xd8000, 0x04000, val & 0xf);
|
||||
if ((dev->regs[0x5d] ^ val) & 0xf0)
|
||||
i420ex_map(0xdc000, 0x04000, val >> 4);
|
||||
dev->regs[0x5d] = val;
|
||||
break;
|
||||
case 0x5e: /* PAM5 */
|
||||
if ((dev->regs[0x5e] ^ val) & 0x0f)
|
||||
i420ex_map(0xe0000, 0x04000, val & 0xf);
|
||||
if ((dev->regs[0x5e] ^ val) & 0xf0)
|
||||
i420ex_map(0xe4000, 0x04000, val >> 4);
|
||||
dev->regs[0x5e] = val;
|
||||
break;
|
||||
case 0x5f: /* PAM6 */
|
||||
if ((dev->regs[0x5f] ^ val) & 0x0f)
|
||||
i420ex_map(0xe8000, 0x04000, val & 0xf);
|
||||
if ((dev->regs[0x5f] ^ val) & 0xf0)
|
||||
i420ex_map(0xec000, 0x04000, val >> 4);
|
||||
dev->regs[0x5f] = val;
|
||||
break;
|
||||
case 0x66: case 0x67:
|
||||
i420ex_log("Set IRQ routing: INT %c -> %02X\n", 0x41 + (addr & 0x01), val);
|
||||
dev->regs[addr] = val & 0x8f;
|
||||
if (val & 0x80)
|
||||
pci_set_irq_routing(PCI_INTA + (addr & 0x01), PCI_IRQ_DISABLED);
|
||||
else
|
||||
pci_set_irq_routing(PCI_INTA + (addr & 0x01), val & 0xf);
|
||||
break;
|
||||
case 0x70: /* SMRAM */
|
||||
i420ex_smram_handler_phase0();
|
||||
if (dev->smram_locked)
|
||||
dev->regs[0x70] = (dev->regs[0x70] & 0xdf) | (val & 0x20);
|
||||
else {
|
||||
dev->regs[0x70] = (dev->regs[0x70] & 0x88) | (val & 0x77);
|
||||
dev->smram_locked = (val & 0x10);
|
||||
if (dev->smram_locked)
|
||||
dev->regs[0x70] &= 0xbf;
|
||||
}
|
||||
i420ex_smram_handler_phase1(dev);
|
||||
break;
|
||||
case 0xa0:
|
||||
dev->regs[addr] = val & 0x1f;
|
||||
apm_set_do_smi(dev->apm, !!(val & 0x01) && !!(dev->regs[0xa2] & 0x80));
|
||||
switch ((val & 0x18) >> 3) {
|
||||
case 0x00:
|
||||
dev->fast_off_period = PCICLK * 32768.0 * 60000.0;
|
||||
break;
|
||||
case 0x01:
|
||||
default:
|
||||
dev->fast_off_period = 0.0;
|
||||
break;
|
||||
case 0x02:
|
||||
dev->fast_off_period = PCICLK;
|
||||
break;
|
||||
case 0x03:
|
||||
dev->fast_off_period = PCICLK * 32768.0;
|
||||
break;
|
||||
}
|
||||
cpu_fast_off_count = dev->regs[0xa8] + 1;
|
||||
timer_disable(&dev->fast_off_timer);
|
||||
if (dev->fast_off_period != 0.0)
|
||||
timer_on_auto(&dev->fast_off_timer, dev->fast_off_period);
|
||||
break;
|
||||
case 0xa2:
|
||||
dev->regs[addr] = val & 0xff;
|
||||
apm_set_do_smi(dev->apm, !!(dev->regs[0xa0] & 0x01) && !!(val & 0x80));
|
||||
break;
|
||||
case 0xaa:
|
||||
dev->regs[addr] &= (val & 0xff);
|
||||
break;
|
||||
case 0xac: case 0xae:
|
||||
dev->regs[addr] = val & 0xff;
|
||||
break;
|
||||
case 0xa4:
|
||||
dev->regs[addr] = val & 0xfb;
|
||||
cpu_fast_off_flags = (cpu_fast_off_flags & 0xffffff00) | dev->regs[addr];
|
||||
break;
|
||||
case 0xa5:
|
||||
dev->regs[addr] = val;
|
||||
cpu_fast_off_flags = (cpu_fast_off_flags & 0xffff00ff) | (dev->regs[addr] << 8);
|
||||
break;
|
||||
case 0xa7:
|
||||
dev->regs[addr] = val & 0xe0;
|
||||
cpu_fast_off_flags = (cpu_fast_off_flags & 0x00ffffff) | (dev->regs[addr] << 24);
|
||||
break;
|
||||
case 0xa8:
|
||||
dev->regs[addr] = val & 0xff;
|
||||
cpu_fast_off_val = val;
|
||||
cpu_fast_off_count = val + 1;
|
||||
timer_disable(&dev->fast_off_timer);
|
||||
if (dev->fast_off_period != 0.0)
|
||||
timer_on_auto(&dev->fast_off_timer, dev->fast_off_period);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
i420ex_read(int func, int addr, void *priv)
|
||||
{
|
||||
i420ex_t *dev = (i420ex_t *) priv;
|
||||
uint8_t ret;
|
||||
|
||||
ret = 0xff;
|
||||
|
||||
if (func == 0)
|
||||
ret = dev->regs[addr];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
i420ex_reset_hard(void *priv)
|
||||
{
|
||||
i420ex_t *dev = (i420ex_t *) priv;
|
||||
|
||||
memset(dev->regs, 0, 256);
|
||||
|
||||
dev->regs[0x00] = 0x86; dev->regs[0x01] = 0x80; /*Intel*/
|
||||
dev->regs[0x02] = 0x86; dev->regs[0x03] = 0x04; /*82378IB (I420EX)*/
|
||||
dev->regs[0x04] = 0x07;
|
||||
dev->regs[0x07] = 0x02;
|
||||
dev->regs[0x08] = dev->id;
|
||||
|
||||
dev->regs[0x4c] = 0x4d;
|
||||
dev->regs[0x4e] = 0x03;
|
||||
/* Bits 2:1 of register 50h are 00 is 25 MHz, and 01 if 33 MHz, 10 and 11 are reserved. */
|
||||
if (cpu_busspeed >= 33333333)
|
||||
dev->regs[0x50] |= 0x02;
|
||||
dev->regs[0x51] = 0x80;
|
||||
dev->regs[0x60] = dev->regs[0x61] = dev->regs[0x62] = dev->regs[0x63] = dev->regs[0x64] = 0x01;
|
||||
dev->regs[0x66] = 0x80; dev->regs[0x67] = 0x80;
|
||||
dev->regs[0x69] = 0x02;
|
||||
dev->regs[0xa0] = 0x08;
|
||||
dev->regs[0xa8] = 0x0f;
|
||||
|
||||
mem_set_mem_state(0x000a0000, 0x00060000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
|
||||
mem_set_mem_state_smm(0x000a0000, 0x00060000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
i420ex_apm_out(uint16_t port, uint8_t val, void *p)
|
||||
{
|
||||
i420ex_t *dev = (i420ex_t *) p;
|
||||
|
||||
if (dev->apm->do_smi)
|
||||
dev->regs[0xaa] |= 0x80;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
i420ex_fast_off_count(void *priv)
|
||||
{
|
||||
i420ex_t *dev = (i420ex_t *) priv;
|
||||
|
||||
cpu_fast_off_count--;
|
||||
|
||||
if (cpu_fast_off_count == 0) {
|
||||
smi_line = 1;
|
||||
dev->regs[0xaa] |= 0x20;
|
||||
cpu_fast_off_count = dev->regs[0xa8] + 1;
|
||||
}
|
||||
|
||||
timer_on_auto(&dev->fast_off_timer, dev->fast_off_period);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
i420ex_reset(void *p)
|
||||
{
|
||||
i420ex_t *dev = (i420ex_t *) p;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 7; i++)
|
||||
i420ex_write(0, 0x59 + i, 0x00, p);
|
||||
|
||||
for (i = 0; i <= 4; i++)
|
||||
i420ex_write(0, 0x60 + i, 0x01, p);
|
||||
|
||||
dev->regs[0x70] &= 0xef; /* Forcibly unlock the SMRAM register. */
|
||||
dev->smram_locked = 0;
|
||||
i420ex_write(0, 0x70, 0x00, p);
|
||||
|
||||
mem_set_mem_state(0x000a0000, 0x00060000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
|
||||
mem_set_mem_state_smm(0x000a0000, 0x00060000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
|
||||
|
||||
i420ex_write(0, 0xa0, 0x08, p);
|
||||
i420ex_write(0, 0xa2, 0x00, p);
|
||||
i420ex_write(0, 0xa4, 0x00, p);
|
||||
i420ex_write(0, 0xa5, 0x00, p);
|
||||
i420ex_write(0, 0xa6, 0x00, p);
|
||||
i420ex_write(0, 0xa7, 0x00, p);
|
||||
i420ex_write(0, 0xa8, 0x0f, p);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
i420ex_close(void *p)
|
||||
{
|
||||
i420ex_t *dev = (i420ex_t *)p;
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
i420ex_speed_changed(void *priv)
|
||||
{
|
||||
i420ex_t *dev = (i420ex_t *) priv;
|
||||
int te;
|
||||
|
||||
te = timer_is_enabled(&dev->timer);
|
||||
|
||||
timer_disable(&dev->timer);
|
||||
if (te)
|
||||
timer_set_delay_u64(&dev->timer, ((uint64_t) dev->timer_latch) * TIMER_USEC);
|
||||
|
||||
if (dev->id == 0x03) {
|
||||
te = timer_is_enabled(&dev->fast_off_timer);
|
||||
|
||||
timer_stop(&dev->fast_off_timer);
|
||||
if (te)
|
||||
timer_on_auto(&dev->fast_off_timer, dev->fast_off_period);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
i420ex_init(const device_t *info)
|
||||
{
|
||||
i420ex_t *dev = (i420ex_t *) malloc(sizeof(i420ex_t));
|
||||
memset(dev, 0, sizeof(i420ex_t));
|
||||
|
||||
pci_add_card(PCI_ADD_NORTHBRIDGE, i420ex_read, i420ex_write, dev);
|
||||
|
||||
dev->id = info->local;
|
||||
|
||||
timer_add(&dev->fast_off_timer, i420ex_fast_off_count, dev, 0);
|
||||
|
||||
i420ex_reset_hard(dev);
|
||||
|
||||
cpu_fast_off_flags = 0x00000000;
|
||||
|
||||
cpu_fast_off_val = dev->regs[0xa8];
|
||||
cpu_fast_off_count = cpu_fast_off_val + 1;
|
||||
|
||||
dev->apm = device_add(&apm_pci_device);
|
||||
/* APM intercept handler to update 82420EX SMI status on APM SMI. */
|
||||
io_sethandler(0x00b2, 0x0001, NULL, NULL, NULL, i420ex_apm_out, NULL, NULL, dev);
|
||||
|
||||
dev->port_92 = device_add(&port_92_pci_device);
|
||||
|
||||
dma_alias_set();
|
||||
|
||||
#ifdef USE_420EX_IDE
|
||||
device_add(&ide_pci_device);
|
||||
ide_pri_disable();
|
||||
#else
|
||||
device_add(&ide_pci_2ch_device);
|
||||
#endif
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
const device_t i420ex_device =
|
||||
{
|
||||
"Intel 82420EX",
|
||||
DEVICE_PCI,
|
||||
0x00,
|
||||
i420ex_init,
|
||||
i420ex_close,
|
||||
i420ex_reset,
|
||||
NULL,
|
||||
i420ex_speed_changed,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
@@ -6,12 +6,11 @@
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the Intel PCISet chips from 420TX to 440FX.
|
||||
* Implementation of the Intel PCISet chips from 420TX to 440BX.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2019,2020 Miran Grca.
|
||||
*/
|
||||
@@ -38,21 +37,22 @@ enum
|
||||
INTEL_430LX,
|
||||
INTEL_430NX,
|
||||
INTEL_430FX,
|
||||
INTEL_430FX_PB640,
|
||||
INTEL_430HX,
|
||||
INTEL_430VX,
|
||||
INTEL_430TX,
|
||||
INTEL_440FX,
|
||||
INTEL_440LX,
|
||||
INTEL_440EX,
|
||||
INTEL_440LX,
|
||||
INTEL_440EX,
|
||||
INTEL_440BX,
|
||||
INTEL_440GX,
|
||||
INTEL_440ZX
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t pm2_cntrl, max_func,
|
||||
smram_locked;
|
||||
smram_locked, max_drb,
|
||||
drb_default;
|
||||
uint8_t regs[2][256], regs_locked[2][256];
|
||||
int type;
|
||||
} i4x0_t;
|
||||
@@ -63,16 +63,16 @@ i4x0_map(uint32_t addr, uint32_t size, int state)
|
||||
{
|
||||
switch (state & 3) {
|
||||
case 0:
|
||||
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
|
||||
mem_set_mem_state_both(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
|
||||
break;
|
||||
case 1:
|
||||
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY);
|
||||
mem_set_mem_state_both(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY);
|
||||
break;
|
||||
case 2:
|
||||
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
|
||||
mem_set_mem_state_both(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
|
||||
break;
|
||||
case 3:
|
||||
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
|
||||
mem_set_mem_state_both(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
|
||||
break;
|
||||
}
|
||||
flushmmucache_nopc();
|
||||
@@ -80,55 +80,34 @@ i4x0_map(uint32_t addr, uint32_t size, int state)
|
||||
|
||||
|
||||
static void
|
||||
i4x0_smram_map(int smm, uint32_t addr, uint32_t size, int ram)
|
||||
i4x0_smram_map(int smm, uint32_t addr, uint32_t size, int is_smram)
|
||||
{
|
||||
int state = ram ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY);
|
||||
|
||||
mem_set_mem_state_common(smm, addr, size, state);
|
||||
flushmmucache();
|
||||
mem_set_mem_state_smram(smm, addr, size, is_smram);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
i4x0_smram_handler_phase0(i4x0_t *dev)
|
||||
{
|
||||
uint32_t i, n;
|
||||
uint32_t tom = (mem_size << 10);
|
||||
|
||||
/* Disable any active mappings. */
|
||||
if (dev->type >= INTEL_430FX) {
|
||||
if (dev->type >= INTEL_440LX) {
|
||||
/* Disable high extended SMRAM. */
|
||||
/* TODO: This area should point to A0000-FFFFF. */
|
||||
for (i = 0x100a0000; i < 0x100fffff; i += MEM_GRANULARITY_SIZE) {
|
||||
/* This is to make sure that if the remaining area is smaller than
|
||||
or equal to MEM_GRANULARITY_SIZE, we do not change the state of
|
||||
too much memory. */
|
||||
n = ((mem_size << 10) - i);
|
||||
/* Cap to MEM_GRANULARITY_SIZE if i is either at or beyond the end
|
||||
of RAM or the remaining area is bigger than MEM_GRANULARITY_SIZE. */
|
||||
if ((i >= (mem_size << 10)) || (n > MEM_GRANULARITY_SIZE))
|
||||
n = MEM_GRANULARITY_SIZE;
|
||||
i4x0_smram_map(0, i, n, (i < (mem_size << 10)));
|
||||
i4x0_smram_map(1, i, n, (i < (mem_size << 10)));
|
||||
if (n < MEM_GRANULARITY_SIZE) {
|
||||
i4x0_smram_map(0, i + n, MEM_GRANULARITY_SIZE - n, 0);
|
||||
i4x0_smram_map(1, i + n, MEM_GRANULARITY_SIZE - n, 0);
|
||||
}
|
||||
}
|
||||
if (smram[0].size != 0x00000000) {
|
||||
i4x0_smram_map(0, smram[0].host_base, smram[0].size, 0);
|
||||
i4x0_smram_map(1, smram[0].host_base, smram[0].size, 0);
|
||||
|
||||
/* Disable TSEG. */
|
||||
i4x0_smram_map(1, ((mem_size << 10) - (1 << 20)), (1 << 20), 1);
|
||||
}
|
||||
memset(&smram[0], 0x00, sizeof(smram_t));
|
||||
mem_mapping_disable(&ram_smram_mapping[0]);
|
||||
}
|
||||
|
||||
/* Disable low extended SMRAM. */
|
||||
i4x0_smram_map(0, 0xa0000, 0x20000, 0);
|
||||
i4x0_smram_map(1, 0xa0000, 0x20000, 0);
|
||||
} else {
|
||||
/* Disable low extended SMRAM. */
|
||||
i4x0_smram_map(0, 0xa0000, 0x20000, 0);
|
||||
i4x0_smram_map(0, (mem_size << 10) - 0x10000, 0x10000, 1);
|
||||
i4x0_smram_map(1, 0xa0000, 0x20000, 0);
|
||||
i4x0_smram_map(1, (mem_size << 10) - 0x10000, 0x10000, 1);
|
||||
if ((dev->type >= INTEL_440BX) && (smram[1].size != 0x00000000)) {
|
||||
i4x0_smram_map(1, smram[1].host_base, smram[1].size, 0);
|
||||
|
||||
tom -= (1 << 20);
|
||||
mem_set_mem_state_smm(tom, (1 << 20), MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
|
||||
|
||||
memset(&smram[1], 0x00, sizeof(smram_t));
|
||||
mem_mapping_disable(&ram_smram_mapping[1]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,6 +116,7 @@ static void
|
||||
i4x0_smram_handler_phase1(i4x0_t *dev)
|
||||
{
|
||||
uint8_t *regs = (uint8_t *) dev->regs[0];
|
||||
uint32_t tom = (mem_size << 10);
|
||||
|
||||
uint32_t s, base[2] = { 0x000a0000, 0x00020000 };
|
||||
uint32_t size[2] = { 0, 0 };
|
||||
@@ -147,26 +127,54 @@ i4x0_smram_handler_phase1(i4x0_t *dev)
|
||||
base[0] = 0x100a0000;
|
||||
size[0] = 0x00060000;
|
||||
} else {
|
||||
base[0] = 0x000a0000;
|
||||
size[0] = 0x00020000;
|
||||
if (((dev->type == INTEL_440LX) || (dev->type == INTEL_440EX)) && ((regs[0x72] & 0x07) == 0x04)) {
|
||||
base[0] = 0x000c0000;
|
||||
size[0] = 0x00010000;
|
||||
} else {
|
||||
base[0] = 0x000a0000;
|
||||
size[0] = 0x00020000;
|
||||
}
|
||||
}
|
||||
|
||||
/* If D_OPEN = 1 and D_LCK = 0, extended SMRAM is visible outside SMM. */
|
||||
i4x0_smram_map(0, base[0], size[0], ((regs[0x72] & 0x70) == 0x40));
|
||||
if (((regs[0x72] & 0x70) == 0x40) || ((regs[0x72] & 0x08) && !(regs[0x72] & 0x20))) {
|
||||
smram[0].host_base = base[0];
|
||||
smram[0].ram_base = base[0] & 0x000f0000;
|
||||
smram[0].size = size[0];
|
||||
|
||||
/* If the register is set accordingly, disable the mapping also in SMM. */
|
||||
i4x0_smram_map(1, base[0], size[0], ((regs[0x72] & 0x08) && !(regs[0x72] & 0x20)));
|
||||
mem_mapping_set_addr(&ram_smram_mapping[0], smram[0].host_base, size[0]);
|
||||
mem_mapping_set_exec(&ram_smram_mapping[0], ram + smram[0].ram_base);
|
||||
|
||||
/* If D_OPEN = 1 and D_LCK = 0, extended SMRAM is visible outside SMM. */
|
||||
i4x0_smram_map(0, base[0], size[0], ((regs[0x72] & 0x70) == 0x40));
|
||||
|
||||
/* If the register is set accordingly, disable the mapping also in SMM. */
|
||||
i4x0_smram_map(1, base[0], size[0], ((regs[0x72] & 0x08) && !(regs[0x72] & 0x20)));
|
||||
}
|
||||
|
||||
/* TSEG mapping. */
|
||||
if (dev->type >= INTEL_440BX) {
|
||||
if ((regs[0x72] & 0x08) && (regs[0x73] & 0x01)) {
|
||||
size[1] = (1 << (17 + ((regs[0x73] >> 1) & 0x03)));
|
||||
base[1] = (mem_size << 10) - size[1];
|
||||
tom -= size[1];
|
||||
base[1] = tom;
|
||||
} else
|
||||
base[1] = size[1] = 0x00000000;
|
||||
i4x0_smram_map(1, base[1], size[1], 1);
|
||||
} else
|
||||
base[1] = size[1] = 0x00000000;
|
||||
|
||||
if (size[1] != 0x00000000) {
|
||||
smram[1].host_base = base[1] + (1 << 28);
|
||||
smram[1].ram_base = base[1];
|
||||
smram[1].size = size[1];
|
||||
|
||||
mem_mapping_set_addr(&ram_smram_mapping[1], smram[1].host_base, smram[1].size);
|
||||
if (smram[1].ram_base < (1 << 30))
|
||||
mem_mapping_set_exec(&ram_smram_mapping[1], ram + smram[1].ram_base);
|
||||
else
|
||||
mem_mapping_set_exec(&ram_smram_mapping[1], ram2 + smram[1].ram_base - (1 << 30));
|
||||
|
||||
mem_set_mem_state_smm(base[1], size[1], MEM_READ_EXTANY | MEM_WRITE_EXTANY);
|
||||
i4x0_smram_map(1, smram[1].host_base, size[1], 1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
size[0] = 0x00010000;
|
||||
switch (regs[0x72] & 0x03) {
|
||||
@@ -189,20 +197,23 @@ i4x0_smram_handler_phase1(i4x0_t *dev)
|
||||
break;
|
||||
}
|
||||
|
||||
if (base[0] != 0x00000000) {
|
||||
if (((((regs[0x72] & 0x38) == 0x20) || s) || (!(regs[0x72] & 0x10) || s)) && (size[0] != 0x00000000)) {
|
||||
smram[0].host_base = base[0];
|
||||
smram[0].ram_base = base[0];
|
||||
smram[0].size = size[0];
|
||||
|
||||
mem_mapping_set_addr(&ram_smram_mapping[0], smram[0].host_base, size[0]);
|
||||
mem_mapping_set_exec(&ram_smram_mapping[0], ram + smram[0].ram_base);
|
||||
|
||||
/* If OSS = 1 and LSS = 0, extended SMRAM is visible outside SMM. */
|
||||
i4x0_smram_map(0, base[0], size[0], ((regs[0x72] & 0x38) == 0x20) || s);
|
||||
/* If base is on top of memory, this mapping will point to RAM.
|
||||
TODO: It should actually point to EXTERNAL (with a SMRAM mapping) instead. */
|
||||
/* If we are open, not closed, and not locked, point to RAM. */
|
||||
i4x0_smram_map(0, base[0], size[0], (((regs[0x72] & 0x38) == 0x20) || s));
|
||||
|
||||
/* If the register is set accordingly, disable the mapping also in SMM. */
|
||||
i4x0_smram_map(0, base[0], size[0], !(regs[0x72] & 0x10) || s);
|
||||
/* If base is on top of memory, this mapping will point to RAM.
|
||||
TODO: It should actually point to EXTERNAL (with a SMRAM mapping) instead. */
|
||||
/* If we are not closed, point to RAM. */
|
||||
i4x0_smram_map(0, base[0], size[0], (!(regs[0x72] & 0x10) || s));
|
||||
}
|
||||
}
|
||||
|
||||
flushmmucache();
|
||||
}
|
||||
|
||||
|
||||
@@ -254,11 +265,11 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
case 0x04: /*Command register*/
|
||||
switch (dev->type) {
|
||||
case INTEL_420TX: case INTEL_420ZX: case INTEL_430LX: case INTEL_430NX:
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
case INTEL_440BX: case INTEL_440GX: case INTEL_440ZX:
|
||||
default:
|
||||
regs[0x04] = (regs[0x04] & ~0x42) | (val & 0x42);
|
||||
break;
|
||||
case INTEL_430FX: case INTEL_430FX_PB640: case INTEL_430HX: case INTEL_430VX: case INTEL_430TX:
|
||||
case INTEL_430FX: case INTEL_430HX: case INTEL_430VX: case INTEL_430TX:
|
||||
case INTEL_440FX: case INTEL_440LX: case INTEL_440EX:
|
||||
regs[0x04] = (regs[0x04] & ~0x02) | (val & 0x02);
|
||||
break;
|
||||
@@ -268,7 +279,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
switch (dev->type) {
|
||||
case INTEL_420TX: case INTEL_420ZX: case INTEL_430LX: case INTEL_430NX: case INTEL_430HX:
|
||||
case INTEL_440FX: case INTEL_440LX: case INTEL_440EX:
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
case INTEL_440BX: case INTEL_440GX: case INTEL_440ZX:
|
||||
regs[0x05] = (regs[0x05] & ~0x01) | (val & 0x01);
|
||||
break;
|
||||
}
|
||||
@@ -279,14 +290,14 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
default:
|
||||
regs[0x07] &= ~(val & 0x70);
|
||||
break;
|
||||
case INTEL_430FX: case INTEL_430FX_PB640: case INTEL_430VX: case INTEL_430TX:
|
||||
case INTEL_430FX: case INTEL_430VX: case INTEL_430TX:
|
||||
case INTEL_440LX: case INTEL_440EX:
|
||||
regs[0x07] &= ~(val & 0x30);
|
||||
break;
|
||||
case INTEL_440FX:
|
||||
regs[0x07] &= ~(val & 0xf9);
|
||||
break;
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
case INTEL_440BX: case INTEL_440GX: case INTEL_440ZX:
|
||||
regs[0x07] &= ~(val & 0xf0);
|
||||
break;
|
||||
}
|
||||
@@ -303,14 +314,14 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
break;
|
||||
case 0x0f:
|
||||
switch (dev->type) {
|
||||
case INTEL_430FX: case INTEL_430FX_PB640: case INTEL_430HX: case INTEL_430VX: case INTEL_430TX:
|
||||
case INTEL_430FX: case INTEL_430HX: case INTEL_430VX: case INTEL_430TX:
|
||||
regs[0x0f] = (val & 0x40);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x12:
|
||||
switch (dev->type) {
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
case INTEL_440BX: case INTEL_440GX: case INTEL_440ZX:
|
||||
regs[0x12] = (val & 0xc0);
|
||||
i4x0_mask_bar(regs);
|
||||
break;
|
||||
@@ -318,7 +329,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
break;
|
||||
case 0x13:
|
||||
switch (dev->type) {
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
case INTEL_440BX: case INTEL_440GX: case INTEL_440ZX:
|
||||
regs[0x13] = val;
|
||||
i4x0_mask_bar(regs);
|
||||
break;
|
||||
@@ -326,7 +337,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
break;
|
||||
case 0x2c: case 0x2d: case 0x2e: case 0x2f:
|
||||
switch (dev->type) {
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
case INTEL_440BX: case INTEL_440GX: case INTEL_440ZX:
|
||||
if (!regs_l[addr]) {
|
||||
regs[addr] = val;
|
||||
regs_l[addr] = 1;
|
||||
@@ -364,7 +375,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
case INTEL_430NX:
|
||||
regs[0x50] = (val & 0xe7);
|
||||
break;
|
||||
case INTEL_430FX: case INTEL_430FX_PB640:
|
||||
case INTEL_430FX:
|
||||
regs[0x50] = (val & 0xef);
|
||||
break;
|
||||
case INTEL_430HX:
|
||||
@@ -385,6 +396,11 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
case INTEL_440BX:
|
||||
regs[0x50] = (regs[0x50] & 0x14) | (val & 0xeb);
|
||||
break;
|
||||
case INTEL_440GX:
|
||||
/* TODO: Understand it more specifically */
|
||||
regs[0x50] = (regs[0x50] & 0x2b) | (val & 0x28);
|
||||
/*regs[0x50] = (regs[0x50] & 0x2b) | (val & 0xd7);*/
|
||||
break;
|
||||
case INTEL_440ZX:
|
||||
regs[0x50] = (regs[0x50] & 0x34) | (val & 0xcb);
|
||||
break;
|
||||
@@ -405,13 +421,16 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
regs[0x51] = (regs[0x50] & 0x70) | (val & 0x8f);
|
||||
break;
|
||||
case INTEL_440GX:
|
||||
regs[0x51] = (regs[0x50] & 0x88) | (val & 0x08);
|
||||
/*regs[0x51] = (regs[0x50] & 0x88) | (val & 0x77);*/
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x52: /* Cache Control Register */
|
||||
switch (dev->type) {
|
||||
case INTEL_420TX: case INTEL_420ZX:
|
||||
case INTEL_430LX:
|
||||
case INTEL_430FX: case INTEL_430FX_PB640:
|
||||
case INTEL_430LX: case INTEL_430FX:
|
||||
case INTEL_430VX: case INTEL_430TX:
|
||||
default:
|
||||
regs[0x52] = (val & 0xfb);
|
||||
@@ -423,7 +442,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
case INTEL_440LX:
|
||||
regs[0x52] = (val & 0xd0);
|
||||
break;
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
case INTEL_440BX: case INTEL_440GX: case INTEL_440ZX:
|
||||
regs[0x52] = val & 0x07;
|
||||
break;
|
||||
}
|
||||
@@ -443,7 +462,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
case INTEL_440LX:
|
||||
regs[0x53] = val & 0x0a;
|
||||
break;
|
||||
case INTEL_440EX: case INTEL_440BX:
|
||||
case INTEL_440EX: case INTEL_440BX: case INTEL_440GX:
|
||||
/* Not applicable to 440ZX as that does not support ECC. */
|
||||
regs[0x53] = val;
|
||||
break;
|
||||
@@ -506,8 +525,8 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
case INTEL_430NX: case INTEL_440EX:
|
||||
regs[0x57] = val;
|
||||
break;
|
||||
case INTEL_430FX: case INTEL_430FX_PB640:
|
||||
case INTEL_430HX: case INTEL_430VX:
|
||||
case INTEL_430FX: case INTEL_430HX:
|
||||
case INTEL_430VX:
|
||||
regs[0x57] = val & 0xcf;
|
||||
break;
|
||||
case INTEL_430TX:
|
||||
@@ -519,7 +538,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
case INTEL_440LX:
|
||||
regs[0x57] = val & 0x11;
|
||||
break;
|
||||
case INTEL_440BX:
|
||||
case INTEL_440BX: case INTEL_440GX:
|
||||
regs[0x57] = val & 0x3f;
|
||||
break;
|
||||
case INTEL_440ZX:
|
||||
@@ -537,8 +556,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
regs[0x58] = val & 0x03;
|
||||
break;
|
||||
case INTEL_430FX: case INTEL_430FX_PB640:
|
||||
case INTEL_440FX:
|
||||
case INTEL_430FX: case INTEL_440FX:
|
||||
regs[0x58] = val & 0x7f;
|
||||
break;
|
||||
case INTEL_430HX: case INTEL_430VX:
|
||||
@@ -619,8 +637,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
default:
|
||||
regs[addr] = val;
|
||||
break;
|
||||
case INTEL_430FX: case INTEL_430FX_PB640:
|
||||
case INTEL_430VX:
|
||||
case INTEL_430FX: case INTEL_430VX:
|
||||
regs[addr] = val & 0x3f;
|
||||
break;
|
||||
case INTEL_430TX:
|
||||
@@ -635,6 +652,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
case INTEL_430HX:
|
||||
case INTEL_440FX:
|
||||
case INTEL_440LX: case INTEL_440EX:
|
||||
case INTEL_440GX:
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
regs[addr] = val;
|
||||
break;
|
||||
@@ -650,7 +668,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
switch (dev->type) {
|
||||
case INTEL_430NX: case INTEL_430HX:
|
||||
case INTEL_440FX: case INTEL_440LX:
|
||||
case INTEL_440EX:
|
||||
case INTEL_440EX: case INTEL_440GX:
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
regs[addr] = val;
|
||||
break;
|
||||
@@ -661,7 +679,8 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
case INTEL_430NX: case INTEL_430HX:
|
||||
case INTEL_440FX: case INTEL_440LX:
|
||||
case INTEL_440EX:
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
case INTEL_440BX: case INTEL_440GX:
|
||||
case INTEL_440ZX:
|
||||
regs[addr] = val;
|
||||
break;
|
||||
case INTEL_430VX:
|
||||
@@ -678,7 +697,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
case INTEL_430VX: case INTEL_430TX:
|
||||
regs[0x68] = val;
|
||||
break;
|
||||
case INTEL_430FX: case INTEL_430FX_PB640:
|
||||
case INTEL_430FX:
|
||||
regs[0x68] = val & 0x1f;
|
||||
break;
|
||||
case INTEL_440FX: case INTEL_440LX:
|
||||
@@ -688,6 +707,9 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
case INTEL_440BX:
|
||||
regs[0x68] = (regs[0x68] & 0x38) | (val & 0xc7);
|
||||
break;
|
||||
case INTEL_440GX:
|
||||
regs[0x68] = (regs[0x68] & 0xc0) | (val & 0x3f);
|
||||
break;
|
||||
case INTEL_440ZX:
|
||||
regs[0x68] = (regs[0x68] & 0x3f) | (val & 0xc0);
|
||||
break;
|
||||
@@ -697,6 +719,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
switch (dev->type) {
|
||||
case INTEL_430NX:
|
||||
case INTEL_440BX:
|
||||
case INTEL_440GX:
|
||||
regs[0x69] = val;
|
||||
break;
|
||||
case INTEL_430VX:
|
||||
@@ -713,6 +736,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
case INTEL_440LX:
|
||||
case INTEL_440EX:
|
||||
case INTEL_440BX:
|
||||
case INTEL_440GX:
|
||||
regs[addr] = val;
|
||||
break;
|
||||
case INTEL_440ZX:
|
||||
@@ -728,6 +752,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
case INTEL_440LX:
|
||||
case INTEL_440EX:
|
||||
case INTEL_440BX:
|
||||
case INTEL_440GX:
|
||||
regs[addr] = val;
|
||||
break;
|
||||
case INTEL_440ZX:
|
||||
@@ -784,7 +809,10 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
if (dev->smram_locked)
|
||||
regs[0x72] = (regs[0x72] & 0xdf) | (val & 0x20);
|
||||
else {
|
||||
regs[0x72] = (regs[0x72] & 0x87) | (val & 0x78);
|
||||
if ((dev->type == INTEL_440LX) || (dev->type == INTEL_440EX))
|
||||
regs[0x72] = (regs[0x72] & 0x80) | (val & 0x7f);
|
||||
else
|
||||
regs[0x72] = (regs[0x72] & 0x87) | (val & 0x78);
|
||||
dev->smram_locked = (val & 0x10);
|
||||
if (dev->smram_locked)
|
||||
regs[0x72] &= 0xbf;
|
||||
@@ -796,7 +824,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
regs[0x72] = (regs[0x72] & 0xc0) | (val & 0x3f);
|
||||
dev->smram_locked = (val & 0x08);
|
||||
if (dev->smram_locked)
|
||||
regs[0x72] &= 0xef;
|
||||
regs[0x72] &= 0xdf;
|
||||
}
|
||||
}
|
||||
i4x0_smram_handler_phase1(dev);
|
||||
@@ -806,7 +834,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
case INTEL_430VX:
|
||||
regs[0x73] = val & 0x03;
|
||||
break;
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
case INTEL_440BX: case INTEL_440GX: case INTEL_440ZX:
|
||||
if (!dev->smram_locked) {
|
||||
i4x0_smram_handler_phase0(dev);
|
||||
regs[0x73] = (regs[0x72] & 0x38) | (val & 0xc7);
|
||||
@@ -826,13 +854,13 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
case 0x75: case 0x76:
|
||||
case 0x7b:
|
||||
switch (dev->type) {
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
case INTEL_440BX: case INTEL_440GX: case INTEL_440ZX:
|
||||
regs[addr] = val;
|
||||
}
|
||||
break;
|
||||
case 0x77:
|
||||
switch (dev->type) {
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
case INTEL_440BX: case INTEL_440GX: case INTEL_440ZX:
|
||||
regs[0x77] = val & 0x03;
|
||||
}
|
||||
break;
|
||||
@@ -841,7 +869,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
case INTEL_430VX:
|
||||
regs[0x78] = val & 0xcf;
|
||||
break;
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
case INTEL_440BX: case INTEL_440GX: case INTEL_440ZX:
|
||||
regs[0x78] = val & 0x0f;
|
||||
break;
|
||||
}
|
||||
@@ -854,14 +882,14 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
if (val & 0x40)
|
||||
io_sethandler(0x0022, 0x01, pm2_cntrl_read, NULL, NULL, pm2_cntrl_write, NULL, NULL, dev);
|
||||
break;
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
case INTEL_440BX: case INTEL_440GX: case INTEL_440ZX:
|
||||
regs[0x79] = val;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x7a:
|
||||
switch (dev->type) {
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
case INTEL_440BX: case INTEL_440GX: case INTEL_440ZX:
|
||||
regs[0x7a] = (regs[0x7a] & 0x0a) | (val & 0xf5);
|
||||
io_removehandler(0x0022, 0x01, pm2_cntrl_read, NULL, NULL, pm2_cntrl_write, NULL, NULL, dev);
|
||||
if (val & 0x40)
|
||||
@@ -875,7 +903,8 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
case INTEL_430LX: case INTEL_430NX:
|
||||
regs[0x7c] = val & 0x8f;
|
||||
break;
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
case INTEL_440BX: case INTEL_440GX:
|
||||
case INTEL_440ZX:
|
||||
regs[0x7c] = val & 0x1f;
|
||||
break;
|
||||
}
|
||||
@@ -911,7 +940,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
case INTEL_440LX:
|
||||
regs[0x80] = val & 0x08;
|
||||
break;
|
||||
case INTEL_440EX:
|
||||
case INTEL_440EX: case INTEL_440GX:
|
||||
regs[0x80] = val & 0x18;
|
||||
break;
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
@@ -923,7 +952,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
switch (dev->type) {
|
||||
case INTEL_430HX: case INTEL_440BX:
|
||||
case INTEL_440FX: case INTEL_440LX:
|
||||
case INTEL_440EX:
|
||||
case INTEL_440EX: case INTEL_440GX:
|
||||
/* Not applicable on 82443ZX. */
|
||||
regs[0x91] &= ~(val & 0x11);
|
||||
break;
|
||||
@@ -932,7 +961,8 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
case 0x92:
|
||||
switch (dev->type) {
|
||||
case INTEL_440LX: case INTEL_440EX:
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
case INTEL_440BX: case INTEL_440GX:
|
||||
case INTEL_440ZX:
|
||||
regs[0x92] &= ~(val & 0x1f);
|
||||
break;
|
||||
}
|
||||
@@ -956,7 +986,8 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
break;
|
||||
case 0xb0:
|
||||
switch (dev->type) {
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
case INTEL_440BX: case INTEL_440GX:
|
||||
case INTEL_440ZX:
|
||||
regs[0xb0] = (val & 0x80);
|
||||
break;
|
||||
}
|
||||
@@ -969,11 +1000,15 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
regs[0xb1] = (val & 0xa0);
|
||||
break;
|
||||
case INTEL_440GX:
|
||||
regs[0xb1] = (val & 0xa2);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xb4:
|
||||
switch (dev->type) {
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
case INTEL_440BX: case INTEL_440GX:
|
||||
case INTEL_440ZX:
|
||||
regs[0xb4] = (val & 0x3f);
|
||||
i4x0_mask_bar(regs);
|
||||
break;
|
||||
@@ -981,7 +1016,8 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
break;
|
||||
case 0xb9:
|
||||
switch (dev->type) {
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
case INTEL_440BX: case INTEL_440GX:
|
||||
case INTEL_440ZX:
|
||||
regs[0xb9] = (val & 0xf0);
|
||||
break;
|
||||
}
|
||||
@@ -989,7 +1025,8 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
|
||||
case 0xba: case 0xbb:
|
||||
switch (dev->type) {
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
case INTEL_440BX: case INTEL_440GX:
|
||||
case INTEL_440ZX:
|
||||
regs[addr] = val;
|
||||
break;
|
||||
}
|
||||
@@ -997,7 +1034,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
|
||||
case 0xbc:
|
||||
switch (dev->type) {
|
||||
case INTEL_440EX:
|
||||
case INTEL_440EX: case INTEL_440GX:
|
||||
regs[addr] = (val & 0xf8);
|
||||
break;
|
||||
}
|
||||
@@ -1005,7 +1042,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
|
||||
case 0xbd:
|
||||
switch (dev->type) {
|
||||
case INTEL_440EX:
|
||||
case INTEL_440EX: case INTEL_440GX:
|
||||
regs[addr] = (val & 0xf8);
|
||||
break;
|
||||
}
|
||||
@@ -1013,14 +1050,15 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
|
||||
case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7:
|
||||
switch (dev->type) {
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
case INTEL_440BX: case INTEL_440GX:
|
||||
case INTEL_440ZX:
|
||||
regs[addr] = val;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xca:
|
||||
switch (dev->type) {
|
||||
case INTEL_440BX:
|
||||
case INTEL_440BX: case INTEL_440GX:
|
||||
regs[addr] = val;
|
||||
break;
|
||||
case INTEL_440ZX:
|
||||
@@ -1030,7 +1068,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
break;
|
||||
case 0xcb:
|
||||
switch (dev->type) {
|
||||
case INTEL_440BX:
|
||||
case INTEL_440BX: case INTEL_440GX:
|
||||
regs[addr] = val;
|
||||
break;
|
||||
case INTEL_440ZX:
|
||||
@@ -1040,7 +1078,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
break;
|
||||
case 0xcc:
|
||||
switch (dev->type) {
|
||||
case INTEL_440BX:
|
||||
case INTEL_440BX: case INTEL_440GX:
|
||||
regs[0xcc] = (val & 0x7f);
|
||||
break;
|
||||
case INTEL_440ZX:
|
||||
@@ -1051,7 +1089,8 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4:
|
||||
case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec:
|
||||
switch (dev->type) {
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
case INTEL_440BX: case INTEL_440GX:
|
||||
case INTEL_440ZX:
|
||||
if (!regs_l[addr])
|
||||
regs[addr] = val;
|
||||
break;
|
||||
@@ -1059,7 +1098,8 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
break;
|
||||
case 0xe5: case 0xed:
|
||||
switch (dev->type) {
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
case INTEL_440BX: case INTEL_440GX:
|
||||
case INTEL_440ZX:
|
||||
if (!regs_l[addr])
|
||||
regs[addr] = (val & 0x3f);
|
||||
break;
|
||||
@@ -1067,7 +1107,8 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
break;
|
||||
case 0xe7:
|
||||
switch (dev->type) {
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
case INTEL_440BX: case INTEL_440GX:
|
||||
case INTEL_440ZX:
|
||||
regs[0xe7] = 0x80;
|
||||
for (i = 0; i < 16; i++)
|
||||
regs_l[0xe0 + i] = !!(val & 0x80);
|
||||
@@ -1079,14 +1120,16 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
break;
|
||||
case 0xf0:
|
||||
switch (dev->type) {
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
case INTEL_440BX: case INTEL_440GX:
|
||||
case INTEL_440ZX:
|
||||
regs[0xf0] = (val & 0xc0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xf1:
|
||||
switch (dev->type) {
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
case INTEL_440BX: case INTEL_440GX:
|
||||
case INTEL_440ZX:
|
||||
regs[0xf1] = (val & 0x03);
|
||||
break;
|
||||
}
|
||||
@@ -1097,18 +1140,22 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
regs[0x04] = (val & 0x1f);
|
||||
break;
|
||||
case INTEL_440GX:
|
||||
regs[0x04] = val;
|
||||
}
|
||||
break;
|
||||
case 0x05:
|
||||
switch (dev->type) {
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
case INTEL_440BX: case INTEL_440GX:
|
||||
case INTEL_440ZX:
|
||||
regs[0x05] = (val & 0x01);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x0d: case 0x1b:
|
||||
switch (dev->type) {
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
case INTEL_440BX: case INTEL_440GX:
|
||||
case INTEL_440ZX:
|
||||
regs[addr] = (val & 0xf8);
|
||||
break;
|
||||
}
|
||||
@@ -1117,7 +1164,8 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
case 0x21: case 0x23:
|
||||
case 0x25: case 0x27:
|
||||
switch (dev->type) {
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
case INTEL_440BX: case INTEL_440GX:
|
||||
case INTEL_440ZX:
|
||||
regs[addr] = val;
|
||||
break;
|
||||
}
|
||||
@@ -1126,21 +1174,24 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
case 0x20: case 0x22:
|
||||
case 0x24: case 0x26:
|
||||
switch (dev->type) {
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
case INTEL_440BX: case INTEL_440GX:
|
||||
case INTEL_440ZX:
|
||||
regs[addr] = (val & 0xf0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x1f:
|
||||
switch (dev->type) {
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
case INTEL_440BX: case INTEL_440GX:
|
||||
case INTEL_440ZX:
|
||||
regs[0x1f] &= ~(val & 0xf0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x3e:
|
||||
switch (dev->type) {
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
case INTEL_440BX: case INTEL_440GX:
|
||||
case INTEL_440ZX:
|
||||
regs[0x3e] = (val & 0xed);
|
||||
break;
|
||||
}
|
||||
@@ -1184,10 +1235,16 @@ i4x0_reset(void *priv)
|
||||
for (i = 0; i < 6; i++)
|
||||
i4x0_write(0, 0x5a + i, 0x00, priv);
|
||||
|
||||
if (dev->type >= INTEL_430FX)
|
||||
for (i = 0; i <= dev->max_drb; i++)
|
||||
i4x0_write(0, 0x60 + i, dev->drb_default, priv);
|
||||
|
||||
if (dev->type >= INTEL_430FX) {
|
||||
dev->regs[0][0x72] &= 0xef; /* Forcibly unlock the SMRAM register. */
|
||||
i4x0_write(0, 0x72, 0x02, priv);
|
||||
else
|
||||
} else {
|
||||
dev->regs[0][0x72] &= 0xf7; /* Forcibly unlock the SMRAM register. */
|
||||
i4x0_write(0, 0x72, 0x00, priv);
|
||||
}
|
||||
|
||||
if ((dev->type == INTEL_440LX) || (dev->type == INTEL_440BX) || (dev->type == INTEL_440ZX)) {
|
||||
for (i = 0; i <= dev->max_func; i++)
|
||||
@@ -1217,9 +1274,6 @@ static void
|
||||
|
||||
regs = (uint8_t *) dev->regs[0];
|
||||
|
||||
// This is off by default and has to be moved to the appropriate register handling.
|
||||
// io_sethandler(0x0022, 0x01, pm2_cntrl_read, NULL, NULL, pm2_cntrl_write, NULL, NULL, dev);
|
||||
|
||||
regs[0x00] = 0x86; regs[0x01] = 0x80; /*Intel*/
|
||||
|
||||
switch (dev->type) {
|
||||
@@ -1250,6 +1304,8 @@ static void
|
||||
regs[0x57] = 0x31;
|
||||
regs[0x59] = 0x0f;
|
||||
regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = 0x02;
|
||||
dev->max_drb = 5;
|
||||
dev->drb_default = 0x02;
|
||||
break;
|
||||
case INTEL_430LX:
|
||||
regs[0x02] = 0xa3; regs[0x03] = 0x04; /* 82434LX/NX */
|
||||
@@ -1266,6 +1322,8 @@ static void
|
||||
regs[0x57] = 0x31;
|
||||
regs[0x59] = 0x0f;
|
||||
regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = 0x02;
|
||||
dev->max_drb = 5;
|
||||
dev->drb_default = 0x02;
|
||||
break;
|
||||
case INTEL_430NX:
|
||||
regs[0x02] = 0xa3; regs[0x03] = 0x04; /* 82434LX/NX */
|
||||
@@ -1284,12 +1342,12 @@ static void
|
||||
regs[0x57] = 0x31;
|
||||
regs[0x59] = 0x0f;
|
||||
regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = regs[0x66] = regs[0x67] = 0x02;
|
||||
dev->max_drb = 7;
|
||||
dev->drb_default = 0x02;
|
||||
break;
|
||||
case INTEL_430FX_PB640:
|
||||
regs[0x08] = 0x02;
|
||||
/* FALLTHROUGH */
|
||||
case INTEL_430FX:
|
||||
regs[0x02] = 0x2d; regs[0x03] = 0x12; /* SB82437FX-66 */
|
||||
regs[0x08] = (info->local >> 8) & 0xff;
|
||||
regs[0x52] = 0xb2; /* 512 kB PLB cache, set to 0x42 for 256 kB */
|
||||
if (cpu_busspeed <= 50000000)
|
||||
regs[0x57] |= 0x01;
|
||||
@@ -1299,6 +1357,8 @@ static void
|
||||
regs[0x57] |= 0x03;
|
||||
regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = 0x02;
|
||||
regs[0x72] = 0x02;
|
||||
dev->max_drb = 4;
|
||||
dev->drb_default = 0x02;
|
||||
break;
|
||||
case INTEL_430HX:
|
||||
regs[0x02] = 0x50; regs[0x03] = 0x12; /* 82439HX */
|
||||
@@ -1311,6 +1371,8 @@ static void
|
||||
regs[0x57] |= 0x03;
|
||||
regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = regs[0x66] = regs[0x67] = 0x02;
|
||||
regs[0x72] = 0x02;
|
||||
dev->max_drb = 7;
|
||||
dev->drb_default = 0x02;
|
||||
break;
|
||||
case INTEL_430VX:
|
||||
regs[0x02] = 0x30; regs[0x03] = 0x70; /* 82437VX */
|
||||
@@ -1330,6 +1392,8 @@ static void
|
||||
regs[0x72] = 0x02;
|
||||
regs[0x74] = 0x0e;
|
||||
regs[0x78] = 0x23;
|
||||
dev->max_drb = 4;
|
||||
dev->drb_default = 0x02;
|
||||
break;
|
||||
case INTEL_430TX:
|
||||
regs[0x02] = 0x00; regs[0x03] = 0x71; /* 82439TX */
|
||||
@@ -1345,6 +1409,8 @@ static void
|
||||
regs[0x67] |= 0x80;
|
||||
regs[0x70] = 0x20;
|
||||
regs[0x72] = 0x02;
|
||||
dev->max_drb = 5;
|
||||
dev->drb_default = 0x02;
|
||||
break;
|
||||
case INTEL_440FX:
|
||||
regs[0x02] = 0x37; regs[0x03] = 0x12; /* 82441FX */
|
||||
@@ -1359,6 +1425,8 @@ static void
|
||||
regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = regs[0x66] = regs[0x67] = 0x02;
|
||||
regs[0x71] = 0x10;
|
||||
regs[0x72] = 0x02;
|
||||
dev->max_drb = 7;
|
||||
dev->drb_default = 0x02;
|
||||
break;
|
||||
case INTEL_440LX:
|
||||
dev->max_func = 1;
|
||||
@@ -1381,6 +1449,8 @@ static void
|
||||
regs[0xa4] = 0x03;
|
||||
regs[0xa5] = 0x02;
|
||||
regs[0xa7] = 0x1f;
|
||||
dev->max_drb = 7;
|
||||
dev->drb_default = 0x01;
|
||||
break;
|
||||
case INTEL_440EX:
|
||||
dev->max_func = 1;
|
||||
@@ -1403,6 +1473,8 @@ static void
|
||||
regs[0xa4] = 0x03;
|
||||
regs[0xa5] = 0x02;
|
||||
regs[0xa7] = 0x1f;
|
||||
dev->max_drb = 7;
|
||||
dev->drb_default = 0x01;
|
||||
break;
|
||||
case INTEL_440BX: case INTEL_440ZX:
|
||||
regs[0x7a] = (info->local >> 8) & 0xff;
|
||||
@@ -1429,6 +1501,33 @@ static void
|
||||
regs[0xa4] = 0x03;
|
||||
regs[0xa5] = 0x02;
|
||||
regs[0xa7] = 0x1f;
|
||||
dev->max_drb = 7;
|
||||
dev->drb_default = 0x01;
|
||||
break;
|
||||
case INTEL_440GX:
|
||||
regs[0x7a] = (info->local >> 8) & 0xff;
|
||||
dev->max_func = (regs[0x7a] & 0x02) ? 0 : 1;
|
||||
|
||||
regs[0x02] = 0xa0; regs[0x03] = 0x71; /* 82443GX */
|
||||
regs[0x06] = (regs[0x7a] & 0x02) ? 0x00 : 0x10;
|
||||
regs[0x08] = 0x02;
|
||||
regs[0x10] = 0x08;
|
||||
regs[0x34] = (regs[0x7a] & 0x02) ? 0x00 : 0xa0;
|
||||
regs[0x51] |= 0x20;
|
||||
regs[0x57] = 0x28;
|
||||
regs[0x58] = 0x03;
|
||||
regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = regs[0x66] = regs[0x67] = 0x01;
|
||||
regs[0x72] = 0x02;
|
||||
regs[0x73] = 0x38;
|
||||
regs[0x7b] = 0x38;
|
||||
regs[0x90] = 0x80;
|
||||
regs[0xa0] = (regs[0x7a] & 0x02) ? 0x00 : 0x02;
|
||||
regs[0xa2] = (regs[0x7a] & 0x02) ? 0x00 : 0x10;
|
||||
regs[0xa4] = 0x03;
|
||||
regs[0xa5] = 0x02;
|
||||
regs[0xa7] = 0x1f;
|
||||
dev->max_drb = 7;
|
||||
dev->drb_default = 0x01;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1463,11 +1562,15 @@ static void
|
||||
regs[0x24] = 0xf0; regs[0x25] = 0xff;
|
||||
}
|
||||
|
||||
if (((dev->type == INTEL_440BX) || (dev->type == INTEL_440ZX)) && (dev->max_func == 1)) {
|
||||
if (((dev->type == INTEL_440BX) || (dev->type == INTEL_440GX) || (dev->type == INTEL_440ZX)) && (dev->max_func == 1)) {
|
||||
regs = (uint8_t *) dev->regs[1];
|
||||
|
||||
regs[0x00] = 0x86; regs[0x01] = 0x80; /* Intel */
|
||||
if(dev->type != INTEL_440GX){
|
||||
regs[0x02] = 0x91; regs[0x03] = 0x71; /* 82443BX */
|
||||
} else {
|
||||
regs[0x02] = 0xa1; regs[0x03] = 0x71; /* 82443GX (They seem to share the same deal*/
|
||||
}
|
||||
regs[0x06] = 0x20; regs[0x07] = 0x02;
|
||||
regs[0x08] = 0x02;
|
||||
regs[0x0a] = 0x04; regs[0x0b] = 0x06;
|
||||
@@ -1560,11 +1663,11 @@ const device_t i430fx_device =
|
||||
};
|
||||
|
||||
|
||||
const device_t i430fx_pb640_device =
|
||||
const device_t i430fx_rev02_device =
|
||||
{
|
||||
"Intel SB82437FX-66 (PB640)",
|
||||
"Intel SB82437FX-66 (Rev. 02)",
|
||||
DEVICE_PCI,
|
||||
INTEL_430FX_PB640,
|
||||
0x0200 | INTEL_430FX,
|
||||
i4x0_init,
|
||||
i4x0_close,
|
||||
i4x0_reset,
|
||||
@@ -1677,6 +1780,19 @@ const device_t i440bx_device =
|
||||
NULL
|
||||
};
|
||||
|
||||
const device_t i440gx_device =
|
||||
{
|
||||
"Intel 82443GX",
|
||||
DEVICE_PCI,
|
||||
0x8000 | INTEL_440GX,
|
||||
i4x0_init,
|
||||
i4x0_close,
|
||||
i4x0_reset,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
const device_t i440zx_device =
|
||||
{
|
||||
|
||||
@@ -13,10 +13,8 @@
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2020 Sarah Walker.
|
||||
* Copyright 2016-2020 Miran Grca.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
@@ -53,7 +51,7 @@
|
||||
#include <86box/zip.h>
|
||||
#include <86box/machine.h>
|
||||
#include <86box/smbus_piix4.h>
|
||||
#include <86box/piix.h>
|
||||
#include <86box/chipset.h>
|
||||
|
||||
|
||||
typedef struct
|
||||
@@ -281,10 +279,10 @@ piix_write(int func, int addr, uint8_t val, void *priv)
|
||||
|
||||
/* Return on unsupported function. */
|
||||
if (dev->max_func > 0) {
|
||||
if (func > dev->max_func)
|
||||
if (func > dev->max_func)
|
||||
return;
|
||||
} else {
|
||||
if (func > 1)
|
||||
if (func > 1)
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -480,11 +478,11 @@ piix_write(int func, int addr, uint8_t val, void *priv)
|
||||
apm_set_do_smi(dev->apm, !!(fregs[0xa0] & 0x01) && !!(val & 0x80));
|
||||
}
|
||||
break;
|
||||
case 0xaa: case 0xac: case 0xae:
|
||||
case 0xac: case 0xae:
|
||||
if (dev->type < 4)
|
||||
fregs[addr] = val & 0xff;
|
||||
break;
|
||||
case 0xa3: case 0xab:
|
||||
case 0xa3:
|
||||
if (dev->type == 3)
|
||||
fregs[addr] = val & 0x01;
|
||||
break;
|
||||
@@ -524,6 +522,14 @@ piix_write(int func, int addr, uint8_t val, void *priv)
|
||||
timer_on_auto(&dev->fast_off_timer, dev->fast_off_period);
|
||||
}
|
||||
break;
|
||||
case 0xaa:
|
||||
if (dev->type < 4)
|
||||
fregs[addr] &= val;
|
||||
break;
|
||||
case 0xab:
|
||||
if (dev->type == 3)
|
||||
fregs[addr] &= (val & 0x01);
|
||||
break;
|
||||
case 0xb0:
|
||||
if (dev->type == 4)
|
||||
fregs[addr] = (fregs[addr] & 0x8c) | (val & 0x73);
|
||||
@@ -755,16 +761,16 @@ piix_write(int func, int addr, uint8_t val, void *priv)
|
||||
fregs[addr] = val & 0x01;
|
||||
break;
|
||||
case 0x6a:
|
||||
if (dev->type == 4)
|
||||
if (dev->type <= 4)
|
||||
fregs[0x6a] = val & 0x01;
|
||||
break;
|
||||
case 0xc0:
|
||||
if (dev->type == 4)
|
||||
fregs[0xc0] = val;
|
||||
if (dev->type <= 4)
|
||||
fregs[0xc0] = (fregs[0xc0] & ~(val & 0xbf)) | (val & 0x20);
|
||||
break;
|
||||
case 0xc1:
|
||||
if (dev->type == 4)
|
||||
fregs[0xc1] = val & 0xbf;
|
||||
if (dev->type <= 4)
|
||||
fregs[0xc1] &= ~val;
|
||||
break;
|
||||
case 0xff:
|
||||
if (dev->type == 4) {
|
||||
@@ -873,6 +879,9 @@ piix_read(int func, int addr, void *priv)
|
||||
piix_t *dev = (piix_t *) priv;
|
||||
uint8_t ret = 0xff, *fregs;
|
||||
|
||||
if ((dev->type == 3) && (func == 2) && (dev->max_func == 1) && (addr >= 0x40))
|
||||
ret = 0x00;
|
||||
|
||||
/* Return on unsupported function. */
|
||||
if ((func <= dev->max_func) || ((func == 1) && (dev->max_func == 0))) {
|
||||
fregs = (uint8_t *) dev->regs[func];
|
||||
@@ -995,6 +1004,8 @@ piix_reset_hard(piix_t *dev)
|
||||
fregs[0x69] = 0x02;
|
||||
if ((dev->type == 1) && (dev->rev != 2))
|
||||
fregs[0x6a] = 0x04;
|
||||
else if (dev->type == 3)
|
||||
fregs[0x6a] = 0x10;
|
||||
fregs[0x70] = (dev->type < 4) ? 0x80 : 0x00;
|
||||
fregs[0x71] = (dev->type < 3) ? 0x80 : 0x00;
|
||||
if (dev->type <= 4) {
|
||||
@@ -1065,7 +1076,7 @@ piix_reset_hard(piix_t *dev)
|
||||
fregs[0xc1] = 0x20;
|
||||
fregs[0xff] = (dev->type > 3) ? 0x10 : 0x00;
|
||||
}
|
||||
dev->max_func = 1; /* It starts with USB disabled, then enables it. */
|
||||
dev->max_func = 2; /* It starts with USB disabled, then enables it. */
|
||||
}
|
||||
|
||||
/* Function 3: Power Management */
|
||||
@@ -1149,6 +1160,13 @@ piix_reset(void *p)
|
||||
piix_write(0, 0xa7, 0x00, p);
|
||||
piix_write(0, 0xa8, 0x0f, p);
|
||||
}
|
||||
|
||||
piix_write(1, 0x04, 0x00, p);
|
||||
piix_write(1, 0x41, 0x00, p);
|
||||
piix_write(1, 0x43, 0x00, p);
|
||||
|
||||
ide_pri_disable();
|
||||
ide_sec_disable();
|
||||
}
|
||||
|
||||
|
||||
@@ -1161,6 +1179,20 @@ piix_close(void *p)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
piix_speed_changed(void *priv)
|
||||
{
|
||||
piix_t *dev = (piix_t *) priv;
|
||||
int te;
|
||||
|
||||
te = timer_is_enabled(&dev->fast_off_timer);
|
||||
|
||||
timer_stop(&dev->fast_off_timer);
|
||||
if (te)
|
||||
timer_on_auto(&dev->fast_off_timer, dev->fast_off_period);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
*piix_init(const device_t *info)
|
||||
{
|
||||
@@ -1300,7 +1332,7 @@ const device_t piix_device =
|
||||
piix_close,
|
||||
piix_reset,
|
||||
NULL,
|
||||
NULL,
|
||||
piix_speed_changed,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
@@ -1314,7 +1346,7 @@ const device_t piix_rev02_device =
|
||||
piix_close,
|
||||
piix_reset,
|
||||
NULL,
|
||||
NULL,
|
||||
piix_speed_changed,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
@@ -1328,7 +1360,7 @@ const device_t piix3_device =
|
||||
piix_close,
|
||||
piix_reset,
|
||||
NULL,
|
||||
NULL,
|
||||
piix_speed_changed,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
@@ -1342,7 +1374,7 @@ const device_t piix4_device =
|
||||
piix_close,
|
||||
piix_reset,
|
||||
NULL,
|
||||
NULL,
|
||||
piix_speed_changed,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
@@ -1356,7 +1388,7 @@ const device_t piix4e_device =
|
||||
piix_close,
|
||||
piix_reset,
|
||||
NULL,
|
||||
NULL,
|
||||
piix_speed_changed,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
@@ -1370,7 +1402,7 @@ const device_t slc90e66_device =
|
||||
piix_close,
|
||||
piix_reset,
|
||||
NULL,
|
||||
NULL,
|
||||
piix_speed_changed,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
573
src/chipset/intel_sio.c
Normal file
573
src/chipset/intel_sio.c
Normal file
@@ -0,0 +1,573 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Emulation of Intel System I/O PCI chip.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/apm.h>
|
||||
#include <86box/dma.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/pci.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/pit.h>
|
||||
#include <86box/port_92.h>
|
||||
#include <86box/machine.h>
|
||||
#include <86box/chipset.h>
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t id,
|
||||
regs[256];
|
||||
|
||||
uint16_t timer_base,
|
||||
timer_latch;
|
||||
|
||||
double fast_off_period;
|
||||
|
||||
pc_timer_t timer, fast_off_timer;
|
||||
|
||||
apm_t * apm;
|
||||
port_92_t * port_92;
|
||||
} sio_t;
|
||||
|
||||
|
||||
#ifdef ENABLE_SIO_LOG
|
||||
int sio_do_log = ENABLE_SIO_LOG;
|
||||
|
||||
|
||||
static void
|
||||
sio_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (sio_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define sio_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
sio_timer_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
sio_t *dev = (sio_t *) priv;
|
||||
|
||||
if (!(addr & 0x0002)) {
|
||||
if (addr & 0x0001)
|
||||
dev->timer_latch = (dev->timer_latch & 0xff) | (val << 8);
|
||||
else
|
||||
dev->timer_latch = (dev->timer_latch & 0xff00) | val;
|
||||
|
||||
timer_set_delay_u64(&dev->timer, ((uint64_t) dev->timer_latch) * TIMER_USEC);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sio_timer_writew(uint16_t addr, uint16_t val, void *priv)
|
||||
{
|
||||
sio_t *dev = (sio_t *) priv;
|
||||
|
||||
if (!(addr & 0x0002)) {
|
||||
dev->timer_latch = val;
|
||||
|
||||
timer_set_delay_u64(&dev->timer, ((uint64_t) dev->timer_latch) * TIMER_USEC);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
sio_timer_read(uint16_t addr, void *priv)
|
||||
{
|
||||
sio_t *dev = (sio_t *) priv;
|
||||
uint16_t sio_timer_latch;
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
if (!(addr & 0x0002)) {
|
||||
sub_cycles((int)(PITCONST >> 32));
|
||||
|
||||
sio_timer_latch = timer_get_remaining_us(&dev->timer);
|
||||
|
||||
if (addr & 0x0001)
|
||||
ret = sio_timer_latch >> 8;
|
||||
else
|
||||
ret = sio_timer_latch & 0xff;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static uint16_t
|
||||
sio_timer_readw(uint16_t addr, void *priv)
|
||||
{
|
||||
sio_t *dev = (sio_t *) priv;
|
||||
uint16_t ret = 0xffff;
|
||||
|
||||
if (!(addr & 0x0002)) {
|
||||
sub_cycles((int)(PITCONST >> 32));
|
||||
|
||||
ret = timer_get_remaining_us(&dev->timer);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sio_write(int func, int addr, uint8_t val, void *priv)
|
||||
{
|
||||
sio_t *dev = (sio_t *) priv;
|
||||
uint8_t old;
|
||||
|
||||
if (func > 0)
|
||||
return;
|
||||
|
||||
if (((addr >= 0x0f) && (addr < 0x4c)) && (addr != 0x40))
|
||||
return;
|
||||
|
||||
/* The IB (original) variant of the SIO has no PCI IRQ steering. */
|
||||
if ((addr >= 0x60) && (addr <= 0x63) && (dev->id < 0x03))
|
||||
return;
|
||||
|
||||
old = dev->regs[addr];
|
||||
|
||||
switch (addr) {
|
||||
case 0x04: /*Command register*/
|
||||
if (dev->id == 0x03)
|
||||
dev->regs[addr] = (dev->regs[addr] & 0xf7) | (val & 0x08);
|
||||
break;
|
||||
|
||||
case 0x07:
|
||||
dev->regs[addr] &= ~(val & 0x38);
|
||||
break;
|
||||
|
||||
case 0x40:
|
||||
if (dev->id == 0x03) {
|
||||
dev->regs[addr] = (val & 0x7f);
|
||||
|
||||
if (!((val ^ old) & 0x40))
|
||||
return;
|
||||
|
||||
dma_alias_remove();
|
||||
if (!(val & 0x40))
|
||||
dma_alias_set();
|
||||
} else
|
||||
dev->regs[addr] = (val & 0x3f);
|
||||
break;
|
||||
case 0x41: case 0x44:
|
||||
dev->regs[addr] = (val & 0x1f);
|
||||
break;
|
||||
case 0x42:
|
||||
if (dev->id == 0x03)
|
||||
dev->regs[addr] = val;
|
||||
else
|
||||
dev->regs[addr] = (val & 0x77);
|
||||
break;
|
||||
case 0x43:
|
||||
if (dev->id == 0x03)
|
||||
dev->regs[addr] = (val & 0x01);
|
||||
break;
|
||||
case 0x45: case 0x46:
|
||||
case 0x47: case 0x48:
|
||||
case 0x49: case 0x4a:
|
||||
case 0x4b: case 0x4e:
|
||||
case 0x54: case 0x55:
|
||||
case 0x56:
|
||||
dev->regs[addr] = val;
|
||||
break;
|
||||
case 0x4c: case 0x4d:
|
||||
dev->regs[addr] = (val & 0x7f);
|
||||
break;
|
||||
case 0x4f:
|
||||
dev->regs[addr] = val;
|
||||
|
||||
if (!((val ^ old) & 0x40))
|
||||
return;
|
||||
|
||||
port_92_remove(dev->port_92);
|
||||
if (val & 0x40)
|
||||
port_92_add(dev->port_92);
|
||||
break;
|
||||
case 0x57:
|
||||
dev->regs[addr] = val;
|
||||
|
||||
dma_remove_sg();
|
||||
dma_set_sg_base(val);
|
||||
break;
|
||||
case 0x60: case 0x61: case 0x62: case 0x63:
|
||||
if (dev->id == 0x03) {
|
||||
sio_log("Set IRQ routing: INT %c -> %02X\n", 0x41 + (addr & 0x03), val);
|
||||
dev->regs[addr] = val & 0x8f;
|
||||
if (val & 0x80)
|
||||
pci_set_irq_routing(PCI_INTA + (addr & 0x03), PCI_IRQ_DISABLED);
|
||||
else
|
||||
pci_set_irq_routing(PCI_INTA + (addr & 0x03), val & 0xf);
|
||||
}
|
||||
break;
|
||||
case 0x80:
|
||||
case 0x81:
|
||||
if (addr == 0x80)
|
||||
dev->regs[addr] = val & 0xfd;
|
||||
else
|
||||
dev->regs[addr] = val;
|
||||
|
||||
if (dev->timer_base & 0x01) {
|
||||
io_removehandler(dev->timer_base & 0xfffc, 0x0004,
|
||||
sio_timer_read, sio_timer_readw, NULL,
|
||||
sio_timer_write, sio_timer_writew, NULL, dev);
|
||||
}
|
||||
dev->timer_base = (dev->regs[0x81] << 8) | (dev->regs[0x80] & 0xfd);
|
||||
if (dev->timer_base & 0x01) {
|
||||
io_sethandler(dev->timer_base & 0xfffc, 0x0004,
|
||||
sio_timer_read, sio_timer_readw, NULL,
|
||||
sio_timer_write, sio_timer_writew, NULL, dev);
|
||||
}
|
||||
break;
|
||||
case 0xa0:
|
||||
if (dev->id == 0x03) {
|
||||
dev->regs[addr] = val & 0x1f;
|
||||
apm_set_do_smi(dev->apm, !!(val & 0x01) && !!(dev->regs[0xa2] & 0x80));
|
||||
switch ((val & 0x18) >> 3) {
|
||||
case 0x00:
|
||||
dev->fast_off_period = PCICLK * 32768.0 * 60000.0;
|
||||
break;
|
||||
case 0x01:
|
||||
default:
|
||||
dev->fast_off_period = 0.0;
|
||||
break;
|
||||
case 0x02:
|
||||
dev->fast_off_period = PCICLK;
|
||||
break;
|
||||
case 0x03:
|
||||
dev->fast_off_period = PCICLK * 32768.0;
|
||||
break;
|
||||
}
|
||||
cpu_fast_off_count = dev->regs[0xa8] + 1;
|
||||
timer_disable(&dev->fast_off_timer);
|
||||
if (dev->fast_off_period != 0.0)
|
||||
timer_on_auto(&dev->fast_off_timer, dev->fast_off_period);
|
||||
}
|
||||
break;
|
||||
case 0xa2:
|
||||
if (dev->id == 0x03) {
|
||||
dev->regs[addr] = val & 0xff;
|
||||
apm_set_do_smi(dev->apm, !!(dev->regs[0xa0] & 0x01) && !!(val & 0x80));
|
||||
}
|
||||
break;
|
||||
case 0xaa:
|
||||
if (dev->id == 0x03)
|
||||
dev->regs[addr] &= (val & 0xff);
|
||||
break;
|
||||
case 0xac: case 0xae:
|
||||
if (dev->id == 0x03)
|
||||
dev->regs[addr] = val & 0xff;
|
||||
break;
|
||||
case 0xa4:
|
||||
if (dev->id == 0x03) {
|
||||
dev->regs[addr] = val & 0xfb;
|
||||
cpu_fast_off_flags = (cpu_fast_off_flags & 0xffffff00) | dev->regs[addr];
|
||||
}
|
||||
break;
|
||||
case 0xa5:
|
||||
if (dev->id == 0x03) {
|
||||
dev->regs[addr] = val & 0xff;
|
||||
cpu_fast_off_flags = (cpu_fast_off_flags & 0xffff00ff) | (dev->regs[addr] << 8);
|
||||
}
|
||||
break;
|
||||
case 0xa7:
|
||||
if (dev->id == 0x03) {
|
||||
dev->regs[addr] = val & 0xa0;
|
||||
cpu_fast_off_flags = (cpu_fast_off_flags & 0x00ffffff) | (dev->regs[addr] << 24);
|
||||
}
|
||||
break;
|
||||
case 0xa8:
|
||||
dev->regs[addr] = val & 0xff;
|
||||
cpu_fast_off_val = val;
|
||||
cpu_fast_off_count = val + 1;
|
||||
timer_disable(&dev->fast_off_timer);
|
||||
if (dev->fast_off_period != 0.0)
|
||||
timer_on_auto(&dev->fast_off_timer, dev->fast_off_period);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
sio_read(int func, int addr, void *priv)
|
||||
{
|
||||
sio_t *dev = (sio_t *) priv;
|
||||
uint8_t ret;
|
||||
|
||||
ret = 0xff;
|
||||
|
||||
if (func == 0)
|
||||
ret = dev->regs[addr];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sio_config_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
sio_config_read(uint16_t port, void *priv)
|
||||
{
|
||||
uint8_t ret = 0x00;
|
||||
|
||||
switch (port & 0x000f) {
|
||||
case 3:
|
||||
ret = 0xff;
|
||||
break;
|
||||
case 5:
|
||||
ret = 0xd3;
|
||||
|
||||
switch (cpu_pci_speed) {
|
||||
case 20000000:
|
||||
ret |= 0x0c;
|
||||
break;
|
||||
case 25000000:
|
||||
default:
|
||||
ret |= 0x00;
|
||||
break;
|
||||
case 30000000:
|
||||
ret |= 0x08;
|
||||
break;
|
||||
case 33333333:
|
||||
ret |= 0x04;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sio_reset_hard(void *priv)
|
||||
{
|
||||
sio_t *dev = (sio_t *) priv;
|
||||
|
||||
memset(dev->regs, 0, 256);
|
||||
|
||||
dev->regs[0x00] = 0x86; dev->regs[0x01] = 0x80; /*Intel*/
|
||||
dev->regs[0x02] = 0x84; dev->regs[0x03] = 0x04; /*82378IB (SIO)*/
|
||||
dev->regs[0x04] = 0x07;
|
||||
dev->regs[0x07] = 0x02;
|
||||
dev->regs[0x08] = dev->id;
|
||||
|
||||
dev->regs[0x40] = 0x20; dev->regs[0x41] = 0x00;
|
||||
dev->regs[0x42] = 0x04;
|
||||
dev->regs[0x45] = 0x10; dev->regs[0x46] = 0x0f;
|
||||
dev->regs[0x48] = 0x01;
|
||||
dev->regs[0x4a] = 0x10; dev->regs[0x4b] = 0x0f;
|
||||
dev->regs[0x4c] = 0x56; dev->regs[0x4d] = 0x40;
|
||||
dev->regs[0x4e] = 0x07; dev->regs[0x4f] = 0x4f;
|
||||
dev->regs[0x57] = 0x04;
|
||||
if (dev->id == 0x03) {
|
||||
dev->regs[0x60] = 0x80; dev->regs[0x61] = 0x80; dev->regs[0x62] = 0x80; dev->regs[0x63] = 0x80;
|
||||
}
|
||||
dev->regs[0x80] = 0x78;
|
||||
if (dev->id == 0x03) {
|
||||
dev->regs[0xa0] = 0x08;
|
||||
dev->regs[0xa8] = 0x0f;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (dev->timer_base & 0x0001) {
|
||||
io_removehandler(dev->timer_base & 0xfffc, 0x0004,
|
||||
sio_timer_read, sio_timer_readw, NULL,
|
||||
sio_timer_write, sio_timer_writew, NULL, dev);
|
||||
}
|
||||
|
||||
dev->timer_base = 0x0078;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sio_apm_out(uint16_t port, uint8_t val, void *p)
|
||||
{
|
||||
sio_t *dev = (sio_t *) p;
|
||||
|
||||
if (dev->apm->do_smi)
|
||||
dev->regs[0xaa] |= 0x80;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sio_fast_off_count(void *priv)
|
||||
{
|
||||
sio_t *dev = (sio_t *) priv;
|
||||
|
||||
cpu_fast_off_count--;
|
||||
|
||||
if (cpu_fast_off_count == 0) {
|
||||
smi_line = 1;
|
||||
dev->regs[0xaa] |= 0x20;
|
||||
cpu_fast_off_count = dev->regs[0xa8] + 1;
|
||||
}
|
||||
|
||||
timer_on_auto(&dev->fast_off_timer, dev->fast_off_period);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sio_reset(void *p)
|
||||
{
|
||||
sio_t *dev = (sio_t *) p;
|
||||
|
||||
sio_write(0, 0x57, 0x04, p);
|
||||
|
||||
dma_set_params(1, 0xffffffff);
|
||||
|
||||
if (dev->id == 0x03) {
|
||||
sio_write(0, 0xa0, 0x08, p);
|
||||
sio_write(0, 0xa2, 0x00, p);
|
||||
sio_write(0, 0xa4, 0x00, p);
|
||||
sio_write(0, 0xa5, 0x00, p);
|
||||
sio_write(0, 0xa6, 0x00, p);
|
||||
sio_write(0, 0xa7, 0x00, p);
|
||||
sio_write(0, 0xa8, 0x0f, p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sio_close(void *p)
|
||||
{
|
||||
sio_t *dev = (sio_t *)p;
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sio_speed_changed(void *priv)
|
||||
{
|
||||
sio_t *dev = (sio_t *) priv;
|
||||
int te;
|
||||
|
||||
te = timer_is_enabled(&dev->timer);
|
||||
|
||||
timer_disable(&dev->timer);
|
||||
if (te)
|
||||
timer_set_delay_u64(&dev->timer, ((uint64_t) dev->timer_latch) * TIMER_USEC);
|
||||
|
||||
if (dev->id == 0x03) {
|
||||
te = timer_is_enabled(&dev->fast_off_timer);
|
||||
|
||||
timer_stop(&dev->fast_off_timer);
|
||||
if (te)
|
||||
timer_on_auto(&dev->fast_off_timer, dev->fast_off_period);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
sio_init(const device_t *info)
|
||||
{
|
||||
sio_t *dev = (sio_t *) malloc(sizeof(sio_t));
|
||||
memset(dev, 0, sizeof(sio_t));
|
||||
|
||||
pci_add_card(PCI_ADD_SOUTHBRIDGE, sio_read, sio_write, dev);
|
||||
|
||||
dev->id = info->local;
|
||||
|
||||
if (dev->id == 0x03)
|
||||
timer_add(&dev->fast_off_timer, sio_fast_off_count, dev, 0);
|
||||
|
||||
sio_reset_hard(dev);
|
||||
|
||||
cpu_fast_off_flags = 0x00000000;
|
||||
|
||||
if (dev->id == 0x03) {
|
||||
cpu_fast_off_val = dev->regs[0xa8];
|
||||
cpu_fast_off_count = cpu_fast_off_val + 1;
|
||||
} else
|
||||
cpu_fast_off_val = cpu_fast_off_count = 0;
|
||||
|
||||
if (dev->id == 0x03) {
|
||||
dev->apm = device_add(&apm_pci_device);
|
||||
/* APM intercept handler to update 82378ZB SMI status on APM SMI. */
|
||||
io_sethandler(0x00b2, 0x0001, NULL, NULL, NULL, sio_apm_out, NULL, NULL, dev);
|
||||
}
|
||||
|
||||
dev->port_92 = device_add(&port_92_pci_device);
|
||||
|
||||
dma_set_sg_base(0x04);
|
||||
dma_set_params(1, 0xffffffff);
|
||||
dma_ext_mode_init();
|
||||
dma_high_page_init();
|
||||
|
||||
if (dev->id == 0x03)
|
||||
dma_alias_set();
|
||||
|
||||
io_sethandler(0x0073, 0x0001,
|
||||
sio_config_read, NULL, NULL, sio_config_write, NULL, NULL, dev);
|
||||
io_sethandler(0x0075, 0x0001,
|
||||
sio_config_read, NULL, NULL, sio_config_write, NULL, NULL, dev);
|
||||
|
||||
timer_add(&dev->timer, NULL, NULL, 0);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
const device_t sio_device =
|
||||
{
|
||||
"Intel 82378IB (SIO)",
|
||||
DEVICE_PCI,
|
||||
0x00,
|
||||
sio_init,
|
||||
sio_close,
|
||||
sio_reset,
|
||||
NULL,
|
||||
sio_speed_changed,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
const device_t sio_zb_device =
|
||||
{
|
||||
"Intel 82378ZB (SIO)",
|
||||
DEVICE_PCI,
|
||||
0x03,
|
||||
sio_init,
|
||||
sio_close,
|
||||
sio_reset,
|
||||
NULL,
|
||||
sio_speed_changed,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
@@ -1,119 +0,0 @@
|
||||
#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/keyboard.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/fdd.h>
|
||||
#include <86box/fdc.h>
|
||||
#include <86box/chipset.h>
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t cur_reg,
|
||||
regs[16];
|
||||
} rabbit_t;
|
||||
|
||||
/*
|
||||
static void
|
||||
rabbit_recalcmapping(rabbit_t *dev)
|
||||
{
|
||||
uint32_t base;
|
||||
uint32_t i, shflags = 0;
|
||||
|
||||
shadowbios = 0;
|
||||
shadowbios_write = 0;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
base = 0xc0000 + (i << 15);
|
||||
|
||||
if (dev->regs[0x00] & 0x08) {
|
||||
shadowbios |= (base >= 0xe0000) && (dev->regs[0x02] & 0x80);
|
||||
shadowbios_write |= (base >= 0xe0000) && !(dev->regs[0x02] & 0x40);
|
||||
shflags = (dev->regs[0x00] & 0x01) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
|
||||
shflags |= (dev->regs[0x00] & 0x08) ? MEM_WRITE_EXTANY : MEM_WRITE_INTERNAL;
|
||||
mem_set_mem_state(base, 0x8000, shflags);
|
||||
} else
|
||||
mem_set_mem_state(base, 0x8000, MEM_READ_EXTANY | MEM_WRITE_EXTERNAL);
|
||||
}
|
||||
|
||||
flushmmucache();
|
||||
}
|
||||
*/
|
||||
|
||||
static void
|
||||
rabbit_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
rabbit_t *dev = (rabbit_t *) priv;
|
||||
|
||||
switch (addr) {
|
||||
case 0x22:
|
||||
dev->cur_reg = val;
|
||||
break;
|
||||
case 0x23:
|
||||
dev->regs[dev->cur_reg] = val;
|
||||
/*
|
||||
if (dev->cur_reg == 0x00) {
|
||||
rabbit_recalcmapping(dev);
|
||||
}
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
rabbit_read(uint16_t addr, void *priv)
|
||||
{
|
||||
uint8_t ret = 0xff;
|
||||
rabbit_t *dev = (rabbit_t *) priv;
|
||||
|
||||
switch (addr) {
|
||||
case 0x23:
|
||||
ret = dev->regs[dev->cur_reg];
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
rabbit_close(void *priv)
|
||||
{
|
||||
rabbit_t *dev = (rabbit_t *) priv;
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
rabbit_init(const device_t *info)
|
||||
{
|
||||
rabbit_t *dev = (rabbit_t *) malloc(sizeof(rabbit_t));
|
||||
memset(dev, 0, sizeof(rabbit_t));
|
||||
|
||||
io_sethandler(0x0022, 0x0001, rabbit_read, NULL, NULL, rabbit_write, NULL, NULL, dev);
|
||||
io_sethandler(0x0023, 0x0001, rabbit_read, NULL, NULL, rabbit_write, NULL, NULL, dev);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
const device_t rabbit_device = {
|
||||
"SiS Rabbit",
|
||||
0,
|
||||
0,
|
||||
rabbit_init, rabbit_close, NULL,
|
||||
NULL, NULL, NULL,
|
||||
NULL
|
||||
};
|
||||
150
src/chipset/sis_85c310.c
Normal file
150
src/chipset/sis_85c310.c
Normal file
@@ -0,0 +1,150 @@
|
||||
#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/keyboard.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/fdd.h>
|
||||
#include <86box/fdc.h>
|
||||
#include <86box/chipset.h>
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t cur_reg, tries,
|
||||
regs[258];
|
||||
} rabbit_t;
|
||||
|
||||
|
||||
static void
|
||||
rabbit_recalcmapping(rabbit_t *dev)
|
||||
{
|
||||
uint32_t shread, shwrite;
|
||||
uint32_t shflags = 0;
|
||||
|
||||
shread = !!(dev->regs[0x101] & 0x40);
|
||||
shwrite = !!(dev->regs[0x100] & 0x02);
|
||||
|
||||
shflags = shread ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
|
||||
shflags |= shwrite ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
|
||||
|
||||
shadowbios = !!shread;
|
||||
shadowbios_write = !!shwrite;
|
||||
|
||||
#ifdef USE_SHADOW_C0000
|
||||
mem_set_mem_state(0x000c0000, 0x00040000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
|
||||
#else
|
||||
mem_set_mem_state(0x000e0000, 0x00020000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
|
||||
#endif
|
||||
|
||||
switch (dev->regs[0x100] & 0x09) {
|
||||
case 0x01:
|
||||
/* The one BIOS we use seems to use something else to control C0000-DFFFF shadow,
|
||||
no idea what. */
|
||||
#ifdef USE_SHADOW_C0000
|
||||
/* 64K at 0C0000-0CFFFF */
|
||||
mem_set_mem_state(0x000c0000, 0x00010000, shflags);
|
||||
/* FALLTHROUGH */
|
||||
#endif
|
||||
case 0x00:
|
||||
/* 64K at 0F0000-0FFFFF */
|
||||
mem_set_mem_state(0x000f0000, 0x00010000, shflags);
|
||||
break;
|
||||
|
||||
case 0x09:
|
||||
#ifdef USE_SHADOW_C0000
|
||||
/* 128K at 0C0000-0DFFFF */
|
||||
mem_set_mem_state(0x000c0000, 0x00020000, shflags);
|
||||
/* FALLTHROUGH */
|
||||
#endif
|
||||
case 0x08:
|
||||
/* 128K at 0E0000-0FFFFF */
|
||||
mem_set_mem_state(0x000e0000, 0x00020000, shflags);
|
||||
break;
|
||||
}
|
||||
|
||||
flushmmucache();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
rabbit_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
rabbit_t *dev = (rabbit_t *) priv;
|
||||
|
||||
switch (addr) {
|
||||
case 0x22:
|
||||
dev->cur_reg = val;
|
||||
dev->tries = 0;
|
||||
break;
|
||||
case 0x23:
|
||||
if (dev->cur_reg == 0x83) {
|
||||
if (dev->tries < 0x02) {
|
||||
dev->regs[dev->tries++ | 0x100] = val;
|
||||
if (dev->tries == 0x02)
|
||||
rabbit_recalcmapping(dev);
|
||||
}
|
||||
} else
|
||||
dev->regs[dev->cur_reg] = val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
rabbit_read(uint16_t addr, void *priv)
|
||||
{
|
||||
uint8_t ret = 0xff;
|
||||
rabbit_t *dev = (rabbit_t *) priv;
|
||||
|
||||
switch (addr) {
|
||||
case 0x23:
|
||||
if (dev->cur_reg == 0x83) {
|
||||
if (dev->tries < 0x02)
|
||||
ret = dev->regs[dev->tries++ | 0x100];
|
||||
} else
|
||||
ret = dev->regs[dev->cur_reg];
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
rabbit_close(void *priv)
|
||||
{
|
||||
rabbit_t *dev = (rabbit_t *) priv;
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
rabbit_init(const device_t *info)
|
||||
{
|
||||
rabbit_t *dev = (rabbit_t *) malloc(sizeof(rabbit_t));
|
||||
memset(dev, 0, sizeof(rabbit_t));
|
||||
|
||||
io_sethandler(0x0022, 0x0002, rabbit_read, NULL, NULL, rabbit_write, NULL, NULL, dev);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
const device_t rabbit_device = {
|
||||
"SiS Rabbit",
|
||||
0,
|
||||
0,
|
||||
rabbit_init, rabbit_close, NULL,
|
||||
NULL, NULL, NULL,
|
||||
NULL
|
||||
};
|
||||
@@ -46,16 +46,16 @@ apollo_map(uint32_t addr, uint32_t size, int state)
|
||||
{
|
||||
switch (state & 3) {
|
||||
case 0:
|
||||
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
|
||||
mem_set_mem_state_both(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
|
||||
break;
|
||||
case 1:
|
||||
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
|
||||
mem_set_mem_state_both(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
|
||||
break;
|
||||
case 2:
|
||||
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY);
|
||||
mem_set_mem_state_both(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY);
|
||||
break;
|
||||
case 3:
|
||||
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
|
||||
mem_set_mem_state_both(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -64,20 +64,17 @@ apollo_map(uint32_t addr, uint32_t size, int state)
|
||||
|
||||
|
||||
static void
|
||||
apollo_smram_map(int smm, uint32_t addr, uint32_t size, int ram)
|
||||
apollo_smram_map(int smm, uint32_t addr, uint32_t size, int is_smram)
|
||||
{
|
||||
int state = (MEM_READ_EXTANY | MEM_WRITE_EXTANY);
|
||||
if (((is_smram & 0x03) == 0x01) || ((is_smram & 0x03) == 0x02)) {
|
||||
smram[0].ram_base = 0x000a0000;
|
||||
smram[0].size = size;
|
||||
|
||||
if (ram == 0)
|
||||
state = (MEM_READ_EXTANY | MEM_WRITE_EXTANY);
|
||||
else if (ram == 1)
|
||||
state = (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
|
||||
else if (ram == 2)
|
||||
state = (MEM_READ_EXTERNAL_EX | MEM_WRITE_EXTANY);
|
||||
else if (ram == 3)
|
||||
state = (MEM_READ_DISABLED | MEM_WRITE_DISABLED);
|
||||
mem_mapping_set_addr(&ram_smram_mapping[0], smram[0].host_base, size);
|
||||
mem_mapping_set_exec(&ram_smram_mapping[0], ram + smram[0].ram_base);
|
||||
}
|
||||
|
||||
mem_set_mem_state_common(smm, addr, size, state);
|
||||
mem_set_mem_state_smram_ex(smm, addr, size, is_smram & 0x03);
|
||||
flushmmucache();
|
||||
}
|
||||
|
||||
@@ -272,6 +269,14 @@ via_apollo_host_bridge_write(int func, int addr, uint8_t val, void *priv)
|
||||
if ((dev->pci_conf[0][0x63] ^ val) & 0xc0)
|
||||
apollo_map(0xe0000, 0x10000, (val & 0xc0) >> 6);
|
||||
dev->pci_conf[0][0x63] = val;
|
||||
if (smram[0].size != 0x00000000) {
|
||||
mem_set_mem_state_smram_ex(0, smram[0].host_base, smram[0].size, 0x00);
|
||||
mem_set_mem_state_smram_ex(1, smram[0].host_base, smram[0].size, 0x00);
|
||||
|
||||
memset(&smram[0], 0x00, sizeof(smram_t));
|
||||
mem_mapping_disable(&ram_smram_mapping[0]);
|
||||
flushmmucache();
|
||||
}
|
||||
if (dev->id == 0x0691) switch (val & 0x03) {
|
||||
case 0x00:
|
||||
default:
|
||||
@@ -310,9 +315,9 @@ via_apollo_host_bridge_write(int func, int addr, uint8_t val, void *priv)
|
||||
/* Reserved */
|
||||
apollo_smram_map(1, 0x000a0000, 0x00020000, 3);
|
||||
if (dev->id == 0x0597) {
|
||||
/* TODO: SMI 3xxxx-4xxxx redirect to Axxxx-Bxxxx
|
||||
(this needs a 3xxxx-4xxxx mapping set to EXTERNAL). */
|
||||
apollo_smram_map(1, 0x00030000, 0x00020000, 3);
|
||||
/* SMI 3xxxx-4xxxx redirect to Axxxx-Bxxxx. */
|
||||
smram[0].host_base = 0x00030000;
|
||||
apollo_smram_map(1, 0x00030000, 0x00020000, 1);
|
||||
}
|
||||
apollo_smram_map(0, 0x000a0000, 0x00020000, 3);
|
||||
break;
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
#include <86box/hdc_ide_sff8038i.h>
|
||||
#include <86box/zip.h>
|
||||
#include <86box/machine.h>
|
||||
#include <86box/via_vt82c586b.h>
|
||||
#include <86box/chipset.h>
|
||||
|
||||
|
||||
#define ACPI_TIMER_FREQ 3579545
|
||||
@@ -49,7 +49,7 @@
|
||||
#include <86box/hdc_ide_sff8038i.h>
|
||||
#include <86box/zip.h>
|
||||
#include <86box/machine.h>
|
||||
#include <86box/via_vt82c586b.h>
|
||||
#include <86box/chipset.h>
|
||||
|
||||
// As of now
|
||||
#include <86box/smbus_piix4.h>
|
||||
@@ -38,7 +38,7 @@
|
||||
#define _CODEGEN_H_
|
||||
|
||||
#include <86box/mem.h>
|
||||
#include "../cpu_common/x86_ops.h"
|
||||
#include "x86_ops.h"
|
||||
|
||||
#ifdef __amd64__
|
||||
#include "codegen_x86-64.h"
|
||||
@@ -48,7 +48,7 @@
|
||||
#include <86box/mem.h>
|
||||
#include "x86.h"
|
||||
#include "x86_flags.h"
|
||||
#include "../cpu_common/x86_ops.h"
|
||||
#include "x86_ops.h"
|
||||
#include "x87.h"
|
||||
|
||||
#include "386_common.h"
|
||||
@@ -614,7 +614,10 @@ generate_call:
|
||||
To prevent having zero cycle blocks (eg with a jump instruction pointing
|
||||
to itself), apply the cycles that would be taken if this jump is taken,
|
||||
then reverse it for subsequent instructions if the jump is not taken*/
|
||||
int jump_cycles = codegen_timing_jump_cycles();
|
||||
int jump_cycles = 0;
|
||||
|
||||
if (codegen_timing_jump_cycles)
|
||||
codegen_timing_jump_cycles();
|
||||
|
||||
if (jump_cycles)
|
||||
codegen_accumulate(ACCREG_cycles, -jump_cycles);
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#include <86box/mem.h>
|
||||
#include <stddef.h>
|
||||
#include "../cpu_common/x86_ops.h"
|
||||
#include "x86_ops.h"
|
||||
|
||||
/*Handling self-modifying code (of which there is a lot on x86) :
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user