mirror of
https://github.com/86Box/86Box.git
synced 2026-02-21 17:15:32 -07:00
Merge branch 'master' into pc98x1
This commit is contained in:
2
.ci/Jenkinsfile
vendored
2
.ci/Jenkinsfile
vendored
@@ -20,7 +20,7 @@ def repository = ['https://github.com/86Box/86Box.git', scm.userRemoteConfigs[0]
|
||||
def commitBrowser = ['https://github.com/86Box/86Box/commit/%s', null]
|
||||
def branch = ['master', scm.branches[0].name]
|
||||
def buildType = ['beta', 'alpha']
|
||||
def tarballFlags = ['', '-s']
|
||||
def tarballFlags = ['', '-t']
|
||||
def buildBranch = env.JOB_BASE_NAME.contains('-') ? 1 : 0
|
||||
|
||||
def osArchs = [
|
||||
|
||||
18
.github/workflows/cmake_macos.yml
vendored
18
.github/workflows/cmake_macos.yml
vendored
@@ -56,22 +56,13 @@ jobs:
|
||||
- name: SDL GUI
|
||||
qt: off
|
||||
static: on
|
||||
src-packages: >-
|
||||
libsndfile
|
||||
- name: Qt GUI
|
||||
qt: on
|
||||
slug: -Qt
|
||||
packages: >-
|
||||
qt@5
|
||||
src-packages: >-
|
||||
libsndfile
|
||||
|
||||
steps:
|
||||
- name: Install source dependencies
|
||||
run: >-
|
||||
brew reinstall -s
|
||||
${{ matrix.ui.src-packages }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: >-
|
||||
brew install
|
||||
@@ -158,22 +149,13 @@ jobs:
|
||||
- name: SDL GUI
|
||||
qt: off
|
||||
static: on
|
||||
src-packages: >-
|
||||
libsndfile
|
||||
- name: Qt GUI
|
||||
qt: on
|
||||
slug: -Qt
|
||||
packages: >-
|
||||
qt@5
|
||||
src-packages: >-
|
||||
libsndfile
|
||||
|
||||
steps:
|
||||
- name: Install source dependencies
|
||||
run: >-
|
||||
brew reinstall -s
|
||||
${{ matrix.ui.src-packages }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: >-
|
||||
brew install
|
||||
|
||||
74
.github/workflows/cmake_windows_msys2.yml
vendored
74
.github/workflows/cmake_windows_msys2.yml
vendored
@@ -18,7 +18,6 @@ on:
|
||||
- cmake/**
|
||||
- "**/CMakeLists.txt"
|
||||
- "CMakePresets.json"
|
||||
- .github/workflows/**
|
||||
- .github/workflows/cmake_windows_msys2.yml
|
||||
- vcpkg.json
|
||||
- "!**/Makefile*"
|
||||
@@ -26,9 +25,9 @@ on:
|
||||
jobs:
|
||||
|
||||
msys2:
|
||||
name: "${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, ${{ matrix.environment.msystem }}"
|
||||
name: "${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, ${{ matrix.environment.msystem }}"
|
||||
|
||||
runs-on: windows-2022
|
||||
runs-on: ${{ matrix.environment.runner }}
|
||||
|
||||
env:
|
||||
BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed
|
||||
@@ -41,47 +40,38 @@ jobs:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
build:
|
||||
# - name: Regular
|
||||
# preset: regular
|
||||
- name: Debug
|
||||
- name: Dev Debug
|
||||
preset: dev_debug
|
||||
slug: -Debug
|
||||
slug: -Dev-Debug
|
||||
- name: Dev
|
||||
preset: development
|
||||
slug: -Dev
|
||||
dynarec:
|
||||
- name: ODR
|
||||
new: off
|
||||
slug: -ODR
|
||||
- name: NDR
|
||||
new: on
|
||||
slug: -NDR
|
||||
ui:
|
||||
- name: Qt GUI
|
||||
qt: on
|
||||
static: on
|
||||
slug: -Qt
|
||||
packages: >-
|
||||
qt5-static:p
|
||||
vulkan-headers:p
|
||||
environment:
|
||||
# - msystem: MSYS
|
||||
# toolchain: ./cmake/flags-gcc-x86_64.cmake
|
||||
- msystem: MINGW64
|
||||
prefix: mingw-w64-x86_64
|
||||
toolchain: ./cmake/flags-gcc-x86_64.cmake
|
||||
# - msystem: CLANG64
|
||||
# prefix: mingw-w64-clang-x86_64
|
||||
# toolchain: ./cmake/llvm-win32-x86_64.cmake
|
||||
# - msystem: UCRT64
|
||||
# prefix: mingw-w64-ucrt-x86_64
|
||||
# toolchain: ./cmake/flags-gcc-x86_64.cmake
|
||||
slug: "-64"
|
||||
runner: windows-2022
|
||||
- msystem: CLANGARM64
|
||||
toolchain: ./cmake/flags-gcc-aarch64.cmake
|
||||
slug: -arm64
|
||||
runner: windows-11-arm
|
||||
exclude:
|
||||
- dynarec:
|
||||
new: off
|
||||
environment:
|
||||
msystem: CLANGARM64
|
||||
|
||||
steps:
|
||||
- name: Prepare MSYS2 environment
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
release: false
|
||||
release: true
|
||||
update: true
|
||||
msystem: ${{ matrix.environment.msystem }}
|
||||
pacboy: >-
|
||||
@@ -98,15 +88,17 @@ jobs:
|
||||
libslirp:p
|
||||
fluidsynth:p
|
||||
libserialport:p
|
||||
${{ matrix.ui.packages }}
|
||||
qt5-static:p
|
||||
vulkan-headers:p
|
||||
openmp:p
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
|
||||
|
||||
- name: Install sonar-scanner and build-wrapper
|
||||
uses: SonarSource/sonarcloud-github-c-cpp@v3
|
||||
# - name: Install sonar-scanner and build-wrapper
|
||||
# uses: SonarSource/sonarcloud-github-c-cpp@v3
|
||||
|
||||
- name: Configure CMake
|
||||
run: >-
|
||||
@@ -114,20 +106,20 @@ jobs:
|
||||
--toolchain ${{ matrix.environment.toolchain }}
|
||||
-D NEW_DYNAREC=${{ matrix.dynarec.new }}
|
||||
-D CMAKE_INSTALL_PREFIX=./build/artifacts
|
||||
-D QT=${{ matrix.ui.qt }}
|
||||
-D STATIC_BUILD=${{ matrix.ui.static }}
|
||||
|
||||
# - name: Build
|
||||
# run: |
|
||||
# .sonar/build-wrapper-win-x86/build-wrapper-win-x86-64.exe --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} cmake --build build
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
.sonar/build-wrapper-win-x86/build-wrapper-win-x86-64.exe --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} cmake --build build
|
||||
run: cmake --build build
|
||||
|
||||
- name: Run sonar-scanner
|
||||
if: 0
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||
run: |
|
||||
.sonar/sonar-scanner-5.0.1.3006-windows/bin/sonar-scanner.bat --define sonar.cfamily.build-wrapper-output="${{ env.BUILD_WRAPPER_OUT_DIR }}"
|
||||
# - name: Run sonar-scanner
|
||||
# env:
|
||||
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
# SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||
# run: |
|
||||
# .sonar/sonar-scanner-5.0.1.3006-windows/bin/sonar-scanner.bat --define sonar.cfamily.build-wrapper-output="${{ env.BUILD_WRAPPER_OUT_DIR }}"
|
||||
|
||||
- name: Generate package
|
||||
run: cmake --install build
|
||||
@@ -135,5 +127,5 @@ jobs:
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: '86Box${{ matrix.ui.slug }}${{ matrix.dynarec.slug }}${{ matrix.build.slug }}-Windows-${{ matrix.environment.msystem }}-gha${{ github.run_number }}'
|
||||
name: '86Box${{ matrix.dynarec.slug }}${{ matrix.build.slug }}-Windows${{ matrix.environment.slug }}-gha${{ github.run_number }}'
|
||||
path: build/artifacts/**
|
||||
|
||||
@@ -36,7 +36,7 @@ if(MUNT_EXTERNAL)
|
||||
endif()
|
||||
|
||||
project(86Box
|
||||
VERSION 4.3
|
||||
VERSION 5.0
|
||||
DESCRIPTION "Emulator of x86-based systems"
|
||||
HOMEPAGE_URL "https://86box.net"
|
||||
LANGUAGES C CXX)
|
||||
@@ -173,16 +173,11 @@ endif()
|
||||
# Option Description Def. Condition Otherwise
|
||||
# ------ ----------- ---- ------------ ---------
|
||||
cmake_dependent_option(AMD_K5 "AMD K5" ON "DEV_BRANCH" OFF)
|
||||
cmake_dependent_option(AN430TX "Intel AN430TX" ON "DEV_BRANCH" OFF)
|
||||
cmake_dependent_option(CDROM_MITSUMI "Mitsumi CDROM" ON "DEV_BRANCH" OFF)
|
||||
cmake_dependent_option(G100 "Matrox Productiva G100" ON "DEV_BRANCH" OFF)
|
||||
cmake_dependent_option(GUSMAX "Gravis UltraSound MAX" ON "DEV_BRANCH" OFF)
|
||||
cmake_dependent_option(ISAMEM_RAMPAGE "AST Rampage" ON "DEV_BRANCH" OFF)
|
||||
cmake_dependent_option(ISAMEM_IAB "Intel Above Board" ON "DEV_BRANCH" OFF)
|
||||
cmake_dependent_option(ISAMEM_BRAT "BocaRAM/AT" ON "DEV_BRANCH" OFF)
|
||||
cmake_dependent_option(LASERXT "VTech Laser XT" ON "DEV_BRANCH" OFF)
|
||||
cmake_dependent_option(OLIVETTI "Olivetti M290" ON "DEV_BRANCH" OFF)
|
||||
cmake_dependent_option(OPEN_AT "OpenAT" ON "DEV_BRANCH" OFF)
|
||||
cmake_dependent_option(OPL4ML "OPL4-ML daughterboard" ON "DEV_BRANCH" OFF)
|
||||
cmake_dependent_option(PCL "Generic PCL5e Printer" ON "DEV_BRANCH" OFF)
|
||||
cmake_dependent_option(SIO_DETECT "Super I/O Detection Helper" ON "DEV_BRANCH" OFF)
|
||||
|
||||
10
README.md
10
README.md
@@ -26,18 +26,18 @@ Minimum system requirements and recommendations
|
||||
* macOS version: macOS High Sierra 10.13 or newer
|
||||
* 4 GB of RAM or higher
|
||||
|
||||
Performance may vary depending on both host and guest configuration. Most emulation logic is executed in a single thread; therefore, systems with better IPC (instructions per clock) generally should be able to emulate higher clock speeds.
|
||||
Performance may vary depending on host and guest configuration. Most emulation logic is executed in a single thread. Therefore, systems with greater IPC (instructions per clock) capacity should be able to emulate higher clock speeds.
|
||||
|
||||
It is also recommended to use a manager application with 86Box for easier handling of multiple virtual machines.
|
||||
For easier handling of multiple virtual machines, use a manager application:
|
||||
|
||||
* [Avalonia 86](https://github.com/notBald/Avalonia86) by [notBald](https://github.com/notBald) (Windows and Linux)
|
||||
* [86Box Manager](https://github.com/86Box/86BoxManager) by [Overdoze](https://github.com/daviunic) (Windows only)
|
||||
* [86Box Manager X](https://github.com/RetBox/86BoxManagerX) by [xafero](https://github.com/xafero) (Cross platform Port of 86Box Manager using Avalonia)
|
||||
* [Avalonia 86](https://github.com/notBald/Avalonia86) by [notBald](https://github.com/notBald) (Windows and Linux)
|
||||
* [sl86](https://github.com/DDXofficial/sl86) by [DDX](https://github.com/DDXofficial) (Command-line 86Box machine manager written in Python)
|
||||
* [Linbox-qt5](https://github.com/Dungeonseeker/linbox-qt5) by [Dungeonseeker](https://github.com/Dungeonseeker/) (Linux focused, should work on Windows though untested)
|
||||
* [MacBox for 86Box](https://github.com/Moonif/MacBox) by [Moonif](https://github.com/Moonif) (MacOS only)
|
||||
|
||||
It is also possible to use 86Box on its own with the `--vmpath`/`-P` command line option.
|
||||
To use 86Box on its own, use the `--vmpath`/`-P` command line option.
|
||||
|
||||
Getting started
|
||||
---------------
|
||||
@@ -47,7 +47,7 @@ See [our documentation](https://86box.readthedocs.io/en/latest/index.html) for a
|
||||
Community
|
||||
---------
|
||||
|
||||
We operate an IRC channel and a Discord server for discussing 86Box, its development and anything related to retro computing. We look forward to hearing from you!
|
||||
We operate an IRC channel and a Discord server for discussing 86Box, its development, and anything related to retro computing. We look forward to hearing from you!
|
||||
|
||||
[](https://kiwiirc.com/client/irc.ringoflightning.net/?nick=86box|?#86Box)
|
||||
|
||||
|
||||
20
cmake/intel-linux-x86_64.cmake
Normal file
20
cmake/intel-linux-x86_64.cmake
Normal file
@@ -0,0 +1,20 @@
|
||||
#
|
||||
# 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
# running old operating systems and software designed for IBM
|
||||
# PC systems and compatibles from 1981 through fairly recent
|
||||
# system designs based on the PCI bus.
|
||||
#
|
||||
# This file is part of the 86Box distribution.
|
||||
#
|
||||
# CMake toolchain file defining GCC compiler flags
|
||||
# for 64-bit x86 targets.
|
||||
#
|
||||
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
|
||||
#
|
||||
# Copyright 2021 David Hrdlička.
|
||||
#
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/flags-gcc-x86_64.cmake)
|
||||
|
||||
set(CMAKE_C_COMPILER icx)
|
||||
set(CMAKE_CXX_COMPILER icpx)
|
||||
23
cmake/llvm-linux-x86_64.cmake
Normal file
23
cmake/llvm-linux-x86_64.cmake
Normal file
@@ -0,0 +1,23 @@
|
||||
#
|
||||
# 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
# running old operating systems and software designed for IBM
|
||||
# PC systems and compatibles from 1981 through fairly recent
|
||||
# system designs based on the PCI bus.
|
||||
#
|
||||
# This file is part of the 86Box distribution.
|
||||
#
|
||||
# CMake toolchain file defining Clang compiler flags
|
||||
# for 64-bit x86 targets.
|
||||
#
|
||||
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
|
||||
# dob205
|
||||
#
|
||||
# Copyright 2021 David Hrdlička.
|
||||
# Copyright 2022 dob205.
|
||||
#
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/flags-gcc-x86_64.cmake)
|
||||
|
||||
# Use the GCC-compatible Clang executables in order to use our flags
|
||||
set(CMAKE_C_COMPILER clang)
|
||||
set(CMAKE_CXX_COMPILER clang++)
|
||||
4
debian/changelog
vendored
4
debian/changelog
vendored
@@ -1,5 +1,5 @@
|
||||
86box (4.3) UNRELEASED; urgency=medium
|
||||
86box (5.0) UNRELEASED; urgency=medium
|
||||
|
||||
* Bump release.
|
||||
|
||||
-- Jasmine Iwanek <jriwanek@gmail.com> Wed, 13 Nov 2024 06:31:46 +0100
|
||||
-- Jasmine Iwanek <jriwanek@gmail.com> Wed, 16 Apr 2025 22:08:04 +0200
|
||||
|
||||
204
src/86box.c
204
src/86box.c
@@ -160,6 +160,7 @@ int window_remember;
|
||||
int vid_resize; /* (C) allow resizing */
|
||||
int invert_display = 0; /* (C) invert the display */
|
||||
int suppress_overscan = 0; /* (C) suppress overscans */
|
||||
int lang_id = 0; /* (C) language id */
|
||||
int scale = 0; /* (C) screen scale factor */
|
||||
int dpi_scale = 0; /* (C) DPI scaling of the emulated
|
||||
screen */
|
||||
@@ -167,13 +168,12 @@ int vid_api = 0; /* (C) video r
|
||||
int vid_cga_contrast = 0; /* (C) video */
|
||||
int video_fullscreen = 0; /* (C) video */
|
||||
int video_fullscreen_scale = 0; /* (C) video */
|
||||
int video_fullscreen_first = 0; /* (C) video */
|
||||
int enable_overscan = 0; /* (C) video */
|
||||
int force_43 = 0; /* (C) video */
|
||||
int video_filter_method = 1; /* (C) video */
|
||||
int video_vsync = 0; /* (C) video */
|
||||
int video_framerate = -1; /* (C) video */
|
||||
bool serial_passthrough_enabled[SERIAL_MAX] = { 0, 0, 0, 0, 0, 0, 0 }; /* (C) activation and kind of
|
||||
bool serial_passthrough_enabled[SERIAL_MAX - 1] = { 0, 0, 0, 0, 0, 0, 0 }; /* (C) activation and kind of
|
||||
pass-through for serial ports */
|
||||
int bugger_enabled = 0; /* (C) enable ISAbugger */
|
||||
int novell_keycard_enabled = 0; /* (C) enable Novell NetWare 2.x key card emulation. */
|
||||
@@ -221,6 +221,37 @@ int other_ide_present = 0; /* IDE control
|
||||
int other_scsi_present = 0; /* SCSI controllers from non-SCSI cards are
|
||||
present */
|
||||
|
||||
// Accelerator key array
|
||||
struct accelKey acc_keys[NUM_ACCELS];
|
||||
|
||||
// Default accelerator key values
|
||||
struct accelKey def_acc_keys[NUM_ACCELS] = {
|
||||
{ .name="send_ctrl_alt_del", .desc="Send Control+Alt+Del",
|
||||
.seq="Ctrl+F12" },
|
||||
|
||||
{ .name="send_ctrl_alt_esc", .desc="Send Control+Alt+Escape",
|
||||
.seq="Ctrl+F10" },
|
||||
|
||||
{ .name="fullscreen", .desc="Toggle fullscreen",
|
||||
.seq="Ctrl+Alt+PgUp" },
|
||||
|
||||
{ .name="screenshot", .desc="Screenshot",
|
||||
.seq="Ctrl+F11" },
|
||||
|
||||
{ .name="release_mouse", .desc="Release mouse pointer",
|
||||
.seq="Ctrl+End" },
|
||||
|
||||
{ .name="hard_reset", .desc="Hard reset",
|
||||
.seq="Ctrl+Alt+F12" },
|
||||
|
||||
{ .name="pause", .desc="Toggle pause",
|
||||
.seq="Ctrl+Alt+F1" },
|
||||
|
||||
{ .name="mute", .desc="Toggle mute",
|
||||
.seq="Ctrl+Alt+M" }
|
||||
};
|
||||
|
||||
|
||||
/* Statistics. */
|
||||
extern int mmuflush;
|
||||
extern int readlnum;
|
||||
@@ -554,6 +585,62 @@ delete_nvr_file(uint8_t flash)
|
||||
|
||||
extern void device_find_all_descs(void);
|
||||
|
||||
static void
|
||||
pc_show_usage(char *s)
|
||||
{
|
||||
char p[4096] = { 0 };
|
||||
|
||||
sprintf(p,
|
||||
"\n%sUsage: 86box [options] [cfg-file]\n\n"
|
||||
"Valid options are:\n\n"
|
||||
"-? or --help\t\t\t- show this information\n"
|
||||
"-C or --config path\t\t- set 'path' to be config file\n"
|
||||
#ifdef _WIN32
|
||||
"-D or --debug\t\t\t- force debug output logging\n"
|
||||
#endif
|
||||
#if 0
|
||||
"-E or --nographic\t\t- forces the old behavior\n"
|
||||
#endif
|
||||
"-F or --fullscreen\t\t- start in fullscreen mode\n"
|
||||
"-G or --lang langid\t\t- start with specified language\n"
|
||||
"\t\t\t\t (e.g. en-US, or system)\n"
|
||||
#ifdef _WIN32
|
||||
"-H or --hwnd id,hwnd\t\t- sends back the main dialog's hwnd\n"
|
||||
#endif
|
||||
"-I or --image d:path\t\t- load 'path' as floppy image on drive d\n"
|
||||
#ifdef USE_INSTRUMENT
|
||||
"-J or --instrument name\t- set 'name' to be the profiling instrument\n"
|
||||
#endif
|
||||
"-L or --logfile pat\t\t- set 'path' to be the logfile\n"
|
||||
"-M or --missing\t\t- dump missing machines and video cards\n"
|
||||
"-N or --noconfirm\t\t- do not ask for confirmation on quit\n"
|
||||
"-P or --vmpath path\t\t- set 'path' to be root for vm\n"
|
||||
"-R or --rompath path\t\t- set 'path' to be ROM path\n"
|
||||
#ifndef USE_SDL_UI
|
||||
"-S or --settings\t\t\t- show only the settings dialog\n"
|
||||
#endif
|
||||
"-T or --testmode\t\t- test mode: execute the test mode entry\n"
|
||||
"\t\t\t\t point on init/hard reset\n"
|
||||
"-V or --vmname name\t\t- overrides the name of the running VM\n"
|
||||
"-W or --nohook\t\t- disables keyboard hook\n"
|
||||
"\t\t\t\t (compatibility-only outside Windows)\n"
|
||||
"-X or --clear what\t\t- clears the 'what' (cmos/flash/both)\n"
|
||||
"-Y or --donothing\t\t- do not show any UI or run the emulation\n"
|
||||
"-Z or --lastvmpath\t\t- the last parameter is VM path rather\n"
|
||||
"\t\t\t\t than config\n"
|
||||
"\nA config file can be specified. If none is, the default file will be used.\n",
|
||||
(s == NULL) ? "" : s);
|
||||
|
||||
#ifdef _WIN32
|
||||
ui_msgbox(MBX_ANSI | ((s == NULL) ? MBX_INFO : MBX_WARNING), p);
|
||||
#else
|
||||
if (s == NULL)
|
||||
pclog(p);
|
||||
else
|
||||
ui_msgbox(MBX_ANSI | MBX_WARNING, p);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform initial startup of the PC.
|
||||
*
|
||||
@@ -577,6 +664,9 @@ pc_init(int argc, char *argv[])
|
||||
time_t now;
|
||||
int c;
|
||||
int lvmp = 0;
|
||||
#ifdef DEPRECATE_USAGE
|
||||
int deprecated = 1;
|
||||
#endif
|
||||
#ifdef ENABLE_NG
|
||||
int ng = 0;
|
||||
#endif
|
||||
@@ -584,7 +674,7 @@ pc_init(int argc, char *argv[])
|
||||
uint32_t *uid;
|
||||
uint32_t *shwnd;
|
||||
#endif
|
||||
uint32_t lang_init = 0;
|
||||
int lang_init = 0;
|
||||
|
||||
/* Grab the executable's full path. */
|
||||
plat_get_exe_name(exe_path, sizeof(exe_path) - 1);
|
||||
@@ -634,41 +724,7 @@ usage:
|
||||
}
|
||||
}
|
||||
|
||||
printf("\nUsage: 86box [options] [cfg-file]\n\n");
|
||||
printf("Valid options are:\n\n");
|
||||
printf("-? or --help - show this information\n");
|
||||
printf("-C or --config path - set 'path' to be config file\n");
|
||||
#ifdef _WIN32
|
||||
printf("-D or --debug - force debug output logging\n");
|
||||
#endif
|
||||
#if 0
|
||||
printf("-E or --nographic - forces the old behavior\n");
|
||||
#endif
|
||||
printf("-F or --fullscreen - start in fullscreen mode\n");
|
||||
printf("-G or --lang langid - start with specified language (e.g. en-US, or system)\n");
|
||||
#ifdef _WIN32
|
||||
printf("-H or --hwnd id,hwnd - sends back the main dialog's hwnd\n");
|
||||
#endif
|
||||
printf("-I or --image d:path - load 'path' as floppy image on drive d\n");
|
||||
#ifdef USE_INSTRUMENT
|
||||
printf("-J or --instrument name - set 'name' to be the profiling instrument\n");
|
||||
#endif
|
||||
printf("-K or --keycodes codes - set 'codes' to be the uncapture combination\n");
|
||||
printf("-L or --logfile path - set 'path' to be the logfile\n");
|
||||
printf("-M or --missing - dump missing machines and video cards\n");
|
||||
printf("-N or --noconfirm - do not ask for confirmation on quit\n");
|
||||
printf("-P or --vmpath path - set 'path' to be root for vm\n");
|
||||
printf("-R or --rompath path - set 'path' to be ROM path\n");
|
||||
#ifndef USE_SDL_UI
|
||||
printf("-S or --settings - show only the settings dialog\n");
|
||||
#endif
|
||||
printf("-T or --testmode - test mode: execute the test mode entry point on init/hard reset\n");
|
||||
printf("-V or --vmname name - overrides the name of the running VM\n");
|
||||
printf("-W or --nohook - disables keyboard hook (compatibility-only outside Windows)\n");
|
||||
printf("-X or --clear what - clears the 'what' (cmos/flash/both)\n");
|
||||
printf("-Y or --donothing - do not show any UI or run the emulation\n");
|
||||
printf("-Z or --lastvmpath - the last parameter is VM path rather than config\n");
|
||||
printf("\nA config file can be specified. If none is, the default file will be used.\n");
|
||||
pc_show_usage(NULL);
|
||||
return 0;
|
||||
} else if (!strcasecmp(argv[c], "--lastvmpath") || !strcasecmp(argv[c], "-Z")) {
|
||||
lvmp = 1;
|
||||
@@ -695,6 +751,9 @@ usage:
|
||||
goto usage;
|
||||
|
||||
ppath = argv[++c];
|
||||
#ifdef DEPRECATE_USAGE
|
||||
deprecated = 0;
|
||||
#endif
|
||||
} else if (!strcasecmp(argv[c], "--rompath") || !strcasecmp(argv[c], "-R")) {
|
||||
if ((c + 1) == argc)
|
||||
goto usage;
|
||||
@@ -706,6 +765,9 @@ usage:
|
||||
goto usage;
|
||||
|
||||
cfg = argv[++c];
|
||||
#ifdef DEPRECATE_USAGE
|
||||
deprecated = 0;
|
||||
#endif
|
||||
} else if (!strcasecmp(argv[c], "--image") || !strcasecmp(argv[c], "-I")) {
|
||||
if ((c + 1) == argc)
|
||||
goto usage;
|
||||
@@ -744,13 +806,6 @@ usage:
|
||||
do_nothing = 1;
|
||||
} else if (!strcasecmp(argv[c], "--nohook") || !strcasecmp(argv[c], "-W")) {
|
||||
hook_enabled = 0;
|
||||
} else if (!strcasecmp(argv[c], "--keycodes") || !strcasecmp(argv[c], "-K")) {
|
||||
if ((c + 1) == argc)
|
||||
goto usage;
|
||||
|
||||
sscanf(argv[++c], "%03hX,%03hX,%03hX,%03hX,%03hX,%03hX",
|
||||
&key_prefix_1_1, &key_prefix_1_2, &key_prefix_2_1, &key_prefix_2_2,
|
||||
&key_uncapture_1, &key_uncapture_2);
|
||||
} else if (!strcasecmp(argv[c], "--clearboth") || !strcasecmp(argv[c], "-X")) {
|
||||
if ((c + 1) == argc)
|
||||
goto usage;
|
||||
@@ -811,11 +866,22 @@ usage:
|
||||
ppath = argv[c++];
|
||||
else
|
||||
cfg = argv[c++];
|
||||
|
||||
#ifdef DEPRECATE_USAGE
|
||||
deprecated = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (c != argc)
|
||||
goto usage;
|
||||
|
||||
#ifdef DEPRECATE_USAGE
|
||||
if (deprecated)
|
||||
pc_show_usage("Running 86Box without a specified VM path and/or configuration\n"
|
||||
"file has been deprected. Please specify one or use a manager\n"
|
||||
"(Avalonia 86 is recommended).\n\n");
|
||||
#endif
|
||||
|
||||
path_slash(usr_path);
|
||||
path_slash(rom_path);
|
||||
|
||||
@@ -972,6 +1038,13 @@ usage:
|
||||
zip_global_init();
|
||||
mo_global_init();
|
||||
|
||||
/* Initialize the keyboard accelerator list with default values */
|
||||
for (int x = 0; x < NUM_ACCELS; x++) {
|
||||
strcpy(acc_keys[x].name, def_acc_keys[x].name);
|
||||
strcpy(acc_keys[x].desc, def_acc_keys[x].desc);
|
||||
strcpy(acc_keys[x].seq, def_acc_keys[x].seq);
|
||||
}
|
||||
|
||||
/* Load the configuration file. */
|
||||
config_load();
|
||||
|
||||
@@ -1177,20 +1250,48 @@ pc_send_ca(uint16_t sc)
|
||||
if (keyboard_mode >= 0x81) {
|
||||
/* Use R-Alt because PS/55 DOS and OS/2 assign L-Alt Kanji */
|
||||
keyboard_input(1, 0x1D); /* Ctrl key pressed */
|
||||
if (keyboard_get_in_reset())
|
||||
return;
|
||||
keyboard_input(1, 0x138); /* R-Alt key pressed */
|
||||
if (keyboard_get_in_reset())
|
||||
return;
|
||||
keyboard_input(1, sc);
|
||||
if (keyboard_get_in_reset())
|
||||
return;
|
||||
usleep(50000);
|
||||
if (keyboard_get_in_reset())
|
||||
return;
|
||||
keyboard_input(0, sc);
|
||||
if (keyboard_get_in_reset())
|
||||
return;
|
||||
keyboard_input(0, 0x138); /* R-Alt key released */
|
||||
if (keyboard_get_in_reset())
|
||||
return;
|
||||
keyboard_input(0, 0x1D); /* Ctrl key released */
|
||||
if (keyboard_get_in_reset())
|
||||
return;
|
||||
} else {
|
||||
keyboard_input(1, 0x1D); /* Ctrl key pressed */
|
||||
if (keyboard_get_in_reset())
|
||||
return;
|
||||
keyboard_input(1, 0x38); /* Alt key pressed */
|
||||
if (keyboard_get_in_reset())
|
||||
return;
|
||||
keyboard_input(1, sc);
|
||||
if (keyboard_get_in_reset())
|
||||
return;
|
||||
usleep(50000);
|
||||
if (keyboard_get_in_reset())
|
||||
return;
|
||||
keyboard_input(0, sc);
|
||||
if (keyboard_get_in_reset())
|
||||
return;
|
||||
keyboard_input(0, 0x38); /* Alt key released */
|
||||
if (keyboard_get_in_reset())
|
||||
return;
|
||||
keyboard_input(0, 0x1D); /* Ctrl key released */
|
||||
if (keyboard_get_in_reset())
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1788,3 +1889,16 @@ do_pause(int p)
|
||||
}
|
||||
atomic_store(&pause_ack, 0);
|
||||
}
|
||||
|
||||
// Helper to find an accelerator key and return it's index in acc_keys
|
||||
int FindAccelerator(const char *name) {
|
||||
for(int x=0;x<NUM_ACCELS;x++)
|
||||
{
|
||||
if(strcmp(acc_keys[x].name, name) == 0)
|
||||
{
|
||||
return(x);
|
||||
}
|
||||
}
|
||||
// No key was found
|
||||
return -1;
|
||||
}
|
||||
14
src/acpi.c
14
src/acpi.c
@@ -36,6 +36,7 @@
|
||||
#include <86box/pit.h>
|
||||
#include <86box/apm.h>
|
||||
#include <86box/acpi.h>
|
||||
#include <86box/dma.h>
|
||||
#include <86box/machine.h>
|
||||
#include <86box/i2c.h>
|
||||
#include <86box/video.h>
|
||||
@@ -1026,8 +1027,11 @@ acpi_reg_write_common_regs(UNUSED(int size), uint16_t addr, uint8_t val, void *p
|
||||
}
|
||||
|
||||
if (sus_typ & SUS_RESET_PCI) {
|
||||
/* DMA is part of the southbridge so it responds to PCI reset. */
|
||||
dma_reset();
|
||||
dma_set_at(1);
|
||||
|
||||
device_reset_all(DEVICE_PCI);
|
||||
mem_zero();
|
||||
}
|
||||
|
||||
if (sus_typ & SUS_RESET_CPU)
|
||||
@@ -2389,6 +2393,14 @@ acpi_reset(void *priv)
|
||||
dev->regs.gpi_val = 0xfff57fc1;
|
||||
if (!strcmp(machine_get_internal_name(), "ficva503a") || !strcmp(machine_get_internal_name(), "6via90ap"))
|
||||
dev->regs.gpi_val |= 0x00000004;
|
||||
/*
|
||||
TriGem Delhi-III second GPI word:
|
||||
- Bit 7 = Save CMOS (must be set);
|
||||
- Bit 6 = Password jumper (must be set);
|
||||
- Bit 5 = Enable Setup (must be set).
|
||||
*/
|
||||
else if (!strcmp(machine_get_internal_name(), "delhi3"))
|
||||
dev->regs.gpi_val |= 0x00008000;
|
||||
}
|
||||
|
||||
if (acpi_power_on) {
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
#include <86box/cdrom.h>
|
||||
#include <86box/cdrom_image.h>
|
||||
#include <86box/cdrom_interface.h>
|
||||
#ifdef USE_CDROM_MITSUMI
|
||||
#include <86box/cdrom_mitsumi.h>
|
||||
#endif
|
||||
#include <86box/log.h>
|
||||
#include <86box/plat.h>
|
||||
#include <86box/plat_cdrom_ioctl.h>
|
||||
@@ -117,6 +120,9 @@ static const struct {
|
||||
} controllers[] = {
|
||||
// clang-format off
|
||||
{ &cdrom_interface_none_device },
|
||||
#ifdef USE_CDROM_MITSUMI
|
||||
{ &mitsumi_cdrom_device },
|
||||
#endif
|
||||
{ NULL }
|
||||
// clang-format on
|
||||
};
|
||||
@@ -2274,13 +2280,73 @@ cdrom_read_disc_info_toc(cdrom_t *dev, uint8_t *b,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
cdrom_msf_to_lba(const int sector, const int ismsf,
|
||||
int cdrom_sector_type, const uint8_t vendor_type)
|
||||
{
|
||||
int pos = sector;
|
||||
uint32_t lba;
|
||||
|
||||
if ((cdrom_sector_type & 0x0f) >= 0x08) {
|
||||
mult = cdrom_sector_type >> 4;
|
||||
pos /= mult;
|
||||
}
|
||||
|
||||
if (ismsf) {
|
||||
const int m = (pos >> 16) & 0xff;
|
||||
const int s = (pos >> 8) & 0xff;
|
||||
const int f = pos & 0xff;
|
||||
|
||||
lba = MSFtoLBA(m, s, f) - 150;
|
||||
} else {
|
||||
switch (vendor_type) {
|
||||
case 0x00:
|
||||
lba = pos;
|
||||
break;
|
||||
case 0x40: {
|
||||
const int m = bcd2bin((pos >> 24) & 0xff);
|
||||
const int s = bcd2bin((pos >> 16) & 0xff);
|
||||
const int f = bcd2bin((pos >> 8) & 0xff);
|
||||
|
||||
lba = MSFtoLBA(m, s, f) - 150;
|
||||
break;
|
||||
} case 0x80:
|
||||
lba = bcd2bin((pos >> 24) & 0xff);
|
||||
break;
|
||||
/* Never used values but the compiler complains. */
|
||||
default:
|
||||
lba = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return lba;
|
||||
}
|
||||
|
||||
int
|
||||
cdrom_is_track_audio(cdrom_t *dev, const int sector,
|
||||
const int ismsf, int cdrom_sector_type,
|
||||
const uint8_t vendor_type)
|
||||
{
|
||||
int audio = 0;
|
||||
uint32_t lba = cdrom_msf_to_lba(sector, ismsf,
|
||||
cdrom_sector_type, vendor_type);
|
||||
|
||||
if (dev->ops->get_track_type)
|
||||
audio = dev->ops->get_track_type(dev->local, lba);
|
||||
|
||||
audio &= CD_TRACK_AUDIO;
|
||||
|
||||
return audio;
|
||||
}
|
||||
|
||||
int
|
||||
cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, const int sector, const int ismsf,
|
||||
int cdrom_sector_type, const int cdrom_sector_flags,
|
||||
int *len, const uint8_t vendor_type)
|
||||
{
|
||||
int pos = sector;
|
||||
int ret = 0;
|
||||
int pos = sector;
|
||||
int ret = 0;
|
||||
const int old_type = cdrom_sector_type;
|
||||
|
||||
if ((cdrom_sector_type & 0x0f) >= 0x08) {
|
||||
mult = cdrom_sector_type >> 4;
|
||||
@@ -2298,38 +2364,12 @@ cdrom_readsector_raw(cdrom_t *dev, uint8_t *buffer, const int sector, const int
|
||||
uint8_t *temp_b;
|
||||
uint8_t *b = temp_b = buffer;
|
||||
int audio = 0;
|
||||
uint32_t lba;
|
||||
uint32_t lba = cdrom_msf_to_lba(sector, ismsf,
|
||||
old_type, vendor_type);
|
||||
int mode2 = 0;
|
||||
|
||||
*len = 0;
|
||||
|
||||
if (ismsf) {
|
||||
const int m = (pos >> 16) & 0xff;
|
||||
const int s = (pos >> 8) & 0xff;
|
||||
const int f = pos & 0xff;
|
||||
|
||||
lba = MSFtoLBA(m, s, f) - 150;
|
||||
} else {
|
||||
switch (vendor_type) {
|
||||
case 0x00:
|
||||
lba = pos;
|
||||
break;
|
||||
case 0x40: {
|
||||
const int m = bcd2bin((pos >> 24) & 0xff);
|
||||
const int s = bcd2bin((pos >> 16) & 0xff);
|
||||
const int f = bcd2bin((pos >> 8) & 0xff);
|
||||
|
||||
lba = MSFtoLBA(m, s, f) - 150;
|
||||
break;
|
||||
} case 0x80:
|
||||
lba = bcd2bin((pos >> 24) & 0xff);
|
||||
break;
|
||||
/* Never used values but the compiler complains. */
|
||||
default:
|
||||
lba = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (dev->ops->get_track_type)
|
||||
audio = dev->ops->get_track_type(dev->local, lba);
|
||||
|
||||
|
||||
@@ -2016,6 +2016,10 @@ image_open(cdrom_t *dev, const char *path)
|
||||
img->has_audio = 0;
|
||||
else if (ret)
|
||||
img->has_audio = 1;
|
||||
else {
|
||||
image_close(img);
|
||||
img = NULL;
|
||||
}
|
||||
} else {
|
||||
ret = image_load_iso(img, path);
|
||||
|
||||
@@ -2033,7 +2037,8 @@ image_open(cdrom_t *dev, const char *path)
|
||||
img->log = log_open(n);
|
||||
|
||||
dev->ops = &image_ops;
|
||||
}
|
||||
} else
|
||||
warning("Unable to load CD-ROM image: %s\n", path);
|
||||
}
|
||||
|
||||
return img;
|
||||
|
||||
@@ -782,9 +782,8 @@ viso_close(void *priv)
|
||||
if (viso->entry_map)
|
||||
free(viso->entry_map);
|
||||
|
||||
if (tf->log != NULL) {
|
||||
|
||||
}
|
||||
if (tf->log != NULL)
|
||||
log_close(tf->log);
|
||||
|
||||
free(viso);
|
||||
}
|
||||
@@ -1607,10 +1606,12 @@ end:
|
||||
|
||||
return &viso->tf;
|
||||
} else {
|
||||
image_viso_log(viso->tf.log, "Initialization failed\n");
|
||||
if (data)
|
||||
free(data);
|
||||
viso_close(&viso->tf);
|
||||
if (viso != NULL) {
|
||||
image_viso_log(viso->tf.log, "Initialization failed\n");
|
||||
if (data)
|
||||
free(data);
|
||||
viso_close(&viso->tf);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
add_library(chipset OBJECT
|
||||
82c100.c
|
||||
acc2168.c
|
||||
cs8220.c
|
||||
cs8230.c
|
||||
ali1429.c
|
||||
ali1435.c
|
||||
@@ -39,8 +40,10 @@ add_library(chipset OBJECT
|
||||
intel_i450kx.c
|
||||
intel_sio.c
|
||||
intel_piix.c
|
||||
isa486c.c
|
||||
../ioapic.c
|
||||
neat.c
|
||||
olivetti_eva.c
|
||||
opti283.c
|
||||
opti291.c
|
||||
opti391.c
|
||||
@@ -71,6 +74,7 @@ add_library(chipset OBJECT
|
||||
sis_5572_usb.c
|
||||
sis_5595_pmu.c
|
||||
sis_55xx.c
|
||||
sl82c461.c
|
||||
via_vt82c49x.c
|
||||
via_vt82c505.c
|
||||
gc100.c
|
||||
@@ -83,7 +87,3 @@ add_library(chipset OBJECT
|
||||
vl82c480.c
|
||||
wd76c10.c
|
||||
)
|
||||
|
||||
if(OLIVETTI)
|
||||
target_sources(chipset PRIVATE olivetti_eva.c)
|
||||
endif()
|
||||
|
||||
@@ -61,91 +61,238 @@ ali1409_log(const char *fmt, ...)
|
||||
#endif
|
||||
|
||||
typedef struct ali_1409_t {
|
||||
uint8_t is_g;
|
||||
uint8_t index;
|
||||
uint8_t cfg_locked;
|
||||
uint8_t reg_57h;
|
||||
uint8_t regs[256];
|
||||
uint8_t shadow[4];
|
||||
uint8_t last_reg;
|
||||
} ali1409_t;
|
||||
|
||||
/*
|
||||
This here is because from the two BIOS'es I used to reverse engineer this,
|
||||
it is unclear which of the two interpretations of the shadow RAM register
|
||||
operation is correct.
|
||||
The 16 kB interpretation appears to work fine right now but it may be wrong,
|
||||
so I left the 32 kB interpretation in as well.
|
||||
*/
|
||||
#ifdef INTERPRETATION_32KB
|
||||
#define SHADOW_SIZE 0x00008000
|
||||
#else
|
||||
#define SHADOW_SIZE 0x00004000
|
||||
#endif
|
||||
|
||||
static void
|
||||
ali1409_shadow_recalc(ali1409_t *dev)
|
||||
{
|
||||
uint32_t base = 0x000c0000;
|
||||
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
uint8_t reg = 0x08 + i;
|
||||
|
||||
#ifdef INTERPRETATION_32KB
|
||||
for (uint8_t j = 0; j < 4; j += 2) {
|
||||
uint8_t mask = (0x03 << j);
|
||||
#else
|
||||
for (uint8_t j = 0; j < 4; j++) {
|
||||
uint8_t mask = (0x01 << j);
|
||||
#endif
|
||||
uint8_t r_on = dev->regs[reg] & 0x10;
|
||||
uint8_t w_on = dev->regs[reg] & 0x20;
|
||||
uint8_t val = dev->regs[reg] & mask;
|
||||
uint8_t xor = (dev->shadow[i] ^ dev->regs[reg]) & (mask | 0x30);
|
||||
int read = r_on ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
|
||||
int write = w_on ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
|
||||
|
||||
if (xor) {
|
||||
#ifdef INTERPRETATION_32KB
|
||||
switch (val >> j) {
|
||||
case 0x00:
|
||||
mem_set_mem_state_both(base, SHADOW_SIZE, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
|
||||
break;
|
||||
case 0x01:
|
||||
mem_set_mem_state_both(base, SHADOW_SIZE, MEM_READ_EXTANY | write);
|
||||
break;
|
||||
case 0x02:
|
||||
mem_set_mem_state_both(base, SHADOW_SIZE, read | write);
|
||||
break;
|
||||
case 0x03:
|
||||
mem_set_mem_state_both(base, SHADOW_SIZE, read | MEM_WRITE_EXTANY);
|
||||
break;
|
||||
}
|
||||
#else
|
||||
switch (val >> j) {
|
||||
case 0x00:
|
||||
mem_set_mem_state_both(base, SHADOW_SIZE, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
|
||||
break;
|
||||
case 0x01:
|
||||
mem_set_mem_state_both(base, SHADOW_SIZE, read | write);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
base += SHADOW_SIZE;
|
||||
}
|
||||
|
||||
dev->shadow[i] = dev->regs[reg];
|
||||
}
|
||||
|
||||
flushmmucache_nopc();
|
||||
}
|
||||
|
||||
static void
|
||||
ali1409_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
ali1409_t *dev = (ali1409_t *) priv;
|
||||
ali1409_log ("INPUT:addr %02x ,Value %02x \n" , addr , val);
|
||||
ali1409_log("[%04X:%08X] [W] %04X = %02X\n", CS, cpu_state.pc, addr, val);
|
||||
|
||||
if (addr & 1) {
|
||||
if (dev->cfg_locked) {
|
||||
if (dev->last_reg == 0x14 && val == 0x09)
|
||||
dev->cfg_locked = 0;
|
||||
if (addr & 0x0001) {
|
||||
if (dev->cfg_locked) {
|
||||
if ((dev->last_reg == 0x14) && (val == 0x09))
|
||||
dev->cfg_locked = 0;
|
||||
|
||||
dev->last_reg = val;
|
||||
return;
|
||||
}
|
||||
dev->last_reg = val;
|
||||
return;
|
||||
}
|
||||
|
||||
if (dev->index == 0xff && val == 0xff)
|
||||
dev->cfg_locked = 1;
|
||||
else {
|
||||
ali1409_log("Write reg %02x %02x %08x\n", dev->index, val, cs);
|
||||
dev->regs[dev->index] = val;
|
||||
/* It appears writing anything at all to register 0xFF locks it again. */
|
||||
if (dev->index == 0xff)
|
||||
dev->cfg_locked = 1;
|
||||
else if (dev->index < 0x44) {
|
||||
ali1409_log("[%04X:%08X] [W] Register %02X = %02X\n", CS, cpu_state.pc, dev->index, val);
|
||||
|
||||
switch (dev->index) {
|
||||
case 0xa:
|
||||
switch ((val >> 4) & 3) {
|
||||
case 0:
|
||||
mem_set_mem_state(0xe0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
|
||||
break;
|
||||
case 1:
|
||||
mem_set_mem_state(0xe0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL);
|
||||
break;
|
||||
case 2:
|
||||
mem_set_mem_state(0xe0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL);
|
||||
break;
|
||||
case 3:
|
||||
mem_set_mem_state(0xe0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
|
||||
break;
|
||||
}
|
||||
if (dev->index < 0x10) {
|
||||
dev->regs[dev->index] = val;
|
||||
|
||||
/*
|
||||
There are still a lot of unknown here, but unfortunately, this is
|
||||
as far as I have been able to come with two BIOS'es that are
|
||||
available (the Acer 100T and an AMI Color dated 07/07/91).
|
||||
*/
|
||||
switch (dev->index) {
|
||||
case 0x02:
|
||||
/*
|
||||
- Bit 7: The RAS address hold time:
|
||||
- 0: 1/2 T;
|
||||
- 1: 1 T.
|
||||
- Bits 6-4: The RAS precharge time:
|
||||
- 0, 0, 0: 1.5 T;
|
||||
- 0, 0, 1: 2 T;
|
||||
- 0, 1, 0: 2.5 T;
|
||||
- 0, 1, 1: 3 T;
|
||||
- 1, 0, 0: 3.5 T;
|
||||
- 1, 0, 1: 4 T;
|
||||
- 1, 1, 0: Reserved;
|
||||
- 1, 1, 1: Reserved.
|
||||
- Bit 3: Early miss cycle:
|
||||
- 0: Disabled;
|
||||
- 1: Enabled.
|
||||
*/
|
||||
break;
|
||||
case 0x03:
|
||||
/*
|
||||
- Bit 6: CAS pulse for read cycle:
|
||||
- 0: 1 T;
|
||||
- 1: 1.5 T or 2 T.
|
||||
I can not get the 2.5 T or 3 T setting to apply so
|
||||
I have no idea what bit governs that.
|
||||
- Bits 5, 4: CAS pulse for write cycle:
|
||||
- 0, 0: 0.5 T or 1 T;
|
||||
- 0, 1: 1.5 T or 2 T;
|
||||
- 1, 0: 2.5 T or 3 T;
|
||||
- 1, 1: Reserved.
|
||||
- Bit 3: CAS active for read cycle:
|
||||
- 0: Disabled;
|
||||
- 1: Enabled.
|
||||
- Bit 2: CAS active for write cycle:
|
||||
- 0: Disabled;
|
||||
- 1: Enabled.
|
||||
*/
|
||||
break;
|
||||
case 0x06:
|
||||
/*
|
||||
- Bits 6-4: Clock divider:
|
||||
- 0, 0, 0: / 2;
|
||||
- 0, 0, 1: / 4;
|
||||
- 0, 1, 0: / 8;
|
||||
- 0, 1, 1: Reserved;
|
||||
- 1, 0, 0: / 3;
|
||||
- 1, 0, 1: / 6;
|
||||
- 1, 1, 0: / 5;
|
||||
- 1, 1, 1: / 10.
|
||||
*/
|
||||
switch ((val >> 4) & 7) {
|
||||
default:
|
||||
case 3: /* Reserved */
|
||||
cpu_set_isa_speed(7159091);
|
||||
break;
|
||||
case 0xb:
|
||||
switch ((val >> 4) & 3) {
|
||||
case 0:
|
||||
mem_set_mem_state(0xf0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
|
||||
break;
|
||||
case 1:
|
||||
mem_set_mem_state(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_EXTANY);
|
||||
break;
|
||||
case 2:
|
||||
mem_set_mem_state(0xf0000, 0x10000, MEM_READ_EXTANY| MEM_WRITE_INTERNAL);
|
||||
break;
|
||||
case 3:
|
||||
mem_set_mem_state(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0:
|
||||
cpu_set_isa_speed(cpu_busspeed / 2);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
cpu_set_isa_speed(cpu_busspeed / 4);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
cpu_set_isa_speed(cpu_busspeed / 8);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
cpu_set_isa_speed(cpu_busspeed / 3);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
cpu_set_isa_speed(cpu_busspeed / 6);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
cpu_set_isa_speed(cpu_busspeed / 5);
|
||||
break;
|
||||
|
||||
case 7:
|
||||
cpu_set_isa_speed(cpu_busspeed / 10);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x08 ... 0x0b:
|
||||
ali1409_shadow_recalc(dev);
|
||||
break;
|
||||
case 0x0c:
|
||||
/*
|
||||
This appears to be turbo in bit 4 (1 = on, 0 = off),
|
||||
and bus speed in the rest of the bits.
|
||||
*/
|
||||
break;
|
||||
case 0x0d:
|
||||
cpu_cache_ext_enabled = !!(val & 0x08);
|
||||
cpu_update_waitstates();
|
||||
break;
|
||||
}
|
||||
} else
|
||||
dev->index = val;
|
||||
}
|
||||
}
|
||||
} else
|
||||
dev->index = val;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
ali1409_read(uint16_t addr, void *priv)
|
||||
{
|
||||
ali1409_log ("reading at %02X\n",addr);
|
||||
const ali1409_t *dev = (ali1409_t *) priv;
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
if (dev->cfg_locked)
|
||||
ret = 0xff;
|
||||
if (addr & 1) {
|
||||
if ((dev->index >= 0xc0 || dev->index == 0x20) && cpu_iscyrix)
|
||||
ret = 0xff;
|
||||
else if (addr & 0x0001) {
|
||||
if (dev->index < 0x44)
|
||||
ret = dev->regs[dev->index];
|
||||
} else
|
||||
ret = dev->index;
|
||||
} else
|
||||
ret = dev->index;
|
||||
|
||||
ali1409_log("[%04X:%08X] [R] %04X = %02X\n", CS, cpu_state.pc, addr, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -166,17 +313,16 @@ ali1409_init(UNUSED(const device_t *info))
|
||||
|
||||
dev->cfg_locked = 1;
|
||||
|
||||
/* M1409 Ports:
|
||||
22h Index Port
|
||||
23h Data Port
|
||||
*/
|
||||
|
||||
ali1409_log ("Bus speed: %i", cpu_busspeed);
|
||||
|
||||
ali1409_log("Bus speed: %i\n", cpu_busspeed);
|
||||
|
||||
io_sethandler(0x0022, 0x0002, ali1409_read, NULL, NULL, ali1409_write, NULL, NULL, dev);
|
||||
io_sethandler(0x037f, 0x0001, ali1409_read, NULL, NULL, ali1409_write, NULL, NULL, dev);
|
||||
io_sethandler(0x03f3, 0x0001, ali1409_read, NULL, NULL, ali1409_write, NULL, NULL, dev);
|
||||
|
||||
dev->regs[0x0f] = 0x08;
|
||||
|
||||
cpu_set_isa_speed(7159091);
|
||||
|
||||
cpu_cache_ext_enabled = 0;
|
||||
cpu_update_waitstates();
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
289
src/chipset/cs8220.c
Normal file
289
src/chipset/cs8220.c
Normal file
@@ -0,0 +1,289 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Emulation of C&T CS8220 ("PC/AT") chipset.
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2025 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <86box/86box.h>
|
||||
#include "cpu.h"
|
||||
#include <86box/timer.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/machine.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/plat_fallthrough.h>
|
||||
#include <86box/plat_unused.h>
|
||||
#include <86box/fdd.h>
|
||||
#include <86box/fdc.h>
|
||||
#include <86box/chipset.h>
|
||||
|
||||
typedef struct {
|
||||
uint32_t virt;
|
||||
uint32_t phys;
|
||||
|
||||
uint32_t size;
|
||||
|
||||
mem_mapping_t mapping;
|
||||
} ram_bank_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t regs[3];
|
||||
|
||||
ram_bank_t ram_banks[3];
|
||||
} cs8220_t;
|
||||
|
||||
static uint8_t
|
||||
cs8220_mem_read(uint32_t addr, void *priv)
|
||||
{
|
||||
ram_bank_t *dev = (ram_bank_t *) priv;
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
addr = (addr - dev->virt) + dev->phys;
|
||||
|
||||
if (addr < (mem_size << 10))
|
||||
ret = ram[addr];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
cs8220_mem_readw(uint32_t addr, void *priv)
|
||||
{
|
||||
ram_bank_t *dev = (ram_bank_t *) priv;
|
||||
uint16_t ret = 0xffff;
|
||||
|
||||
addr = (addr - dev->virt) + dev->phys;
|
||||
|
||||
if (addr < (mem_size << 10))
|
||||
ret = *(uint16_t *) &(ram[addr]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
cs8220_mem_write(uint32_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
ram_bank_t *dev = (ram_bank_t *) priv;
|
||||
|
||||
addr = (addr - dev->virt) + dev->phys;
|
||||
|
||||
if (addr < (mem_size << 10))
|
||||
ram[addr] = val;
|
||||
}
|
||||
|
||||
static void
|
||||
cs8220_mem_writew(uint32_t addr, uint16_t val, void *priv)
|
||||
{
|
||||
ram_bank_t *dev = (ram_bank_t *) priv;
|
||||
|
||||
addr = (addr - dev->virt) + dev->phys;
|
||||
|
||||
if (addr < (mem_size << 10))
|
||||
*(uint16_t *) &(ram[addr]) = val;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
cs8220_in(uint16_t port, void *priv) {
|
||||
cs8220_t *dev = (cs8220_t *) priv;
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
switch (port) {
|
||||
case 0x00a4 ... 0x00a5:
|
||||
ret = dev->regs[port & 0x0001];
|
||||
break;
|
||||
case 0x00ab:
|
||||
ret = dev->regs[2];
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
cs8220_out(uint16_t port, uint8_t val, void *priv) {
|
||||
cs8220_t *dev = (cs8220_t *) priv;
|
||||
|
||||
switch (port) {
|
||||
case 0x00a4:
|
||||
dev->regs[0] = val;
|
||||
mem_a20_alt = val & 0x40;
|
||||
mem_a20_recalc();
|
||||
break;
|
||||
case 0x00a5:
|
||||
dev->regs[1] = val;
|
||||
if (val & 0x01) {
|
||||
mem_mapping_set_addr(&dev->ram_banks[0].mapping, 0, 0x000040000);
|
||||
mem_mapping_disable(&dev->ram_banks[1].mapping);
|
||||
mem_mapping_disable(&dev->ram_banks[2].mapping);
|
||||
} else {
|
||||
mem_mapping_set_addr(&dev->ram_banks[0].mapping, 0, dev->ram_banks[0].size);
|
||||
mem_mapping_enable(&dev->ram_banks[1].mapping);
|
||||
mem_mapping_enable(&dev->ram_banks[2].mapping);
|
||||
}
|
||||
break;
|
||||
case 0x00ab:
|
||||
dev->regs[2] = val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cs8220_close(void *priv)
|
||||
{
|
||||
cs8220_t *dev = (cs8220_t *) priv;
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
static void *
|
||||
cs8220_init(UNUSED(const device_t *info))
|
||||
{
|
||||
cs8220_t *dev = (cs8220_t *) calloc(1, sizeof(cs8220_t));
|
||||
|
||||
mem_mapping_disable(&ram_low_mapping);
|
||||
mem_mapping_disable(&ram_mid_mapping);
|
||||
mem_mapping_disable(&ram_high_mapping);
|
||||
|
||||
/*
|
||||
Dell System 200: 640 kB soldered on-board, any other RAM is expansion.
|
||||
*/
|
||||
if (!strcmp(machine_get_internal_name(), "dells200")) switch (mem_size) {
|
||||
default:
|
||||
dev->ram_banks[2].virt = 0x00100000;
|
||||
dev->ram_banks[2].phys = 0x000a0000;
|
||||
dev->ram_banks[2].size = (mem_size << 10) - 0x000a0000;
|
||||
fallthrough;
|
||||
case 640:
|
||||
dev->ram_banks[0].virt = 0x00000000;
|
||||
dev->ram_banks[0].phys = 0x00000000;
|
||||
dev->ram_banks[0].size = 0x00080000;
|
||||
dev->ram_banks[1].virt = 0x00080000;
|
||||
dev->ram_banks[1].phys = 0x00080000;
|
||||
dev->ram_banks[1].size = 0x00020000;
|
||||
break;
|
||||
/*
|
||||
We are limited to steps of equal size, so we have to simulate some
|
||||
memory expansions to work around the chipset's limits.
|
||||
*/
|
||||
} else switch (mem_size) {
|
||||
case 256:
|
||||
dev->ram_banks[0].virt = 0x00000000;
|
||||
dev->ram_banks[0].phys = 0x00000000;
|
||||
dev->ram_banks[0].size = 0x00020000;
|
||||
dev->ram_banks[1].virt = 0x00020000;
|
||||
dev->ram_banks[1].phys = 0x00020000;
|
||||
dev->ram_banks[1].size = 0x00020000;
|
||||
break;
|
||||
case 384:
|
||||
dev->ram_banks[0].virt = 0x00000000;
|
||||
dev->ram_banks[0].phys = 0x00000000;
|
||||
dev->ram_banks[0].size = 0x00020000;
|
||||
/* Pretend there's a 128k expansion. */
|
||||
dev->ram_banks[2].virt = 0x00020000;
|
||||
dev->ram_banks[2].phys = 0x00020000;
|
||||
dev->ram_banks[2].size = 0x00040000;
|
||||
break;
|
||||
case 512:
|
||||
dev->ram_banks[0].virt = 0x00000000;
|
||||
dev->ram_banks[0].phys = 0x00000000;
|
||||
dev->ram_banks[0].size = 0x00080000;
|
||||
break;
|
||||
default:
|
||||
dev->ram_banks[2].virt = 0x00100000;
|
||||
dev->ram_banks[2].phys = 0x000a0000;
|
||||
dev->ram_banks[2].size = (mem_size << 10) - 0x000a0000;
|
||||
fallthrough;
|
||||
case 640:
|
||||
dev->ram_banks[0].virt = 0x00000000;
|
||||
dev->ram_banks[0].phys = 0x00000000;
|
||||
dev->ram_banks[0].size = 0x00080000;
|
||||
dev->ram_banks[1].virt = 0x00080000;
|
||||
dev->ram_banks[1].phys = 0x00080000;
|
||||
dev->ram_banks[1].size = 0x00020000;
|
||||
break;
|
||||
case 768:
|
||||
dev->ram_banks[0].virt = 0x00000000;
|
||||
dev->ram_banks[0].phys = 0x00000000;
|
||||
dev->ram_banks[0].size = 0x00080000;
|
||||
dev->ram_banks[1].virt = 0x00080000;
|
||||
dev->ram_banks[1].phys = 0x00080000;
|
||||
dev->ram_banks[1].size = 0x00020000;
|
||||
/* Pretend there's a 128k expansion. */
|
||||
dev->ram_banks[2].virt = 0x00100000;
|
||||
dev->ram_banks[2].phys = 0x00080000;
|
||||
dev->ram_banks[2].size = 0x00020000;
|
||||
break;
|
||||
case 896:
|
||||
dev->ram_banks[0].virt = 0x00000000;
|
||||
dev->ram_banks[0].phys = 0x00000000;
|
||||
dev->ram_banks[0].size = 0x00080000;
|
||||
dev->ram_banks[1].virt = 0x00080000;
|
||||
dev->ram_banks[1].phys = 0x00080000;
|
||||
dev->ram_banks[1].size = 0x00020000;
|
||||
/* Pretend there's a 256k expansion. */
|
||||
dev->ram_banks[2].virt = 0x00100000;
|
||||
dev->ram_banks[2].phys = 0x00080000;
|
||||
dev->ram_banks[2].size = 0x00040000;
|
||||
break;
|
||||
case 1024:
|
||||
dev->ram_banks[0].virt = 0x00000000;
|
||||
dev->ram_banks[0].phys = 0x00000000;
|
||||
dev->ram_banks[0].size = 0x00080000;
|
||||
dev->ram_banks[1].virt = 0x00100000;
|
||||
dev->ram_banks[1].phys = 0x00080000;
|
||||
dev->ram_banks[1].size = 0x00080000;
|
||||
break;
|
||||
}
|
||||
|
||||
if (dev->ram_banks[0].size > 0x00000000)
|
||||
mem_mapping_add(&dev->ram_banks[0].mapping, dev->ram_banks[0].virt, dev->ram_banks[0].size,
|
||||
cs8220_mem_read, cs8220_mem_readw, NULL,
|
||||
cs8220_mem_write, cs8220_mem_writew, NULL,
|
||||
ram + dev->ram_banks[0].phys, MEM_MAPPING_INTERNAL, &(dev->ram_banks[0]));
|
||||
|
||||
if (dev->ram_banks[1].size > 0x00000000)
|
||||
mem_mapping_add(&dev->ram_banks[1].mapping, dev->ram_banks[1].virt, dev->ram_banks[1].size,
|
||||
cs8220_mem_read, cs8220_mem_readw, NULL,
|
||||
cs8220_mem_write, cs8220_mem_writew, NULL,
|
||||
ram + dev->ram_banks[1].phys, MEM_MAPPING_INTERNAL, &(dev->ram_banks[1]));
|
||||
|
||||
if (dev->ram_banks[2].size > 0x00000000)
|
||||
mem_mapping_add(&dev->ram_banks[2].mapping, dev->ram_banks[2].virt, dev->ram_banks[2].size,
|
||||
cs8220_mem_read, cs8220_mem_readw, NULL,
|
||||
cs8220_mem_write, cs8220_mem_writew, NULL,
|
||||
ram + dev->ram_banks[2].phys, MEM_MAPPING_INTERNAL, &(dev->ram_banks[2]));
|
||||
|
||||
io_sethandler(0x00a4, 0x0002,
|
||||
cs8220_in, NULL, NULL, cs8220_out, NULL, NULL, dev);
|
||||
io_sethandler(0x00ab, 0x0001,
|
||||
cs8220_in, NULL, NULL, cs8220_out, NULL, NULL, dev);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
const device_t cs8220_device = {
|
||||
.name = "C&T CS8220 (PC/AT)",
|
||||
.internal_name = "cs8220",
|
||||
.flags = 0,
|
||||
.local = 0,
|
||||
.init = cs8220_init,
|
||||
.close = cs8220_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
@@ -1013,7 +1013,8 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
case INTEL_430TX:
|
||||
if (!dev->smram_locked) {
|
||||
i4x0_smram_handler_phase0(dev);
|
||||
regs[0x71] = (regs[0x71] & 0x20) | (val & 0xdf);
|
||||
regs[0x71] = (regs[0x71] & 0x60) | (val & 0x9f);
|
||||
regs[0x71] &= (val & 0x40);
|
||||
i4x0_smram_handler_phase1(dev);
|
||||
}
|
||||
break;
|
||||
@@ -1041,9 +1042,11 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
|
||||
regs[0x72] = (val & 0x7f);
|
||||
else
|
||||
regs[0x72] = (regs[0x72] & 0x87) | (val & 0x78);
|
||||
dev->smram_locked = (val & 0x10);
|
||||
if (dev->smram_locked)
|
||||
regs[0x72] &= 0xbf;
|
||||
if (val & 0x08) {
|
||||
dev->smram_locked = (val & 0x10);
|
||||
if (dev->smram_locked)
|
||||
regs[0x72] &= 0xbf;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (dev->smram_locked)
|
||||
@@ -1577,6 +1580,8 @@ i4x0_reset(void *priv)
|
||||
dev->regs[0x68 + i] = 0x00;
|
||||
}
|
||||
|
||||
dev->smram_locked = 0;
|
||||
|
||||
if (dev->type >= INTEL_430FX) {
|
||||
dev->regs[0x72] &= 0xef; /* Forcibly unlock the SMRAM register. */
|
||||
i4x0_write(0, 0x72, 0x02, priv);
|
||||
@@ -1656,7 +1661,12 @@ i4x0_init(const device_t *info)
|
||||
regs[0x57] = 0x31;
|
||||
regs[0x59] = 0x0f;
|
||||
regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = 0x02;
|
||||
dev->max_drb = 3;
|
||||
/* At the very least the 420ZX seems to read to 0x64, per the SB486PV. */
|
||||
if (dev->type == INTEL_420ZX) {
|
||||
regs[0x64] = 0x02;
|
||||
dev->max_drb = 4;
|
||||
} else
|
||||
dev->max_drb = 3;
|
||||
dev->drb_unit = 1;
|
||||
dev->drb_default = 0x02;
|
||||
break;
|
||||
|
||||
@@ -59,7 +59,6 @@ typedef struct piix_io_trap_t {
|
||||
} piix_io_trap_t;
|
||||
|
||||
typedef struct _piix_ {
|
||||
uint8_t cur_readout_reg;
|
||||
uint8_t rev;
|
||||
uint8_t type;
|
||||
uint8_t func_shift;
|
||||
@@ -67,7 +66,6 @@ typedef struct _piix_ {
|
||||
uint8_t pci_slot;
|
||||
uint8_t no_mirq0;
|
||||
uint8_t regs[4][256];
|
||||
uint8_t readout_regs[256];
|
||||
uint16_t func0_id;
|
||||
uint16_t nvr_io_base;
|
||||
uint16_t acpi_io_base;
|
||||
@@ -157,6 +155,7 @@ piix_ide_handlers(piix_t *dev, int bus)
|
||||
uint16_t side;
|
||||
|
||||
if (bus & 0x01) {
|
||||
piix_log("Disabling primary IDE...\n");
|
||||
ide_pri_disable();
|
||||
|
||||
if (dev->type == 5) {
|
||||
@@ -172,11 +171,14 @@ piix_ide_handlers(piix_t *dev, int bus)
|
||||
ide_set_side(0, side);
|
||||
}
|
||||
|
||||
if ((dev->regs[1][0x04] & 0x01) && (dev->regs[1][0x41] & 0x80))
|
||||
if ((dev->regs[1][0x04] & 0x01) && (dev->regs[1][0x41] & 0x80)) {
|
||||
piix_log("Enabling primary IDE...\n");
|
||||
ide_pri_enable();
|
||||
}
|
||||
}
|
||||
|
||||
if (bus & 0x02) {
|
||||
piix_log("Disabling secondary IDE...\n");
|
||||
ide_sec_disable();
|
||||
|
||||
if (dev->type == 5) {
|
||||
@@ -192,8 +194,10 @@ piix_ide_handlers(piix_t *dev, int bus)
|
||||
ide_set_side(1, side);
|
||||
}
|
||||
|
||||
if ((dev->regs[1][0x04] & 0x01) && (dev->regs[1][0x43] & 0x80))
|
||||
if ((dev->regs[1][0x04] & 0x01) && (dev->regs[1][0x43] & 0x80)) {
|
||||
piix_log("Enabling secondary IDE...\n");
|
||||
ide_sec_enable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -467,6 +471,13 @@ piix_write(int func, int addr, uint8_t val, void *priv)
|
||||
uint8_t *fregs;
|
||||
uint16_t base;
|
||||
|
||||
/* Dell OptiPlex Gn+ shows that register 02:FF is aliased in 01:FF. */
|
||||
if ((dev->type == 4) && (func == 1) && (addr == 0xff))
|
||||
func = 2;
|
||||
|
||||
if ((func == 1) || (addr == 0xf8) || (addr == 0xf9))
|
||||
piix_log("[W] %02X:%02X = %02X\n", func, addr, val);
|
||||
|
||||
/* Return on unsupported function. */
|
||||
if (dev->max_func > 0) {
|
||||
if (func > dev->max_func)
|
||||
@@ -738,6 +749,8 @@ piix_write(int func, int addr, uint8_t val, void *priv)
|
||||
fregs[addr] = val;
|
||||
break;
|
||||
case 0xb0:
|
||||
if (val & 0x10)
|
||||
warning("Write %02X to B0\n", val);
|
||||
if (dev->type == 4)
|
||||
fregs[addr] = (fregs[addr] & 0x8c) | (val & 0x73);
|
||||
else if (dev->type == 5)
|
||||
@@ -747,6 +760,8 @@ piix_write(int func, int addr, uint8_t val, void *priv)
|
||||
alt_access = !!(val & 0x20);
|
||||
break;
|
||||
case 0xb1:
|
||||
if (val & 0x18)
|
||||
warning("Write %02X to B1\n", val);
|
||||
if (dev->type > 3)
|
||||
fregs[addr] = val & 0xdf;
|
||||
break;
|
||||
@@ -925,6 +940,12 @@ piix_write(int func, int addr, uint8_t val, void *priv)
|
||||
if (dev->type > 4)
|
||||
fregs[addr] = val;
|
||||
break;
|
||||
case 0xf8:
|
||||
case 0xf9:
|
||||
/* Undocumented! */
|
||||
if (dev->type == 4)
|
||||
fregs[addr] = val;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1171,6 +1192,10 @@ piix_read(int func, int addr, void *priv)
|
||||
uint8_t ret = 0xff;
|
||||
const uint8_t *fregs;
|
||||
|
||||
/* Dell OptiPlex Gn+ shows that register 02:FF is aliased in 01:FF. */
|
||||
if ((dev->type == 4) && (func == 1) && (addr == 0xff))
|
||||
func = 2;
|
||||
|
||||
if ((dev->type == 3) && (func == 2) && (dev->max_func == 1) && (addr >= 0x40))
|
||||
ret = 0x00;
|
||||
|
||||
@@ -1185,31 +1210,6 @@ piix_read(int func, int addr, void *priv)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
board_write(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
piix_t *dev = (piix_t *) priv;
|
||||
|
||||
if (port == 0x00e0)
|
||||
dev->cur_readout_reg = val;
|
||||
else if (port == 0x00e1)
|
||||
dev->readout_regs[dev->cur_readout_reg] = val;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
board_read(uint16_t port, void *priv)
|
||||
{
|
||||
const piix_t *dev = (piix_t *) priv;
|
||||
uint8_t ret = 0x64;
|
||||
|
||||
if (port == 0x00e0)
|
||||
ret = dev->cur_readout_reg;
|
||||
else if (port == 0x00e1)
|
||||
ret = dev->readout_regs[dev->cur_readout_reg];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
piix_reset_hard(piix_t *dev)
|
||||
{
|
||||
@@ -1226,7 +1226,7 @@ piix_reset_hard(piix_t *dev)
|
||||
|
||||
sff_set_slot(dev->bm[1], dev->pci_slot);
|
||||
sff_set_irq_pin(dev->bm[1], PCI_INTA);
|
||||
sff_set_irq_line(dev->bm[1], 14);
|
||||
sff_set_irq_line(dev->bm[1], 15);
|
||||
sff_set_irq_mode(dev->bm[1], IRQ_MODE_LEGACY);
|
||||
}
|
||||
|
||||
@@ -1342,6 +1342,10 @@ piix_reset_hard(piix_t *dev)
|
||||
fregs[0x45] = 0x55;
|
||||
fregs[0x46] = 0x01;
|
||||
}
|
||||
if (dev->type == 4) {
|
||||
fregs[0xf8] = 0x30;
|
||||
fregs[0xf9] = 0x0f;
|
||||
}
|
||||
if ((dev->type == 1) && (dev->rev == 2))
|
||||
dev->max_func = 0; /* It starts with IDE disabled, then enables it. */
|
||||
else
|
||||
@@ -1617,47 +1621,16 @@ piix_init(const device_t *info)
|
||||
else
|
||||
cpu_set_isa_pci_div(3);
|
||||
|
||||
dma_alias_set();
|
||||
if (dev->type > 1)
|
||||
dma_alias_set();
|
||||
else
|
||||
dma_alias_set_piix();
|
||||
|
||||
if (dev->type < 4)
|
||||
pci_enable_mirq(0);
|
||||
if (dev->type < 3)
|
||||
pci_enable_mirq(1);
|
||||
|
||||
dev->readout_regs[0] = 0xff;
|
||||
dev->readout_regs[1] = 0x40;
|
||||
dev->readout_regs[2] = 0xff;
|
||||
|
||||
/* Port E1 register 01 (TODO: Find how multipliers > 3.0 are defined):
|
||||
|
||||
Bit 6: 1 = can boot, 0 = no;
|
||||
Bit 7, 1 = multiplier (00 = 2.5, 01 = 2.0, 10 = 3.0, 11 = 1.5);
|
||||
Bit 5, 4 = bus speed (00 = 50 MHz, 01 = 66 MHz, 10 = 60 MHz, 11 = ????):
|
||||
Bit 7, 5, 4, 1: 0000 = 125 MHz, 0010 = 166 MHz, 0100 = 150 MHz, 0110 = ??? MHz;
|
||||
0001 = 100 MHz, 0011 = 133 MHz, 0101 = 120 MHz, 0111 = ??? MHz;
|
||||
1000 = 150 MHz, 1010 = 200 MHz, 1100 = 180 MHz, 1110 = ??? MHz;
|
||||
1001 = 75 MHz, 1011 = 100 MHz, 1101 = 90 MHz, 1111 = ??? MHz */
|
||||
|
||||
if (cpu_busspeed <= 40000000)
|
||||
dev->readout_regs[1] |= 0x30;
|
||||
else if ((cpu_busspeed > 40000000) && (cpu_busspeed <= 50000000))
|
||||
dev->readout_regs[1] |= 0x00;
|
||||
else if ((cpu_busspeed > 50000000) && (cpu_busspeed <= 60000000))
|
||||
dev->readout_regs[1] |= 0x20;
|
||||
else if (cpu_busspeed > 60000000)
|
||||
dev->readout_regs[1] |= 0x10;
|
||||
|
||||
if (cpu_dmulti <= 1.5)
|
||||
dev->readout_regs[1] |= 0x82;
|
||||
else if ((cpu_dmulti > 1.5) && (cpu_dmulti <= 2.0))
|
||||
dev->readout_regs[1] |= 0x02;
|
||||
else if ((cpu_dmulti > 2.0) && (cpu_dmulti <= 2.5))
|
||||
dev->readout_regs[1] |= 0x00;
|
||||
else if (cpu_dmulti > 2.5)
|
||||
dev->readout_regs[1] |= 0x80;
|
||||
|
||||
io_sethandler(0x00e0, 0x0002, board_read, NULL, NULL, board_write, NULL, NULL, dev);
|
||||
|
||||
#if 0
|
||||
device_add(&i8254_sec_device);
|
||||
#endif
|
||||
|
||||
@@ -355,7 +355,23 @@ sio_config_read(uint16_t port, UNUSED(void *priv))
|
||||
ret = 0xff;
|
||||
break;
|
||||
case 5:
|
||||
ret = 0xd3;
|
||||
/*
|
||||
Dell Dimension XPS P60 jumpers:
|
||||
- Bit 5: Disable CMOS Setup (1 = yes, 0 = no).
|
||||
|
||||
Dell OptiPlex 560/L jumpers:
|
||||
- Bit 1: Password (1 = disable, 0 = enable);
|
||||
- Bit 5: Clear CMOS (1 = no, 0 = yes).
|
||||
- Bits 7, 6: Board type:
|
||||
- 0, 0 = L;
|
||||
- 0, 1 = MT;
|
||||
- 1, 0 = M;
|
||||
- 1, 1 = M.
|
||||
*/
|
||||
if (!strcmp(machine_get_internal_name(), "opti560l"))
|
||||
ret = 0x20;
|
||||
else
|
||||
ret = 0xd3;
|
||||
|
||||
switch (cpu_pci_speed) {
|
||||
case 20000000:
|
||||
|
||||
131
src/chipset/isa486c.c
Normal file
131
src/chipset/isa486c.c
Normal file
@@ -0,0 +1,131 @@
|
||||
#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/io.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/plat_unused.h>
|
||||
#include <86box/chipset.h>
|
||||
|
||||
typedef struct isa486c_t {
|
||||
uint8_t regs[3];
|
||||
} isa486c_t;
|
||||
|
||||
static void
|
||||
isa486c_recalcmapping(isa486c_t *dev)
|
||||
{
|
||||
uint32_t shflags = 0;
|
||||
uint32_t bases[5] = { 0x000c0000, 0x000c8000, 0x000d0000, 0x000d8000, 0x000e0000 };
|
||||
uint32_t sizes[5] = { 0x00008000, 0x00008000, 0x00008000, 0x00008000, 0x00020000 };
|
||||
|
||||
if (dev->regs[1] & 0x20)
|
||||
shflags = MEM_READ_EXTANY | MEM_WRITE_INTERNAL;
|
||||
else
|
||||
shflags = MEM_READ_INTERNAL | MEM_WRITE_EXTANY;
|
||||
|
||||
shadowbios = 0;
|
||||
shadowbios_write = 0;
|
||||
|
||||
for (uint8_t i = 0; i < 5; i++)
|
||||
if (dev->regs[1] & (1 << i)) {
|
||||
if (i == 4) {
|
||||
shadowbios = 1;
|
||||
shadowbios_write = !!(dev->regs[1] & 0x20);
|
||||
}
|
||||
|
||||
mem_set_mem_state_both(bases[i], sizes[i], shflags);
|
||||
} else
|
||||
mem_set_mem_state_both(bases[i], sizes[i], MEM_READ_EXTANY | MEM_WRITE_EXTANY);
|
||||
|
||||
flushmmucache_nopc();
|
||||
}
|
||||
|
||||
static void
|
||||
isa486c_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
isa486c_t *dev = (isa486c_t *) priv;
|
||||
|
||||
switch (addr) {
|
||||
case 0x0023:
|
||||
dev->regs[0] = val;
|
||||
break;
|
||||
/*
|
||||
Port 25h:
|
||||
- Bit 0 = Video BIOS (C000-C7FF) shadow enabled;
|
||||
- Bit 1 = C800-C8FF shadow enabled;
|
||||
- Bit 2 = D000-D7FF shadow enabled;
|
||||
- Bit 3 = D800-DFFF shadow enabled;
|
||||
- Bit 4 = E000-FFFF shadow enabled (or F0000-FFFFF?);
|
||||
- Bit 5 = If set, read from ROM, write to shadow;
|
||||
- Bit 6 = KEN Video & BIOS enabled (cacheability!).
|
||||
*/
|
||||
case 0x0025:
|
||||
dev->regs[1] = val;
|
||||
isa486c_recalcmapping(dev);
|
||||
break;
|
||||
case 0x0027:
|
||||
dev->regs[2] = val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
isa486c_read(uint16_t addr, void *priv)
|
||||
{
|
||||
isa486c_t *dev = (isa486c_t *) priv;
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
switch (addr) {
|
||||
case 0x0023:
|
||||
ret = dev->regs[0];
|
||||
break;
|
||||
case 0x0025:
|
||||
ret = dev->regs[1];
|
||||
break;
|
||||
case 0x0027:
|
||||
ret = dev->regs[2];
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
isa486c_close(void *priv)
|
||||
{
|
||||
isa486c_t *dev = (isa486c_t *) priv;
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
static void *
|
||||
isa486c_init(UNUSED(const device_t *info))
|
||||
{
|
||||
isa486c_t *dev = (isa486c_t *) calloc(1, sizeof(isa486c_t));
|
||||
|
||||
io_sethandler(0x0023, 0x0001, isa486c_read, NULL, NULL, isa486c_write, NULL, NULL, dev);
|
||||
io_sethandler(0x0025, 0x0001, isa486c_read, NULL, NULL, isa486c_write, NULL, NULL, dev);
|
||||
io_sethandler(0x0027, 0x0001, isa486c_read, NULL, NULL, isa486c_write, NULL, NULL, dev);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
const device_t isa486c_device = {
|
||||
.name = "ASUS ISA-486C Gate Array",
|
||||
.internal_name = "isa486c",
|
||||
.flags = 0,
|
||||
.local = 0,
|
||||
.init = isa486c_init,
|
||||
.close = isa486c_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
@@ -956,8 +956,9 @@ neat_write(uint16_t port, uint8_t val, void *priv)
|
||||
dev->ems_size);
|
||||
}
|
||||
|
||||
mem_a20_key = !(val & RB12_GA20);
|
||||
mem_a20_alt = !(val & RB12_GA20);
|
||||
mem_a20_recalc();
|
||||
flushmmucache();
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -987,7 +988,7 @@ neat_read(uint16_t port, void *priv)
|
||||
if ((dev->indx >= 0x60) && (dev->indx <= 0x6e))
|
||||
ret = dev->regs[dev->indx];
|
||||
else if (dev->indx == 0x6f)
|
||||
ret = (dev->regs[dev->indx] & 0xfd) | (mem_a20_key & 2);
|
||||
ret = (dev->regs[dev->indx] & 0xfd) | ~(mem_a20_alt & 0x02);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -73,26 +73,24 @@ olivetti_eva_write(uint16_t addr, uint8_t val, void *priv)
|
||||
break;
|
||||
case 0x069:
|
||||
dev->reg_069 = val;
|
||||
/*
|
||||
* Unfortunately, if triggered, the BIOS remapping function fails causing
|
||||
* a fatal error. Therefore, this code section is currently commented.
|
||||
*/
|
||||
#if 0
|
||||
if (val & 1) {
|
||||
mem_remap_top(0);
|
||||
if (val == 0x01) {
|
||||
/*
|
||||
* Set the register to 7 or above for the BIOS to trigger the
|
||||
* memory remapping function if shadowing is active.
|
||||
*/
|
||||
dev->reg_069 = 0x7;
|
||||
dev->reg_069 = 0x07;
|
||||
}
|
||||
if (val & 8) {
|
||||
if (val & 0x08) {
|
||||
/*
|
||||
* Activate shadowing for region e0000-fffff
|
||||
*/
|
||||
mem_remap_top(256);
|
||||
mem_set_mem_state_both(0xa0000, 0x60000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
|
||||
mem_set_mem_state_both(0xe0000, 0x20000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
|
||||
} else {
|
||||
mem_remap_top(384);
|
||||
mem_set_mem_state_both(0xe0000, 0x20000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -143,7 +141,7 @@ olivetti_eva_init(UNUSED(const device_t *info))
|
||||
dev->reg_067 = 0x00;
|
||||
|
||||
/* RAM enable registers */
|
||||
dev->reg_069 = 0x0;
|
||||
dev->reg_069 = 0x00;
|
||||
|
||||
io_sethandler(0x0065, 0x0001, olivetti_eva_read, NULL, NULL, olivetti_eva_write, NULL, NULL, dev);
|
||||
io_sethandler(0x0067, 0x0001, olivetti_eva_read, NULL, NULL, olivetti_eva_write, NULL, NULL, dev);
|
||||
@@ -152,13 +150,6 @@ olivetti_eva_init(UNUSED(const device_t *info))
|
||||
/* When shadowing is not enabled in BIOS, all upper memory is available as XMS */
|
||||
mem_remap_top(384);
|
||||
|
||||
/*
|
||||
* Default settings when NVRAM is cleared activate shadowing.
|
||||
* Thus, to avoid boot errors, remap only 256k from UMB to XMS.
|
||||
* Remove this block once BIOS memory remapping works.
|
||||
*/
|
||||
mem_remap_top(256);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
@@ -1177,7 +1177,7 @@ scamp_init(UNUSED(const device_t *info))
|
||||
dev->mem_flags[i] = MEM_FLAG_READ | MEM_FLAG_WRITE;
|
||||
scamp_mem_update_state(dev, i * EMS_PGSIZE, EMS_PGSIZE, 0x00, MEM_FMASK_RW);
|
||||
|
||||
if (i >= 60)
|
||||
if (i >= 56)
|
||||
scamp_mem_update_state(dev, i * EMS_PGSIZE, EMS_PGSIZE, MEM_FLAG_ROMCS, MEM_FMASK_ROMCS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,7 +259,7 @@ sis_5511_host_to_pci_write(int addr, uint8_t val, void *priv)
|
||||
case 0x7a: /* DRAM Bank Register 2-1 */
|
||||
case 0x7c: /* DRAM Bank Register 3-0 */
|
||||
case 0x7e: /* DRAM Bank Register 3-1 */
|
||||
spd_write_drbs(dev->pci_conf, 0x70, 0x7e, 0x82);
|
||||
spd_write_drbs(dev->pci_conf, 0x70, 0x7e, 0x02);
|
||||
break;
|
||||
|
||||
case 0x71: /* DRAM Bank Register 0-0 */
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*
|
||||
* Copyright 2019-2020 Miran Grca.
|
||||
*/
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
@@ -33,27 +34,384 @@
|
||||
#include <86box/mem.h>
|
||||
#include <86box/smram.h>
|
||||
#include <86box/pic.h>
|
||||
#include <86box/plat_fallthrough.h>
|
||||
#include <86box/keyboard.h>
|
||||
#include <86box/machine.h>
|
||||
#include <86box/chipset.h>
|
||||
|
||||
typedef struct ram_bank_t {
|
||||
uint32_t virt_base;
|
||||
uint32_t virt_size;
|
||||
uint32_t phys_base;
|
||||
uint32_t phys_size;
|
||||
|
||||
mem_mapping_t mapping;
|
||||
} ram_bank_t;
|
||||
|
||||
typedef struct sis_85c4xx_t {
|
||||
uint8_t cur_reg;
|
||||
uint8_t tries;
|
||||
uint8_t reg_base;
|
||||
uint8_t reg_last;
|
||||
uint8_t reg_00;
|
||||
uint8_t is_471;
|
||||
uint8_t force_flush;
|
||||
uint8_t shadowed;
|
||||
uint8_t smram_enabled;
|
||||
uint8_t pad;
|
||||
uint8_t regs[39];
|
||||
uint8_t scratch[2];
|
||||
uint32_t mem_state[8];
|
||||
smram_t *smram;
|
||||
port_92_t *port_92;
|
||||
uint8_t cur_reg;
|
||||
uint8_t tries;
|
||||
uint8_t reg_base;
|
||||
uint8_t reg_last;
|
||||
uint8_t reg_00;
|
||||
uint8_t is_471;
|
||||
uint8_t ram_banks_val;
|
||||
uint8_t force_flush;
|
||||
uint8_t shadowed;
|
||||
uint8_t smram_enabled;
|
||||
uint8_t pad;
|
||||
uint8_t regs[39];
|
||||
uint8_t scratch[2];
|
||||
uint32_t mem_state[8];
|
||||
ram_bank_t ram_banks[8];
|
||||
smram_t * smram;
|
||||
port_92_t * port_92;
|
||||
} sis_85c4xx_t;
|
||||
|
||||
static uint8_t ram_4xx[64] = { 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00,
|
||||
0x04, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00,
|
||||
0x19, 0x00, 0x06, 0x00, 0x14, 0x00, 0x00, 0x00,
|
||||
0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x1b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
|
||||
0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
static uint8_t ram_471[64] = { 0x00, 0x00, 0x01, 0x01, 0x02, 0x20, 0x09, 0x09,
|
||||
0x04, 0x04, 0x05, 0x05, 0x0b, 0x0b, 0x0b, 0x0b,
|
||||
0x13, 0x21, 0x06, 0x06, 0x0d, 0x0d, 0x0d, 0x0d,
|
||||
0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
|
||||
0x1b, 0x1b, 0x1b, 0x1b, 0x0f, 0x0f, 0x0f, 0x0f,
|
||||
0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
|
||||
0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d,
|
||||
0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d };
|
||||
static uint8_t ram_asus[64] = { 0x00, 0x00, 0x01, 0x10, 0x10, 0x20, 0x03, 0x11,
|
||||
0x11, 0x05, 0x05, 0x12, 0x12, 0x13, 0x13, 0x13,
|
||||
0x13, 0x21, 0x06, 0x14, 0x14, 0x15, 0x15, 0x15,
|
||||
0x15, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d,
|
||||
0x1d, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17,
|
||||
0x17, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
|
||||
0x1e, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
|
||||
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f };
|
||||
static uint8_t ram_tg486g[64] = { 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11,
|
||||
0x11, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13,
|
||||
0x13, 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15,
|
||||
0x15, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d,
|
||||
0x1d, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17,
|
||||
0x17, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
|
||||
0x1e, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
|
||||
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f };
|
||||
|
||||
static uint32_t banks_471[64][4] = { { 0x00100000, 0x00000000, 0x00000000, 0x00000000 }, /* 0x00 */
|
||||
{ 0x00100000, 0x00100000, 0x00000000, 0x00000000 },
|
||||
{ 0x00100000, 0x00100000, 0x00200000, 0x00000000 },
|
||||
{ 0x00100000, 0x00100000, 0x00400000, 0x00000000 },
|
||||
{ 0x00100000, 0x00100000, 0x00200000, 0x00400000 },
|
||||
{ 0x00100000, 0x00100000, 0x00400000, 0x00400000 },
|
||||
{ 0x00100000, 0x00100000, 0x01000000, 0x00000000 },
|
||||
{ 0x00200000, 0x00000000, 0x00000000, 0x00000000 },
|
||||
{ 0x00200000, 0x00200000, 0x00000000, 0x00000000 }, /* 0x08 */
|
||||
{ 0x00200000, 0x00400000, 0x00000000, 0x00000000 },
|
||||
{ 0x00200000, 0x00200000, 0x00400000, 0x00000000 },
|
||||
{ 0x00200000, 0x00200000, 0x00400000, 0x00400000 },
|
||||
{ 0x00200000, 0x01000000, 0x00000000, 0x00000000 },
|
||||
{ 0x00200000, 0x00200000, 0x01000000, 0x00000000 },
|
||||
{ 0x00200000, 0x00200000, 0x00400000, 0x01000000 },
|
||||
{ 0x00200000, 0x00200000, 0x01000000, 0x01000000 },
|
||||
{ 0x00400000, 0x00000000, 0x00000000, 0x00000000 }, /* 0x10 */
|
||||
{ 0x00400000, 0x00400000, 0x00000000, 0x00000000 },
|
||||
{ 0x00400000, 0x00400000, 0x00400000, 0x00000000 },
|
||||
{ 0x00400000, 0x00400000, 0x00400000, 0x00400000 },
|
||||
{ 0x00400000, 0x01000000, 0x00000000, 0x00000000 },
|
||||
{ 0x00400000, 0x00400000, 0x01000000, 0x00000000 },
|
||||
{ 0x00400000, 0x01000000, 0x01000000, 0x00000000 },
|
||||
{ 0x00400000, 0x00400000, 0x01000000, 0x01000000 },
|
||||
{ 0x00800000, 0x00000000, 0x00000000, 0x00000000 }, /* 0x18 */
|
||||
{ 0x00800000, 0x00800000, 0x00000000, 0x00000000 },
|
||||
{ 0x00800000, 0x00800000, 0x00800000, 0x00000000 },
|
||||
{ 0x00800000, 0x00800000, 0x00800000, 0x00800000 },
|
||||
{ 0x01000000, 0x00000000, 0x00000000, 0x00000000 },
|
||||
{ 0x01000000, 0x01000000, 0x00000000, 0x00000000 },
|
||||
{ 0x01000000, 0x01000000, 0x01000000, 0x00000000 },
|
||||
{ 0x01000000, 0x01000000, 0x01000000, 0x01000000 },
|
||||
{ 0x00100000, 0x00400000, 0x00000000, 0x00000000 }, /* 0x20 */
|
||||
{ 0x00100000, 0x01000000, 0x00000000, 0x00000000 },
|
||||
{ 0x00100000, 0x04000000, 0x00000000, 0x00000000 },
|
||||
{ 0x00400000, 0x00800000, 0x00000000, 0x00000000 },
|
||||
{ 0x00400000, 0x04000000, 0x00000000, 0x00000000 },
|
||||
{ 0x00400000, 0x00400000, 0x04000000, 0x00000000 },
|
||||
{ 0x01000000, 0x04000000, 0x00000000, 0x00000000 },
|
||||
{ 0x01000000, 0x01000000, 0x04000000, 0x00000000 },
|
||||
{ 0x04000000, 0x00000000, 0x00000000, 0x00000000 }, /* 0x28 */
|
||||
{ 0x04000000, 0x04000000, 0x00000000, 0x00000000 },
|
||||
{ 0x00400000, 0x02000000, 0x00000000, 0x00000000 },
|
||||
{ 0x00400000, 0x02000000, 0x02000000, 0x00000000 },
|
||||
{ 0x00400000, 0x00400000, 0x02000000, 0x00000000 },
|
||||
{ 0x00400000, 0x00400000, 0x02000000, 0x02000000 },
|
||||
{ 0x01000000, 0x02000000, 0x00000000, 0x00000000 },
|
||||
{ 0x01000000, 0x02000000, 0x02000000, 0x00000000 },
|
||||
{ 0x01000000, 0x01000000, 0x02000000, 0x00000000 }, /* 0x30 */
|
||||
{ 0x01000000, 0x01000000, 0x02000000, 0x02000000 },
|
||||
{ 0x02000000, 0x00000000, 0x00000000, 0x00000000 },
|
||||
{ 0x02000000, 0x02000000, 0x00000000, 0x00000000 },
|
||||
{ 0x02000000, 0x02000000, 0x02000000, 0x00000000 },
|
||||
{ 0x02000000, 0x02000000, 0x02000000, 0x02000000 },
|
||||
{ 0x00400000, 0x00800000, 0x00800000, 0x00000000 },
|
||||
{ 0x00400000, 0x00800000, 0x00800000, 0x00800000 },
|
||||
{ 0x00400000, 0x00400000, 0x00800000, 0x00000000 }, /* 0x38 */
|
||||
{ 0x00400000, 0x00400000, 0x00800000, 0x00800000 },
|
||||
{ 0x00800000, 0x01000000, 0x00000000, 0x00000000 },
|
||||
{ 0x00800000, 0x00800000, 0x00800000, 0x01000000 },
|
||||
{ 0x00800000, 0x00800000, 0x01000000, 0x00000000 },
|
||||
{ 0x00800000, 0x00800000, 0x01000000, 0x01000000 },
|
||||
{ 0x00800000, 0x00800000, 0x02000000, 0x00000000 },
|
||||
{ 0x00800000, 0x00800000, 0x02000000, 0x02000000 } };
|
||||
|
||||
static uint32_t
|
||||
sis_85c471_get_row(ram_bank_t *dev, uint32_t addr)
|
||||
{
|
||||
uint32_t ret = 0x00000000;
|
||||
|
||||
switch (dev->virt_size) {
|
||||
case 0x00100000:
|
||||
case 0x00200000:
|
||||
ret |= (addr >> 13) & 0x00000001;
|
||||
ret |= ((addr >> 12) & 0x00000001) << 1;
|
||||
ret |= ((addr >> 14) & 0x0000003f) << 2;
|
||||
ret |= ((addr >> 11) & 0x00000001) << 8;
|
||||
ret |= ((addr >> 20) & 0x00000001) << 9;
|
||||
ret |= ((addr >> 22) & 0x00000001) << 10;
|
||||
ret |= ((addr >> 24) & 0x00000001) << 11;
|
||||
break;
|
||||
case 0x00400000:
|
||||
case 0x00800000:
|
||||
ret |= (addr >> 13) & 0x00000001;
|
||||
ret |= ((addr >> 12) & 0x00000001) << 1;
|
||||
ret |= ((addr >> 14) & 0x000000ff) << 2;
|
||||
ret |= ((addr >> 22) & 0x00000001) << 10;
|
||||
ret |= ((addr >> 24) & 0x00000001) << 11;
|
||||
break;
|
||||
case 0x01000000:
|
||||
case 0x02000000:
|
||||
case 0x04000000:
|
||||
ret |= (addr >> 13) & 0x00000001;
|
||||
ret |= ((addr >> 22) & 0x00000001) << 1;
|
||||
ret |= ((addr >> 14) & 0x000000ff) << 2;
|
||||
ret |= ((addr >> 23) & 0x00000001) << 10;
|
||||
ret |= ((addr >> 24) & 0x00000001) << 11;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
sis_85c471_get_col(ram_bank_t *dev, uint32_t addr)
|
||||
{
|
||||
uint32_t ret = 0x00000000;
|
||||
|
||||
switch (dev->virt_size) {
|
||||
case 0x00100000:
|
||||
case 0x00200000:
|
||||
ret |= (addr >> 3) & 0x00000001;
|
||||
ret |= ((addr >> 2) & 0x00000001) << 1;
|
||||
ret |= ((addr >> 4) & 0x0000003f) << 2;
|
||||
ret |= ((addr >> 10) & 0x00000001) << 8;
|
||||
ret |= ((addr >> 21) & 0x00000001) << 9;
|
||||
ret |= ((addr >> 23) & 0x00000001) << 10;
|
||||
ret |= ((addr >> 25) & 0x00000001) << 11;
|
||||
break;
|
||||
case 0x00400000:
|
||||
case 0x00800000:
|
||||
ret |= (addr >> 3) & 0x00000001;
|
||||
ret |= ((addr >> 2) & 0x00000001) << 1;
|
||||
ret |= ((addr >> 4) & 0x000000ff) << 2;
|
||||
ret |= ((addr >> 23) & 0x00000001) << 10;
|
||||
ret |= ((addr >> 25) & 0x00000001) << 11;
|
||||
break;
|
||||
case 0x01000000:
|
||||
case 0x02000000:
|
||||
case 0x04000000:
|
||||
ret |= (addr >> 3) & 0x00000001;
|
||||
ret |= ((addr >> 2) & 0x00000001) << 1;
|
||||
ret |= ((addr >> 4) & 0x000001ff) << 2;
|
||||
ret |= ((addr >> 25) & 0x00000001) << 11;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
sis_85c471_set_row(ram_bank_t *dev, uint32_t addr)
|
||||
{
|
||||
uint32_t ret = 0x00000000;
|
||||
|
||||
switch (dev->phys_size) {
|
||||
case 0x00100000:
|
||||
ret = (addr & 0x1ff) << 11;
|
||||
break;
|
||||
case 0x00200000:
|
||||
ret = (addr & 0x3ff) << 11;
|
||||
break;
|
||||
case 0x00400000:
|
||||
ret = (addr & 0x3ff) << 12;
|
||||
break;
|
||||
case 0x00800000:
|
||||
ret = (addr & 0x7ff) << 12;
|
||||
break;
|
||||
case 0x01000000:
|
||||
ret = (addr & 0x7ff) << 13;
|
||||
break;
|
||||
case 0x02000000:
|
||||
ret = (addr & 0xfff) << 13;
|
||||
break;
|
||||
case 0x04000000:
|
||||
ret = (addr & 0xfff) << 14;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
sis_85c471_set_col(ram_bank_t *dev, uint32_t addr)
|
||||
{
|
||||
uint32_t ret = 0x00000000;
|
||||
|
||||
switch (dev->phys_size) {
|
||||
case 0x00100000:
|
||||
case 0x00200000:
|
||||
ret = (addr & 0x1ff) << 2;
|
||||
break;
|
||||
case 0x00400000:
|
||||
case 0x00800000:
|
||||
ret = (addr & 0x3ff) << 2;
|
||||
break;
|
||||
case 0x01000000:
|
||||
case 0x02000000:
|
||||
ret = (addr & 0x7ff) << 2;
|
||||
break;
|
||||
case 0x04000000:
|
||||
ret = (addr & 0xfff) << 2;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8_t reg09 = 0x00;
|
||||
|
||||
static uint8_t
|
||||
sis_85c471_read_ram(uint32_t addr, void *priv)
|
||||
{
|
||||
ram_bank_t *dev = (ram_bank_t *) priv;
|
||||
uint32_t rel = addr - dev->virt_base;
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
uint32_t row = sis_85c471_set_row(dev, sis_85c471_get_row(dev, rel));
|
||||
uint32_t col = sis_85c471_set_col(dev, sis_85c471_get_col(dev, rel));
|
||||
uint32_t dw = rel & 0x00000003;
|
||||
rel = row | col | dw;
|
||||
|
||||
addr = (rel + dev->phys_base);
|
||||
|
||||
if ((addr < (mem_size << 10)) && (rel < dev->phys_size))
|
||||
ret = ram[addr];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
sis_85c471_read_ramw(uint32_t addr, void *priv)
|
||||
{
|
||||
ram_bank_t *dev = (ram_bank_t *) priv;
|
||||
uint32_t rel = addr - dev->virt_base;
|
||||
uint16_t ret = 0xffff;
|
||||
|
||||
uint32_t row = sis_85c471_set_row(dev, sis_85c471_get_row(dev, rel));
|
||||
uint32_t col = sis_85c471_set_col(dev, sis_85c471_get_col(dev, rel));
|
||||
uint32_t dw = rel & 0x00000003;
|
||||
rel = row | col | dw;
|
||||
|
||||
addr = (rel + dev->phys_base);
|
||||
|
||||
if ((addr < (mem_size << 10)) && (rel < dev->phys_size))
|
||||
ret = *(uint16_t *) &(ram[addr]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
sis_85c471_read_raml(uint32_t addr, void *priv)
|
||||
{
|
||||
ram_bank_t *dev = (ram_bank_t *) priv;
|
||||
uint32_t rel = addr - dev->virt_base;
|
||||
uint32_t ret = 0xffffffff;
|
||||
|
||||
uint32_t row = sis_85c471_set_row(dev, sis_85c471_get_row(dev, rel));
|
||||
uint32_t col = sis_85c471_set_col(dev, sis_85c471_get_col(dev, rel));
|
||||
uint32_t dw = rel & 0x00000003;
|
||||
rel = row | col | dw;
|
||||
|
||||
addr = (rel + dev->phys_base);
|
||||
|
||||
if ((addr < (mem_size << 10)) && (rel < dev->phys_size))
|
||||
ret = *(uint32_t *) &(ram[addr]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
sis_85c471_write_ram(uint32_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
ram_bank_t *dev = (ram_bank_t *) priv;
|
||||
uint32_t rel = addr - dev->virt_base;
|
||||
|
||||
uint32_t row = sis_85c471_set_row(dev, sis_85c471_get_row(dev, rel));
|
||||
uint32_t col = sis_85c471_set_col(dev, sis_85c471_get_col(dev, rel));
|
||||
uint32_t dw = rel & 0x00000003;
|
||||
rel = row | col | dw;
|
||||
|
||||
addr = (rel + dev->phys_base);
|
||||
|
||||
if ((addr < (mem_size << 10)) && (rel < dev->phys_size))
|
||||
ram[addr] = val;
|
||||
}
|
||||
|
||||
static void
|
||||
sis_85c471_write_ramw(uint32_t addr, uint16_t val, void *priv)
|
||||
{
|
||||
ram_bank_t *dev = (ram_bank_t *) priv;
|
||||
uint32_t rel = addr - dev->virt_base;
|
||||
|
||||
uint32_t row = sis_85c471_set_row(dev, sis_85c471_get_row(dev, rel));
|
||||
uint32_t col = sis_85c471_set_col(dev, sis_85c471_get_col(dev, rel));
|
||||
uint32_t dw = rel & 0x00000003;
|
||||
rel = row | col | dw;
|
||||
|
||||
addr = (rel + dev->phys_base);
|
||||
|
||||
if ((addr < (mem_size << 10)) && (rel < dev->phys_size))
|
||||
*(uint16_t *) &(ram[addr]) = val;
|
||||
}
|
||||
|
||||
static void
|
||||
sis_85c471_write_raml(uint32_t addr, uint32_t val, void *priv)
|
||||
{
|
||||
ram_bank_t *dev = (ram_bank_t *) priv;
|
||||
uint32_t rel = addr - dev->virt_base;
|
||||
|
||||
uint32_t row = sis_85c471_set_row(dev, sis_85c471_get_row(dev, rel));
|
||||
uint32_t col = sis_85c471_set_col(dev, sis_85c471_get_col(dev, rel));
|
||||
uint32_t dw = rel & 0x00000003;
|
||||
rel = row | col | dw;
|
||||
|
||||
addr = (rel + dev->phys_base);
|
||||
|
||||
if ((addr < (mem_size << 10)) && (rel < dev->phys_size))
|
||||
*(uint32_t *) &(ram[addr]) = val;
|
||||
}
|
||||
|
||||
static void
|
||||
sis_85c4xx_recalcremap(sis_85c4xx_t *dev)
|
||||
{
|
||||
@@ -158,6 +516,62 @@ sis_85c4xx_sw_smi_handler(sis_85c4xx_t *dev)
|
||||
NULL, NULL, NULL, sis_85c4xx_sw_smi_out, NULL, NULL, dev);
|
||||
}
|
||||
|
||||
static void
|
||||
sis_85c471_banks_split(uint32_t *b_ex, uint32_t *banks)
|
||||
{
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
if ((banks[i] == 0x00200000) || (banks[i] == 0x00800000) ||
|
||||
(banks[i] == 0x02000000))
|
||||
b_ex[i << 1] = b_ex[(i << 1) + 1] = banks[i] >> 1;
|
||||
else {
|
||||
b_ex[i << 1] = banks[i];
|
||||
b_ex[(i << 1) + 1] = 0x00000000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sis_85c471_banks_recalc(sis_85c4xx_t *dev)
|
||||
{
|
||||
reg09 = dev->regs[0x09];
|
||||
|
||||
for (uint8_t i = 0; i < 8; i++)
|
||||
mem_mapping_disable(&dev->ram_banks[i].mapping);
|
||||
|
||||
mem_mapping_disable(&ram_low_mapping);
|
||||
mem_mapping_disable(&ram_high_mapping);
|
||||
mem_set_mem_state_both(1 << 20, 127 << 20, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
|
||||
|
||||
if ((dev->regs[0x09] & 0x3f) == dev->ram_banks_val) {
|
||||
if (mem_size > 1024) {
|
||||
mem_mapping_enable(&ram_low_mapping);
|
||||
mem_mapping_enable(&ram_high_mapping);
|
||||
mem_set_mem_state_both(1 << 20, (mem_size << 10) - (1 << 20),
|
||||
MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
|
||||
}
|
||||
} else {
|
||||
uint8_t banks_val = dev->regs[0x09] & 0x3f;
|
||||
uint32_t *banks = banks_471[banks_val];
|
||||
uint32_t b_ex[8] = { 0x00000000 };
|
||||
uint32_t size = 0x00000000;
|
||||
|
||||
sis_85c471_banks_split(b_ex, banks);
|
||||
|
||||
for (uint8_t i = 0; i < 8; i++) if (b_ex[i] != 0x00000000) {
|
||||
dev->ram_banks[i].virt_base = size;
|
||||
dev->ram_banks[i].virt_size = b_ex[i];
|
||||
|
||||
mem_mapping_set_addr(&dev->ram_banks[i].mapping, size, b_ex[i]);
|
||||
|
||||
size += b_ex[i];
|
||||
}
|
||||
|
||||
mem_set_mem_state_both(1 << 20, 127 << 20, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
|
||||
}
|
||||
|
||||
flushmmucache_nopc();
|
||||
}
|
||||
|
||||
static void
|
||||
sis_85c4xx_out(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
@@ -174,12 +588,25 @@ sis_85c4xx_out(uint16_t port, uint8_t val, void *priv)
|
||||
case 0x23:
|
||||
if ((dev->cur_reg >= dev->reg_base) && (dev->cur_reg <= dev->reg_last)) {
|
||||
valxor = val ^ dev->regs[rel_reg];
|
||||
if (rel_reg == 0x00)
|
||||
|
||||
if (!dev->is_471 && (rel_reg == 0x00))
|
||||
dev->regs[rel_reg] = (dev->regs[rel_reg] & 0x1f) | (val & 0xe0);
|
||||
else
|
||||
dev->regs[rel_reg] = val;
|
||||
|
||||
switch (rel_reg) {
|
||||
case 0x00:
|
||||
if (dev->is_471) {
|
||||
if (val & 0x01) {
|
||||
kbc_at_set_fast_reset(0);
|
||||
cpu_cpurst_on_sr = 1;
|
||||
} else {
|
||||
kbc_at_set_fast_reset(1);
|
||||
cpu_cpurst_on_sr = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x01:
|
||||
cpu_cache_ext_enabled = ((val & 0x84) == 0x84);
|
||||
cpu_update_waitstates();
|
||||
@@ -190,6 +617,13 @@ sis_85c4xx_out(uint16_t port, uint8_t val, void *priv)
|
||||
case 0x08:
|
||||
if (valxor)
|
||||
sis_85c4xx_recalcmapping(dev);
|
||||
if ((rel_reg == 0x08) && dev->is_471)
|
||||
flushmmucache();
|
||||
break;
|
||||
|
||||
case 0x09:
|
||||
if (dev->is_471)
|
||||
sis_85c471_banks_recalc(dev);
|
||||
break;
|
||||
|
||||
case 0x0b:
|
||||
@@ -198,6 +632,41 @@ sis_85c4xx_out(uint16_t port, uint8_t val, void *priv)
|
||||
sis_85c4xx_recalcremap(dev);
|
||||
break;
|
||||
|
||||
case 0x10:
|
||||
if (dev->reg_base == 0x50) {
|
||||
double bus_clk;
|
||||
|
||||
switch (val & 0xe0) {
|
||||
default:
|
||||
case 0x00:
|
||||
bus_clk = 7159091.0;
|
||||
break;
|
||||
case 0x02:
|
||||
bus_clk = cpu_busspeed / 10.0;
|
||||
break;
|
||||
case 0x04:
|
||||
bus_clk = cpu_busspeed / 8.0;
|
||||
break;
|
||||
case 0x06:
|
||||
bus_clk = cpu_busspeed / 6.0;
|
||||
break;
|
||||
case 0x80:
|
||||
bus_clk = cpu_busspeed / 5.0;
|
||||
break;
|
||||
case 0xa0:
|
||||
bus_clk = cpu_busspeed / 4.0;
|
||||
break;
|
||||
case 0xc0:
|
||||
bus_clk = cpu_busspeed / 3.0;
|
||||
break;
|
||||
case 0xe0:
|
||||
bus_clk = cpu_busspeed / 2.0;
|
||||
break;
|
||||
}
|
||||
cpu_set_isa_speed((int) round(bus_clk));
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x13:
|
||||
if (dev->is_471 && (valxor & 0xf0)) {
|
||||
smram_disable(dev->smram);
|
||||
@@ -297,14 +766,6 @@ sis_85c4xx_reset(void *priv)
|
||||
{
|
||||
sis_85c4xx_t *dev = (sis_85c4xx_t *) priv;
|
||||
int mem_size_mb = mem_size >> 10;
|
||||
static uint8_t ram_4xx[64] = { 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00,
|
||||
0x19, 0x00, 0x06, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x1b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
static uint8_t ram_471[64] = { 0x00, 0x00, 0x01, 0x01, 0x02, 0x20, 0x09, 0x09, 0x04, 0x04, 0x05, 0x05, 0x0b, 0x0b, 0x0b, 0x0b,
|
||||
0x13, 0x21, 0x06, 0x06, 0x0d, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
|
||||
0x1b, 0x1b, 0x1b, 0x1b, 0x0f, 0x0f, 0x0f, 0x0f, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
|
||||
0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e };
|
||||
|
||||
memset(dev->regs, 0x00, sizeof(dev->regs));
|
||||
|
||||
@@ -313,13 +774,44 @@ sis_85c4xx_reset(void *priv)
|
||||
|
||||
if (dev->is_471) {
|
||||
dev->regs[0x09] = 0x40;
|
||||
if (mem_size_mb >= 64) {
|
||||
if ((mem_size_mb >= 65) && (mem_size_mb < 68))
|
||||
dev->regs[0x09] |= 0x22;
|
||||
|
||||
if (!strcmp(machine_get_internal_name(), "vli486sv2g")) {
|
||||
if (mem_size_mb == 64)
|
||||
dev->regs[0x09] |= 0x1f;
|
||||
else
|
||||
dev->regs[0x09] |= 0x24;
|
||||
} else
|
||||
dev->regs[0x09] |= ram_asus[mem_size_mb];
|
||||
} else if (mem_size_mb >= 64) {
|
||||
if ((mem_size_mb >= 64) && (mem_size_mb < 68))
|
||||
dev->regs[0x09] |= 0x33;
|
||||
else if ((mem_size_mb >= 68) && (mem_size_mb < 72))
|
||||
dev->regs[0x09] |= 0x2b;
|
||||
else if ((mem_size_mb >= 72) && (mem_size_mb < 80))
|
||||
dev->regs[0x09] |= 0x2d;
|
||||
else if ((mem_size_mb >= 80) && (mem_size_mb < 96))
|
||||
dev->regs[0x09] |= 0x2f;
|
||||
else if ((mem_size_mb >= 96) && (mem_size_mb < 128))
|
||||
dev->regs[0x09] |= 0x34;
|
||||
else
|
||||
dev->regs[0x09] |= 0x35;
|
||||
} else if (!strcmp(machine_get_internal_name(), "tg486g"))
|
||||
dev->regs[0x09] |= ram_tg486g[mem_size_mb];
|
||||
else
|
||||
dev->regs[0x09] |= ram_471[mem_size_mb];
|
||||
dev->ram_banks_val = dev->regs[0x09] & 0x3f;
|
||||
dev->regs[0x09] = 0x00;
|
||||
|
||||
uint32_t *banks = banks_471[dev->ram_banks_val];
|
||||
uint32_t b_ex[8] = { 0x00000000 };
|
||||
uint32_t size = 0x00000000;
|
||||
|
||||
sis_85c471_banks_split(b_ex, banks);
|
||||
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
dev->ram_banks[i].phys_base = size;
|
||||
dev->ram_banks[i].phys_size = b_ex[i];
|
||||
|
||||
size += b_ex[i];
|
||||
}
|
||||
|
||||
dev->regs[0x11] = 0x09;
|
||||
dev->regs[0x12] = 0xff;
|
||||
@@ -332,6 +824,11 @@ sis_85c4xx_reset(void *priv)
|
||||
port_92_remove(dev->port_92);
|
||||
|
||||
soft_reset_mask = 0;
|
||||
|
||||
sis_85c471_banks_recalc(dev);
|
||||
|
||||
kbc_at_set_fast_reset(1);
|
||||
cpu_cpurst_on_sr = 0;
|
||||
} else {
|
||||
/* Bits 6 and 7 must be clear on the SiS 40x. */
|
||||
if (dev->reg_base == 0x60)
|
||||
@@ -352,6 +849,9 @@ sis_85c4xx_reset(void *priv)
|
||||
|
||||
dev->force_flush = 1;
|
||||
sis_85c4xx_recalcmapping(dev);
|
||||
|
||||
if (dev->reg_base == 0x50)
|
||||
cpu_set_isa_speed((int) round(7159091.0));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -375,11 +875,19 @@ sis_85c4xx_init(const device_t *info)
|
||||
dev->reg_base = info->local & 0xff;
|
||||
|
||||
if (dev->is_471) {
|
||||
dev->reg_last = dev->reg_base + 0x76;
|
||||
dev->reg_last = 0x76;
|
||||
|
||||
dev->smram = smram_add();
|
||||
|
||||
dev->port_92 = device_add(&port_92_device);
|
||||
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
mem_mapping_add(&dev->ram_banks[i].mapping, 0x00000000, 0x00000000,
|
||||
sis_85c471_read_ram, sis_85c471_read_ramw, sis_85c471_read_raml,
|
||||
sis_85c471_write_ram, sis_85c471_write_ramw, sis_85c471_write_raml,
|
||||
NULL, MEM_MAPPING_INTERNAL, &(dev->ram_banks[i]));
|
||||
mem_mapping_disable(&dev->ram_banks[i].mapping);
|
||||
}
|
||||
} else
|
||||
dev->reg_last = dev->reg_base + 0x11;
|
||||
|
||||
|
||||
362
src/chipset/sl82c461.c
Normal file
362
src/chipset/sl82c461.c
Normal file
@@ -0,0 +1,362 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the Symphony SL82C461 (Haydn II) chipset.
|
||||
*
|
||||
* Symphony SL82C461 Configuration Registers (WARNING: May be inaccurate!):
|
||||
*
|
||||
* - Register 00h:
|
||||
* - Bit 6: External cache present (if clear, AMI BIOS'es will not
|
||||
* allow enabling external cache).
|
||||
*
|
||||
* - Register 01h:
|
||||
* - Bit 0: Fast Gate A20 Enable (Handler mostly).
|
||||
* Is it? Enabling/disabling fast gate A20 doesn't appear
|
||||
* to do much to any register at all.
|
||||
*
|
||||
* - Register 02h:
|
||||
* - Bit 0: Optional Chipset Turbo Pin;
|
||||
* - Bits 4-2:
|
||||
* - 000 = CLK2/3;
|
||||
* - 001 = CLK2/4;
|
||||
* - 010 = CLK2/5;
|
||||
* - 011 = 7.159 MHz (ATCLK2);
|
||||
* - 100 = CLK2/6;
|
||||
* - 110 = CLK2/2.5;
|
||||
* - 111 = CLK2/2.
|
||||
*
|
||||
* - Register 06h:
|
||||
* - Bit 2: Decoupled Refresh Option.
|
||||
*
|
||||
* - Register 08h:
|
||||
* - Bits 3, 2: I/O Recovery Time (SYSCLK):
|
||||
* - 0, 0 = 0;
|
||||
* - 1, 1 = 12.
|
||||
* - Bit 1: Extended ALE.
|
||||
*
|
||||
* - Register 25h:
|
||||
* Bit 7 here causes AMI 111192 CMOS Setup to return 7168 KB RAM
|
||||
* instead of 6912 KB. This is 256 KB off. Relocation?
|
||||
* Also, returning bit 5 clear instead of set, causes the AMI BIOS
|
||||
* to set bits 0,1 of register 45h to 1,0 instead of 0,1.
|
||||
*
|
||||
* - Register 2Dh:
|
||||
* - Bit 7: Enable 256KB Memory Relocation;
|
||||
* - Bit 6: Enable 384KB Memory Relocation, bit 7 must also be set.
|
||||
*
|
||||
* - Register 2Eh:
|
||||
* - Bit 7: CC000-CFFFF Shadow Read Enable;
|
||||
* - Bit 6: CC000-CFFFF Shadow Write Enable;
|
||||
* - Bit 5: C8000-CBFFF Shadow Read Enable;
|
||||
* - Bit 4: C8000-CBFFF Shadow Write Enable;
|
||||
* - Bit 3: C4000-C7FFF Shadow Read Enable;
|
||||
* - Bit 2: C4000-C7FFF Shadow Write Enable;
|
||||
* - Bit 1: C0000-C3FFF Shadow Read Enable;
|
||||
* - Bit 0: C0000-C3FFF Shadow Write Enable.
|
||||
*
|
||||
* - Register 2Fh:
|
||||
* - Bit 7: DC000-DFFFF Shadow Read Enable;
|
||||
* - Bit 6: DC000-DFFFF Shadow Write Enable;
|
||||
* - Bit 5: D8000-DBFFF Shadow Read Enable;
|
||||
* - Bit 4: D8000-DBFFF Shadow Write Enable;
|
||||
* - Bit 3: D4000-D7FFF Shadow Read Enable;
|
||||
* - Bit 2: D4000-D7FFF Shadow Write Enable;
|
||||
* - Bit 1: D0000-D3FFF Shadow Read Enable;
|
||||
* - Bit 0: D0000-D3FFF Shadow Write Enable.
|
||||
*
|
||||
* - Register 30h:
|
||||
* - Bit 7: E0000-EFFFF Shadow Read Enable;
|
||||
* - Bit 6: E0000-EFFFF Shadow Write Enable.
|
||||
*
|
||||
* - Register 31h:
|
||||
* - Bit 7: F0000-FFFFF Shadow Read Enable;
|
||||
* - Bit 6: F0000-FFFFF Shadow Write Enable.
|
||||
*
|
||||
* - Register 33h (NOTE: Waitstates also affect register 32h):
|
||||
* - Bits 3, 0:
|
||||
* - 0,0 = 0 W/S;
|
||||
* - 1,0 = 1 W/S;
|
||||
* - 1,1 = 2 W/S.
|
||||
*
|
||||
* - Register 40h:
|
||||
* - Bit 3: External Cache Enabled (0 = yes, 1 = no);
|
||||
* I also see bits 5, 4, 3 of register 44h affected:
|
||||
* - 38h (so all 3 set) when cache is disabled;
|
||||
* - 00h (all 3 clear) when it's enabled.
|
||||
*
|
||||
* - Register 45h:
|
||||
* - Bit 3: Video Shadow RAM Cacheable;
|
||||
* - Bit 4: Adapter Shadow RAM Cacheable;
|
||||
* - Bit 5: BIOS Shadow RAM Cacheable.
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* Tiseno100,
|
||||
*
|
||||
* Copyright 2025 Miran Grca.
|
||||
* Copyright 2021-2025 Tiseno100.
|
||||
*/
|
||||
#include <math.h>
|
||||
#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/mem.h>
|
||||
#include <86box/chipset.h>
|
||||
|
||||
typedef struct {
|
||||
uint8_t index;
|
||||
uint8_t regs[256];
|
||||
uint8_t shadow[4];
|
||||
} sl82c461_t;
|
||||
|
||||
#ifdef ENABLE_SL82C461_LOG
|
||||
int sl82c461_do_log = ENABLE_SL82C461_LOG;
|
||||
|
||||
static void
|
||||
sl82c461_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (sl82c461_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define sl82c461_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
static void
|
||||
sl82c461_recalcmapping(sl82c461_t *dev)
|
||||
{
|
||||
int do_shadow = 0;
|
||||
|
||||
for (uint32_t i = 0; i < 8; i += 2) {
|
||||
if ((dev->regs[0x2e] ^ dev->shadow[0x00]) & (3 << i)) {
|
||||
uint32_t base = 0x000c0000 + ((i >> 1) << 14);
|
||||
uint32_t read = ((dev->regs[0x2e] >> i) & 0x02) ? MEM_READ_INTERNAL :
|
||||
MEM_READ_EXTANY;
|
||||
uint32_t write = ((dev->regs[0x2e] >> i) & 0x01) ? MEM_WRITE_INTERNAL :
|
||||
MEM_WRITE_EXTANY;
|
||||
|
||||
mem_set_mem_state_both(base, 0x00004000, read | write);
|
||||
|
||||
do_shadow++;
|
||||
}
|
||||
|
||||
if ((dev->regs[0x2f] ^ dev->shadow[0x01]) & (3 << i)) {
|
||||
uint32_t base = 0x000d0000 + ((i >> 1) << 14);
|
||||
uint32_t read = ((dev->regs[0x2f] >> i) & 0x02) ? MEM_READ_INTERNAL :
|
||||
MEM_READ_EXTANY;
|
||||
uint32_t write = ((dev->regs[0x2f] >> i) & 0x01) ? MEM_WRITE_INTERNAL :
|
||||
MEM_WRITE_EXTANY;
|
||||
|
||||
mem_set_mem_state_both(base, 0x00004000, read | write);
|
||||
|
||||
do_shadow++;
|
||||
}
|
||||
}
|
||||
|
||||
if ((dev->regs[0x30] ^ dev->shadow[0x02]) & 0xc0) {
|
||||
uint32_t base = 0x000e0000;
|
||||
uint32_t read = ((dev->regs[0x30] >> 6) & 0x02) ? MEM_READ_INTERNAL :
|
||||
MEM_READ_EXTANY;
|
||||
uint32_t write = ((dev->regs[0x30] >> 6) & 0x01) ? MEM_WRITE_INTERNAL :
|
||||
MEM_WRITE_EXTANY;
|
||||
|
||||
mem_set_mem_state_both(base, 0x00010000, read | write);
|
||||
|
||||
do_shadow++;
|
||||
}
|
||||
|
||||
if ((dev->regs[0x31] ^ dev->shadow[0x03]) & 0xc0) {
|
||||
uint32_t base = 0x000f0000;
|
||||
uint32_t read = ((dev->regs[0x31] >> 6) & 0x02) ? MEM_READ_INTERNAL :
|
||||
MEM_READ_EXTANY;
|
||||
uint32_t write = ((dev->regs[0x31] >> 6) & 0x01) ? MEM_WRITE_INTERNAL :
|
||||
MEM_WRITE_EXTANY;
|
||||
|
||||
shadowbios = !!((dev->regs[0x31] >> 6) & 0x02);
|
||||
shadowbios_write = !!((dev->regs[0x31] >> 6) & 0x01);
|
||||
|
||||
mem_set_mem_state_both(base, 0x00010000, read | write);
|
||||
|
||||
do_shadow++;
|
||||
}
|
||||
|
||||
if (do_shadow) {
|
||||
memcpy(dev->shadow, &(dev->regs[0x2e]), 4 * sizeof(uint8_t));
|
||||
flushmmucache_nopc();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
sl82c461_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
sl82c461_t *dev = (sl82c461_t *) priv;
|
||||
|
||||
sl82c461_log("[%04X:%08X] [W] %04X = %02X\n", CS, cpu_state.pc, addr, val);
|
||||
|
||||
if (addr & 0x0001) {
|
||||
dev->regs[dev->index] = val;
|
||||
|
||||
switch (dev->index) {
|
||||
case 0x01:
|
||||
/* NOTE: This is to be verified. */
|
||||
mem_a20_alt = val & 1;
|
||||
mem_a20_recalc();
|
||||
break;
|
||||
case 0x02: {
|
||||
double bus_clk;
|
||||
switch (val & 0x1c) {
|
||||
case 0x00:
|
||||
bus_clk = cpu_busspeed / 3.0;
|
||||
break;
|
||||
case 0x04:
|
||||
bus_clk = cpu_busspeed / 4.0;
|
||||
break;
|
||||
case 0x08:
|
||||
bus_clk = cpu_busspeed / 5.0;
|
||||
break;
|
||||
default:
|
||||
case 0x0c:
|
||||
bus_clk = 7159091.0;
|
||||
break;
|
||||
case 0x10:
|
||||
bus_clk = cpu_busspeed / 6.0;
|
||||
break;
|
||||
case 0x18:
|
||||
bus_clk = cpu_busspeed / 2.5;
|
||||
break;
|
||||
case 0x1c:
|
||||
bus_clk = cpu_busspeed / 2.0;
|
||||
break;
|
||||
}
|
||||
cpu_set_isa_speed((int) round(bus_clk));
|
||||
break;
|
||||
} case 0x2d:
|
||||
switch (val & 0xc0) {
|
||||
case 0xc0:
|
||||
mem_remap_top(384);
|
||||
break;
|
||||
case 0x80:
|
||||
mem_remap_top(256);
|
||||
break;
|
||||
default:
|
||||
case 0x00:
|
||||
mem_remap_top(0);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x2e ... 0x31:
|
||||
sl82c461_recalcmapping(dev);
|
||||
break;
|
||||
case 0x33:
|
||||
switch (val & 0x09) {
|
||||
default:
|
||||
case 0x00:
|
||||
cpu_waitstates = 0;
|
||||
break;
|
||||
case 0x08:
|
||||
cpu_waitstates = 1;
|
||||
break;
|
||||
case 0x09:
|
||||
cpu_waitstates = 2;
|
||||
break;
|
||||
}
|
||||
cpu_update_waitstates();
|
||||
break;
|
||||
case 0x40:
|
||||
cpu_cache_ext_enabled = !(val & 0x08);
|
||||
cpu_update_waitstates();
|
||||
break;
|
||||
}
|
||||
} else
|
||||
dev->index = val;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
sl82c461_read(uint16_t addr, void *priv)
|
||||
{
|
||||
sl82c461_t *dev = (sl82c461_t *) priv;
|
||||
uint8_t ret = 0x00;
|
||||
|
||||
if (addr & 0x0001)
|
||||
if (dev->index == 0x00)
|
||||
ret = dev->regs[dev->index] | 0x40;
|
||||
else
|
||||
ret = dev->regs[dev->index];
|
||||
else
|
||||
ret = dev->index;
|
||||
|
||||
sl82c461_log("[%04X:%08X] [R] %04X = %02X\n", CS, cpu_state.pc, addr, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
sl82c461_close(void *priv)
|
||||
{
|
||||
sl82c461_t *dev = (sl82c461_t *) priv;
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
static void *
|
||||
sl82c461_init(const device_t *info)
|
||||
{
|
||||
sl82c461_t *dev = (sl82c461_t *) calloc(1, sizeof(sl82c461_t));
|
||||
|
||||
dev->regs[0x00] = 0x40;
|
||||
|
||||
dev->regs[0x02] = 0x0c;
|
||||
dev->regs[0x40] = 0x08;
|
||||
|
||||
memset(dev->shadow, 0xff, 4 * sizeof(uint8_t));
|
||||
|
||||
mem_a20_alt = 0x00;
|
||||
mem_a20_recalc();
|
||||
|
||||
cpu_set_isa_speed(7159091.0);
|
||||
|
||||
sl82c461_recalcmapping(dev);
|
||||
|
||||
cpu_waitstates = 0;
|
||||
cpu_cache_ext_enabled = 0;
|
||||
|
||||
cpu_update_waitstates();
|
||||
|
||||
io_sethandler(0x00a8, 2,
|
||||
sl82c461_read, NULL, NULL,
|
||||
sl82c461_write, NULL, NULL, dev);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
const device_t sl82c461_device = {
|
||||
.name = "Symphony SL82C461 (Haydn II)",
|
||||
.internal_name = "sis_85c471",
|
||||
.flags = 0,
|
||||
.local = 0,
|
||||
.init = sl82c461_init,
|
||||
.close = sl82c461_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
@@ -270,6 +270,8 @@ hb4_smram(hb4_t *dev)
|
||||
}
|
||||
|
||||
umc_smram_recalc(dev->smram_base >> 12, 1);
|
||||
|
||||
flushmmucache();
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -398,55 +400,6 @@ hb4_close(void *priv)
|
||||
free(dev);
|
||||
}
|
||||
|
||||
static void
|
||||
ims8848_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
hb4_t *dev = (hb4_t *) priv;
|
||||
|
||||
switch (addr) {
|
||||
case 0x22:
|
||||
dev->idx = val;
|
||||
break;
|
||||
case 0x23:
|
||||
if (((val & 0x0f) == ((dev->idx >> 4) & 0x0f)) && ((val & 0xf0) == ((dev->idx << 4) & 0xf0)))
|
||||
dev->access_data = 1;
|
||||
break;
|
||||
case 0x24:
|
||||
if (dev->access_data)
|
||||
dev->access_data = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
ims8848_read(uint16_t addr, void *priv)
|
||||
{
|
||||
uint8_t ret = 0xff;
|
||||
hb4_t *dev = (hb4_t *) priv;
|
||||
|
||||
switch (addr) {
|
||||
case 0x22:
|
||||
ret = dev->idx;
|
||||
break;
|
||||
case 0x23:
|
||||
ret = (dev->idx >> 4) | (dev->idx << 4);
|
||||
break;
|
||||
case 0x24:
|
||||
if (dev->access_data) {
|
||||
ret = dev->pci_conf[dev->idx];
|
||||
dev->access_data = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void *
|
||||
hb4_init(UNUSED(const device_t *info))
|
||||
{
|
||||
@@ -463,8 +416,6 @@ hb4_init(UNUSED(const device_t *info))
|
||||
dev->smram_base = 0x000a0000;
|
||||
hb4_reset(dev);
|
||||
|
||||
io_sethandler(0x0022, 0x0003, ims8848_read, NULL, NULL, ims8848_write, NULL, NULL, dev);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,14 +24,16 @@
|
||||
#include <86box/timer.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/machine.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/nmi.h>
|
||||
#include <86box/port_92.h>
|
||||
#include <86box/chipset.h>
|
||||
|
||||
typedef struct vl82c480_t {
|
||||
uint8_t idx;
|
||||
uint8_t regs[256];
|
||||
uint8_t idx;
|
||||
uint8_t regs[256];
|
||||
uint32_t banks[4];
|
||||
} vl82c480_t;
|
||||
|
||||
static int
|
||||
@@ -59,7 +61,7 @@ vl82c480_shflags(uint8_t access)
|
||||
}
|
||||
|
||||
static void
|
||||
vl82c480_recalc(vl82c480_t *dev)
|
||||
vl82c480_recalc_shadow(vl82c480_t *dev)
|
||||
{
|
||||
uint32_t base;
|
||||
uint8_t access;
|
||||
@@ -69,8 +71,8 @@ vl82c480_recalc(vl82c480_t *dev)
|
||||
|
||||
for (uint8_t i = 0; i < 6; i++) {
|
||||
for (uint8_t j = 0; j < 8; j += 2) {
|
||||
base = 0x000a0000 + (i << 16) + (j << 13);
|
||||
access = (dev->regs[0x0d + i] >> j) & 3;
|
||||
base = 0x000a0000 + (i << 16) + (j << 13);
|
||||
access = (dev->regs[0x0d + i] >> j) & 3;
|
||||
mem_set_mem_state(base, 0x4000, vl82c480_shflags(access));
|
||||
shadowbios |= ((base >= 0xe0000) && (access & 0x02));
|
||||
shadowbios_write |= ((base >= 0xe0000) && (access & 0x01));
|
||||
@@ -80,6 +82,37 @@ vl82c480_recalc(vl82c480_t *dev)
|
||||
flushmmucache();
|
||||
}
|
||||
|
||||
static void
|
||||
vl82c480_recalc_banks(vl82c480_t *dev)
|
||||
{
|
||||
uint32_t sizes[8] = { 0, 0, 1024, 2048, 4096, 8192, 16384, 32768 };
|
||||
uint8_t shifts[4] = { 0, 4, 0, 4 };
|
||||
uint8_t regs[4] = { 0x02, 0x02, 0x03, 0x03 };
|
||||
uint32_t total = 0;
|
||||
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
uint8_t shift = shifts[i];
|
||||
uint8_t reg = regs[i];
|
||||
uint8_t cfg = (dev->regs[reg] >> shift) & 0x7;
|
||||
uint32_t size = sizes[cfg];
|
||||
|
||||
total += MIN(dev->banks[i], size);
|
||||
}
|
||||
|
||||
if (total > 1024) {
|
||||
mem_mapping_set_addr(&ram_low_mapping, 0x00000000, 0x000a0000);
|
||||
mem_mapping_set_addr(&ram_high_mapping, 0x00100000, (total - 1024) << 10);
|
||||
} else {
|
||||
if (total >= 1024)
|
||||
mem_mapping_set_addr(&ram_low_mapping, 0x00000000, 0x000a0000);
|
||||
else
|
||||
mem_mapping_disable(&ram_low_mapping);
|
||||
mem_mapping_disable(&ram_high_mapping);
|
||||
}
|
||||
|
||||
flushmmucache();
|
||||
}
|
||||
|
||||
static void
|
||||
vl82c480_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
@@ -91,11 +124,18 @@ vl82c480_write(uint16_t addr, uint8_t val, void *priv)
|
||||
break;
|
||||
|
||||
case 0xed:
|
||||
if (dev->idx >= 0x01 && dev->idx <= 0x24) {
|
||||
if (((dev->idx >= 0x01) && (dev->idx <= 0x19)) ||
|
||||
((dev->idx >= 0x20) && (dev->idx <= 0x24))) {
|
||||
switch (dev->idx) {
|
||||
default:
|
||||
dev->regs[dev->idx] = val;
|
||||
break;
|
||||
case 0x02: case 0x03:
|
||||
dev->regs[dev->idx] = val;
|
||||
if (!strcmp(machine_get_internal_name(), "martin") ||
|
||||
!strcmp(machine_get_internal_name(), "prolineamt"))
|
||||
vl82c480_recalc_banks(dev);
|
||||
break;
|
||||
case 0x04:
|
||||
if (dev->regs[0x00] == 0x98)
|
||||
dev->regs[dev->idx] = (dev->regs[dev->idx] & 0x08) | (val & 0xf7);
|
||||
@@ -108,14 +148,9 @@ vl82c480_write(uint16_t addr, uint8_t val, void *priv)
|
||||
case 0x07:
|
||||
dev->regs[dev->idx] = (dev->regs[dev->idx] & 0x40) | (val & 0xbf);
|
||||
break;
|
||||
case 0x0d:
|
||||
case 0x0e:
|
||||
case 0x0f:
|
||||
case 0x10:
|
||||
case 0x11:
|
||||
case 0x12:
|
||||
case 0x0d ... 0x12:
|
||||
dev->regs[dev->idx] = val;
|
||||
vl82c480_recalc(dev);
|
||||
vl82c480_recalc_shadow(dev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -124,8 +159,8 @@ vl82c480_write(uint16_t addr, uint8_t val, void *priv)
|
||||
/* TODO: This is actually Fast A20 disable. */
|
||||
#if 0
|
||||
case 0xee:
|
||||
if (mem_a20_alt)
|
||||
outb(0x92, inb(0x92) & ~2);
|
||||
mem_a20_alt = 0x00;
|
||||
mem_a20_recalc();
|
||||
break;
|
||||
#endif
|
||||
|
||||
@@ -146,14 +181,16 @@ vl82c480_read(uint16_t addr, void *priv)
|
||||
break;
|
||||
|
||||
case 0xed:
|
||||
ret = dev->regs[dev->idx];
|
||||
if (((dev->idx >= 0x01) && (dev->idx <= 0x19)) ||
|
||||
((dev->idx >= 0x20) && (dev->idx <= 0x24)))
|
||||
ret = dev->regs[dev->idx];
|
||||
break;
|
||||
|
||||
/* TODO: This is actually Fast A20 enable. */
|
||||
#if 0
|
||||
case 0xee:
|
||||
if (!mem_a20_alt)
|
||||
outb(0x92, inb(0x92) | 2);
|
||||
mem_a20_alt = 0x02;
|
||||
mem_a20_recalc();
|
||||
break;
|
||||
#endif
|
||||
|
||||
@@ -180,7 +217,12 @@ vl82c480_close(void *priv)
|
||||
static void *
|
||||
vl82c480_init(const device_t *info)
|
||||
{
|
||||
vl82c480_t *dev = (vl82c480_t *) calloc(1, sizeof(vl82c480_t));
|
||||
vl82c480_t *dev = (vl82c480_t *) calloc(1, sizeof(vl82c480_t));
|
||||
uint32_t sizes[8] = { 0, 0, 1024, 2048, 4096, 8192, 16384, 32768 };
|
||||
uint32_t ms = mem_size;
|
||||
uint8_t min_i = !strcmp(machine_get_internal_name(), "prolineamt") ? 1 : 0;
|
||||
uint8_t min_j = !strcmp(machine_get_internal_name(), "prolineamt") ? 4 : 2;
|
||||
uint8_t max_j = !strcmp(machine_get_internal_name(), "prolineamt") ? 8 : 7;
|
||||
|
||||
dev->regs[0x00] = info->local;
|
||||
dev->regs[0x01] = 0xff;
|
||||
@@ -191,9 +233,31 @@ vl82c480_init(const device_t *info)
|
||||
dev->regs[0x07] = 0x21;
|
||||
dev->regs[0x08] = 0x38;
|
||||
|
||||
if (!strcmp(machine_get_internal_name(), "prolineamt")) {
|
||||
dev->banks[0] = 4096;
|
||||
|
||||
/* Bank 0 is ignored if 64 MB is installed. */
|
||||
if (ms != 65536)
|
||||
ms -= 4096;
|
||||
}
|
||||
|
||||
if (ms > 0) for (uint8_t i = min_i; i < 4; i++) {
|
||||
for (uint8_t j = min_j; j < max_j; j++) {
|
||||
if (ms >= sizes[j])
|
||||
dev->banks[i] = sizes[j];
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
ms -= dev->banks[i];
|
||||
|
||||
if ((ms == 0) || (dev->banks[i] == 0))
|
||||
break;
|
||||
}
|
||||
|
||||
io_sethandler(0x00ec, 0x0004, vl82c480_read, NULL, NULL, vl82c480_write, NULL, NULL, dev);
|
||||
|
||||
device_add(&port_92_device);
|
||||
device_add(&port_92_pci_device);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
@@ -65,9 +65,10 @@ wd76c10_log(const char *fmt, ...)
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint32_t enable;
|
||||
uint32_t phys_on, enable;
|
||||
uint32_t virt_addr, phys_addr;
|
||||
uint32_t virt_size, phys_size;
|
||||
uint32_t adj_virt_addr, adj_virt_size;
|
||||
} ram_bank_t;
|
||||
|
||||
typedef struct {
|
||||
@@ -103,6 +104,7 @@ typedef struct
|
||||
int locked;
|
||||
|
||||
uint32_t mem_top, hmwp_base;
|
||||
uint32_t fast;
|
||||
|
||||
ram_bank_t ram_banks[5];
|
||||
|
||||
@@ -121,6 +123,40 @@ static uint32_t bank_sizes[4] = { 0x00020000, /* 64 Kbit X 16 = 1024 Kbit
|
||||
0x00200000, /* 1 Mbit X 16 = 16 Mbit = 2 MB, 10x10 */
|
||||
0x00800000 }; /* 4 Mbit X 16 = 64 Mbit = 8 MB, 11x11 */
|
||||
|
||||
static uint32_t
|
||||
wd76c10_calc_phys(uint32_t row, uint32_t col, uint32_t size, uint32_t a0)
|
||||
{
|
||||
uint32_t ret = WD76C10_ADDR_INVALID;
|
||||
|
||||
switch (size) {
|
||||
default:
|
||||
ret = WD76C10_ADDR_INVALID;
|
||||
break;
|
||||
case 0x00020000:
|
||||
row = (row & 0x0000ff) << 9;
|
||||
col = (col & 0x0000ff) << 1;
|
||||
ret = row | col | a0;
|
||||
break;
|
||||
case 0x00080000:
|
||||
row = (row & 0x0001ff) << 10;
|
||||
col = (col & 0x0001ff) << 1;
|
||||
ret = row | col | a0;
|
||||
break;
|
||||
case 0x00200000:
|
||||
row = (row & 0x0003ff) << 11;
|
||||
col = (col & 0x0003ff) << 1;
|
||||
ret = row | col | a0;
|
||||
break;
|
||||
case 0x00800000:
|
||||
row = (row & 0x0007ff) << 12;
|
||||
col = (col & 0x0007ff) << 1;
|
||||
ret = row | col | a0;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
wd76c10_calc_addr(wd76c10_t *dev, uint32_t addr)
|
||||
{
|
||||
@@ -159,20 +195,303 @@ wd76c10_calc_addr(wd76c10_t *dev, uint32_t addr)
|
||||
ret = WD76C10_ADDR_INVALID;
|
||||
|
||||
/* Then, handle the physical memory banks. */
|
||||
int ilv4 = (dev->mem_ctl >> 8) & 4;
|
||||
int8_t add = 0;
|
||||
uint32_t pg = (dev->mem_ctl & 0x0800);
|
||||
uint32_t nrt = WD76C10_ADDR_INVALID;
|
||||
|
||||
if (ret != WD76C10_ADDR_INVALID) {
|
||||
if (dev->fast) for (int8_t i = 0; i < 4; i++) {
|
||||
rb = &(dev->ram_banks[i]);
|
||||
|
||||
uint32_t ret2 = ret - rb->phys_addr;
|
||||
|
||||
if (rb->phys_on && (ret >= rb->phys_addr) &&
|
||||
(ret < (rb->phys_addr + rb->phys_size))) {
|
||||
if (ret2 < rb->phys_size)
|
||||
nrt = ret2 + rb->phys_addr;
|
||||
break;
|
||||
}
|
||||
} else for (int8_t i = 0; i < 4; i++) {
|
||||
rb = &(dev->ram_banks[i]);
|
||||
|
||||
int ilv2 = (dev->mem_ctl >> 8) & (1 << (i >> 1));
|
||||
uint32_t size = rb->virt_size;
|
||||
uint32_t ret2 = ret - rb->virt_addr;
|
||||
uint32_t ret4 = ret2;
|
||||
uint32_t row = WD76C10_ADDR_INVALID;
|
||||
uint32_t col = WD76C10_ADDR_INVALID;
|
||||
uint32_t rb_or = 0;
|
||||
|
||||
if (ilv4) {
|
||||
size <<= 2;
|
||||
switch (rb->virt_size) {
|
||||
default:
|
||||
ret4 = WD76C10_ADDR_INVALID;
|
||||
break;
|
||||
case 0x00020000:
|
||||
if (pg) {
|
||||
row = (ret2 >> 9) & 0x0000fc;
|
||||
row |= (ret2 >> 17) & 0x000001;
|
||||
row |= ((ret2 >> 19) & 0x000001) << 1;
|
||||
row |= ((ret2 >> 18) & 0x000001) << 8;
|
||||
row |= ((ret2 >> 20) & 0x000001) << 9;
|
||||
row |= ((ret2 >> 22) & 0x000001) << 10;
|
||||
col = (ret2 >> 1) & 0x000007ff;
|
||||
rb_or = (ret2 >> 9) & 0x000003;
|
||||
} else
|
||||
ret4 = WD76C10_ADDR_INVALID;
|
||||
break;
|
||||
case 0x00080000:
|
||||
if (pg) {
|
||||
row = (ret2 >> 9) & 0x0000f8;
|
||||
row |= (ret2 >> 17) & 0x000001;
|
||||
row |= ((ret2 >> 19) & 0x000001) << 1;
|
||||
row |= ((ret2 >> 21) & 0x000001) << 2;
|
||||
row |= ((ret2 >> 18) & 0x000001) << 8;
|
||||
row |= ((ret2 >> 20) & 0x000001) << 9;
|
||||
row |= ((ret2 >> 22) & 0x000001) << 10;
|
||||
col = (ret2 >> 1) & 0x000007ff;
|
||||
rb_or = (ret2 >> 10) & 0x000003;
|
||||
} else
|
||||
ret4 = WD76C10_ADDR_INVALID;
|
||||
break;
|
||||
case 0x00200000:
|
||||
if (pg) {
|
||||
row = (ret2 >> 9) & 0x0000f0;
|
||||
row |= (ret2 >> 17) & 0x000001;
|
||||
row |= ((ret2 >> 19) & 0x000001) << 1;
|
||||
row |= ((ret2 >> 21) & 0x000001) << 2;
|
||||
row |= ((ret2 >> 23) & 0x000001) << 3;
|
||||
row |= ((ret2 >> 18) & 0x000001) << 8;
|
||||
row |= ((ret2 >> 20) & 0x000001) << 9;
|
||||
row |= ((ret2 >> 22) & 0x000001) << 10;
|
||||
col = (ret2 >> 1) & 0x000007ff;
|
||||
rb_or = (ret2 >> 11) & 0x000003;
|
||||
} else
|
||||
ret4 = WD76C10_ADDR_INVALID;
|
||||
break;
|
||||
case 0x00800000:
|
||||
if (pg) {
|
||||
row = (ret2 >> 9) & 0x0000e0;
|
||||
row |= (ret2 >> 17) & 0x000001;
|
||||
row |= ((ret2 >> 19) & 0x000001) << 1;
|
||||
row |= ((ret2 >> 21) & 0x000001) << 2;
|
||||
row |= ((ret2 >> 23) & 0x000001) << 3;
|
||||
row |= ((ret2 >> 24) & 0x000001) << 4;
|
||||
row |= ((ret2 >> 18) & 0x000001) << 8;
|
||||
row |= ((ret2 >> 20) & 0x000001) << 9;
|
||||
row |= ((ret2 >> 22) & 0x000001) << 10;
|
||||
col = (ret2 >> 1) & 0x000007ff;
|
||||
rb_or = (ret2 >> 12) & 0x000003;
|
||||
} else
|
||||
ret4 = WD76C10_ADDR_INVALID;
|
||||
break;
|
||||
}
|
||||
add = 3;
|
||||
} else if (ilv2) {
|
||||
size <<= 1;
|
||||
switch (rb->virt_size) {
|
||||
default:
|
||||
ret4 = WD76C10_ADDR_INVALID;
|
||||
break;
|
||||
case 0x00020000:
|
||||
if (pg) {
|
||||
row = (ret2 >> 9) & 0x0000fe;
|
||||
row |= (ret2 >> 17) & 0x000001;
|
||||
row |= ((ret2 >> 18) & 0x000001) << 8;
|
||||
row |= ((ret2 >> 20) & 0x000001) << 9;
|
||||
row |= ((ret2 >> 22) & 0x000001) << 10;
|
||||
col = (ret2 >> 1) & 0x000007ff;
|
||||
rb_or = (ret2 >> 9) & 0x000001;
|
||||
} else {
|
||||
row = (ret2 >> 1) & 0x0007fe;
|
||||
row |= (ret2 >> 13) & 0x000001;
|
||||
col = (ret2 >> 9) & 0x0000ef;
|
||||
col |= ((ret2 >> 17) & 0x000001) << 4;
|
||||
col |= ((ret2 >> 18) & 0x000001) << 8;
|
||||
col |= ((ret2 >> 20) & 0x000001) << 9;
|
||||
col |= ((ret2 >> 22) & 0x000001) << 10;
|
||||
rb_or = (ret2 >> 1) & 0x000001;
|
||||
}
|
||||
break;
|
||||
case 0x00080000:
|
||||
if (pg) {
|
||||
row = (ret2 >> 9) & 0x0000fc;
|
||||
row |= (ret2 >> 17) & 0x000001;
|
||||
row |= ((ret2 >> 19) & 0x000001) << 1;
|
||||
row |= ((ret2 >> 18) & 0x000001) << 8;
|
||||
row |= ((ret2 >> 20) & 0x000001) << 9;
|
||||
row |= ((ret2 >> 22) & 0x000001) << 10;
|
||||
col = (ret2 >> 1) & 0x000007ff;
|
||||
rb_or = (ret2 >> 10) & 0x000001;
|
||||
} else {
|
||||
row = (ret2 >> 1) & 0x0007fe;
|
||||
row |= (ret2 >> 13) & 0x000001;
|
||||
col = (ret2 >> 9) & 0x0000ee;
|
||||
col |= (ret2 >> 17) & 0x000001;
|
||||
col |= ((ret2 >> 19) & 0x000001) << 4;
|
||||
col |= ((ret2 >> 18) & 0x000001) << 8;
|
||||
col |= ((ret2 >> 20) & 0x000001) << 9;
|
||||
col |= ((ret2 >> 22) & 0x000001) << 10;
|
||||
rb_or = (ret2 >> 1) & 0x000001;
|
||||
}
|
||||
break;
|
||||
case 0x00200000:
|
||||
if (pg) {
|
||||
row = (ret2 >> 9) & 0x0000f8;
|
||||
row |= (ret2 >> 17) & 0x000001;
|
||||
row |= ((ret2 >> 19) & 0x000001) << 1;
|
||||
row |= ((ret2 >> 21) & 0x000001) << 2;
|
||||
row |= ((ret2 >> 18) & 0x000001) << 8;
|
||||
row |= ((ret2 >> 20) & 0x000001) << 9;
|
||||
row |= ((ret2 >> 22) & 0x000001) << 10;
|
||||
col = (ret2 >> 1) & 0x000007ff;
|
||||
rb_or = (ret2 >> 11) & 0x000001;
|
||||
} else {
|
||||
row = (ret2 >> 1) & 0x0007fe;
|
||||
row |= (ret2 >> 13) & 0x000001;
|
||||
col = (ret2 >> 9) & 0x0000ec;
|
||||
col |= (ret2 >> 17) & 0x000001;
|
||||
col |= ((ret2 >> 19) & 0x000001) << 1;
|
||||
col |= ((ret2 >> 21) & 0x000001) << 4;
|
||||
col |= ((ret2 >> 18) & 0x000001) << 8;
|
||||
col |= ((ret2 >> 20) & 0x000001) << 9;
|
||||
col |= ((ret2 >> 22) & 0x000001) << 10;
|
||||
rb_or = (ret2 >> 1) & 0x000001;
|
||||
}
|
||||
break;
|
||||
case 0x00800000:
|
||||
if (pg) {
|
||||
row = (ret2 >> 9) & 0x0000f0;
|
||||
row |= (ret2 >> 17) & 0x000001;
|
||||
row |= ((ret2 >> 19) & 0x000001) << 1;
|
||||
row |= ((ret2 >> 21) & 0x000001) << 2;
|
||||
row |= ((ret2 >> 23) & 0x000001) << 3;
|
||||
row |= ((ret2 >> 18) & 0x000001) << 8;
|
||||
row |= ((ret2 >> 20) & 0x000001) << 9;
|
||||
row |= ((ret2 >> 22) & 0x000001) << 10;
|
||||
col = (ret2 >> 1) & 0x000007ff;
|
||||
rb_or = (ret2 >> 12) & 0x000001;
|
||||
} else {
|
||||
row = (ret2 >> 1) & 0x0007fe;
|
||||
row |= (ret2 >> 13) & 0x000001;
|
||||
col = (ret2 >> 9) & 0x0000e0;
|
||||
col |= (ret2 >> 17) & 0x000001;
|
||||
col |= ((ret2 >> 19) & 0x000001) << 1;
|
||||
col |= ((ret2 >> 21) & 0x000001) << 2;
|
||||
col |= ((ret2 >> 23) & 0x000001) << 3;
|
||||
col |= ((ret2 >> 12) & 0x000001) << 4;
|
||||
col |= ((ret2 >> 18) & 0x000001) << 8;
|
||||
col |= ((ret2 >> 20) & 0x000001) << 9;
|
||||
col |= ((ret2 >> 22) & 0x000001) << 10;
|
||||
rb_or = (ret2 >> 1) & 0x000001;
|
||||
}
|
||||
break;
|
||||
}
|
||||
add = 1;
|
||||
} else if (pg) switch (rb->virt_size) {
|
||||
default:
|
||||
ret4 = WD76C10_ADDR_INVALID;
|
||||
break;
|
||||
case 0x00020000:
|
||||
row = (ret2 >> 9) & 0x0000ff;
|
||||
row |= ((ret2 >> 18) & 0x000001) << 8;
|
||||
row |= ((ret2 >> 20) & 0x000001) << 9;
|
||||
row |= ((ret2 >> 22) & 0x000001) << 10;
|
||||
col = (ret2 >> 1) & 0x0007ff;
|
||||
break;
|
||||
case 0x00080000:
|
||||
row = (ret2 >> 9) & 0x0000fe;
|
||||
row |= (ret2 >> 17) & 0x000001;
|
||||
row |= ((ret2 >> 18) & 0x000001) << 8;
|
||||
row |= ((ret2 >> 20) & 0x000001) << 9;
|
||||
row |= ((ret2 >> 22) & 0x000001) << 10;
|
||||
col = (ret2 >> 1) & 0x0007ff;
|
||||
break;
|
||||
case 0x00200000:
|
||||
row = (ret2 >> 9) & 0x0000fc;
|
||||
row |= (ret2 >> 17) & 0x000001;
|
||||
row |= ((ret2 >> 19) & 0x000001) << 1;
|
||||
row |= ((ret2 >> 18) & 0x000001) << 8;
|
||||
row |= ((ret2 >> 20) & 0x000001) << 9;
|
||||
row |= ((ret2 >> 22) & 0x000001) << 10;
|
||||
col = (ret2 >> 1) & 0x0007ff;
|
||||
break;
|
||||
case 0x00800000:
|
||||
row = (ret2 >> 9) & 0x0000f8;
|
||||
row |= (ret2 >> 17) & 0x000001;
|
||||
row |= ((ret2 >> 19) & 0x000001) << 1;
|
||||
row |= ((ret2 >> 21) & 0x000001) << 2;
|
||||
row |= ((ret2 >> 18) & 0x000001) << 8;
|
||||
row |= ((ret2 >> 20) & 0x000001) << 9;
|
||||
row |= ((ret2 >> 22) & 0x000001) << 10;
|
||||
col = (ret2 >> 1) & 0x0007ff;
|
||||
break;
|
||||
} else switch (rb->virt_size) {
|
||||
default:
|
||||
ret4 = WD76C10_ADDR_INVALID;
|
||||
break;
|
||||
case 0x00020000:
|
||||
row = (ret2 >> 1) & 0x0007ff;
|
||||
col = (ret2 >> 9) & 0x0000ff;
|
||||
col |= ((ret2 >> 18) & 0x000001) << 8;
|
||||
col |= ((ret2 >> 20) & 0x000001) << 9;
|
||||
col |= ((ret2 >> 22) & 0x000001) << 10;
|
||||
break;
|
||||
case 0x00080000:
|
||||
row = (ret2 >> 1) & 0x0007ff;
|
||||
col = (ret2 >> 9) & 0x0000fe;
|
||||
col |= (ret2 >> 17) & 0x000001;
|
||||
col |= ((ret2 >> 18) & 0x000001) << 8;
|
||||
col |= ((ret2 >> 20) & 0x000001) << 9;
|
||||
col |= ((ret2 >> 22) & 0x000001) << 10;
|
||||
break;
|
||||
case 0x00200000:
|
||||
row = (ret2 >> 1) & 0x0007ff;
|
||||
col = (ret2 >> 9) & 0x0000fc;
|
||||
col |= (ret2 >> 17) & 0x000001;
|
||||
col |= ((ret2 >> 19) & 0x000001) << 1;
|
||||
col |= ((ret2 >> 18) & 0x000001) << 8;
|
||||
col |= ((ret2 >> 20) & 0x000001) << 9;
|
||||
col |= ((ret2 >> 22) & 0x000001) << 10;
|
||||
break;
|
||||
case 0x00800000:
|
||||
row = (ret2 >> 1) & 0x0007ff;
|
||||
col = (ret2 >> 9) & 0x0000f8;
|
||||
col |= (ret2 >> 17) & 0x000001;
|
||||
col |= ((ret2 >> 19) & 0x000001) << 1;
|
||||
col |= ((ret2 >> 21) & 0x000001) << 2;
|
||||
col |= ((ret2 >> 18) & 0x000001) << 8;
|
||||
col |= ((ret2 >> 20) & 0x000001) << 9;
|
||||
col |= ((ret2 >> 22) & 0x000001) << 10;
|
||||
break;
|
||||
}
|
||||
|
||||
if (row != WD76C10_ADDR_INVALID) {
|
||||
ret4 = wd76c10_calc_phys(row & 0x0007ff, col & 0x0007ff,
|
||||
rb->phys_size, ret2 & 0x000001);
|
||||
|
||||
if (ilv4 || ilv2)
|
||||
rb = &(dev->ram_banks[i | rb_or]);
|
||||
|
||||
i += add;
|
||||
}
|
||||
|
||||
if (rb->enable && (ret >= rb->virt_addr) &&
|
||||
(ret < (rb->virt_addr + size))) {
|
||||
if ((ret4 != WD76C10_ADDR_INVALID) && (rb->phys_size > 0x00000000))
|
||||
nrt = ret4 + rb->phys_addr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ret = nrt;
|
||||
}
|
||||
|
||||
if (ret >= (mem_size << 10))
|
||||
/* The physical memory address is too high or disabled, which is invalid. */
|
||||
ret = WD76C10_ADDR_INVALID;
|
||||
/* Otherwise, map it to the correct bank so the BIOS can auto-size it correctly. */
|
||||
else for (uint8_t i = 0; i < 4; i++) {
|
||||
rb = &(dev->ram_banks[i]);
|
||||
if (rb->enable && (ret >= rb->virt_addr) && (ret < (rb->virt_addr + rb->virt_size))) {
|
||||
if (rb->phys_size == 0x00000000)
|
||||
ret = WD76C10_ADDR_INVALID;
|
||||
else
|
||||
ret = ((ret - rb->virt_addr) % rb->phys_size) + rb->phys_addr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -185,8 +504,12 @@ wd76c10_read_ram(uint32_t addr, void *priv)
|
||||
|
||||
addr = wd76c10_calc_addr(dev, addr);
|
||||
|
||||
if (addr != WD76C10_ADDR_INVALID)
|
||||
ret = mem_read_ram(addr, priv);
|
||||
if (addr != WD76C10_ADDR_INVALID) {
|
||||
if (dev->fast)
|
||||
ret = mem_read_ram(addr, priv);
|
||||
else
|
||||
ret = ram[addr];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -199,8 +522,12 @@ wd76c10_read_ramw(uint32_t addr, void *priv)
|
||||
|
||||
addr = wd76c10_calc_addr(dev, addr);
|
||||
|
||||
if (addr != WD76C10_ADDR_INVALID)
|
||||
ret = mem_read_ramw(addr, priv);
|
||||
if (addr != WD76C10_ADDR_INVALID) {
|
||||
if (dev->fast)
|
||||
ret = mem_read_ramw(addr, priv);
|
||||
else
|
||||
ret = *(uint16_t *) &(ram[addr]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -212,8 +539,12 @@ wd76c10_write_ram(uint32_t addr, uint8_t val, void *priv)
|
||||
|
||||
addr = wd76c10_calc_addr(dev, addr);
|
||||
|
||||
if (addr != WD76C10_ADDR_INVALID)
|
||||
mem_write_ram(addr, val, priv);
|
||||
if (addr != WD76C10_ADDR_INVALID) {
|
||||
if (dev->fast)
|
||||
mem_write_ram(addr, val, priv);
|
||||
else
|
||||
ram[addr] = val;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -223,8 +554,12 @@ wd76c10_write_ramw(uint32_t addr, uint16_t val, void *priv)
|
||||
|
||||
addr = wd76c10_calc_addr(dev, addr);
|
||||
|
||||
if (addr != WD76C10_ADDR_INVALID)
|
||||
mem_write_ramw(addr, val, priv);
|
||||
if (addr != WD76C10_ADDR_INVALID) {
|
||||
if (dev->fast)
|
||||
mem_write_ramw(addr, val, priv);
|
||||
else
|
||||
*(uint16_t *) &(ram[addr]) = val;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -258,6 +593,9 @@ wd76c10_recalc_exec(wd76c10_t *dev, uint32_t base, uint32_t size)
|
||||
static void
|
||||
wd76c10_banks_recalc(wd76c10_t *dev)
|
||||
{
|
||||
int match = 0;
|
||||
dev->fast = 0;
|
||||
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
ram_bank_t *rb = &(dev->ram_banks[i]);
|
||||
uint8_t bit = i << 1;
|
||||
@@ -266,8 +604,42 @@ wd76c10_banks_recalc(wd76c10_t *dev)
|
||||
rb->enable = (dev->split_sa >> bit) & 0x01;
|
||||
rb->virt_addr = ((uint32_t) dev->bank_bases[i]) << 17;
|
||||
|
||||
if (rb->enable) {
|
||||
rb->adj_virt_addr = rb->virt_addr;
|
||||
rb->adj_virt_size = rb->virt_size;
|
||||
|
||||
if (dev->mem_ctl & 0x0400)
|
||||
rb->adj_virt_addr += (i * rb->adj_virt_size);
|
||||
else if ((dev->mem_ctl >> 8) & (1 << (i >> 1)))
|
||||
rb->adj_virt_addr += ((i & 1) * rb->adj_virt_size);
|
||||
} else {
|
||||
rb->adj_virt_addr = WD76C10_ADDR_INVALID;
|
||||
rb->adj_virt_size = 0x00000000;
|
||||
}
|
||||
|
||||
if ((rb->enable == rb->phys_on) &&
|
||||
(rb->adj_virt_addr == rb->phys_addr) &&
|
||||
(rb->adj_virt_size == rb->phys_size))
|
||||
match++;
|
||||
}
|
||||
|
||||
dev->fast = (match == 4);
|
||||
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
ram_bank_t *rb = &(dev->ram_banks[i]);
|
||||
|
||||
if (cpu_use_exec)
|
||||
wd76c10_recalc_exec(dev, rb->virt_addr, rb->virt_size);
|
||||
|
||||
wd76c10_log("Bank %i (%s), physical: %i, %08X-%08X, "
|
||||
"virtual: %i, %08X-%08X, adj.: %i, %08X-%08X\n",
|
||||
i, dev->fast ? "FAST" : "SLOW",
|
||||
rb->phys_on,
|
||||
rb->phys_addr, rb->phys_addr + rb->phys_size - 1,
|
||||
rb->enable,
|
||||
rb->virt_addr, rb->virt_addr + rb->virt_size - 1,
|
||||
rb->enable,
|
||||
rb->adj_virt_addr, rb->adj_virt_addr + rb->adj_virt_size - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -899,11 +1271,22 @@ wd76c10_init(UNUSED(const device_t *info))
|
||||
}
|
||||
}
|
||||
if (size != 0x00000000) {
|
||||
rb->phys_on = 1;
|
||||
rb->phys_addr = accum_mem;
|
||||
rb->phys_size = size;
|
||||
wd76c10_log("Bank %i size: %5i KiB, starting at %5i KiB\n", i, rb->phys_size >> 10, rb->phys_addr >> 10);
|
||||
total_mem -= size;
|
||||
accum_mem += size;
|
||||
}
|
||||
} else
|
||||
rb->phys_addr = WD76C10_ADDR_INVALID;
|
||||
}
|
||||
|
||||
if (mem_size == 3072) {
|
||||
/* Reorganize the banks a bit so, we have 2048, 0, 512, 512. */
|
||||
ram_bank_t rt = dev->ram_banks[3];
|
||||
dev->ram_banks[3] = dev->ram_banks[2];
|
||||
dev->ram_banks[2] = dev->ram_banks[1];
|
||||
dev->ram_banks[1] = rt;
|
||||
}
|
||||
|
||||
rb = &(dev->ram_banks[4]);
|
||||
|
||||
@@ -600,12 +600,12 @@ ropMOV_seg_w(UNUSED(uint8_t opcode), uint32_t fetchdat, uint32_t op_32, uint32_t
|
||||
MEM_LOAD_ADDR_EA_L(target_seg); \
|
||||
STORE_HOST_REG_ADDR((uintptr_t) &codegen_temp, 0); \
|
||||
LOAD_EA(); \
|
||||
MEM_LOAD_ADDR_EA_W_OFFSET(target_seg, 4); \
|
||||
MEM_LOAD_ADDR_EA_W_OFFSET(target_seg, 4, op_32); \
|
||||
} else { \
|
||||
MEM_LOAD_ADDR_EA_W(target_seg); \
|
||||
STORE_HOST_REG_ADDR_W((uintptr_t) &codegen_temp, 0); \
|
||||
LOAD_EA(); \
|
||||
MEM_LOAD_ADDR_EA_W_OFFSET(target_seg, 2); \
|
||||
MEM_LOAD_ADDR_EA_W_OFFSET(target_seg, 2, op_32); \
|
||||
} \
|
||||
LOAD_SEG(0, &rseg); \
|
||||
if (op_32 & 0x100) { \
|
||||
|
||||
@@ -1049,11 +1049,18 @@ MEM_LOAD_ADDR_EA_W(x86seg *seg)
|
||||
/*done:*/
|
||||
}
|
||||
static __inline void
|
||||
MEM_LOAD_ADDR_EA_W_OFFSET(x86seg *seg, int offset)
|
||||
MEM_LOAD_ADDR_EA_W_OFFSET(x86seg *seg, int offset, int op_32)
|
||||
{
|
||||
addbyte(0x83); /*ADD EAX, offset*/
|
||||
addbyte(0xc0);
|
||||
addbyte(offset);
|
||||
if (!(op_32 & 0x200)) {
|
||||
addbyte(0x25); /* AND EAX, ffffh */
|
||||
addbyte(0xff);
|
||||
addbyte(0xff);
|
||||
addbyte(0x00);
|
||||
addbyte(0x00);
|
||||
}
|
||||
MEM_LOAD_ADDR_EA_W(seg);
|
||||
}
|
||||
static __inline void
|
||||
|
||||
@@ -789,7 +789,7 @@ MEM_LOAD_ADDR_EA_W(x86seg *seg)
|
||||
host_reg_mapping[0] = 8;
|
||||
}
|
||||
static __inline void
|
||||
MEM_LOAD_ADDR_EA_W_OFFSET(x86seg *seg, int offset)
|
||||
MEM_LOAD_ADDR_EA_W_OFFSET(x86seg *seg, int offset, int op_32)
|
||||
{
|
||||
if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) || (seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS))) {
|
||||
addbyte(0x31); /*XOR EDX, EDX*/
|
||||
@@ -802,6 +802,13 @@ MEM_LOAD_ADDR_EA_W_OFFSET(x86seg *seg, int offset)
|
||||
addbyte(0x83); /*ADD EAX, offset*/
|
||||
addbyte(0xc0);
|
||||
addbyte(offset);
|
||||
if (!(op_32 & 0x200)) {
|
||||
addbyte(0x25); /* AND EAX, ffffh */
|
||||
addbyte(0xff);
|
||||
addbyte(0xff);
|
||||
addbyte(0x00);
|
||||
addbyte(0x00);
|
||||
}
|
||||
addbyte(0xe8); /*CALL mem_load_addr_ea_w*/
|
||||
addlong(mem_load_addr_ea_w - (uint32_t) (&codeblock[block_current].data[block_pos + 4]));
|
||||
|
||||
|
||||
@@ -818,7 +818,9 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p
|
||||
int over = 0;
|
||||
int pc_off = 0;
|
||||
int test_modrm = 1;
|
||||
int in_lock = 0;
|
||||
int c;
|
||||
uint32_t op87 = 0x00000000;
|
||||
|
||||
op_ea_seg = &cpu_state.seg_ds;
|
||||
op_ssegs = 0;
|
||||
@@ -872,6 +874,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p
|
||||
break;
|
||||
|
||||
case 0xd8:
|
||||
op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d8_a32 : x86_dynarec_opcodes_d8_a16;
|
||||
recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_d8;
|
||||
opcode_shift = 3;
|
||||
@@ -882,6 +885,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p
|
||||
block->flags |= CODEBLOCK_HAS_FPU;
|
||||
break;
|
||||
case 0xd9:
|
||||
op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d9_a32 : x86_dynarec_opcodes_d9_a16;
|
||||
recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_d9;
|
||||
opcode_mask = 0xff;
|
||||
@@ -891,6 +895,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p
|
||||
block->flags |= CODEBLOCK_HAS_FPU;
|
||||
break;
|
||||
case 0xda:
|
||||
op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_da_a32 : x86_dynarec_opcodes_da_a16;
|
||||
recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_da;
|
||||
opcode_mask = 0xff;
|
||||
@@ -900,6 +905,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p
|
||||
block->flags |= CODEBLOCK_HAS_FPU;
|
||||
break;
|
||||
case 0xdb:
|
||||
op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_db_a32 : x86_dynarec_opcodes_db_a16;
|
||||
recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_db;
|
||||
opcode_mask = 0xff;
|
||||
@@ -909,6 +915,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p
|
||||
block->flags |= CODEBLOCK_HAS_FPU;
|
||||
break;
|
||||
case 0xdc:
|
||||
op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16;
|
||||
recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_dc;
|
||||
opcode_shift = 3;
|
||||
@@ -919,6 +926,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p
|
||||
block->flags |= CODEBLOCK_HAS_FPU;
|
||||
break;
|
||||
case 0xdd:
|
||||
op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dd_a32 : x86_dynarec_opcodes_dd_a16;
|
||||
recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_dd;
|
||||
opcode_mask = 0xff;
|
||||
@@ -928,6 +936,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p
|
||||
block->flags |= CODEBLOCK_HAS_FPU;
|
||||
break;
|
||||
case 0xde:
|
||||
op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_de_a32 : x86_dynarec_opcodes_de_a16;
|
||||
recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_de;
|
||||
opcode_mask = 0xff;
|
||||
@@ -937,6 +946,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p
|
||||
block->flags |= CODEBLOCK_HAS_FPU;
|
||||
break;
|
||||
case 0xdf:
|
||||
op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_df_a32 : x86_dynarec_opcodes_df_a16;
|
||||
recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_df;
|
||||
opcode_mask = 0xff;
|
||||
@@ -947,6 +957,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p
|
||||
break;
|
||||
|
||||
case 0xf0: /*LOCK*/
|
||||
in_lock = 0;
|
||||
break;
|
||||
|
||||
case 0xf2: /*REPNE*/
|
||||
@@ -1000,6 +1011,13 @@ generate_call:
|
||||
recomp_op_table = recomp_opcodes;
|
||||
}
|
||||
|
||||
if (op87 != 0x0000) {
|
||||
STORE_IMM_ADDR_L((uintptr_t) &x87_op, op87);
|
||||
}
|
||||
|
||||
if (in_lock && ((opcode == 0x90) || (opcode == 0xec)))
|
||||
goto codegen_skip;
|
||||
|
||||
if (recomp_op_table && recomp_op_table[(opcode | op_32) & 0x1ff]) {
|
||||
uint32_t new_pc = recomp_op_table[(opcode | op_32) & 0x1ff](opcode, fetchdat, op_32, op_pc, block);
|
||||
if (new_pc) {
|
||||
@@ -1027,7 +1045,13 @@ generate_call:
|
||||
}
|
||||
}
|
||||
|
||||
op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask];
|
||||
codegen_skip:
|
||||
if (in_lock && ((opcode == 0x90) || (opcode == 0xec)))
|
||||
/* This is always ILLEGAL. */
|
||||
op = x86_dynarec_opcodes_3DNOW[0xff];
|
||||
else
|
||||
op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask];
|
||||
|
||||
if (op_ssegs != last_ssegs) {
|
||||
last_ssegs = op_ssegs;
|
||||
addbyte(0xC6); /*MOVB $0,(ssegs)*/
|
||||
|
||||
@@ -1857,7 +1857,9 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p
|
||||
int over = 0;
|
||||
int pc_off = 0;
|
||||
int test_modrm = 1;
|
||||
int in_lock = 0;
|
||||
int c;
|
||||
uint32_t op87 = 0x00000000;
|
||||
|
||||
op_ea_seg = &cpu_state.seg_ds;
|
||||
op_ssegs = 0;
|
||||
@@ -1912,6 +1914,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p
|
||||
break;
|
||||
|
||||
case 0xd8:
|
||||
op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d8_a32 : x86_dynarec_opcodes_d8_a16;
|
||||
recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_d8;
|
||||
opcode_shift = 3;
|
||||
@@ -1922,6 +1925,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p
|
||||
block->flags |= CODEBLOCK_HAS_FPU;
|
||||
break;
|
||||
case 0xd9:
|
||||
op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d9_a32 : x86_dynarec_opcodes_d9_a16;
|
||||
recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_d9;
|
||||
opcode_mask = 0xff;
|
||||
@@ -1931,6 +1935,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p
|
||||
block->flags |= CODEBLOCK_HAS_FPU;
|
||||
break;
|
||||
case 0xda:
|
||||
op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_da_a32 : x86_dynarec_opcodes_da_a16;
|
||||
recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_da;
|
||||
opcode_mask = 0xff;
|
||||
@@ -1940,6 +1945,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p
|
||||
block->flags |= CODEBLOCK_HAS_FPU;
|
||||
break;
|
||||
case 0xdb:
|
||||
op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_db_a32 : x86_dynarec_opcodes_db_a16;
|
||||
recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_db;
|
||||
opcode_mask = 0xff;
|
||||
@@ -1949,6 +1955,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p
|
||||
block->flags |= CODEBLOCK_HAS_FPU;
|
||||
break;
|
||||
case 0xdc:
|
||||
op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16;
|
||||
recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_dc;
|
||||
opcode_shift = 3;
|
||||
@@ -1959,6 +1966,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p
|
||||
block->flags |= CODEBLOCK_HAS_FPU;
|
||||
break;
|
||||
case 0xdd:
|
||||
op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dd_a32 : x86_dynarec_opcodes_dd_a16;
|
||||
recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_dd;
|
||||
opcode_mask = 0xff;
|
||||
@@ -1968,6 +1976,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p
|
||||
block->flags |= CODEBLOCK_HAS_FPU;
|
||||
break;
|
||||
case 0xde:
|
||||
op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_de_a32 : x86_dynarec_opcodes_de_a16;
|
||||
recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_de;
|
||||
opcode_mask = 0xff;
|
||||
@@ -1977,6 +1986,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p
|
||||
block->flags |= CODEBLOCK_HAS_FPU;
|
||||
break;
|
||||
case 0xdf:
|
||||
op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_df_a32 : x86_dynarec_opcodes_df_a16;
|
||||
recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_df;
|
||||
opcode_mask = 0xff;
|
||||
@@ -1987,6 +1997,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p
|
||||
break;
|
||||
|
||||
case 0xf0: /*LOCK*/
|
||||
in_lock = 1;
|
||||
break;
|
||||
|
||||
case 0xf2: /*REPNE*/
|
||||
@@ -2041,6 +2052,13 @@ generate_call:
|
||||
recomp_op_table = recomp_opcodes;
|
||||
}
|
||||
|
||||
if (op87 != 0x0000) {
|
||||
STORE_IMM_ADDR_L((uintptr_t) &x87_op, op87);
|
||||
}
|
||||
|
||||
if (in_lock && ((opcode == 0x90) || (opcode == 0xec)))
|
||||
goto codegen_skip;
|
||||
|
||||
if (recomp_op_table && recomp_op_table[(opcode | op_32) & 0x1ff]) {
|
||||
uint32_t new_pc = recomp_op_table[(opcode | op_32) & 0x1ff](opcode, fetchdat, op_32, op_pc, block);
|
||||
if (new_pc) {
|
||||
@@ -2067,7 +2085,13 @@ generate_call:
|
||||
}
|
||||
}
|
||||
|
||||
op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask];
|
||||
codegen_skip:
|
||||
if (in_lock && ((opcode == 0x90) || (opcode == 0xec)))
|
||||
/* This is always ILLEGAL. */
|
||||
op = x86_dynarec_opcodes_3DNOW[0xff];
|
||||
else
|
||||
op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask];
|
||||
|
||||
if (op_ssegs != last_ssegs) {
|
||||
last_ssegs = op_ssegs;
|
||||
|
||||
|
||||
@@ -395,7 +395,9 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p
|
||||
int over = 0;
|
||||
int test_modrm = 1;
|
||||
int pc_off = 0;
|
||||
int in_lock = 0;
|
||||
uint32_t next_pc = 0;
|
||||
uint16_t op87 = 0x0000;
|
||||
#ifdef DEBUG_EXTRA
|
||||
uint8_t last_prefix = 0;
|
||||
#endif
|
||||
@@ -451,6 +453,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p
|
||||
#ifdef DEBUG_EXTRA
|
||||
last_prefix = 0xd8;
|
||||
#endif
|
||||
op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d8_a32 : x86_dynarec_opcodes_d8_a16;
|
||||
recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_d8;
|
||||
opcode_shift = 3;
|
||||
@@ -464,6 +467,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p
|
||||
#ifdef DEBUG_EXTRA
|
||||
last_prefix = 0xd9;
|
||||
#endif
|
||||
op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d9_a32 : x86_dynarec_opcodes_d9_a16;
|
||||
recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_d9;
|
||||
opcode_mask = 0xff;
|
||||
@@ -476,6 +480,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p
|
||||
#ifdef DEBUG_EXTRA
|
||||
last_prefix = 0xda;
|
||||
#endif
|
||||
op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_da_a32 : x86_dynarec_opcodes_da_a16;
|
||||
recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_da;
|
||||
opcode_mask = 0xff;
|
||||
@@ -488,6 +493,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p
|
||||
#ifdef DEBUG_EXTRA
|
||||
last_prefix = 0xdb;
|
||||
#endif
|
||||
op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_db_a32 : x86_dynarec_opcodes_db_a16;
|
||||
recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_db;
|
||||
opcode_mask = 0xff;
|
||||
@@ -500,6 +506,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p
|
||||
#ifdef DEBUG_EXTRA
|
||||
last_prefix = 0xdc;
|
||||
#endif
|
||||
op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16;
|
||||
recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_dc;
|
||||
opcode_shift = 3;
|
||||
@@ -513,6 +520,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p
|
||||
#ifdef DEBUG_EXTRA
|
||||
last_prefix = 0xdd;
|
||||
#endif
|
||||
op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dd_a32 : x86_dynarec_opcodes_dd_a16;
|
||||
recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_dd;
|
||||
opcode_mask = 0xff;
|
||||
@@ -525,6 +533,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p
|
||||
#ifdef DEBUG_EXTRA
|
||||
last_prefix = 0xde;
|
||||
#endif
|
||||
op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_de_a32 : x86_dynarec_opcodes_de_a16;
|
||||
recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_de;
|
||||
opcode_mask = 0xff;
|
||||
@@ -537,6 +546,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p
|
||||
#ifdef DEBUG_EXTRA
|
||||
last_prefix = 0xdf;
|
||||
#endif
|
||||
op87 = (op87 & 0xf800) | ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_df_a32 : x86_dynarec_opcodes_df_a16;
|
||||
recomp_op_table = fpu_softfloat ? NULL : recomp_opcodes_df;
|
||||
opcode_mask = 0xff;
|
||||
@@ -547,6 +557,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p
|
||||
break;
|
||||
|
||||
case 0xf0: /*LOCK*/
|
||||
in_lock = 1;
|
||||
break;
|
||||
|
||||
case 0xf2: /*REPNE*/
|
||||
@@ -657,12 +668,18 @@ generate_call:
|
||||
}
|
||||
}
|
||||
codegen_mark_code_present(block, cs + old_pc, (op_pc - old_pc) - pc_off);
|
||||
if (op87 != 0x0000) {
|
||||
uop_MOV_IMM(ir, IREG_x87_op, op87);
|
||||
}
|
||||
/* It is apparently a prefixed instruction. */
|
||||
#if 0
|
||||
if ((recomp_op_table == recomp_opcodes) && (opcode == 0x48))
|
||||
goto codegen_skip;
|
||||
#endif
|
||||
|
||||
if (in_lock && ((opcode == 0x90) || (opcode == 0xec)))
|
||||
goto codegen_skip;
|
||||
|
||||
if (recomp_op_table && recomp_op_table[(opcode | op_32) & recomp_opcode_mask]) {
|
||||
uint32_t new_pc = recomp_op_table[(opcode | op_32) & recomp_opcode_mask](block, ir, opcode, fetchdat, op_32, op_pc);
|
||||
if (new_pc) {
|
||||
@@ -680,13 +697,17 @@ generate_call:
|
||||
}
|
||||
}
|
||||
|
||||
// codegen_skip:
|
||||
codegen_skip:
|
||||
if ((op_table == x86_dynarec_opcodes_REPNE || op_table == x86_dynarec_opcodes_REPE) && !op_table[opcode | op_32]) {
|
||||
op_table = x86_dynarec_opcodes;
|
||||
recomp_op_table = recomp_opcodes;
|
||||
}
|
||||
|
||||
op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask];
|
||||
if (in_lock && ((opcode == 0x90) || (opcode == 0xec)))
|
||||
/* This is always ILLEGAL. */
|
||||
op = x86_dynarec_opcodes_3DNOW[0xff];
|
||||
else
|
||||
op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask];
|
||||
|
||||
if (!test_modrm || (op_table == x86_dynarec_opcodes && opcode_modrm[opcode]) || (op_table == x86_dynarec_opcodes_0f && opcode_0f_modrm[opcode]) || (op_table == x86_dynarec_opcodes_3DNOW)) {
|
||||
int stack_offset = 0;
|
||||
|
||||
@@ -306,6 +306,7 @@ struct ir_data_t;
|
||||
x86seg *codegen_generate_ea(struct ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32, int stack_offset);
|
||||
extern void codegen_check_seg_read(codeblock_t *block, struct ir_data_t *ir, x86seg *seg);
|
||||
extern void codegen_check_seg_write(codeblock_t *block, struct ir_data_t *ir, x86seg *seg);
|
||||
extern void codegen_check_regs(void);
|
||||
|
||||
extern int codegen_purge_purgable_list(void);
|
||||
/*Delete a random code block to free memory. This is obviously quite expensive, and
|
||||
|
||||
@@ -931,6 +931,8 @@ codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop)
|
||||
host_arm64_ADD_REG(block, REG_X0, seg_reg, addr_reg, 0);
|
||||
if (uop->imm_data)
|
||||
host_arm64_ADD_IMM(block, REG_X0, REG_X0, uop->imm_data);
|
||||
if (uop->is_a16)
|
||||
host_arm64_AND_IMM(block, REG_X0, REG_X0, 0xffff);
|
||||
if (REG_IS_B(dest_size) || REG_IS_BH(dest_size)) {
|
||||
host_arm64_call(block, codegen_mem_load_byte);
|
||||
} else if (REG_IS_W(dest_size)) {
|
||||
|
||||
@@ -995,6 +995,8 @@ codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop)
|
||||
host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg);
|
||||
if (uop->imm_data)
|
||||
host_arm_ADD_IMM(block, REG_R0, REG_R0, uop->imm_data);
|
||||
if (uop->is_a16)
|
||||
host_arm_AND_IMM(block, REG_R0, REG_R0, 0xffff);
|
||||
if (REG_IS_B(dest_size) || REG_IS_BH(dest_size)) {
|
||||
host_arm_BL(block, (uintptr_t) codegen_mem_load_byte);
|
||||
} else if (REG_IS_W(dest_size)) {
|
||||
|
||||
@@ -329,7 +329,7 @@ codegen_backend_init(void)
|
||||
host_x86_POP(block, REG_RSI);
|
||||
#endif
|
||||
host_x86_POP(block, REG_RBP);
|
||||
host_x86_POP(block, REG_RDX);
|
||||
host_x86_POP(block, REG_RBX);
|
||||
host_x86_RET(block);
|
||||
|
||||
block_write_data = NULL;
|
||||
@@ -392,7 +392,7 @@ codegen_backend_epilogue(codeblock_t *block)
|
||||
host_x86_POP(block, REG_RSI);
|
||||
#endif
|
||||
host_x86_POP(block, REG_RBP);
|
||||
host_x86_POP(block, REG_RDX);
|
||||
host_x86_POP(block, REG_RBX);
|
||||
host_x86_RET(block);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -780,8 +780,13 @@ host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p)
|
||||
codegen_alloc_bytes(block, 8);
|
||||
codegen_addbyte4(block, 0x41, 0x8b, 0x84 | ((dst_reg & 7) << 3), 0x24); /*MOV dst_reg, ram_offset[R12]*/
|
||||
codegen_addlong(block, ram_offset);
|
||||
} else if ((ram_offset < -2147483648LL) || (ram_offset > 2147483647LL) || !(block->flags & CODEBLOCK_NO_IMMEDIATES)) {
|
||||
codegen_alloc_bytes(block, 13);
|
||||
codegen_addbyte2(block, 0x49, 0xb9); /*MOV r9,(uintptr_t) p*/
|
||||
codegen_addquad(block, (uintptr_t) p);
|
||||
codegen_addbyte3(block, 0x41, 0x8b, 0x01 | ((dst_reg & 7) << 3)); /*MOV dst_reg, [R9]*/
|
||||
} else {
|
||||
fatal("host_x86_MOV32_REG_ABS - out of range\n");
|
||||
fatal("host_x86_MOV32_REG_ABS - RAM offset = %016" PRIX64 " (p - ram = %016" PRIX64 ")\n", ram_offset, (uintptr_t) p - (uintptr_t) ram);
|
||||
codegen_alloc_bytes(block, 6);
|
||||
codegen_addbyte(block, 0x8b); /*MOV [p], src_reg*/
|
||||
codegen_addbyte(block, 0x05 | ((dst_reg & 7) << 3));
|
||||
|
||||
@@ -997,8 +997,12 @@ codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop)
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real);
|
||||
|
||||
host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg);
|
||||
if (uop->imm_data)
|
||||
if (uop->imm_data) {
|
||||
host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data);
|
||||
if (uop->is_a16) {
|
||||
host_x86_AND32_REG_IMM(block, REG_ESI, 0x0000ffff);
|
||||
}
|
||||
}
|
||||
if (REG_IS_B(dest_size)) {
|
||||
host_x86_CALL(block, codegen_mem_load_byte);
|
||||
} else if (REG_IS_W(dest_size)) {
|
||||
|
||||
@@ -981,8 +981,12 @@ codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop)
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real);
|
||||
|
||||
host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg);
|
||||
if (uop->imm_data)
|
||||
if (uop->imm_data) {
|
||||
host_x86_ADD32_REG_IMM(block, REG_ESI, uop->imm_data);
|
||||
if (uop->is_a16) {
|
||||
host_x86_AND32_REG_IMM(block, REG_ESI, 0x0000ffff);
|
||||
}
|
||||
}
|
||||
if (REG_IS_B(dest_size)) {
|
||||
host_x86_CALL(block, codegen_mem_load_byte);
|
||||
} else if (REG_IS_W(dest_size)) {
|
||||
|
||||
@@ -217,6 +217,7 @@ block_free_list_get(void)
|
||||
void
|
||||
codegen_init(void)
|
||||
{
|
||||
codegen_check_regs();
|
||||
codegen_allocator_init();
|
||||
|
||||
codegen_backend_init();
|
||||
|
||||
@@ -340,6 +340,7 @@ typedef struct uop_t {
|
||||
void *p;
|
||||
ir_host_reg_t dest_reg_a_real;
|
||||
ir_host_reg_t src_reg_a_real, src_reg_b_real, src_reg_c_real;
|
||||
int is_a16;
|
||||
int jump_dest_uop;
|
||||
int jump_list_next;
|
||||
void *jump_dest;
|
||||
@@ -364,6 +365,8 @@ uop_alloc(ir_data_t *ir, uint32_t uop_type)
|
||||
|
||||
uop = &ir->uops[ir->wr_pos++];
|
||||
|
||||
uop->is_a16 = 0;
|
||||
|
||||
uop->dest_reg_a = invalid_ir_reg;
|
||||
uop->src_reg_a = invalid_ir_reg;
|
||||
uop->src_reg_b = invalid_ir_reg;
|
||||
@@ -488,8 +491,14 @@ uop_gen_reg_dst_src2_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src
|
||||
uop_t *uop = uop_alloc(ir, uop_type);
|
||||
|
||||
uop->type = uop_type;
|
||||
uop->is_a16 = 0;
|
||||
uop->src_reg_a = codegen_reg_read(src_reg_a);
|
||||
uop->src_reg_b = codegen_reg_read(src_reg_b);
|
||||
if (src_reg_b == IREG_eaa16) {
|
||||
uop->src_reg_b = codegen_reg_read(IREG_eaaddr);
|
||||
uop->is_a16 = 1;
|
||||
} else
|
||||
uop->src_reg_b = codegen_reg_read(src_reg_b);
|
||||
uop->is_a16 = 0;
|
||||
uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1);
|
||||
uop->imm_data = imm;
|
||||
}
|
||||
|
||||
@@ -533,8 +533,8 @@ ropCWDE(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSE
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
|
||||
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
|
||||
codegen_check_seg_read(block, ir, target_seg); \
|
||||
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); \
|
||||
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 2); \
|
||||
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), (op_32 & 0x200) ? IREG_eaaddr : IREG_eaa16); \
|
||||
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), (op_32 & 0x200) ? IREG_eaaddr : IREG_eaa16, 2); \
|
||||
uop_LOAD_SEG(ir, seg, IREG_temp1_W); \
|
||||
uop_MOV(ir, IREG_16(dest_reg), IREG_temp0_W); \
|
||||
\
|
||||
@@ -556,8 +556,8 @@ ropCWDE(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUSE
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
|
||||
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
|
||||
codegen_check_seg_read(block, ir, target_seg); \
|
||||
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); \
|
||||
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 4); \
|
||||
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), (op_32 & 0x200) ? IREG_eaaddr : IREG_eaa16); \
|
||||
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), (op_32 & 0x200) ? IREG_eaaddr : IREG_eaa16, 4); \
|
||||
uop_LOAD_SEG(ir, seg, IREG_temp1_W); \
|
||||
uop_MOV(ir, IREG_32(dest_reg), IREG_temp0); \
|
||||
\
|
||||
|
||||
@@ -390,6 +390,8 @@ ropPUSHF(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNUS
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||
uop_CALL_FUNC(ir, flags_rebuild);
|
||||
sp_reg = LOAD_SP_WITH_OFFSET(ir, -2);
|
||||
uop_AND_IMM(ir, IREG_flags, IREG_flags, 0x7fd5);
|
||||
uop_OR_IMM(ir, IREG_flags, IREG_flags, 0x0002);
|
||||
uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, IREG_flags);
|
||||
SUB_SP(ir, 2);
|
||||
|
||||
@@ -406,6 +408,8 @@ ropPUSHFD(UNUSED(codeblock_t *block), ir_data_t *ir, UNUSED(uint8_t opcode), UNU
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||
uop_CALL_FUNC(ir, flags_rebuild);
|
||||
|
||||
uop_AND_IMM(ir, IREG_flags, IREG_flags, 0x7fd5);
|
||||
uop_OR_IMM(ir, IREG_flags, IREG_flags, 0x0002);
|
||||
if (cpu_CR4_mask & CR4_VME)
|
||||
uop_AND_IMM(ir, IREG_temp0_W, IREG_eflags, 0x3c);
|
||||
else if (CPUID)
|
||||
|
||||
@@ -169,6 +169,9 @@ struct
|
||||
[IREG_GS_limit_high] = { REG_DWORD, &cpu_state.seg_gs.limit_high, REG_INTEGER, REG_PERMANENT},
|
||||
[IREG_SS_limit_high] = { REG_DWORD, &cpu_state.seg_ss.limit_high, REG_INTEGER, REG_PERMANENT},
|
||||
|
||||
[IREG_eaa16] = { REG_WORD, &cpu_state.eaaddr, REG_INTEGER, REG_PERMANENT},
|
||||
[IREG_x87_op] = { REG_WORD, &x87_op, REG_INTEGER, REG_PERMANENT},
|
||||
|
||||
/*Temporary registers are stored on the stack, and are not guaranteed to
|
||||
be preserved across uOPs. They will not be written back if they will
|
||||
not be read again.*/
|
||||
@@ -223,6 +226,20 @@ reg_is_native_size(ir_reg_t ir_reg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
codegen_check_regs(void)
|
||||
{
|
||||
int i = 0;
|
||||
for (i = 0; i < IREG_COUNT; i++) {
|
||||
if (ireg_data[i].is_volatile == REG_VOLATILE)
|
||||
continue;
|
||||
|
||||
if (ireg_data[i].p && ((uintptr_t)ireg_data[i].p - (uintptr_t)&cpu_state) >= sizeof(cpu_state)) {
|
||||
fatal("Register number %d outside cpu_state!\n", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
codegen_reg_reset(void)
|
||||
{
|
||||
|
||||
@@ -132,7 +132,10 @@ enum {
|
||||
IREG_GS_limit_high = 86,
|
||||
IREG_SS_limit_high = 87,
|
||||
|
||||
IREG_COUNT = 88,
|
||||
IREG_eaa16 = 88,
|
||||
IREG_x87_op = 89,
|
||||
|
||||
IREG_COUNT = 90,
|
||||
|
||||
IREG_INVALID = 255,
|
||||
|
||||
|
||||
73
src/config.c
73
src/config.c
@@ -107,6 +107,7 @@ config_log(const char *fmt, ...)
|
||||
# define config_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
/* Load "General" section. */
|
||||
static void
|
||||
load_general(void)
|
||||
@@ -127,8 +128,6 @@ load_general(void)
|
||||
|
||||
video_fullscreen_scale = ini_section_get_int(cat, "video_fullscreen_scale", 1);
|
||||
|
||||
video_fullscreen_first = ini_section_get_int(cat, "video_fullscreen_first", 1);
|
||||
|
||||
video_filter_method = ini_section_get_int(cat, "video_filter_method", 1);
|
||||
|
||||
inhibit_multimedia_keys = ini_section_get_int(cat, "inhibit_multimedia_keys", 0);
|
||||
@@ -185,6 +184,8 @@ load_general(void)
|
||||
p = ini_section_get_string(cat, "language", NULL);
|
||||
if (p != NULL)
|
||||
lang_id = plat_language_code(p);
|
||||
else
|
||||
lang_id = plat_language_code(DEFAULT_LANGUAGE);
|
||||
|
||||
mouse_sensitivity = ini_section_get_double(cat, "mouse_sensitivity", 1.0);
|
||||
if (mouse_sensitivity < 0.1)
|
||||
@@ -743,7 +744,7 @@ load_ports(void)
|
||||
char temp[512];
|
||||
memset(temp, 0, sizeof(temp));
|
||||
|
||||
for (int c = 0; c < SERIAL_MAX; c++) {
|
||||
for (int c = 0; c < (SERIAL_MAX - 1); c++) {
|
||||
sprintf(temp, "serial%d_enabled", c + 1);
|
||||
com_ports[c].enabled = !!ini_section_get_int(cat, temp, (c >= 2) ? 0 : 1);
|
||||
|
||||
@@ -1760,6 +1761,36 @@ load_gl3_shaders(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Load "Keybinds" section. */
|
||||
static void
|
||||
load_keybinds(void)
|
||||
{
|
||||
ini_section_t cat = ini_find_section(config, "Keybinds");
|
||||
char *p;
|
||||
char temp[512];
|
||||
memset(temp, 0, sizeof(temp));
|
||||
|
||||
/* Now load values from config */
|
||||
for (int x = 0; x < NUM_ACCELS; x++) {
|
||||
p = ini_section_get_string(cat, acc_keys[x].name, "default");
|
||||
/* Check if the binding was marked as cleared */
|
||||
if (strcmp(p, "none") == 0)
|
||||
acc_keys[x].seq[0] = '\0';
|
||||
/* If there's no binding in the file, leave it alone. */
|
||||
else if (strcmp(p, "default") != 0) {
|
||||
/*
|
||||
It would be ideal to validate whether the user entered a
|
||||
valid combo at this point, but the Qt method for testing that is
|
||||
not available from C. Fortunately, if you feed Qt an invalid
|
||||
keysequence string it just assigns nothing, so this won't blow up.
|
||||
However, to improve the user experience, we should validate keys
|
||||
and erase any bad combos from config on mainwindow load.
|
||||
*/
|
||||
strcpy(acc_keys[x].seq, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Load the specified or a default configuration file. */
|
||||
void
|
||||
config_load(void)
|
||||
@@ -1799,14 +1830,13 @@ config_load(void)
|
||||
gfxcard[0] = video_get_video_from_internal_name("cga");
|
||||
vid_api = plat_vidapi("default");
|
||||
vid_resize = 0;
|
||||
video_fullscreen_first = 1;
|
||||
video_fullscreen_scale = 1;
|
||||
time_sync = TIME_SYNC_ENABLED;
|
||||
hdc_current[0] = hdc_get_from_internal_name("none");
|
||||
|
||||
com_ports[0].enabled = 1;
|
||||
com_ports[1].enabled = 1;
|
||||
for (i = 2; i < SERIAL_MAX; i++)
|
||||
for (i = 2; i < (SERIAL_MAX - 1); i++)
|
||||
com_ports[i].enabled = 0;
|
||||
|
||||
lpt_ports[0].enabled = 1;
|
||||
@@ -1840,6 +1870,8 @@ config_load(void)
|
||||
cassette_pcm = 0;
|
||||
cassette_ui_writeprot = 0;
|
||||
|
||||
lang_id = plat_language_code(DEFAULT_LANGUAGE);
|
||||
|
||||
config_log("Config file not present or invalid!\n");
|
||||
} else {
|
||||
load_general(); /* General */
|
||||
@@ -1859,6 +1891,7 @@ config_load(void)
|
||||
#ifndef USE_SDL_UI
|
||||
load_gl3_shaders(); /* GL3 Shaders */
|
||||
#endif
|
||||
load_keybinds(); /* Load shortcut keybinds */
|
||||
|
||||
/* Migrate renamed device configurations. */
|
||||
c = ini_find_section(config, "MDA");
|
||||
@@ -1919,11 +1952,6 @@ save_general(void)
|
||||
else
|
||||
ini_section_set_int(cat, "video_fullscreen_scale", video_fullscreen_scale);
|
||||
|
||||
if (video_fullscreen_first == 1)
|
||||
ini_section_delete_var(cat, "video_fullscreen_first");
|
||||
else
|
||||
ini_section_set_int(cat, "video_fullscreen_first", video_fullscreen_first);
|
||||
|
||||
if (video_filter_method == 1)
|
||||
ini_section_delete_var(cat, "video_filter_method");
|
||||
else
|
||||
@@ -2025,7 +2053,7 @@ save_general(void)
|
||||
else
|
||||
ini_section_delete_var(cat, "mouse_sensitivity");
|
||||
|
||||
if (lang_id == DEFAULT_LANGUAGE)
|
||||
if (lang_id == plat_language_code(DEFAULT_LANGUAGE))
|
||||
ini_section_delete_var(cat, "language");
|
||||
else {
|
||||
plat_language_code_r(lang_id, buffer, 511);
|
||||
@@ -2423,7 +2451,7 @@ save_ports(void)
|
||||
ini_section_t cat = ini_find_or_create_section(config, "Ports (COM & LPT)");
|
||||
char temp[512];
|
||||
|
||||
for (int c = 0; c < SERIAL_MAX; c++) {
|
||||
for (int c = 0; c < (SERIAL_MAX - 1); c++) {
|
||||
sprintf(temp, "serial%d_enabled", c + 1);
|
||||
if (((c < 2) && com_ports[c].enabled) || ((c >= 2) && !com_ports[c].enabled))
|
||||
ini_section_delete_var(cat, temp);
|
||||
@@ -2484,6 +2512,26 @@ save_ports(void)
|
||||
ini_delete_section_if_empty(config, cat);
|
||||
}
|
||||
|
||||
/* Save "Keybinds" section. */
|
||||
static void
|
||||
save_keybinds(void)
|
||||
{
|
||||
ini_section_t cat = ini_find_or_create_section(config, "Keybinds");
|
||||
|
||||
for (int x = 0; x < NUM_ACCELS; x++) {
|
||||
/* Has accelerator been changed from default? */
|
||||
if (strcmp(def_acc_keys[x].seq, acc_keys[x].seq) == 0)
|
||||
ini_section_delete_var(cat, acc_keys[x].name);
|
||||
/* Check for a cleared binding to avoid saving it as an empty string */
|
||||
else if (acc_keys[x].seq[0] == '\0')
|
||||
ini_section_set_string(cat, acc_keys[x].name, "none");
|
||||
else
|
||||
ini_section_set_string(cat, acc_keys[x].name, acc_keys[x].seq);
|
||||
}
|
||||
|
||||
ini_delete_section_if_empty(config, cat);
|
||||
}
|
||||
|
||||
/* Save "Storage Controllers" section. */
|
||||
static void
|
||||
save_storage_controllers(void)
|
||||
@@ -3094,6 +3142,7 @@ config_save(void)
|
||||
#ifndef USE_SDL_UI
|
||||
save_gl3_shaders(); /* GL3 Shaders */
|
||||
#endif
|
||||
save_keybinds(); /* Key bindings */
|
||||
|
||||
ini_write(config, cfg_path);
|
||||
}
|
||||
|
||||
@@ -277,6 +277,19 @@ int checkio(uint32_t port, int mask);
|
||||
#define CHECK_WRITE(chseg, low, high) \
|
||||
CHECK_WRITE_COMMON(chseg, low, high)
|
||||
|
||||
#define CHECK_WRITE_2OP(chseg, low, high, low2, high2) \
|
||||
if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high) || (low2 < (chseg)->limit_low) || (high2 > (chseg)->limit_high) || !((chseg)->access & 2) || ((msw & 1) && !(cpu_state.eflags & VM_FLAG) && ((chseg)->access & 8))) { \
|
||||
x86gpf("Limit check (WRITE)", 0); \
|
||||
return 1; \
|
||||
} \
|
||||
if (msw & 1 && !(cpu_state.eflags & VM_FLAG) && !((chseg)->access & 0x80)) { \
|
||||
if ((chseg) == &cpu_state.seg_ss) \
|
||||
x86ss(NULL, (chseg)->seg & 0xfffc); \
|
||||
else \
|
||||
x86np("Write to seg not present", (chseg)->seg & 0xfffc); \
|
||||
return 1; \
|
||||
}
|
||||
|
||||
#define CHECK_WRITE_REP(chseg, low, high) \
|
||||
if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high)) { \
|
||||
x86gpf("Limit check (WRITE REP)", 0); \
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <86box/ppi.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/gdbstub.h>
|
||||
#include <86box/plat_fallthrough.h>
|
||||
#include <86box/plat_unused.h>
|
||||
|
||||
/* Is the CPU 8088 or 8086. */
|
||||
@@ -3438,10 +3439,13 @@ execx86(int cycs)
|
||||
set_pzs(8);
|
||||
break;
|
||||
case 0xD6: /*SALC*/
|
||||
wait(1, 0);
|
||||
AL = (cpu_state.flags & C_FLAG) ? 0xff : 0x00;
|
||||
wait(1, 0);
|
||||
break;
|
||||
if (!is_nec) {
|
||||
wait(1, 0);
|
||||
AL = (cpu_state.flags & C_FLAG) ? 0xff : 0x00;
|
||||
wait(1, 0);
|
||||
break;
|
||||
}
|
||||
fallthrough;
|
||||
case 0xD7: /*XLATB*/
|
||||
cpu_state.eaaddr = (BX + AL) & 0xffff;
|
||||
access(4, 8);
|
||||
|
||||
@@ -2449,11 +2449,6 @@ cpu_CPUID(void)
|
||||
EAX = CPUID;
|
||||
EBX = ECX = 0;
|
||||
EDX = CPUID_FPU | CPUID_DE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_CMOV | CPUID_MMX;
|
||||
/*
|
||||
Return anything non-zero in bits 32-63 of the BIOS signature MSR
|
||||
to indicate there has been an update.
|
||||
*/
|
||||
msr.bbl_cr_dx[3] = 0xffffffff00000000ULL;
|
||||
} else
|
||||
EAX = EBX = ECX = EDX = 0;
|
||||
break;
|
||||
@@ -2468,6 +2463,11 @@ cpu_CPUID(void)
|
||||
EAX = CPUID;
|
||||
EBX = ECX = 0;
|
||||
EDX = CPUID_FPU | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CMPXCHG8B | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_SEP | CPUID_CMOV;
|
||||
/*
|
||||
Return anything non-zero in bits 32-63 of the BIOS signature MSR
|
||||
to indicate there has been an update.
|
||||
*/
|
||||
msr.bbl_cr_dx[3] = 0xffffffff00000000ULL;
|
||||
} else if (EAX == 2) {
|
||||
EAX = 0x03020101; /* Instruction TLB: 4 KB pages, 4-way set associative, 32 entries
|
||||
Instruction TLB: 4 MB pages, fully associative, 2 entries
|
||||
@@ -2650,6 +2650,12 @@ cpu_ven_reset(void)
|
||||
case CPU_PENTIUM2:
|
||||
case CPU_PENTIUM2D:
|
||||
msr.mtrr_cap = 0x00000508ULL;
|
||||
|
||||
/* 4 GB cacheable space on Deschutes 651h and later (including the 1632h
|
||||
Overdrive) according to the Pentium II Processor Specification Update.
|
||||
Covington 651h (no L2 cache) reports the same 512 MB value as Klamath. */
|
||||
if (CPUID >= (!strncmp(cpu_f->internal_name, "celeron", 7) ? 0x660 : 0x651))
|
||||
msr.bbl_cr_ctl3 |= 0x00300000;
|
||||
break;
|
||||
|
||||
case CPU_CYRIX3S:
|
||||
@@ -3296,7 +3302,6 @@ pentium_invalid_rdmsr:
|
||||
case 0x88 ... 0x8b:
|
||||
EAX = msr.bbl_cr_dx[ECX - 0x88] & 0xffffffff;
|
||||
EDX = msr.bbl_cr_dx[ECX - 0x88] >> 32;
|
||||
// EDX |= 0xffffffff;
|
||||
break;
|
||||
/* Unknown */
|
||||
case 0xae:
|
||||
@@ -4104,7 +4109,7 @@ pentium_invalid_wrmsr:
|
||||
break;
|
||||
/* BBL_CR_CTL3 - L2 Cache Control Register 3 */
|
||||
case 0x11e:
|
||||
msr.bbl_cr_ctl3 = EAX | ((uint64_t) EDX << 32);
|
||||
msr.bbl_cr_ctl3 = (msr.bbl_cr_ctl3 & 0x02f00000) | (EAX & ~0x02f00000) | ((uint64_t) EDX << 32);
|
||||
break;
|
||||
/* Unknown */
|
||||
case 0x131:
|
||||
@@ -4260,7 +4265,7 @@ cpu_write(uint16_t addr, uint8_t val, UNUSED(void *priv))
|
||||
cyrix_addr = val;
|
||||
else if (addr < 0xf1) switch (cyrix_addr) {
|
||||
default:
|
||||
if (cyrix_addr >= 0xc0)
|
||||
if ((cyrix_addr >= 0xc0) && (cyrix_addr != 0xff))
|
||||
fatal("Writing unimplemented Cyrix register %02X\n", cyrix_addr);
|
||||
break;
|
||||
|
||||
|
||||
@@ -335,7 +335,10 @@ typedef struct {
|
||||
uint8_t tag[8];
|
||||
|
||||
x86seg *ea_seg;
|
||||
uint32_t eaaddr;
|
||||
union {
|
||||
uint32_t eaaddr;
|
||||
uint16_t eaa16[2];
|
||||
};
|
||||
|
||||
int flags_op;
|
||||
uint32_t flags_res;
|
||||
@@ -413,6 +416,8 @@ typedef struct {
|
||||
uint16_t eflags;
|
||||
|
||||
uint32_t _smbase;
|
||||
|
||||
uint32_t x87_op;
|
||||
} cpu_state_t;
|
||||
|
||||
#define in_smm cpu_state._in_smm
|
||||
@@ -781,6 +786,8 @@ typedef struct {
|
||||
uint32_t smhr;
|
||||
} cyrix_t;
|
||||
|
||||
#define x87_op cpu_state.x87_op
|
||||
|
||||
extern uint32_t addr64;
|
||||
extern uint32_t addr64_2;
|
||||
extern uint32_t addr64a[8];
|
||||
|
||||
@@ -7793,7 +7793,7 @@ const cpu_family_t cpu_families[] = {
|
||||
{
|
||||
.package = CPU_PKG_SOCKET370,
|
||||
.manufacturer = "VIA",
|
||||
.name = "Cyrix III",
|
||||
.name = "Cyrix III (Samuel)",
|
||||
.internal_name = "c3_samuel",
|
||||
.cpus = (const CPU[]) {
|
||||
{ /* out of multiplier range */
|
||||
|
||||
@@ -272,6 +272,7 @@ reset_common(int hard)
|
||||
msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
|
||||
msw = 0;
|
||||
new_ne = 0;
|
||||
x87_op = 0;
|
||||
|
||||
ccr0 = ccr1 = ccr2 = ccr3 = ccr4 = ccr5 = ccr6 = ccr7 = 0;
|
||||
ccr4 = 0x85;
|
||||
@@ -325,7 +326,6 @@ reset_common(int hard)
|
||||
resetreadlookup();
|
||||
makemod1table();
|
||||
cpu_set_edx();
|
||||
mmu_perm = 4;
|
||||
}
|
||||
x86seg_reset();
|
||||
#ifdef USE_DYNAREC
|
||||
|
||||
@@ -121,6 +121,7 @@ opPUSHF(UNUSED(uint32_t fetchdat))
|
||||
temp = (cpu_state.flags & ~I_FLAG) | 0x3000;
|
||||
if (cpu_state.eflags & VIF_FLAG)
|
||||
temp |= I_FLAG;
|
||||
temp = (temp & 0x7fd5) | 2;
|
||||
PUSH_W(temp);
|
||||
} else {
|
||||
x86gpf(NULL, 0);
|
||||
@@ -128,6 +129,7 @@ opPUSHF(UNUSED(uint32_t fetchdat))
|
||||
}
|
||||
} else {
|
||||
flags_rebuild();
|
||||
cpu_state.flags = (cpu_state.flags & 0x7fd5) | 2;
|
||||
PUSH_W(cpu_state.flags);
|
||||
}
|
||||
CLOCK_CYCLES(4);
|
||||
@@ -149,6 +151,7 @@ opPUSHFD(UNUSED(uint32_t fetchdat))
|
||||
else
|
||||
tempw = cpu_state.eflags & 4;
|
||||
flags_rebuild();
|
||||
cpu_state.flags = (cpu_state.flags & 0x7fd5) | 2;
|
||||
PUSH_L(cpu_state.flags | (tempw << 16));
|
||||
CLOCK_CYCLES(4);
|
||||
PREFETCH_RUN(4, 1, -1, 0, 0, 0, 1, 0);
|
||||
@@ -160,23 +163,11 @@ opPOPF_186(UNUSED(uint32_t fetchdat))
|
||||
{
|
||||
uint16_t tempw;
|
||||
|
||||
if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) {
|
||||
x86gpf(NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
tempw = POP_W();
|
||||
if (cpu_state.abrt)
|
||||
return 1;
|
||||
|
||||
if (!(msw & 1))
|
||||
cpu_state.flags = (cpu_state.flags & 0x7000) | (tempw & 0x0fd5) | 2;
|
||||
else if (!(CPL))
|
||||
cpu_state.flags = (tempw & 0x7fd5) | 2;
|
||||
else if (IOPLp)
|
||||
cpu_state.flags = (cpu_state.flags & 0x3000) | (tempw & 0x4fd5) | 2;
|
||||
else
|
||||
cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2;
|
||||
cpu_state.flags = (cpu_state.flags & 0x7000) | (tempw & 0x0fd5) | 2;
|
||||
flags_extract();
|
||||
#ifdef USE_DEBUG_REGS_486
|
||||
rf_flag_no_clear = 1;
|
||||
|
||||
@@ -121,6 +121,7 @@ opPUSHF(UNUSED(uint32_t fetchdat))
|
||||
temp = (cpu_state.flags & ~I_FLAG) | 0x3000;
|
||||
if (cpu_state.eflags & VIF_FLAG)
|
||||
temp |= I_FLAG;
|
||||
temp = (temp & 0x7fd5) | 2;
|
||||
PUSH_W(temp);
|
||||
} else {
|
||||
x86gpf(NULL, 0);
|
||||
@@ -128,6 +129,7 @@ opPUSHF(UNUSED(uint32_t fetchdat))
|
||||
}
|
||||
} else {
|
||||
flags_rebuild();
|
||||
cpu_state.flags = (cpu_state.flags & 0x7fd5) | 2;
|
||||
PUSH_W(cpu_state.flags);
|
||||
}
|
||||
CLOCK_CYCLES(4);
|
||||
@@ -149,6 +151,7 @@ opPUSHFD(UNUSED(uint32_t fetchdat))
|
||||
else
|
||||
tempw = cpu_state.eflags & 4;
|
||||
flags_rebuild();
|
||||
cpu_state.flags = (cpu_state.flags & 0x7fd5) | 2;
|
||||
PUSH_L(cpu_state.flags | (tempw << 16));
|
||||
CLOCK_CYCLES(4);
|
||||
PREFETCH_RUN(4, 1, -1, 0, 0, 0, 1, 0);
|
||||
@@ -160,23 +163,11 @@ opPOPF_186(UNUSED(uint32_t fetchdat))
|
||||
{
|
||||
uint16_t tempw;
|
||||
|
||||
if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3)) {
|
||||
x86gpf(NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
tempw = POP_W();
|
||||
if (cpu_state.abrt)
|
||||
return 1;
|
||||
|
||||
if (!(msw & 1))
|
||||
cpu_state.flags = (cpu_state.flags & 0x7000) | (tempw & 0x0fd5) | 2;
|
||||
else if (!(CPL))
|
||||
cpu_state.flags = (tempw & 0x7fd5) | 2;
|
||||
else if (IOPLp)
|
||||
cpu_state.flags = (cpu_state.flags & 0x3000) | (tempw & 0x4fd5) | 2;
|
||||
else
|
||||
cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2;
|
||||
cpu_state.flags = (cpu_state.flags & 0x7000) | (tempw & 0x0fd5) | 2;
|
||||
flags_extract();
|
||||
rf_flag_no_clear = 1;
|
||||
|
||||
|
||||
@@ -4,88 +4,104 @@
|
||||
static int
|
||||
opESCAPE_d8_a16(uint32_t fetchdat)
|
||||
{
|
||||
x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
return x86_opcodes_d8_a16[(fetchdat >> 3) & 0x1f](fetchdat);
|
||||
}
|
||||
static int
|
||||
opESCAPE_d8_a32(uint32_t fetchdat)
|
||||
{
|
||||
x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
return x86_opcodes_d8_a32[(fetchdat >> 3) & 0x1f](fetchdat);
|
||||
}
|
||||
|
||||
static int
|
||||
opESCAPE_d9_a16(uint32_t fetchdat)
|
||||
{
|
||||
x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
return x86_opcodes_d9_a16[fetchdat & 0xff](fetchdat);
|
||||
}
|
||||
static int
|
||||
opESCAPE_d9_a32(uint32_t fetchdat)
|
||||
{
|
||||
x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
return x86_opcodes_d9_a32[fetchdat & 0xff](fetchdat);
|
||||
}
|
||||
|
||||
static int
|
||||
opESCAPE_da_a16(uint32_t fetchdat)
|
||||
{
|
||||
x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
return x86_opcodes_da_a16[fetchdat & 0xff](fetchdat);
|
||||
}
|
||||
static int
|
||||
opESCAPE_da_a32(uint32_t fetchdat)
|
||||
{
|
||||
x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
return x86_opcodes_da_a32[fetchdat & 0xff](fetchdat);
|
||||
}
|
||||
|
||||
static int
|
||||
opESCAPE_db_a16(uint32_t fetchdat)
|
||||
{
|
||||
x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
return x86_opcodes_db_a16[fetchdat & 0xff](fetchdat);
|
||||
}
|
||||
static int
|
||||
opESCAPE_db_a32(uint32_t fetchdat)
|
||||
{
|
||||
x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
return x86_opcodes_db_a32[fetchdat & 0xff](fetchdat);
|
||||
}
|
||||
|
||||
static int
|
||||
opESCAPE_dc_a16(uint32_t fetchdat)
|
||||
{
|
||||
x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
return x86_opcodes_dc_a16[(fetchdat >> 3) & 0x1f](fetchdat);
|
||||
}
|
||||
static int
|
||||
opESCAPE_dc_a32(uint32_t fetchdat)
|
||||
{
|
||||
x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
return x86_opcodes_dc_a32[(fetchdat >> 3) & 0x1f](fetchdat);
|
||||
}
|
||||
|
||||
static int
|
||||
opESCAPE_dd_a16(uint32_t fetchdat)
|
||||
{
|
||||
x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
return x86_opcodes_dd_a16[fetchdat & 0xff](fetchdat);
|
||||
}
|
||||
static int
|
||||
opESCAPE_dd_a32(uint32_t fetchdat)
|
||||
{
|
||||
x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
return x86_opcodes_dd_a32[fetchdat & 0xff](fetchdat);
|
||||
}
|
||||
|
||||
static int
|
||||
opESCAPE_de_a16(uint32_t fetchdat)
|
||||
{
|
||||
x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
return x86_opcodes_de_a16[fetchdat & 0xff](fetchdat);
|
||||
}
|
||||
static int
|
||||
opESCAPE_de_a32(uint32_t fetchdat)
|
||||
{
|
||||
x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
return x86_opcodes_de_a32[fetchdat & 0xff](fetchdat);
|
||||
}
|
||||
|
||||
static int
|
||||
opESCAPE_df_a16(uint32_t fetchdat)
|
||||
{
|
||||
x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
return x86_opcodes_df_a16[fetchdat & 0xff](fetchdat);
|
||||
}
|
||||
static int
|
||||
opESCAPE_df_a32(uint32_t fetchdat)
|
||||
{
|
||||
x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
return x86_opcodes_df_a32[fetchdat & 0xff](fetchdat);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,88 +4,104 @@
|
||||
static int
|
||||
opESCAPE_d8_a16(uint32_t fetchdat)
|
||||
{
|
||||
x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
return x86_2386_opcodes_d8_a16[(fetchdat >> 3) & 0x1f](fetchdat);
|
||||
}
|
||||
static int
|
||||
opESCAPE_d8_a32(uint32_t fetchdat)
|
||||
{
|
||||
x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
return x86_2386_opcodes_d8_a32[(fetchdat >> 3) & 0x1f](fetchdat);
|
||||
}
|
||||
|
||||
static int
|
||||
opESCAPE_d9_a16(uint32_t fetchdat)
|
||||
{
|
||||
x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
return x86_2386_opcodes_d9_a16[fetchdat & 0xff](fetchdat);
|
||||
}
|
||||
static int
|
||||
opESCAPE_d9_a32(uint32_t fetchdat)
|
||||
{
|
||||
x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
return x86_2386_opcodes_d9_a32[fetchdat & 0xff](fetchdat);
|
||||
}
|
||||
|
||||
static int
|
||||
opESCAPE_da_a16(uint32_t fetchdat)
|
||||
{
|
||||
x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
return x86_2386_opcodes_da_a16[fetchdat & 0xff](fetchdat);
|
||||
}
|
||||
static int
|
||||
opESCAPE_da_a32(uint32_t fetchdat)
|
||||
{
|
||||
x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
return x86_2386_opcodes_da_a32[fetchdat & 0xff](fetchdat);
|
||||
}
|
||||
|
||||
static int
|
||||
opESCAPE_db_a16(uint32_t fetchdat)
|
||||
{
|
||||
x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
return x86_2386_opcodes_db_a16[fetchdat & 0xff](fetchdat);
|
||||
}
|
||||
static int
|
||||
opESCAPE_db_a32(uint32_t fetchdat)
|
||||
{
|
||||
x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
return x86_2386_opcodes_db_a32[fetchdat & 0xff](fetchdat);
|
||||
}
|
||||
|
||||
static int
|
||||
opESCAPE_dc_a16(uint32_t fetchdat)
|
||||
{
|
||||
x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
return x86_2386_opcodes_dc_a16[(fetchdat >> 3) & 0x1f](fetchdat);
|
||||
}
|
||||
static int
|
||||
opESCAPE_dc_a32(uint32_t fetchdat)
|
||||
{
|
||||
x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
return x86_2386_opcodes_dc_a32[(fetchdat >> 3) & 0x1f](fetchdat);
|
||||
}
|
||||
|
||||
static int
|
||||
opESCAPE_dd_a16(uint32_t fetchdat)
|
||||
{
|
||||
x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
return x86_2386_opcodes_dd_a16[fetchdat & 0xff](fetchdat);
|
||||
}
|
||||
static int
|
||||
opESCAPE_dd_a32(uint32_t fetchdat)
|
||||
{
|
||||
x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
return x86_2386_opcodes_dd_a32[fetchdat & 0xff](fetchdat);
|
||||
}
|
||||
|
||||
static int
|
||||
opESCAPE_de_a16(uint32_t fetchdat)
|
||||
{
|
||||
x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
return x86_2386_opcodes_de_a16[fetchdat & 0xff](fetchdat);
|
||||
}
|
||||
static int
|
||||
opESCAPE_de_a32(uint32_t fetchdat)
|
||||
{
|
||||
x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
return x86_2386_opcodes_de_a32[fetchdat & 0xff](fetchdat);
|
||||
}
|
||||
|
||||
static int
|
||||
opESCAPE_df_a16(uint32_t fetchdat)
|
||||
{
|
||||
x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
return x86_2386_opcodes_df_a16[fetchdat & 0xff](fetchdat);
|
||||
}
|
||||
static int
|
||||
opESCAPE_df_a32(uint32_t fetchdat)
|
||||
{
|
||||
x87_op = ((opcode & 0x07) << 8) | (fetchdat & 0xff);
|
||||
return x86_2386_opcodes_df_a32[fetchdat & 0xff](fetchdat);
|
||||
}
|
||||
|
||||
|
||||
@@ -46,8 +46,6 @@ sf_fx_save_stor_common(uint32_t fetchdat, int bits)
|
||||
if (CPUID < 0x650)
|
||||
return ILLEGAL(fetchdat);
|
||||
|
||||
FP_ENTER();
|
||||
|
||||
if (bits == 32) {
|
||||
fetch_ea_32(fetchdat);
|
||||
} else {
|
||||
@@ -82,12 +80,18 @@ sf_fx_save_stor_common(uint32_t fetchdat, int bits)
|
||||
/* The lower 11 bits contain the FPU opcode, upper 5 bits are reserved */
|
||||
fpu_state.foo = readmemw(easeg, cpu_state.eaaddr + 6) & 0x7FF;
|
||||
|
||||
fpu_state.fip = readmeml(easeg, cpu_state.eaaddr + 8);
|
||||
if (bits == 32)
|
||||
fpu_state.fip = readmeml(easeg, cpu_state.eaaddr + 8);
|
||||
else
|
||||
fpu_state.fip = readmemw(easeg, cpu_state.eaaddr + 8);
|
||||
fpu_state.fcs = readmemw(easeg, cpu_state.eaaddr + 12);
|
||||
|
||||
tag_byte = readmemb(easeg, cpu_state.eaaddr + 4);
|
||||
|
||||
fpu_state.fdp = readmeml(easeg, cpu_state.eaaddr + 16);
|
||||
if (bits == 32)
|
||||
fpu_state.fdp = readmeml(easeg, cpu_state.eaaddr + 16);
|
||||
else
|
||||
fpu_state.fdp = readmemw(easeg, cpu_state.eaaddr + 16);
|
||||
fpu_state.fds = readmemw(easeg, cpu_state.eaaddr + 20);
|
||||
|
||||
/* load i387 register file */
|
||||
@@ -110,7 +114,6 @@ sf_fx_save_stor_common(uint32_t fetchdat, int bits)
|
||||
fpu_state.swd &= ~(FPU_SW_Summary | FPU_SW_Backward);
|
||||
}
|
||||
|
||||
// CLOCK_CYCLES((cr0 & 1) ? 34 : 44);
|
||||
CLOCK_CYCLES(1);
|
||||
} else {
|
||||
/* FXSAVE */
|
||||
@@ -132,7 +135,10 @@ sf_fx_save_stor_common(uint32_t fetchdat, int bits)
|
||||
* x87 CS FPU IP Selector
|
||||
* + 16 bit, in 16/32 bit mode only
|
||||
*/
|
||||
writememl(easeg, cpu_state.eaaddr + 8, fpu_state.fip);
|
||||
if (bits == 32)
|
||||
writememl(easeg, cpu_state.eaaddr + 8, fpu_state.fip);
|
||||
else
|
||||
writememl(easeg, cpu_state.eaaddr + 8, fpu_state.fip & 0xffff);
|
||||
writememl(easeg, cpu_state.eaaddr + 12, fpu_state.fcs);
|
||||
|
||||
/*
|
||||
@@ -145,7 +151,10 @@ sf_fx_save_stor_common(uint32_t fetchdat, int bits)
|
||||
* x87 DS FPU Instruction Operand (Data) Pointer Selector
|
||||
* + 16 bit, in 16/32 bit mode only
|
||||
*/
|
||||
writememl(easeg, cpu_state.eaaddr + 16, fpu_state.fdp);
|
||||
if (bits == 32)
|
||||
writememl(easeg, cpu_state.eaaddr + 16, fpu_state.fdp);
|
||||
else
|
||||
writememl(easeg, cpu_state.eaaddr + 16, fpu_state.fdp & 0xffff);
|
||||
writememl(easeg, cpu_state.eaaddr + 20, fpu_state.fds);
|
||||
|
||||
/* store i387 register file */
|
||||
@@ -256,8 +265,6 @@ fx_save_stor_common(uint32_t fetchdat, int bits)
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
|
||||
FP_ENTER();
|
||||
|
||||
old_eaaddr = cpu_state.eaaddr;
|
||||
|
||||
if (fxinst == 1) {
|
||||
@@ -269,13 +276,19 @@ fx_save_stor_common(uint32_t fetchdat, int bits)
|
||||
cpu_state.TOP = (fpus >> 11) & 7;
|
||||
cpu_state.npxs &= fpus & ~0x3800;
|
||||
|
||||
x87_pc_off = readmeml(easeg, cpu_state.eaaddr + 8);
|
||||
if (bits == 32)
|
||||
x87_pc_off = readmeml(easeg, cpu_state.eaaddr + 8);
|
||||
else
|
||||
x87_pc_off = readmemw(easeg, cpu_state.eaaddr + 8);
|
||||
x87_pc_seg = readmemw(easeg, cpu_state.eaaddr + 12);
|
||||
|
||||
ftwb = readmemb(easeg, cpu_state.eaaddr + 4);
|
||||
x87_op = readmemw(easeg, cpu_state.eaaddr + 6) & 0x07ff;
|
||||
|
||||
x87_op_off = readmeml(easeg, cpu_state.eaaddr + 16);
|
||||
x87_op_off |= (readmemw(easeg, cpu_state.eaaddr + 6) >> 12) << 16;
|
||||
if (bits == 32)
|
||||
x87_op_off = readmeml(easeg, cpu_state.eaaddr + 16);
|
||||
else
|
||||
x87_op_off = readmemw(easeg, cpu_state.eaaddr +16);
|
||||
x87_op_seg = readmemw(easeg, cpu_state.eaaddr + 20);
|
||||
|
||||
for (i = 0; i <= 7; i++) {
|
||||
@@ -320,7 +333,6 @@ fx_save_stor_common(uint32_t fetchdat, int bits)
|
||||
}
|
||||
}
|
||||
|
||||
// CLOCK_CYCLES((cr0 & 1) ? 34 : 44);
|
||||
CLOCK_CYCLES(1);
|
||||
} else {
|
||||
/* FXSAVE */
|
||||
@@ -345,11 +357,17 @@ fx_save_stor_common(uint32_t fetchdat, int bits)
|
||||
writememw(easeg, cpu_state.eaaddr + 2, cpu_state.npxs);
|
||||
writememb(easeg, cpu_state.eaaddr + 4, ftwb);
|
||||
|
||||
writememw(easeg, cpu_state.eaaddr + 6, (x87_op_off >> 16) << 12);
|
||||
writememl(easeg, cpu_state.eaaddr + 8, x87_pc_off);
|
||||
writememw(easeg, cpu_state.eaaddr + 6, x87_op);
|
||||
if (bits == 32)
|
||||
writememl(easeg, cpu_state.eaaddr + 8, x87_pc_off);
|
||||
else
|
||||
writememl(easeg, cpu_state.eaaddr + 8, x87_pc_off & 0xffff);
|
||||
writememw(easeg, cpu_state.eaaddr + 12, x87_pc_seg);
|
||||
|
||||
writememl(easeg, cpu_state.eaaddr + 16, x87_op_off);
|
||||
if (bits == 32)
|
||||
writememl(easeg, cpu_state.eaaddr + 16, x87_op_off);
|
||||
else
|
||||
writememl(easeg, cpu_state.eaaddr + 16, x87_op_off & 0xffff);
|
||||
writememw(easeg, cpu_state.eaaddr + 20, x87_op_seg);
|
||||
|
||||
if (cpu_state.ismmx) {
|
||||
|
||||
@@ -753,7 +753,7 @@ opLOCK(uint32_t fetchdat)
|
||||
return 0;
|
||||
cpu_state.pc++;
|
||||
|
||||
ILLEGAL_ON((fetchdat & 0xff) == 0x90);
|
||||
ILLEGAL_ON(((fetchdat & 0xff) == 0x90) || ((fetchdat & 0xff) == 0xec));
|
||||
|
||||
CLOCK_CYCLES(4);
|
||||
PREFETCH_PREFIX();
|
||||
|
||||
@@ -22,12 +22,12 @@
|
||||
}
|
||||
|
||||
#define MMX_ENTER() \
|
||||
if (!cpu_has_feature(CPU_FEATURE_MMX)) { \
|
||||
if (!cpu_has_feature(CPU_FEATURE_MMX) || (cr0 & 0x4)) { \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
x86illegal(); \
|
||||
return 1; \
|
||||
} \
|
||||
if (cr0 & 0xc) { \
|
||||
if (cr0 & 0x8) { \
|
||||
x86_int(7); \
|
||||
return 1; \
|
||||
} \
|
||||
|
||||
@@ -201,8 +201,6 @@ opMOV_CRx_r_a16(uint32_t fetchdat)
|
||||
cr0 = cpu_state.regs[cpu_rm].l;
|
||||
if (cpu_16bitbus)
|
||||
cr0 |= 0x10;
|
||||
if (!(cr0 & 0x80000000))
|
||||
mmu_perm = 4;
|
||||
if (hascache && !(cr0 & (1 << 30)))
|
||||
cpu_cache_int_enabled = 1;
|
||||
else
|
||||
@@ -267,8 +265,6 @@ opMOV_CRx_r_a32(uint32_t fetchdat)
|
||||
cr0 = cpu_state.regs[cpu_rm].l;
|
||||
if (cpu_16bitbus)
|
||||
cr0 |= 0x10;
|
||||
if (!(cr0 & 0x80000000))
|
||||
mmu_perm = 4;
|
||||
if (hascache && !(cr0 & (1 << 30)))
|
||||
cpu_cache_int_enabled = 1;
|
||||
else
|
||||
|
||||
@@ -193,8 +193,6 @@ opMOV_CRx_r_a16(uint32_t fetchdat)
|
||||
cr0 = cpu_state.regs[cpu_rm].l;
|
||||
if (cpu_16bitbus)
|
||||
cr0 |= 0x10;
|
||||
if (!(cr0 & 0x80000000))
|
||||
mmu_perm = 4;
|
||||
if (hascache && !(cr0 & (1 << 30)))
|
||||
cpu_cache_int_enabled = 1;
|
||||
else
|
||||
@@ -255,8 +253,6 @@ opMOV_CRx_r_a32(uint32_t fetchdat)
|
||||
cr0 = cpu_state.regs[cpu_rm].l;
|
||||
if (cpu_16bitbus)
|
||||
cr0 |= 0x10;
|
||||
if (!(cr0 & 0x80000000))
|
||||
mmu_perm = 4;
|
||||
if (hascache && !(cr0 & (1 << 30)))
|
||||
cpu_cache_int_enabled = 1;
|
||||
else
|
||||
|
||||
@@ -272,9 +272,13 @@ opLDS_w_a16(uint32_t fetchdat)
|
||||
fetch_ea_16(fetchdat);
|
||||
ILLEGAL_ON(cpu_mod == 3);
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3);
|
||||
addr = readmemw(easeg, cpu_state.eaaddr);
|
||||
seg = readmemw(easeg, cpu_state.eaaddr + 2);
|
||||
CHECK_READ(cpu_state.ea_seg, cpu_state.eaa16[0], ((cpu_state.eaa16[0] + 1) & 0xffff));
|
||||
addr = readmemw(easeg, cpu_state.eaa16[0]);
|
||||
if (cpu_state.abrt)
|
||||
return 1;
|
||||
cpu_state.eaa16[0] += 2;
|
||||
CHECK_READ(cpu_state.ea_seg, cpu_state.eaa16[0], ((cpu_state.eaa16[0] + 1) & 0xffff));
|
||||
seg = readmemw(easeg, cpu_state.eaa16[0]);
|
||||
if (cpu_state.abrt)
|
||||
return 1;
|
||||
op_loadseg(seg, &cpu_state.seg_ds);
|
||||
@@ -318,9 +322,13 @@ opLDS_l_a16(uint32_t fetchdat)
|
||||
fetch_ea_16(fetchdat);
|
||||
ILLEGAL_ON(cpu_mod == 3);
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 5);
|
||||
addr = readmeml(easeg, cpu_state.eaaddr);
|
||||
seg = readmemw(easeg, cpu_state.eaaddr + 4);
|
||||
CHECK_READ(cpu_state.ea_seg, cpu_state.eaa16[0], ((cpu_state.eaa16[0] + 3) & 0xffff));
|
||||
addr = readmeml(easeg, cpu_state.eaa16[0]);
|
||||
if (cpu_state.abrt)
|
||||
return 1;
|
||||
cpu_state.eaa16[0] += 4;
|
||||
CHECK_READ(cpu_state.ea_seg, cpu_state.eaa16[0], ((cpu_state.eaa16[0] + 1) & 0xffff));
|
||||
seg = readmemw(easeg, cpu_state.eaa16[0]);
|
||||
if (cpu_state.abrt)
|
||||
return 1;
|
||||
op_loadseg(seg, &cpu_state.seg_ds);
|
||||
@@ -365,9 +373,13 @@ opLSS_w_a16(uint32_t fetchdat)
|
||||
fetch_ea_16(fetchdat);
|
||||
ILLEGAL_ON(cpu_mod == 3);
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3);
|
||||
addr = readmemw(easeg, cpu_state.eaaddr);
|
||||
seg = readmemw(easeg, cpu_state.eaaddr + 2);
|
||||
CHECK_READ(cpu_state.ea_seg, cpu_state.eaa16[0], ((cpu_state.eaa16[0] + 1) & 0xffff));
|
||||
addr = readmemw(easeg, cpu_state.eaa16[0]);
|
||||
if (cpu_state.abrt)
|
||||
return 1;
|
||||
cpu_state.eaa16[0] += 2;
|
||||
CHECK_READ(cpu_state.ea_seg, cpu_state.eaa16[0], ((cpu_state.eaa16[0] + 1) & 0xffff));
|
||||
seg = readmemw(easeg, cpu_state.eaa16[0]);
|
||||
if (cpu_state.abrt)
|
||||
return 1;
|
||||
op_loadseg(seg, &cpu_state.seg_ss);
|
||||
@@ -411,9 +423,13 @@ opLSS_l_a16(uint32_t fetchdat)
|
||||
fetch_ea_16(fetchdat);
|
||||
ILLEGAL_ON(cpu_mod == 3);
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 5);
|
||||
addr = readmeml(easeg, cpu_state.eaaddr);
|
||||
seg = readmemw(easeg, cpu_state.eaaddr + 4);
|
||||
CHECK_READ(cpu_state.ea_seg, cpu_state.eaa16[0], ((cpu_state.eaa16[0] + 3) & 0xffff));
|
||||
addr = readmeml(easeg, cpu_state.eaa16[0]);
|
||||
if (cpu_state.abrt)
|
||||
return 1;
|
||||
cpu_state.eaa16[0] += 4;
|
||||
CHECK_READ(cpu_state.ea_seg, cpu_state.eaa16[0], ((cpu_state.eaa16[0] + 1) & 0xffff));
|
||||
seg = readmemw(easeg, cpu_state.eaa16[0]);
|
||||
if (cpu_state.abrt)
|
||||
return 1;
|
||||
op_loadseg(seg, &cpu_state.seg_ss);
|
||||
@@ -457,9 +473,13 @@ opLSS_l_a32(uint32_t fetchdat)
|
||||
fetch_ea_16(fetchdat); \
|
||||
SEG_CHECK_READ(cpu_state.ea_seg); \
|
||||
ILLEGAL_ON(cpu_mod == 3); \
|
||||
CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); \
|
||||
addr = readmemw(easeg, cpu_state.eaaddr); \
|
||||
seg = readmemw(easeg, cpu_state.eaaddr + 2); \
|
||||
CHECK_READ(cpu_state.ea_seg, cpu_state.eaa16[0], ((cpu_state.eaa16[0] + 1) & 0xffff)); \
|
||||
addr = readmemw(easeg, cpu_state.eaa16[0]); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
cpu_state.eaa16[0] += 2; \
|
||||
CHECK_READ(cpu_state.ea_seg, cpu_state.eaa16[0], ((cpu_state.eaa16[0] + 1) & 0xffff)); \
|
||||
seg = readmemw(easeg, cpu_state.eaa16[0]); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
op_loadseg(seg, &sel); \
|
||||
@@ -502,9 +522,13 @@ opLSS_l_a32(uint32_t fetchdat)
|
||||
fetch_ea_16(fetchdat); \
|
||||
SEG_CHECK_READ(cpu_state.ea_seg); \
|
||||
ILLEGAL_ON(cpu_mod == 3); \
|
||||
CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 5); \
|
||||
addr = readmeml(easeg, cpu_state.eaaddr); \
|
||||
seg = readmemw(easeg, cpu_state.eaaddr + 4); \
|
||||
CHECK_READ(cpu_state.ea_seg, cpu_state.eaa16[0], ((cpu_state.eaa16[0] + 3) & 0xffff)); \
|
||||
addr = readmeml(easeg, cpu_state.eaa16[0]); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
cpu_state.eaa16[0] += 4; \
|
||||
CHECK_READ(cpu_state.ea_seg, cpu_state.eaa16[0], ((cpu_state.eaa16[0] + 1) & 0xffff)); \
|
||||
seg = readmemw(easeg, cpu_state.eaa16[0]); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
op_loadseg(seg, &sel); \
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
op_loadcs(readmemw(ss, ESP + 2)); \
|
||||
} else { \
|
||||
cpu_state.pc = readmemw(ss, SP); \
|
||||
op_loadcs(readmemw(ss, SP + 2)); \
|
||||
op_loadcs(readmemw(ss, (SP + 2) & 0xffff)); \
|
||||
} \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
op_loadcs(readmemw(ss, ESP + 2)); \
|
||||
} else { \
|
||||
cpu_state.pc = readmemw(ss, SP); \
|
||||
op_loadcs(readmemw(ss, SP + 2)); \
|
||||
op_loadcs(readmemw(ss, (SP + 2) & 0xffff)); \
|
||||
} \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
|
||||
78
src/device.c
78
src/device.c
@@ -390,42 +390,18 @@ device_get_priv(const device_t *dev)
|
||||
int
|
||||
device_available(const device_t *dev)
|
||||
{
|
||||
if (dev != NULL) {
|
||||
const device_config_t *config = dev->config;
|
||||
if (config != NULL) {
|
||||
while (config->type != CONFIG_END) {
|
||||
if (config->type == CONFIG_BIOS) {
|
||||
int roms_present = 0;
|
||||
const device_config_bios_t *bios = (const device_config_bios_t *) config->bios;
|
||||
|
||||
/* Go through the ROM's in the device configuration. */
|
||||
while ((bios != NULL) &&
|
||||
(bios->name != NULL) &&
|
||||
(bios->internal_name != NULL) &&
|
||||
(bios->files_no != 0)) {
|
||||
int i = 0;
|
||||
for (uint8_t bf = 0; bf < bios->files_no; bf++)
|
||||
i += !!rom_present(bios->files[bf]);
|
||||
if (i == bios->files_no)
|
||||
roms_present++;
|
||||
bios++;
|
||||
}
|
||||
|
||||
return (roms_present ? -1 : 0);
|
||||
}
|
||||
config++;
|
||||
}
|
||||
}
|
||||
int ret = machine_device_available(dev);
|
||||
|
||||
if (ret == 0) {
|
||||
/* No CONFIG_BIOS field present, use the classic available(). */
|
||||
if (dev->available != NULL)
|
||||
return (dev->available());
|
||||
ret = (dev->available());
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
ret = (dev != NULL);
|
||||
} else
|
||||
ret = (ret == -1);
|
||||
|
||||
/* A NULL device is never available. */
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
@@ -921,8 +897,14 @@ device_is_valid(const device_t *device, int mch)
|
||||
{
|
||||
int ret = 1;
|
||||
|
||||
if ((device != NULL) && ((device->flags & DEVICE_BUS) != 0))
|
||||
ret = machine_has_bus(mch, device->flags & DEVICE_BUS);
|
||||
if ((device != NULL) && ((device->flags & DEVICE_BUS) != 0)) {
|
||||
/* Hide PCI devices on machines with only an internal PCI bus. */
|
||||
if ((device->flags & DEVICE_PCI) &&
|
||||
machine_has_flags(mch, MACHINE_PCI_INTERNAL))
|
||||
ret = 0;
|
||||
else
|
||||
ret = machine_has_bus(mch, device->flags & DEVICE_BUS);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -969,6 +951,36 @@ machine_get_config_string(char *str)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
machine_device_available(const device_t *dev)
|
||||
{
|
||||
if (dev != NULL) {
|
||||
const device_config_t *config = dev->config;
|
||||
if ((config != NULL) && (config->type == CONFIG_BIOS)) {
|
||||
int roms_present = 0;
|
||||
const device_config_bios_t *bios = (const device_config_bios_t *) config->bios;
|
||||
|
||||
/* Go through the ROM's in the device configuration. */
|
||||
while ((bios != NULL) &&
|
||||
(bios->name != NULL) &&
|
||||
(bios->internal_name != NULL) &&
|
||||
(bios->files_no != 0)) {
|
||||
int i = 0;
|
||||
for (uint8_t bf = 0; bf < bios->files_no; bf++)
|
||||
i += !!rom_present(bios->files[bf]);
|
||||
if (i == bios->files_no)
|
||||
roms_present++;
|
||||
bios++;
|
||||
}
|
||||
|
||||
return (roms_present ? -1 : -2);
|
||||
}
|
||||
}
|
||||
|
||||
/* NULL device or no CONFIG_BIOS field, return 0. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
const device_t *
|
||||
device_context_get_device(void)
|
||||
{
|
||||
|
||||
@@ -22,6 +22,7 @@ add_library(dev OBJECT
|
||||
cartridge.c
|
||||
cassette.c
|
||||
clock_ics9xxx.c
|
||||
dell_jumper.c
|
||||
hasp.c
|
||||
hwm.c
|
||||
hwm_gl518sm.c
|
||||
|
||||
@@ -84,7 +84,10 @@ static uint8_t bug_spcfg; /* serial port configuration */
|
||||
#define FIFO_LEN 256
|
||||
static uint8_t bug_buff[FIFO_LEN]; /* serial port data buffer */
|
||||
static uint8_t *bug_bptr;
|
||||
#define UISTR_LEN 24
|
||||
|
||||
static char LED_R[] = "<font color=\"#EE0000\">R</font>";
|
||||
static char LED_G[] = "<font color=\"#00CC00\">G</font>";
|
||||
#define UISTR_LEN (17 + 8 * sizeof(LED_G) + 8 * sizeof(LED_R))
|
||||
static char bug_str[UISTR_LEN]; /* UI output string */
|
||||
|
||||
extern void ui_sb_bugui(char *__str);
|
||||
@@ -112,16 +115,16 @@ static void
|
||||
bug_setui(void)
|
||||
{
|
||||
/* Format all current info in a string. */
|
||||
sprintf(bug_str, "%02X:%02X %c%c%c%c%c%c%c%c-%c%c%c%c%c%c%c%c",
|
||||
sprintf(bug_str, "<tt>%02X:%02X %s%s%s%s%s%s%s%s-%s%s%s%s%s%s%s%s</tt>",
|
||||
bug_seg2, bug_seg1,
|
||||
(bug_ledg & 0x80) ? 'G' : 'g', (bug_ledg & 0x40) ? 'G' : 'g',
|
||||
(bug_ledg & 0x20) ? 'G' : 'g', (bug_ledg & 0x10) ? 'G' : 'g',
|
||||
(bug_ledg & 0x08) ? 'G' : 'g', (bug_ledg & 0x04) ? 'G' : 'g',
|
||||
(bug_ledg & 0x02) ? 'G' : 'g', (bug_ledg & 0x01) ? 'G' : 'g',
|
||||
(bug_ledr & 0x80) ? 'R' : 'r', (bug_ledr & 0x40) ? 'R' : 'r',
|
||||
(bug_ledr & 0x20) ? 'R' : 'r', (bug_ledr & 0x10) ? 'R' : 'r',
|
||||
(bug_ledr & 0x08) ? 'R' : 'r', (bug_ledr & 0x04) ? 'R' : 'r',
|
||||
(bug_ledr & 0x02) ? 'R' : 'r', (bug_ledr & 0x01) ? 'R' : 'r');
|
||||
(bug_ledg & 0x80) ? LED_G : "g", (bug_ledg & 0x40) ? LED_G : "g",
|
||||
(bug_ledg & 0x20) ? LED_G : "g", (bug_ledg & 0x10) ? LED_G : "g",
|
||||
(bug_ledg & 0x08) ? LED_G : "g", (bug_ledg & 0x04) ? LED_G : "g",
|
||||
(bug_ledg & 0x02) ? LED_G : "g", (bug_ledg & 0x01) ? LED_G : "g",
|
||||
(bug_ledr & 0x80) ? LED_R : "r", (bug_ledr & 0x40) ? LED_R : "r",
|
||||
(bug_ledr & 0x20) ? LED_R : "r", (bug_ledr & 0x10) ? LED_R : "r",
|
||||
(bug_ledr & 0x08) ? LED_R : "r", (bug_ledr & 0x04) ? LED_R : "r",
|
||||
(bug_ledr & 0x02) ? LED_R : "r", (bug_ledr & 0x01) ? LED_R : "r");
|
||||
|
||||
/* Send formatted string to the UI. */
|
||||
ui_sb_bugui(bug_str);
|
||||
|
||||
175
src/device/dell_jumper.c
Normal file
175
src/device/dell_jumper.c
Normal file
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the Dell 486 and 586 Jumper Readout.
|
||||
*
|
||||
* Register 0x02:
|
||||
* - Bit 0: ATX power: 1 = off, 0 = on.
|
||||
*
|
||||
* Register 0x05:
|
||||
* - Appears to be: 0x02 = On-board audio enabled;
|
||||
* 0x07 = On-board audio disabled.
|
||||
*
|
||||
* Register 0x07:
|
||||
* - Bit 0: On-board NIC: 1 = present, 0 = absent;
|
||||
* - Bit 1: On-board audio: 1 = present, 0 = absent;
|
||||
* - Bits 4-2:
|
||||
* - 0, 0, 0 = GXL;
|
||||
* - 0, 0, 1 = GL+;
|
||||
* - 0, 1, 0 = GXMT;
|
||||
* - 0, 1, 1 = GMT+;
|
||||
* - 1, 0, 0 = GXM;
|
||||
* - 1, 0, 1 = GM+;
|
||||
* - 1, 1, 0 = WS;
|
||||
* - 1, 1, 1 = GWS+.
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2025 Miran Grca.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include <86box/86box.h>
|
||||
#include "cpu.h"
|
||||
#include <86box/timer.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/machine.h>
|
||||
#include <86box/sound.h>
|
||||
#include <86box/chipset.h>
|
||||
#include <86box/plat.h>
|
||||
#include <86box/plat_unused.h>
|
||||
|
||||
typedef struct dell_jumper_t {
|
||||
uint8_t index;
|
||||
uint8_t regs[256];
|
||||
} dell_jumper_t;
|
||||
|
||||
#ifdef ENABLE_DELL_JUMPER_LOG
|
||||
int dell_jumper_do_log = ENABLE_DELL_JUMPER_LOG;
|
||||
|
||||
static void
|
||||
dell_jumper_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (dell_jumper_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
# define dell_jumper_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
static void
|
||||
dell_jumper_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
dell_jumper_t *dev = (dell_jumper_t *) priv;
|
||||
|
||||
dell_jumper_log("Dell Jumper: Write %02x\n", val);
|
||||
|
||||
if (addr & 1) switch (dev->index) {
|
||||
default:
|
||||
dev->regs[dev->index] = val;
|
||||
break;
|
||||
case 0x02:
|
||||
dev->regs[dev->index] = val;
|
||||
if (val & 0x04)
|
||||
/* Soft power off. */
|
||||
plat_power_off();
|
||||
break;
|
||||
case 0x05:
|
||||
dev->regs[dev->index] = (dev->regs[dev->index] & 0x02) | (val & 0xfd);
|
||||
if (machine_snd != NULL) switch (val & 0x05) {
|
||||
default:
|
||||
case 0x05:
|
||||
sb_vibra16s_onboard_relocate_base(0x0000, machine_snd);
|
||||
break;
|
||||
case 0x00:
|
||||
sb_vibra16s_onboard_relocate_base(0x0220, machine_snd);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x07:
|
||||
break;
|
||||
} else
|
||||
dev->index = val;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
dell_jumper_read(uint16_t addr, void *priv)
|
||||
{
|
||||
const dell_jumper_t *dev = (dell_jumper_t *) priv;
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
dell_jumper_log("Dell Jumper: Read %02x\n", dev->jumper);
|
||||
|
||||
if (addr & 1)
|
||||
ret = dev->regs[dev->index];
|
||||
else
|
||||
ret = dev->index;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
dell_jumper_reset(void *priv)
|
||||
{
|
||||
dell_jumper_t *dev = (dell_jumper_t *) priv;
|
||||
|
||||
dev->index = 0x00;
|
||||
memset(dev->regs, 0x00, 256);
|
||||
|
||||
if (sound_card_current[0] == SOUND_INTERNAL)
|
||||
/* GXL, on-board audio present, on-board NIC absent. */
|
||||
dev->regs[0x07] = 0x02;
|
||||
else
|
||||
/* GXL, on-board audio absent, on-board NIC absent. */
|
||||
dev->regs[0x07] = 0x00;
|
||||
}
|
||||
|
||||
static void
|
||||
dell_jumper_close(void *priv)
|
||||
{
|
||||
dell_jumper_t *dev = (dell_jumper_t *) priv;
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
static void *
|
||||
dell_jumper_init(const device_t *info)
|
||||
{
|
||||
dell_jumper_t *dev = (dell_jumper_t *) calloc(1, sizeof(dell_jumper_t));
|
||||
|
||||
dell_jumper_reset(dev);
|
||||
|
||||
io_sethandler(0x00e8, 0x0002, dell_jumper_read, NULL, NULL, dell_jumper_write, NULL, NULL, dev);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
const device_t dell_jumper_device = {
|
||||
.name = "Dell Jumper Readout",
|
||||
.internal_name = "dell_jumper",
|
||||
.flags = 0,
|
||||
.local = 0,
|
||||
.init = dell_jumper_init,
|
||||
.close = dell_jumper_close,
|
||||
.reset = dell_jumper_reset,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
@@ -145,6 +145,11 @@ typedef struct atkbc_t {
|
||||
/* Internal FIFO for the purpose of commands with multi-byte output. */
|
||||
uint8_t key_ctrl_queue[64];
|
||||
|
||||
uint8_t handler_enable[2];
|
||||
|
||||
uint16_t base_addr[2];
|
||||
uint16_t irq[2];
|
||||
|
||||
uint32_t flags;
|
||||
|
||||
/* Main timers. */
|
||||
@@ -157,8 +162,13 @@ typedef struct atkbc_t {
|
||||
/* Local copies of the pointers to both ports for easier swapping (AMI '5' MegaKey). */
|
||||
kbc_at_port_t *ports[2];
|
||||
|
||||
uint8_t (*write60_ven)(void *priv, uint8_t val);
|
||||
uint8_t (*write64_ven)(void *priv, uint8_t val);
|
||||
struct {
|
||||
uint8_t (*read)(uint16_t port, void *priv);
|
||||
void (*write)(uint16_t port, uint8_t val, void *priv);
|
||||
} handlers[2];
|
||||
|
||||
uint8_t (*write_cmd_data_ven)(void *priv, uint8_t val);
|
||||
uint8_t (*write_cmd_ven)(void *priv, uint8_t val);
|
||||
} atkbc_t;
|
||||
|
||||
/* Keyboard controller ports. */
|
||||
@@ -167,8 +177,6 @@ kbc_at_port_t *kbc_at_ports[2] = { NULL, NULL };
|
||||
static uint8_t kbc_ami_revision = '8';
|
||||
static uint8_t kbc_award_revision = 0x42;
|
||||
|
||||
static uint8_t kbc_handler_set = 0;
|
||||
|
||||
static void (*kbc_at_do_poll)(atkbc_t *dev);
|
||||
|
||||
/* Non-translated to translated scan codes. */
|
||||
@@ -362,12 +370,19 @@ kbc_do_irq(atkbc_t *dev)
|
||||
if (dev->do_irq) {
|
||||
/* WARNING: On PS/2, all IRQ's are level-triggered, but the IBM PS/2 KBC firmware is explicitly
|
||||
written to pulse its P2 IRQ bits, so they should be kept as as edge-triggered here. */
|
||||
picint_common(1 << 1, 0, 0, NULL);
|
||||
picint_common(1 << 12, 0, 0, NULL);
|
||||
if (dev->channel >= 2)
|
||||
picint_common(1 << 12, 0, 1, NULL);
|
||||
else
|
||||
picint_common(1 << 1, 0, 1, NULL);
|
||||
if (dev->irq[0] != 0xffff)
|
||||
picint_common(1 << dev->irq[0], 0, 0, NULL);
|
||||
|
||||
if (dev->irq[1] != 0xffff)
|
||||
picint_common(1 << dev->irq[1], 0, 0, NULL);
|
||||
|
||||
if (dev->channel >= 2) {
|
||||
if (dev->irq[1] != 0xffff)
|
||||
picint_common(1 << dev->irq[1], 0, 1, NULL);
|
||||
} else {
|
||||
if (dev->irq[0] != 0xffff)
|
||||
picint_common(1 << dev->irq[0], 0, 1, NULL);
|
||||
}
|
||||
|
||||
dev->do_irq = 0;
|
||||
}
|
||||
@@ -404,7 +419,9 @@ kbc_send_to_ob(atkbc_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi)
|
||||
} else if (dev->mem[0x20] & 0x01)
|
||||
kbc_set_do_irq(dev, channel);
|
||||
} else if (dev->mem[0x20] & 0x01)
|
||||
picintlevel(1 << 1, &dev->irq_state); /* AT KBC: IRQ 1 is level-triggered because it is tied to OBF. */
|
||||
/* AT KBC: IRQ 1 is level-triggered because it is tied to OBF. */
|
||||
if (dev->irq[0] != 0xffff)
|
||||
picintlevel(1 << dev->irq[0], &dev->irq_state);
|
||||
|
||||
#ifdef WRONG_CONDITION
|
||||
if ((dev->channel > 0) || dev->is_asic || (kbc_ven == KBC_VEN_IBM_PS1) || (kbc_ven == KBC_VEN_IBM))
|
||||
@@ -509,9 +526,6 @@ kbc_scan_kbd_at(atkbc_t *dev)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
write_p2(atkbc_t *dev, uint8_t val);
|
||||
|
||||
static void
|
||||
kbc_at_poll_at(atkbc_t *dev)
|
||||
{
|
||||
@@ -778,6 +792,7 @@ static void
|
||||
write_p2(atkbc_t *dev, uint8_t val)
|
||||
{
|
||||
uint8_t old = dev->p2;
|
||||
|
||||
kbc_at_log("ATkbc: write P2: %02X (old: %02X)\n", val, dev->p2);
|
||||
|
||||
uint8_t kbc_ven = dev->flags & KBC_VEN_MASK;
|
||||
@@ -786,10 +801,12 @@ write_p2(atkbc_t *dev, uint8_t val)
|
||||
/* PS/2: Handle IRQ's. */
|
||||
if (dev->misc_flags & FLAG_PS2) {
|
||||
/* IRQ 12 */
|
||||
picint_common(1 << 12, 0, val & 0x20, NULL);
|
||||
if (dev->irq[1] != 0xffff)
|
||||
picint_common(1 << dev->irq[1], 0, val & 0x20, NULL);
|
||||
|
||||
/* IRQ 1 */
|
||||
picint_common(1 << 1, 0, val & 0x10, NULL);
|
||||
if (dev->irq[0] != 0xffff)
|
||||
picint_common(1 << dev->irq[0], 0, val & 0x10, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -813,7 +830,9 @@ write_p2(atkbc_t *dev, uint8_t val)
|
||||
softresetx86(); /* Pulse reset! */
|
||||
cpu_set_edx();
|
||||
flushmmucache();
|
||||
if ((kbc_ven == KBC_VEN_ALI) || !strcmp(machine_get_internal_name(), "spc7700plw"))
|
||||
if ((kbc_ven == KBC_VEN_ALI) ||
|
||||
!strcmp(machine_get_internal_name(), "spc7700plw") ||
|
||||
!strcmp(machine_get_internal_name(), "pl4600c"))
|
||||
smbase = 0x00030000;
|
||||
|
||||
/* Yes, this is a hack, but until someone gets ahold of the real PCD-2L
|
||||
@@ -851,6 +870,25 @@ write_p2(atkbc_t *dev, uint8_t val)
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t
|
||||
kbc_at_read_p(void *priv, uint8_t port, uint8_t mask)
|
||||
{
|
||||
atkbc_t *dev = (atkbc_t *) priv;
|
||||
uint8_t *p = (port == 2) ? &dev->p2 : &dev->p1;
|
||||
uint8_t ret = *p & mask;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
kbc_at_write_p(void *priv, uint8_t port, uint8_t mask, uint8_t val)
|
||||
{
|
||||
atkbc_t *dev = (atkbc_t *) priv;
|
||||
uint8_t *p = (port == 2) ? &dev->p2 : &dev->p1;
|
||||
|
||||
*p = (*p & mask) | val;
|
||||
}
|
||||
|
||||
static void
|
||||
write_p2_fast_a20(atkbc_t *dev, uint8_t val)
|
||||
{
|
||||
@@ -915,7 +953,7 @@ pulse_poll(void *priv)
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
write64_generic(void *priv, uint8_t val)
|
||||
write_cmd_generic(void *priv, uint8_t val)
|
||||
{
|
||||
atkbc_t *dev = (atkbc_t *) priv;
|
||||
uint8_t current_drive;
|
||||
@@ -1041,7 +1079,14 @@ write64_generic(void *priv, uint8_t val)
|
||||
/* The SMM handlers of Intel AMI Pentium BIOS'es expect bit 6 to be set. */
|
||||
if ((kbc_ven == KBC_VEN_AMI) && ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_GREEN))
|
||||
fixed_bits |= 0x40;
|
||||
if (kbc_ven == KBC_VEN_IBM_PS1) {
|
||||
if (!strcmp(machine_get_internal_name(), "dells333sl")) {
|
||||
/*
|
||||
Dell System 333s/L:
|
||||
- Bit 5: Stuck in reboot loop if clear.
|
||||
*/
|
||||
uint8_t p1 = 0x20 | (video_is_mda() ? 0x40 : 0x00);
|
||||
kbc_delay_to_ob(dev, p1, 0, 0x00);
|
||||
} else if (kbc_ven == KBC_VEN_IBM_PS1) {
|
||||
current_drive = fdc_get_current_drive();
|
||||
/* (B0 or F0) | (fdd_is_525(current_drive) on bit 6) */
|
||||
kbc_delay_to_ob(dev, dev->p1 | fixed_bits | (fdd_is_525(current_drive) ? 0x40 : 0x00),
|
||||
@@ -1070,10 +1115,45 @@ write64_generic(void *priv, uint8_t val)
|
||||
fixed_bits |= 8;
|
||||
/* (B0 or F0) | (0x04 or 0x0c) */
|
||||
kbc_delay_to_ob(dev, dev->p1 | fixed_bits, 0, 0x00);
|
||||
} else if (((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_GREEN))
|
||||
/* (B0 or F0) | (0x08 or 0x0c) */
|
||||
kbc_delay_to_ob(dev, ((dev->p1 | fixed_bits) & 0xf0) | (((dev->flags & KBC_VEN_MASK) == KBC_VEN_ACER) ? 0x08 : 0x0c), 0, 0x00);
|
||||
else if (kbc_ven == KBC_VEN_COMPAQ)
|
||||
} else if (((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_GREEN)) {
|
||||
if (!strcmp(machine_get_internal_name(), "dell466np")) {
|
||||
/*
|
||||
Dell 466/NP:
|
||||
- Bit 2: Keyboard fuse (must be set);
|
||||
- Bit 4: Password disable jumper (must be clear);
|
||||
- Bit 5: Manufacturing jumper (must be set).
|
||||
*/
|
||||
uint8_t p1 = 0x24;
|
||||
kbc_delay_to_ob(dev, p1, 0, 0x00);
|
||||
} else if (!strcmp(machine_get_internal_name(), "optiplex_gxl")) {
|
||||
/*
|
||||
Dell OptiPlex GXL/GXM:
|
||||
- Bit 3: Password disable jumper (must be clear);
|
||||
- Bit 4: Keyboard fuse (must be set);
|
||||
- Bit 5: Manufacturing jumper (must be set).
|
||||
*/
|
||||
uint8_t p1 = 0x30;
|
||||
kbc_delay_to_ob(dev, p1, 0, 0x00);
|
||||
} else if (!strcmp(machine_get_internal_name(), "dellplato") ||
|
||||
!strcmp(machine_get_internal_name(), "dellhannibalp") ||
|
||||
!strcmp(machine_get_internal_name(), "dellxp60")) {
|
||||
/*
|
||||
Dell Dimension XPS Pxxx & Pxxxa/Mxxxa:
|
||||
- Bit 3: Password disable jumper (must be clear);
|
||||
- Bit 4: Clear CMOS jumper (must be set);
|
||||
*/
|
||||
uint8_t p1 = 0x10;
|
||||
kbc_delay_to_ob(dev, p1, 0, 0x00);
|
||||
} else {
|
||||
/* (B0 or F0) | (0x08 or 0x0c) */
|
||||
uint8_t p1_out = ((dev->p1 | fixed_bits) & 0xf0) |
|
||||
(((dev->flags & KBC_VEN_MASK) == KBC_VEN_ACER) ? 0x08 : 0x0c);
|
||||
if (!strcmp(machine_get_internal_name(), "alfredo"))
|
||||
p1_out &= 0xef;
|
||||
|
||||
kbc_delay_to_ob(dev, p1_out, 0, 0x00);
|
||||
}
|
||||
} else if (kbc_ven == KBC_VEN_COMPAQ)
|
||||
kbc_delay_to_ob(dev, dev->p1 | (hasfpu ? 0x00 : 0x04), 0, 0x00);
|
||||
else
|
||||
/* (B0 or F0) | (0x04 or 0x44) */
|
||||
@@ -1128,7 +1208,7 @@ write64_generic(void *priv, uint8_t val)
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
write60_ami(void *priv, uint8_t val)
|
||||
write_cmd_data_ami(void *priv, uint8_t val)
|
||||
{
|
||||
atkbc_t *dev = (atkbc_t *) priv;
|
||||
|
||||
@@ -1198,7 +1278,7 @@ kbc_at_set_ps2(void *priv, const uint8_t ps2)
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
write64_ami(void *priv, uint8_t val)
|
||||
write_cmd_ami(void *priv, uint8_t val)
|
||||
{
|
||||
atkbc_t *dev = (atkbc_t *) priv;
|
||||
uint8_t kbc_ven = dev->flags & KBC_VEN_MASK;
|
||||
@@ -1315,7 +1395,10 @@ write64_ami(void *priv, uint8_t val)
|
||||
kbc_at_log("ATkbc: set KBC lines P22-P23 (P2 bits 2-3) low\n");
|
||||
if (!(dev->flags & DEVICE_PCI))
|
||||
write_p2(dev, dev->p2 & ~(4 << (val & 0x01)));
|
||||
kbc_delay_to_ob(dev, dev->ob, 0, 0x00);
|
||||
if (strstr(machine_get_internal_name(), "sb486pv") != NULL)
|
||||
kbc_delay_to_ob(dev, 0x03, 0, 0x00);
|
||||
else
|
||||
kbc_delay_to_ob(dev, dev->ob, 0, 0x00);
|
||||
dev->pending++;
|
||||
return 0;
|
||||
|
||||
@@ -1400,11 +1483,11 @@ write64_ami(void *priv, uint8_t val)
|
||||
break;
|
||||
}
|
||||
|
||||
return write64_generic(dev, val);
|
||||
return write_cmd_generic(dev, val);
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
write60_phoenix(void *priv, uint8_t val)
|
||||
write_cmd_data_phoenix(void *priv, uint8_t val)
|
||||
{
|
||||
atkbc_t *dev = (atkbc_t *) priv;
|
||||
|
||||
@@ -1477,7 +1560,7 @@ write60_phoenix(void *priv, uint8_t val)
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
write64_phoenix(void *priv, uint8_t val)
|
||||
write_cmd_phoenix(void *priv, uint8_t val)
|
||||
{
|
||||
atkbc_t *dev = (atkbc_t *) priv;
|
||||
|
||||
@@ -1578,8 +1661,13 @@ write64_phoenix(void *priv, uint8_t val)
|
||||
case 0xd5: /* Read MultiKey code revision level */
|
||||
kbc_at_log("ATkbc: Phoenix - Read MultiKey code revision level\n");
|
||||
if (dev->misc_flags & FLAG_PS2) {
|
||||
kbc_at_queue_add(dev, 0x04);
|
||||
kbc_at_queue_add(dev, 0x16);
|
||||
if (dev->flags & DEVICE_PCI) {
|
||||
kbc_at_queue_add(dev, 0x04);
|
||||
kbc_at_queue_add(dev, 0x16);
|
||||
} else {
|
||||
kbc_at_queue_add(dev, 0x01);
|
||||
kbc_at_queue_add(dev, 0x38);
|
||||
}
|
||||
} else {
|
||||
kbc_at_queue_add(dev, 0x01);
|
||||
kbc_at_queue_add(dev, 0x29);
|
||||
@@ -1598,9 +1686,15 @@ write64_phoenix(void *priv, uint8_t val)
|
||||
case 0xd7: /* Read MultiKey model numbers */
|
||||
kbc_at_log("ATkbc: Phoenix - Read MultiKey model numbers\n");
|
||||
if (dev->misc_flags & FLAG_PS2) {
|
||||
kbc_at_queue_add(dev, 0x02);
|
||||
kbc_at_queue_add(dev, 0x87);
|
||||
kbc_at_queue_add(dev, 0x02);
|
||||
if (dev->flags & DEVICE_PCI) {
|
||||
kbc_at_queue_add(dev, 0x02);
|
||||
kbc_at_queue_add(dev, 0x87);
|
||||
kbc_at_queue_add(dev, 0x02);
|
||||
} else {
|
||||
kbc_at_queue_add(dev, 0x99);
|
||||
kbc_at_queue_add(dev, 0x75);
|
||||
kbc_at_queue_add(dev, 0x01);
|
||||
}
|
||||
} else {
|
||||
kbc_at_queue_add(dev, 0x90);
|
||||
kbc_at_queue_add(dev, 0x88);
|
||||
@@ -1612,11 +1706,11 @@ write64_phoenix(void *priv, uint8_t val)
|
||||
break;
|
||||
}
|
||||
|
||||
return write64_generic(dev, val);
|
||||
return write_cmd_generic(dev, val);
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
write64_siemens(void *priv, uint8_t val)
|
||||
write_cmd_siemens(void *priv, uint8_t val)
|
||||
{
|
||||
atkbc_t *dev = (atkbc_t *) priv;
|
||||
|
||||
@@ -1645,11 +1739,11 @@ write64_siemens(void *priv, uint8_t val)
|
||||
break;
|
||||
}
|
||||
|
||||
return write64_ami(dev, val);
|
||||
return write_cmd_ami(dev, val);
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
write60_quadtel(void *priv, UNUSED(uint8_t val))
|
||||
write_cmd_data_quadtel(void *priv, UNUSED(uint8_t val))
|
||||
{
|
||||
const atkbc_t *dev = (atkbc_t *) priv;
|
||||
|
||||
@@ -1666,7 +1760,7 @@ write60_quadtel(void *priv, UNUSED(uint8_t val))
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
write64_olivetti(void *priv, uint8_t val)
|
||||
write_cmd_olivetti(void *priv, uint8_t val)
|
||||
{
|
||||
atkbc_t *dev = (atkbc_t *) priv;
|
||||
|
||||
@@ -1687,11 +1781,11 @@ write64_olivetti(void *priv, uint8_t val)
|
||||
break;
|
||||
}
|
||||
|
||||
return write64_generic(dev, val);
|
||||
return write_cmd_generic(dev, val);
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
write64_quadtel(void *priv, uint8_t val)
|
||||
write_cmd_quadtel(void *priv, uint8_t val)
|
||||
{
|
||||
atkbc_t *dev = (atkbc_t *) priv;
|
||||
|
||||
@@ -1710,11 +1804,11 @@ write64_quadtel(void *priv, uint8_t val)
|
||||
break;
|
||||
}
|
||||
|
||||
return write64_generic(dev, val);
|
||||
return write_cmd_generic(dev, val);
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
write60_toshiba(void *priv, uint8_t val)
|
||||
write_cmd_data_toshiba(void *priv, uint8_t val)
|
||||
{
|
||||
const atkbc_t *dev = (atkbc_t *) priv;
|
||||
|
||||
@@ -1732,7 +1826,7 @@ write60_toshiba(void *priv, uint8_t val)
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
write64_toshiba(void *priv, uint8_t val)
|
||||
write_cmd_toshiba(void *priv, uint8_t val)
|
||||
{
|
||||
atkbc_t *dev = (atkbc_t *) priv;
|
||||
|
||||
@@ -1821,7 +1915,7 @@ write64_toshiba(void *priv, uint8_t val)
|
||||
break;
|
||||
}
|
||||
|
||||
return write64_generic(dev, val);
|
||||
return write_cmd_generic(dev, val);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1865,8 +1959,10 @@ kbc_at_process_cmd(void *priv)
|
||||
/* TODO: Proper P1 implementation, with OR and AND flags in the machine table. */
|
||||
dev->p1 = dev->p1 & 0xff;
|
||||
write_p2(dev, 0x4b);
|
||||
picintc(0x1000);
|
||||
picintc(0x0002);
|
||||
if (dev->irq[1] != 0xffff)
|
||||
picintc(1 << dev->irq[1]);
|
||||
if (dev->irq[0] != 0xffff)
|
||||
picintc(1 << dev->irq[0]);
|
||||
}
|
||||
|
||||
dev->status = (dev->status & 0x0f) | 0x60;
|
||||
@@ -1885,7 +1981,8 @@ kbc_at_process_cmd(void *priv)
|
||||
/* TODO: Proper P1 implementation, with OR and AND flags in the machine table. */
|
||||
dev->p1 = dev->p1 & 0xff;
|
||||
write_p2(dev, 0xcf);
|
||||
picintclevel(0x0002, &dev->irq_state);
|
||||
if (dev->irq[0] != 0xffff)
|
||||
picintclevel(1 << dev->irq[0], &dev->irq_state);
|
||||
dev->irq_state = 0;
|
||||
}
|
||||
|
||||
@@ -2000,8 +2097,8 @@ kbc_at_process_cmd(void *priv)
|
||||
* that. Otherwise, or if that handler fails,
|
||||
* log a bad command.
|
||||
*/
|
||||
if (dev->write64_ven)
|
||||
bad = dev->write64_ven(dev, dev->ib);
|
||||
if (dev->write_cmd_ven)
|
||||
bad = dev->write_cmd_ven(dev, dev->ib);
|
||||
|
||||
kbc_at_log(bad ? "ATkbc: bad controller command %02X\n" : "", dev->ib);
|
||||
}
|
||||
@@ -2087,8 +2184,8 @@ kbc_at_process_cmd(void *priv)
|
||||
* it returns an error, log a bad
|
||||
* controller command.
|
||||
*/
|
||||
if (dev->write60_ven)
|
||||
bad = dev->write60_ven(dev, dev->ib);
|
||||
if (dev->write_cmd_data_ven)
|
||||
bad = dev->write_cmd_data_ven(dev, dev->ib);
|
||||
|
||||
if (bad) {
|
||||
kbc_at_log("ATkbc: bad controller command %02x data %02x\n", dev->command, dev->ib);
|
||||
@@ -2098,7 +2195,7 @@ kbc_at_process_cmd(void *priv)
|
||||
}
|
||||
|
||||
static void
|
||||
kbc_at_write(uint16_t port, uint8_t val, void *priv)
|
||||
kbc_at_port_1_write(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
atkbc_t *dev = (atkbc_t *) priv;
|
||||
uint8_t kbc_ven = dev->flags & KBC_VEN_MASK;
|
||||
@@ -2106,46 +2203,89 @@ kbc_at_write(uint16_t port, uint8_t val, void *priv)
|
||||
|
||||
kbc_at_log("ATkbc: [%04X:%08X] write(%04X) = %02X\n", CS, cpu_state.pc, port, val);
|
||||
|
||||
switch (port) {
|
||||
case 0x60:
|
||||
dev->status &= ~STAT_CD;
|
||||
if (fast_a20 && dev->wantdata && (dev->command == 0xd1)) {
|
||||
kbc_at_log("ATkbc: write P2\n");
|
||||
dev->status &= ~STAT_CD;
|
||||
|
||||
/* Fast A20 - ignore all other bits. */
|
||||
write_p2_fast_a20(dev, (dev->p2 & 0xfd) | (val & 0x02));
|
||||
if (fast_a20 && dev->wantdata && (dev->command == 0xd1)) {
|
||||
kbc_at_log("ATkbc: write P2\n");
|
||||
|
||||
dev->wantdata = 0;
|
||||
dev->state = STATE_MAIN_IBF;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
/* Fast A20 - ignore all other bits. */
|
||||
write_p2_fast_a20(dev, (dev->p2 & 0xfd) | (val & 0x02));
|
||||
|
||||
case 0x64:
|
||||
dev->status |= STAT_CD;
|
||||
if (fast_a20 && (val == 0xd1)) {
|
||||
kbc_at_log("ATkbc: write P2\n");
|
||||
dev->wantdata = 1;
|
||||
dev->state = STATE_KBC_PARAM;
|
||||
dev->command = 0xd1;
|
||||
return;
|
||||
} else if (fast_reset && ((val & 0xf0) == 0xf0)) {
|
||||
pulse_output(dev, val & 0x0f);
|
||||
dev->wantdata = 0;
|
||||
dev->state = STATE_MAIN_IBF;
|
||||
|
||||
dev->state = STATE_MAIN_IBF;
|
||||
return;
|
||||
} else if (val == 0xae) {
|
||||
/* Fast track it because of the LG MultiNet. */
|
||||
kbc_at_log("ATkbc: enable keyboard\n");
|
||||
set_enable_kbd(dev, 1);
|
||||
/*
|
||||
Explicitly clear IBF so that any preceding
|
||||
command is not executed.
|
||||
*/
|
||||
dev->status &= ~STAT_IFULL;
|
||||
return;
|
||||
}
|
||||
|
||||
dev->state = STATE_MAIN_IBF;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
dev->ib = val;
|
||||
dev->status |= STAT_IFULL;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
static void
|
||||
kbc_at_port_2_write(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
atkbc_t *dev = (atkbc_t *) priv;
|
||||
uint8_t kbc_ven = dev->flags & KBC_VEN_MASK;
|
||||
uint8_t fast_a20 = (kbc_ven != KBC_VEN_SIEMENS);
|
||||
|
||||
kbc_at_log("ATkbc: [%04X:%08X] write(%04X) = %02X\n", CS, cpu_state.pc, port, val);
|
||||
|
||||
dev->status |= STAT_CD;
|
||||
|
||||
if (fast_a20 && (val == 0xd1)) {
|
||||
kbc_at_log("ATkbc: write P2\n");
|
||||
dev->wantdata = 1;
|
||||
dev->state = STATE_KBC_PARAM;
|
||||
dev->command = 0xd1;
|
||||
|
||||
/*
|
||||
Explicitly clear IBF so that any preceding
|
||||
command is not executed.
|
||||
*/
|
||||
dev->status &= ~STAT_IFULL;
|
||||
return;
|
||||
} else if (fast_reset && ((val & 0xf0) == 0xf0)) {
|
||||
pulse_output(dev, val & 0x0f);
|
||||
|
||||
dev->state = STATE_MAIN_IBF;
|
||||
|
||||
/*
|
||||
Explicitly clear IBF so that any preceding
|
||||
command is not executed.
|
||||
*/
|
||||
dev->status &= ~STAT_IFULL;
|
||||
return;
|
||||
} else if (val == 0xad) {
|
||||
/* Fast track it because of the Bochs BIOS. */
|
||||
kbc_at_log("ATkbc: disable keyboard\n");
|
||||
set_enable_kbd(dev, 0);
|
||||
|
||||
dev->state = STATE_MAIN_IBF;
|
||||
|
||||
/*
|
||||
Explicitly clear IBF so that any preceding
|
||||
command is not executed.
|
||||
*/
|
||||
dev->status &= ~STAT_IFULL;
|
||||
return;
|
||||
} else if (val == 0xae) {
|
||||
/* Fast track it because of the LG MultiNet. */
|
||||
kbc_at_log("ATkbc: enable keyboard\n");
|
||||
set_enable_kbd(dev, 1);
|
||||
|
||||
dev->state = STATE_MAIN_IBF;
|
||||
|
||||
/*
|
||||
Explicitly clear IBF so that any preceding
|
||||
command is not executed.
|
||||
*/
|
||||
dev->status &= ~STAT_IFULL;
|
||||
return;
|
||||
}
|
||||
|
||||
dev->ib = val;
|
||||
@@ -2153,7 +2293,7 @@ kbc_at_write(uint16_t port, uint8_t val, void *priv)
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
kbc_at_read(uint16_t port, void *priv)
|
||||
kbc_at_port_1_read(uint16_t port, void *priv)
|
||||
{
|
||||
atkbc_t *dev = (atkbc_t *) priv;
|
||||
uint8_t ret = 0xff;
|
||||
@@ -2161,26 +2301,32 @@ kbc_at_read(uint16_t port, void *priv)
|
||||
if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1)
|
||||
cycles -= ISA_CYCLES(8);
|
||||
|
||||
switch (port) {
|
||||
case 0x60:
|
||||
ret = dev->ob;
|
||||
dev->status &= ~STAT_OFULL;
|
||||
/* TODO: IRQ is only tied to OBF on the AT KBC, on the PS/2 KBC, it is controlled by a P2 bit.
|
||||
This also means that in AT mode, the IRQ is level-triggered. */
|
||||
if (!(dev->misc_flags & FLAG_PS2))
|
||||
picintclevel(1 << 1, &dev->irq_state);
|
||||
if ((strstr(machine_get_internal_name(), "pb41") != NULL) && (cpu_override_dynarec == 1))
|
||||
cpu_override_dynarec = 0;
|
||||
break;
|
||||
ret = dev->ob;
|
||||
dev->status &= ~STAT_OFULL;
|
||||
/*
|
||||
TODO: IRQ is only tied to OBF on the AT KBC, on the PS/2 KBC, it is controlled by a P2 bit.
|
||||
This also means that in AT mode, the IRQ is level-triggered.
|
||||
*/
|
||||
if (!(dev->misc_flags & FLAG_PS2) && (dev->irq[0] != 0xffff))
|
||||
picintclevel(1 << dev->irq[0], &dev->irq_state);
|
||||
if ((strstr(machine_get_internal_name(), "pb41") != NULL) && (cpu_override_dynarec == 1))
|
||||
cpu_override_dynarec = 0;
|
||||
|
||||
case 0x64:
|
||||
ret = dev->status;
|
||||
break;
|
||||
kbc_at_log("ATkbc: [%04X:%08X] read (%04X) = %02X\n", CS, cpu_state.pc, port, ret);
|
||||
|
||||
default:
|
||||
kbc_at_log("ATkbc: read(%04x) invalid!\n",port);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
kbc_at_port_2_read(uint16_t port, void *priv)
|
||||
{
|
||||
atkbc_t *dev = (atkbc_t *) priv;
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1)
|
||||
cycles -= ISA_CYCLES(8);
|
||||
|
||||
ret = dev->status;
|
||||
|
||||
kbc_at_log("ATkbc: [%04X:%08X] read (%04X) = %02X\n", CS, cpu_state.pc, port, ret);
|
||||
|
||||
@@ -2219,11 +2365,14 @@ kbc_at_reset(void *priv)
|
||||
if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_1) {
|
||||
dev->misc_flags |= FLAG_PS2;
|
||||
kbc_at_do_poll = kbc_at_poll_ps2;
|
||||
picintc(0x1000);
|
||||
picintc(0x0002);
|
||||
if (dev->irq[1] != 0xffff)
|
||||
picintc(1 << dev->irq[1]);
|
||||
if (dev->irq[0] != 0xffff)
|
||||
picintc(1 << dev->irq[0]);
|
||||
} else {
|
||||
kbc_at_do_poll = kbc_at_poll_at;
|
||||
picintclevel(0x0002, &dev->irq_state);
|
||||
if (dev->irq[0] != 0xffff)
|
||||
picintclevel(1 << dev->irq[0], &dev->irq_state);
|
||||
dev->irq_state = 0;
|
||||
}
|
||||
|
||||
@@ -2266,19 +2415,44 @@ kbc_at_close(void *priv)
|
||||
}
|
||||
|
||||
void
|
||||
kbc_at_handler(int set, void *priv)
|
||||
kbc_at_port_handler(int num, int set, uint16_t port, void *priv)
|
||||
{
|
||||
if (kbc_handler_set) {
|
||||
io_removehandler(0x0060, 1, kbc_at_read, NULL, NULL, kbc_at_write, NULL, NULL, priv);
|
||||
io_removehandler(0x0064, 1, kbc_at_read, NULL, NULL, kbc_at_write, NULL, NULL, priv);
|
||||
atkbc_t *dev = (atkbc_t *) priv;
|
||||
|
||||
if (dev->handler_enable[num] && (dev->base_addr[num] != 0x0000))
|
||||
io_removehandler(dev->base_addr[num], 1,
|
||||
dev->handlers[num].read, NULL, NULL,
|
||||
dev->handlers[num].write, NULL, NULL, priv);
|
||||
|
||||
dev->handler_enable[num] = set;
|
||||
dev->base_addr[num] = port;
|
||||
|
||||
if (dev->handler_enable[num] && (dev->base_addr[num] != 0x0000))
|
||||
io_sethandler(dev->base_addr[num], 1,
|
||||
dev->handlers[num].read, NULL, NULL,
|
||||
dev->handlers[num].write, NULL, NULL, priv);
|
||||
}
|
||||
|
||||
void
|
||||
kbc_at_handler(int set, uint16_t port, void *priv)
|
||||
{
|
||||
kbc_at_port_handler(0, set, port, priv);
|
||||
kbc_at_port_handler(1, set, port + 0x0004, priv);
|
||||
}
|
||||
|
||||
void
|
||||
kbc_at_set_irq(int num, uint16_t irq, void *priv)
|
||||
{
|
||||
atkbc_t *dev = (atkbc_t *) priv;
|
||||
|
||||
if (dev->irq[num] != 0xffff) {
|
||||
if ((num == 0) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_1))
|
||||
picintclevel(1 << dev->irq[num], &dev->irq_state);
|
||||
else
|
||||
picintc(1 << dev->irq[num]);
|
||||
}
|
||||
|
||||
kbc_handler_set = set;
|
||||
|
||||
if (kbc_handler_set) {
|
||||
io_sethandler(0x0060, 1, kbc_at_read, NULL, NULL, kbc_at_write, NULL, NULL, priv);
|
||||
io_sethandler(0x0064, 1, kbc_at_read, NULL, NULL, kbc_at_write, NULL, NULL, priv);
|
||||
}
|
||||
dev->irq[num] = irq;
|
||||
}
|
||||
|
||||
static void *
|
||||
@@ -2299,16 +2473,21 @@ kbc_at_init(const device_t *info)
|
||||
if (info->flags & DEVICE_PCI)
|
||||
dev->misc_flags |= FLAG_PCI;
|
||||
|
||||
kbc_handler_set = 0;
|
||||
kbc_at_handler(1, dev);
|
||||
dev->handlers[0].read = kbc_at_port_1_read;
|
||||
dev->handlers[0].write = kbc_at_port_1_write;
|
||||
dev->handlers[1].read = kbc_at_port_2_read;
|
||||
dev->handlers[1].write = kbc_at_port_2_write;
|
||||
|
||||
dev->irq[0] = 1;
|
||||
dev->irq[1] = 12;
|
||||
|
||||
timer_add(&dev->kbc_poll_timer, kbc_at_poll, dev, 1);
|
||||
timer_add(&dev->pulse_cb, pulse_poll, dev, 0);
|
||||
|
||||
timer_add(&dev->kbc_dev_poll_timer, kbc_at_dev_poll, dev, 1);
|
||||
|
||||
dev->write60_ven = NULL;
|
||||
dev->write64_ven = NULL;
|
||||
dev->write_cmd_data_ven = NULL;
|
||||
dev->write_cmd_ven = NULL;
|
||||
|
||||
kbc_ami_revision = '8';
|
||||
kbc_award_revision = 0x42;
|
||||
@@ -2317,8 +2496,8 @@ kbc_at_init(const device_t *info)
|
||||
case KBC_VEN_SIEMENS:
|
||||
kbc_ami_revision = '8';
|
||||
kbc_award_revision = 0x42;
|
||||
dev->write60_ven = write60_ami;
|
||||
dev->write64_ven = write64_siemens;
|
||||
dev->write_cmd_data_ven = write_cmd_data_ami;
|
||||
dev->write_cmd_ven = write_cmd_siemens;
|
||||
break;
|
||||
|
||||
case KBC_VEN_ACER:
|
||||
@@ -2327,24 +2506,24 @@ kbc_at_init(const device_t *info)
|
||||
case KBC_VEN_IBM_PS1:
|
||||
case KBC_VEN_IBM:
|
||||
case KBC_VEN_COMPAQ:
|
||||
dev->write64_ven = write64_generic;
|
||||
dev->write_cmd_ven = write_cmd_generic;
|
||||
break;
|
||||
|
||||
case KBC_VEN_OLIVETTI:
|
||||
dev->write64_ven = write64_olivetti;
|
||||
dev->write_cmd_ven = write_cmd_olivetti;
|
||||
break;
|
||||
|
||||
case KBC_VEN_ALI:
|
||||
kbc_ami_revision = 'F';
|
||||
kbc_award_revision = 0x43;
|
||||
dev->write60_ven = write60_ami;
|
||||
dev->write64_ven = write64_ami;
|
||||
dev->write_cmd_data_ven = write_cmd_data_ami;
|
||||
dev->write_cmd_ven = write_cmd_ami;
|
||||
break;
|
||||
|
||||
case KBC_VEN_TRIGEM_AMI:
|
||||
kbc_ami_revision = 'Z';
|
||||
dev->write60_ven = write60_ami;
|
||||
dev->write64_ven = write64_ami;
|
||||
dev->write_cmd_data_ven = write_cmd_data_ami;
|
||||
dev->write_cmd_ven = write_cmd_ami;
|
||||
break;
|
||||
|
||||
case KBC_VEN_AMI:
|
||||
@@ -2367,23 +2546,23 @@ kbc_at_init(const device_t *info)
|
||||
else
|
||||
kbc_ami_revision = 'F';
|
||||
|
||||
dev->write60_ven = write60_ami;
|
||||
dev->write64_ven = write64_ami;
|
||||
dev->write_cmd_data_ven = write_cmd_data_ami;
|
||||
dev->write_cmd_ven = write_cmd_ami;
|
||||
break;
|
||||
|
||||
case KBC_VEN_PHOENIX:
|
||||
dev->write60_ven = write60_phoenix;
|
||||
dev->write64_ven = write64_phoenix;
|
||||
dev->write_cmd_data_ven = write_cmd_data_phoenix;
|
||||
dev->write_cmd_ven = write_cmd_phoenix;
|
||||
break;
|
||||
|
||||
case KBC_VEN_QUADTEL:
|
||||
dev->write60_ven = write60_quadtel;
|
||||
dev->write64_ven = write64_quadtel;
|
||||
dev->write_cmd_data_ven = write_cmd_data_quadtel;
|
||||
dev->write_cmd_ven = write_cmd_quadtel;
|
||||
break;
|
||||
|
||||
case KBC_VEN_TOSHIBA:
|
||||
dev->write60_ven = write60_toshiba;
|
||||
dev->write64_ven = write64_toshiba;
|
||||
dev->write_cmd_data_ven = write_cmd_data_toshiba;
|
||||
dev->write_cmd_ven = write_cmd_toshiba;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -2409,6 +2588,8 @@ kbc_at_init(const device_t *info)
|
||||
|
||||
fast_reset = 0x00;
|
||||
|
||||
kbc_at_handler(1, 0x0060, dev);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
@@ -2608,6 +2789,20 @@ const device_t keyboard_ps2_ami_device = {
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t keyboard_ps2_compaq_device = {
|
||||
.name = "PS/2 Keyboard (Compaq)",
|
||||
.internal_name = "keyboard_at_compaq",
|
||||
.flags = DEVICE_KBC,
|
||||
.local = KBC_TYPE_PS2_1 | KBC_VEN_COMPAQ,
|
||||
.init = kbc_at_init,
|
||||
.close = kbc_at_close,
|
||||
.reset = kbc_at_reset,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t keyboard_ps2_holtek_device = {
|
||||
.name = "PS/2 Keyboard (Holtek)",
|
||||
.internal_name = "keyboard_ps2_holtek",
|
||||
@@ -2775,3 +2970,17 @@ const device_t keyboard_ps2_acer_pci_device = {
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t keyboard_ps2_phoenix_pci_device = {
|
||||
.name = "PS/2 Keyboard (Phoenix)",
|
||||
.internal_name = "keyboard_ps2_phoenix_pci",
|
||||
.flags = DEVICE_KBC | DEVICE_PCI,
|
||||
.local = KBC_TYPE_PS2_1 | KBC_VEN_PHOENIX,
|
||||
.init = kbc_at_init,
|
||||
.close = kbc_at_close,
|
||||
.reset = kbc_at_reset,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
@@ -58,7 +58,7 @@ kbc_at_dev_log(const char *fmt, ...)
|
||||
# define kbc_at_dev_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
static void
|
||||
void
|
||||
kbc_at_dev_queue_reset(atkbc_dev_t *dev, uint8_t reset_main)
|
||||
{
|
||||
if (reset_main) {
|
||||
@@ -95,10 +95,6 @@ kbc_at_dev_queue_add(atkbc_dev_t *dev, uint8_t val, uint8_t main)
|
||||
dev->cmd_queue[dev->cmd_queue_end] = val;
|
||||
dev->cmd_queue_end = (dev->cmd_queue_end + 1) & 0xf;
|
||||
}
|
||||
|
||||
/* TODO: This should be done on actual send to host. */
|
||||
if (val != 0xfe)
|
||||
dev->last_scan_code = val;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -123,6 +119,8 @@ kbc_at_dev_poll(void *priv)
|
||||
(dev->queue_start != dev->queue_end)) {
|
||||
kbc_at_dev_log("%s: %02X (DATA) on channel 1\n", dev->name, dev->queue[dev->queue_start]);
|
||||
dev->port->out_new = dev->queue[dev->queue_start];
|
||||
if (dev->port->out_new != 0xfe)
|
||||
dev->last_scan_code = dev->port->out_new;
|
||||
dev->queue_start = (dev->queue_start + 1) & dev->fifo_mask;
|
||||
}
|
||||
if (dev->ignore || !(*dev->scan) || dev->port->wantcmd)
|
||||
@@ -143,6 +141,8 @@ kbc_at_dev_poll(void *priv)
|
||||
if ((dev->port->out_new == -1) && (dev->cmd_queue_start != dev->cmd_queue_end)) {
|
||||
kbc_at_dev_log("%s: %02X (CMD ) on channel 1\n", dev->name, dev->cmd_queue[dev->cmd_queue_start]);
|
||||
dev->port->out_new = dev->cmd_queue[dev->cmd_queue_start];
|
||||
if (dev->port->out_new != 0xfe)
|
||||
dev->last_scan_code = dev->port->out_new;
|
||||
dev->cmd_queue_start = (dev->cmd_queue_start + 1) & 0xf;
|
||||
}
|
||||
if (dev->cmd_queue_start == dev->cmd_queue_end)
|
||||
@@ -166,6 +166,8 @@ kbc_at_dev_poll(void *priv)
|
||||
if ((dev->port->out_new == -1) && (dev->cmd_queue_start != dev->cmd_queue_end)) {
|
||||
kbc_at_dev_log("%s: %02X (CMD ) on channel 1\n", dev->name, dev->cmd_queue[dev->cmd_queue_start]);
|
||||
dev->port->out_new = dev->cmd_queue[dev->cmd_queue_start];
|
||||
if (dev->port->out_new != 0xfe)
|
||||
dev->last_scan_code = dev->port->out_new;
|
||||
dev->cmd_queue_start = (dev->cmd_queue_start + 1) & 0xf;
|
||||
}
|
||||
if (dev->cmd_queue_start == dev->cmd_queue_end)
|
||||
|
||||
@@ -36,14 +36,6 @@ uint16_t scancode_map[768] = { 0 };
|
||||
|
||||
int keyboard_scan;
|
||||
|
||||
/* F8+F12 */
|
||||
uint16_t key_prefix_1_1 = 0x042; /* F8 */
|
||||
uint16_t key_prefix_1_2 = 0x000; /* Invalid */
|
||||
uint16_t key_prefix_2_1 = 0x000; /* Invalid */
|
||||
uint16_t key_prefix_2_2 = 0x000; /* Invalid */
|
||||
uint16_t key_uncapture_1 = 0x058; /* F12 */
|
||||
uint16_t key_uncapture_2 = 0x000; /* Invalid */
|
||||
|
||||
#ifdef ENABLE_KBC_AT_LOG
|
||||
int kbc_at_do_log = ENABLE_KBC_AT_LOG;
|
||||
|
||||
@@ -72,10 +64,12 @@ static int keydelay[512];
|
||||
#endif
|
||||
static scancode *scan_table; /* scancode table for keyboard */
|
||||
|
||||
static uint8_t caps_lock = 0;
|
||||
static uint8_t num_lock = 0;
|
||||
static uint8_t scroll_lock = 0;
|
||||
static uint8_t shift = 0;
|
||||
static volatile uint8_t caps_lock = 0;
|
||||
static volatile uint8_t num_lock = 0;
|
||||
static volatile uint8_t scroll_lock = 0;
|
||||
static volatile uint8_t kana_lock = 0;
|
||||
static volatile uint8_t kbd_in_reset = 0;
|
||||
static uint8_t shift = 0;
|
||||
|
||||
static int key5576mode = 0;
|
||||
|
||||
@@ -113,10 +107,12 @@ static scconvtbl scconv55_8a[18 + 1] =
|
||||
void
|
||||
keyboard_init(void)
|
||||
{
|
||||
num_lock = 0;
|
||||
caps_lock = 0;
|
||||
scroll_lock = 0;
|
||||
shift = 0;
|
||||
num_lock = 0;
|
||||
caps_lock = 0;
|
||||
scroll_lock = 0;
|
||||
kana_lock = 0;
|
||||
shift = 0;
|
||||
kbd_in_reset = 0;
|
||||
|
||||
memset(recv_key, 0x00, sizeof(recv_key));
|
||||
memset(recv_key_ui, 0x00, sizeof(recv_key));
|
||||
@@ -244,6 +240,9 @@ key_process(uint16_t scan, int down)
|
||||
void
|
||||
keyboard_input(int down, uint16_t scan)
|
||||
{
|
||||
if (kbd_in_reset)
|
||||
return;
|
||||
|
||||
/* Special case for E1 1D, translate it to 0100 - special case. */
|
||||
if ((scan >> 8) == 0xe1) {
|
||||
if ((scan & 0xff) == 0x1d)
|
||||
@@ -318,13 +317,16 @@ keyboard_input(int down, uint16_t scan)
|
||||
shift &= ~0x80;
|
||||
break;
|
||||
case 0x03a: /* Caps Lock */
|
||||
caps_lock ^= 1;
|
||||
if (!(machine_has_bus(machine, MACHINE_AT) > 0))
|
||||
caps_lock ^= 1;
|
||||
break;
|
||||
case 0x045:
|
||||
num_lock ^= 1;
|
||||
if (!(machine_has_bus(machine, MACHINE_AT) > 0))
|
||||
num_lock ^= 1;
|
||||
break;
|
||||
case 0x046:
|
||||
scroll_lock ^= 1;
|
||||
if (!(machine_has_bus(machine, MACHINE_AT) > 0))
|
||||
scroll_lock ^= 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -346,9 +348,9 @@ void
|
||||
keyboard_all_up(void)
|
||||
{
|
||||
for (unsigned short i = 0; i < 0x200; i++) {
|
||||
if (recv_key_ui[i]) {
|
||||
if (recv_key_ui[i])
|
||||
recv_key_ui[i] = 0;
|
||||
}
|
||||
|
||||
if (recv_key[i]) {
|
||||
recv_key[i] = 0;
|
||||
key_process(i, 0);
|
||||
@@ -356,6 +358,18 @@ keyboard_all_up(void)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
keyboard_set_in_reset(uint8_t in_reset)
|
||||
{
|
||||
kbd_in_reset = in_reset;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
keyboard_get_in_reset(void)
|
||||
{
|
||||
return kbd_in_reset;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
keyboard_do_break(uint16_t scan)
|
||||
{
|
||||
@@ -375,11 +389,12 @@ keyboard_do_break(uint16_t scan)
|
||||
Caps Lock, Num Lock, and Scroll Lock when receving the "Set keyboard LEDs"
|
||||
command. */
|
||||
void
|
||||
keyboard_update_states(uint8_t cl, uint8_t nl, uint8_t sl)
|
||||
keyboard_update_states(uint8_t cl, uint8_t nl, uint8_t sl, uint8_t kl)
|
||||
{
|
||||
caps_lock = cl;
|
||||
num_lock = nl;
|
||||
scroll_lock = sl;
|
||||
kana_lock = kl;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
@@ -389,7 +404,7 @@ keyboard_get_shift(void)
|
||||
}
|
||||
|
||||
void
|
||||
keyboard_get_states(uint8_t *cl, uint8_t *nl, uint8_t *sl)
|
||||
keyboard_get_states(uint8_t *cl, uint8_t *nl, uint8_t *sl, uint8_t *kl)
|
||||
{
|
||||
if (cl)
|
||||
*cl = caps_lock;
|
||||
@@ -397,6 +412,8 @@ keyboard_get_states(uint8_t *cl, uint8_t *nl, uint8_t *sl)
|
||||
*nl = num_lock;
|
||||
if (sl)
|
||||
*sl = scroll_lock;
|
||||
if (kl)
|
||||
*kl = kana_lock;
|
||||
}
|
||||
|
||||
/* Called by the UI to update the states of Caps Lock, Num Lock, and Scroll Lock. */
|
||||
@@ -440,7 +457,7 @@ keyboard_set_states(uint8_t cl, uint8_t nl, uint8_t sl)
|
||||
}
|
||||
}
|
||||
|
||||
keyboard_update_states(cl, nl, sl);
|
||||
keyboard_update_states(cl, nl, sl, kana_lock);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -481,19 +498,6 @@ keyboard_isfsexit_up(void)
|
||||
return (!recv_key_ui[0x01d] && !recv_key_ui[0x11d] && !recv_key_ui[0x038] && !recv_key_ui[0x138] && !recv_key_ui[0x051] && !recv_key_ui[0x151]);
|
||||
}
|
||||
|
||||
/* Do we have the mouse uncapture combination in the keyboard buffer? */
|
||||
int
|
||||
keyboard_ismsexit(void)
|
||||
{
|
||||
if ((key_prefix_2_1 != 0x000) || (key_prefix_2_2 != 0x000))
|
||||
return ((recv_key_ui[key_prefix_1_1] || recv_key_ui[key_prefix_1_2]) &&
|
||||
(recv_key_ui[key_prefix_2_1] || recv_key_ui[key_prefix_2_2]) &&
|
||||
(recv_key_ui[key_uncapture_1] || recv_key_ui[key_uncapture_2]));
|
||||
else
|
||||
return ((recv_key_ui[key_prefix_1_1] || recv_key_ui[key_prefix_1_2]) &&
|
||||
(recv_key_ui[key_uncapture_1] || recv_key_ui[key_uncapture_2]));
|
||||
}
|
||||
|
||||
/* This is so we can disambiguate scan codes that would otherwise conflict and get
|
||||
passed on incorrectly. */
|
||||
uint16_t
|
||||
|
||||
@@ -428,11 +428,11 @@ static const scancode scancode_set1[512] = {
|
||||
{ .mk = {0xe0, 0x57, 0 }, .brk = { 0xe0, 0xd7, 0 } }, /* 157 */
|
||||
{ .mk = {0xe0, 0x58, 0 }, .brk = { 0xe0, 0xd8, 0 } }, /* 158 */
|
||||
{ .mk = {0xe0, 0x59, 0 }, .brk = { 0xe0, 0xd9, 0 } }, /* 159 */
|
||||
{ .mk = {0xe0, 0x5a, 0 }, .brk = { 0xe0, 0xaa, 0 } }, /* 15a */
|
||||
{ .mk = {0xe0, 0x5a, 0 }, .brk = { 0xe0, 0xda, 0 } }, /* 15a */
|
||||
{ .mk = {0xe0, 0x5b, 0 }, .brk = { 0xe0, 0xdb, 0 } }, /* 15b */
|
||||
{ .mk = {0xe0, 0x5c, 0 }, .brk = { 0xe0, 0xdc, 0 } }, /* 15c */
|
||||
{ .mk = {0xe0, 0x5d, 0 }, .brk = { 0xe0, 0xdd, 0 } }, /* 15d */
|
||||
{ .mk = {0xe0, 0x5e, 0 }, .brk = { 0xe0, 0xee, 0 } }, /* 15e */
|
||||
{ .mk = {0xe0, 0x5e, 0 }, .brk = { 0xe0, 0xde, 0 } }, /* 15e */
|
||||
{ .mk = {0xe0, 0x5f, 0 }, .brk = { 0xe0, 0xdf, 0 } }, /* 15f */
|
||||
{ .mk = { 0 }, .brk = { 0 } }, /* 160 */
|
||||
{ .mk = {0xe0, 0x61, 0 }, .brk = { 0xe0, 0xe1, 0 } }, /* 161 */
|
||||
@@ -3276,7 +3276,7 @@ add_data_kbd(uint16_t val)
|
||||
|
||||
dev->ignore = 1;
|
||||
|
||||
keyboard_get_states(NULL, &num_lock, NULL);
|
||||
keyboard_get_states(NULL, &num_lock, NULL, NULL);
|
||||
shift_states = keyboard_get_shift() & STATE_SHIFT_MASK;
|
||||
|
||||
switch (val) {
|
||||
@@ -3476,6 +3476,10 @@ keyboard_at_bat(void *priv)
|
||||
|
||||
keyboard_scan = 1;
|
||||
|
||||
keyboard_all_up();
|
||||
keyboard_update_states(0, 0, 0, 0);
|
||||
|
||||
keyboard_set_in_reset(0);
|
||||
kbc_at_dev_queue_add(dev, 0xaa, 0);
|
||||
} else {
|
||||
bat_counter--;
|
||||
@@ -3490,7 +3494,6 @@ keyboard_at_invalid_cmd(atkbc_dev_t *dev)
|
||||
kbc_at_dev_queue_add(dev, inv_cmd_response, 0);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
keyboard_at_write(void *priv)
|
||||
{
|
||||
@@ -3510,6 +3513,7 @@ keyboard_at_write(void *priv)
|
||||
switch (dev->command) {
|
||||
case 0xed: /* Set/reset LEDs */
|
||||
kbc_at_dev_queue_add(dev, 0xfa, 0);
|
||||
keyboard_update_states(!!(val & 0x4), !!(val & 0x2), val & 0x1, !!(val & 0x8));
|
||||
keyboard_at_log("%s: Set/reset LEDs [%02X]\n", dev->name, val);
|
||||
break;
|
||||
|
||||
@@ -3638,6 +3642,13 @@ keyboard_at_write(void *priv)
|
||||
case 0xf6: /* set defaults */
|
||||
keyboard_at_log("%s: set defaults%s\n",
|
||||
dev->name, (val == 0xf6) ? "" : " and disable keyboard");
|
||||
dev->port->out_new = -1;
|
||||
dev->port->wantcmd = 0;
|
||||
|
||||
kbc_at_dev_queue_reset(dev, 1);
|
||||
|
||||
dev->last_scan_code = 0x00;
|
||||
|
||||
keyboard_scan = !(val & 0x01);
|
||||
keyboard_at_log("%s: val = %02X, keyboard_scan = %i\n",
|
||||
dev->name, val, keyboard_scan);
|
||||
@@ -3707,11 +3718,11 @@ keyboard_at_write(void *priv)
|
||||
/* TODO: This is supposed to resend multiple bytes after some commands. */
|
||||
case 0xfe: /* resend last scan code */
|
||||
keyboard_at_log("%s: resend last scan code\n", dev->name);
|
||||
kbc_at_dev_queue_add(dev, 0xfa, 0);
|
||||
kbc_at_dev_queue_add(dev, dev->last_scan_code, 0);
|
||||
break;
|
||||
|
||||
case 0xff: /* reset */
|
||||
keyboard_set_in_reset(1);
|
||||
kbc_at_dev_reset(dev, 1);
|
||||
bat_counter = 1000;
|
||||
break;
|
||||
@@ -3722,6 +3733,44 @@ keyboard_at_write(void *priv)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SCAN_CODE_TABLES_COMPARISON
|
||||
/* Non-translated to translated scan codes. */
|
||||
static const uint8_t nont_to_t[256] = {
|
||||
0x00, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x3c, 0x58,
|
||||
0x64, 0x44, 0x42, 0x40, 0x3e, 0x0f, 0x29, 0x59,
|
||||
0x65, 0x38, 0x2a, 0x70, 0x1d, 0x10, 0x02, 0x5a,
|
||||
0x66, 0x71, 0x2c, 0x1f, 0x1e, 0x11, 0x03, 0x5b,
|
||||
0x67, 0x2e, 0x2d, 0x20, 0x12, 0x05, 0x04, 0x5c,
|
||||
0x68, 0x39, 0x2f, 0x21, 0x14, 0x13, 0x06, 0x5d,
|
||||
0x69, 0x31, 0x30, 0x23, 0x22, 0x15, 0x07, 0x5e,
|
||||
0x6a, 0x72, 0x32, 0x24, 0x16, 0x08, 0x09, 0x5f,
|
||||
0x6b, 0x33, 0x25, 0x17, 0x18, 0x0b, 0x0a, 0x60,
|
||||
0x6c, 0x34, 0x35, 0x26, 0x27, 0x19, 0x0c, 0x61,
|
||||
0x6d, 0x73, 0x28, 0x74, 0x1a, 0x0d, 0x62, 0x6e,
|
||||
0x3a, 0x36, 0x1c, 0x1b, 0x75, 0x2b, 0x63, 0x76,
|
||||
0x55, 0x56, 0x77, 0x78, 0x79, 0x7a, 0x0e, 0x7b,
|
||||
0x7c, 0x4f, 0x7d, 0x4b, 0x47, 0x7e, 0x7f, 0x6f,
|
||||
0x52, 0x53, 0x50, 0x4c, 0x4d, 0x48, 0x01, 0x45,
|
||||
0x57, 0x4e, 0x51, 0x4a, 0x37, 0x49, 0x46, 0x54,
|
||||
0x80, 0x81, 0x82, 0x41, 0x54, 0x85, 0x86, 0x87,
|
||||
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
|
||||
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
|
||||
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
|
||||
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
|
||||
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
|
||||
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
|
||||
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
|
||||
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
|
||||
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
|
||||
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
|
||||
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
|
||||
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
|
||||
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
|
||||
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Initialize the device for use by the user.
|
||||
*
|
||||
@@ -3767,9 +3816,142 @@ keyboard_at_init(const device_t *info)
|
||||
|
||||
keyboard_send = add_data_kbd;
|
||||
SavedKbd = dev;
|
||||
keyboard_update_states(0, 0, 0, 0);
|
||||
|
||||
inv_cmd_response = (dev->type & FLAG_PS2) ? 0xfe : 0xfa;
|
||||
|
||||
#ifdef SCAN_CODE_TABLES_COMPARISON
|
||||
pclog_toggle_suppr();
|
||||
|
||||
pclog("Scan code set 01 vs. 81 (make):\n===============================\n");
|
||||
for (int i = 0; i < 512; i++) {
|
||||
pclog("Scan code %03X:", i);
|
||||
int j = 0;
|
||||
do {
|
||||
if (scancode_set1[i].mk[j] == scancode_set81[i].mk[j])
|
||||
pclog(" --");
|
||||
else
|
||||
pclog(" (%02X != %02X)", scancode_set1[i].mk[j], scancode_set81[i].mk[j]);
|
||||
j++;
|
||||
} while ((scancode_set1[i].mk[j] != 0) && (scancode_set81[i].mk[j] != 0));
|
||||
pclog("\n");
|
||||
}
|
||||
|
||||
pclog("\nScan code set 01 vs. 81 (break):\n================================\n");
|
||||
for (int i = 0; i < 512; i++) {
|
||||
pclog("Scan code %03X:", i);
|
||||
int j = 0;
|
||||
do {
|
||||
if (scancode_set1[i].brk[j] == scancode_set81[i].brk[j])
|
||||
pclog(" --");
|
||||
else
|
||||
pclog(" (%02X != %02X)", scancode_set1[i].brk[j], scancode_set81[i].brk[j]);
|
||||
j++;
|
||||
} while ((scancode_set1[i].brk[j] != 0) && (scancode_set81[i].brk[j] != 0));
|
||||
pclog("\n");
|
||||
}
|
||||
|
||||
pclog("\nScan code set 02 vs. 82 (make):\n===============================\n");
|
||||
for (int i = 0; i < 512; i++) {
|
||||
pclog("Scan code %03X:", i);
|
||||
int j = 0;
|
||||
do {
|
||||
if (scancode_set2[i].mk[j] == scancode_set82[i].mk[j])
|
||||
pclog(" --");
|
||||
else
|
||||
pclog(" (%02X != %02X)", scancode_set2[i].mk[j], scancode_set82[i].mk[j]);
|
||||
j++;
|
||||
} while ((scancode_set2[i].mk[j] != 0) && (scancode_set82[i].mk[j] != 0));
|
||||
pclog("\n");
|
||||
}
|
||||
|
||||
pclog("\nScan code set 02 vs. 82 (break):\n================================\n");
|
||||
for (int i = 0; i < 512; i++) {
|
||||
pclog("Scan code %03X:", i);
|
||||
int j = 0;
|
||||
do {
|
||||
if (scancode_set2[i].brk[j] == scancode_set82[i].brk[j])
|
||||
pclog(" --");
|
||||
else
|
||||
pclog(" (%02X != %02X)", scancode_set2[i].brk[j], scancode_set82[i].brk[j]);
|
||||
j++;
|
||||
} while ((scancode_set2[i].brk[j] != 0) && (scancode_set82[i].brk[j] != 0));
|
||||
pclog("\n");
|
||||
}
|
||||
|
||||
pclog("\nScan code set 01 vs. 02 (make):\n===============================\n");
|
||||
for (int i = 0; i < 512; i++) {
|
||||
pclog("Scan code %03X:", i);
|
||||
int j = 0;
|
||||
int k = 0;
|
||||
int was_f0 = 0;
|
||||
do {
|
||||
if (scancode_set2[i].mk[k] == 0xf0)
|
||||
was_f0 = 1;
|
||||
else {
|
||||
uint8_t code = nont_to_t[scancode_set2[i].mk[k]];
|
||||
|
||||
if (was_f0) {
|
||||
if (code & 0x80)
|
||||
code = 0x00;
|
||||
else
|
||||
code |= 0x80;
|
||||
|
||||
was_f0 = 0;
|
||||
}
|
||||
|
||||
if (scancode_set1[i].mk[j] == code)
|
||||
pclog(" --");
|
||||
else
|
||||
pclog(" (%02X != %02X)", scancode_set1[i].mk[j], code);
|
||||
|
||||
j++;
|
||||
}
|
||||
|
||||
k++;
|
||||
} while ((scancode_set1[i].mk[j] != 0) && (scancode_set2[i].mk[k] != 0));
|
||||
pclog("\n");
|
||||
}
|
||||
|
||||
pclog("\nScan code set 01 vs. 02 (break):\n================================\n");
|
||||
for (int i = 0; i < 512; i++) {
|
||||
pclog("Scan code %03X:", i);
|
||||
int j = 0;
|
||||
int k = 0;
|
||||
int was_f0 = 0;
|
||||
do {
|
||||
if (scancode_set2[i].brk[k] == 0xf0)
|
||||
was_f0 = 1;
|
||||
else {
|
||||
uint8_t code = nont_to_t[scancode_set2[i].brk[k]];
|
||||
|
||||
if (was_f0) {
|
||||
if (code & 0x80)
|
||||
code = 0x00;
|
||||
else
|
||||
code |= 0x80;
|
||||
|
||||
was_f0 = 0;
|
||||
}
|
||||
|
||||
if (scancode_set1[i].brk[j] == code)
|
||||
pclog(" --");
|
||||
else
|
||||
pclog(" (%02X != %02X)", scancode_set1[i].brk[j], code);
|
||||
|
||||
j++;
|
||||
}
|
||||
|
||||
k++;
|
||||
} while ((scancode_set1[i].brk[j] != 0) && (scancode_set2[i].brk[k] != 0));
|
||||
pclog("\n");
|
||||
}
|
||||
|
||||
pclog_toggle_suppr();
|
||||
|
||||
fatal("Comparison finished\n");
|
||||
#endif
|
||||
|
||||
/* Return our private data to the I/O layer. */
|
||||
return dev;
|
||||
}
|
||||
@@ -3785,6 +3967,8 @@ keyboard_at_close(void *priv)
|
||||
/* Disable the scancode maps. */
|
||||
keyboard_set_table(NULL);
|
||||
|
||||
keyboard_update_states(0, 0, 0, 0);
|
||||
|
||||
SavedKbd = NULL;
|
||||
|
||||
free(dev);
|
||||
|
||||
@@ -742,7 +742,7 @@ kbd_adddata_process(uint16_t val, void (*adddata)(uint16_t val))
|
||||
if (!adddata)
|
||||
return;
|
||||
|
||||
keyboard_get_states(NULL, &num_lock, NULL);
|
||||
keyboard_get_states(NULL, &num_lock, NULL, NULL);
|
||||
shift_states = keyboard_get_shift() & STATE_LSHIFT;
|
||||
|
||||
if (is_amstrad)
|
||||
@@ -1312,7 +1312,6 @@ const device_t keyboard_xt_t1x00_device = {
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
#ifdef USE_LASERXT
|
||||
const device_t keyboard_xt_lxt3_device = {
|
||||
.name = "VTech Laser Turbo XT Keyboard",
|
||||
.internal_name = "keyboard_xt_lxt",
|
||||
@@ -1326,7 +1325,6 @@ const device_t keyboard_xt_lxt3_device = {
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
#endif /* USE_LASERXT */
|
||||
|
||||
const device_t keyboard_xt_olivetti_device = {
|
||||
.name = "Olivetti XT Keyboard",
|
||||
|
||||
@@ -83,23 +83,24 @@ static const device_t mouse_internal_device = {
|
||||
|
||||
static mouse_t mouse_devices[] = {
|
||||
// clang-format off
|
||||
{ &mouse_none_device },
|
||||
{ &mouse_internal_device },
|
||||
{ &mouse_logibus_device },
|
||||
{ &mouse_msinport_device },
|
||||
{ &mouse_none_device },
|
||||
{ &mouse_internal_device },
|
||||
{ &mouse_logibus_device },
|
||||
{ &mouse_msinport_device },
|
||||
#ifdef USE_GENIBUS
|
||||
{ &mouse_genibus_device },
|
||||
{ &mouse_genibus_device },
|
||||
#endif
|
||||
{ &mouse_mssystems_device },
|
||||
{ &mouse_msserial_device },
|
||||
{ &mouse_ltserial_device },
|
||||
{ &mouse_ps2_device },
|
||||
{ &mouse_mssystems_device },
|
||||
{ &mouse_mssystems_bus_device },
|
||||
{ &mouse_msserial_device },
|
||||
{ &mouse_ltserial_device },
|
||||
{ &mouse_ps2_device },
|
||||
#ifdef USE_WACOM
|
||||
{ &mouse_wacom_device },
|
||||
{ &mouse_wacom_artpad_device },
|
||||
{ &mouse_wacom_device },
|
||||
{ &mouse_wacom_artpad_device },
|
||||
#endif
|
||||
{ &mouse_mtouch_device },
|
||||
{ NULL }
|
||||
{ &mouse_mtouch_device },
|
||||
{ NULL }
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
|
||||
@@ -333,13 +333,13 @@ ps2_poll(void *priv)
|
||||
atkbc_dev_t *dev = (atkbc_dev_t *) priv;
|
||||
int packet_size = (dev->flags & FLAG_INTMODE) ? 4 : 3;
|
||||
|
||||
int cond = (!mouse_capture && !video_fullscreen) || (!mouse_scan || !mouse_state_changed()) ||
|
||||
((dev->mode == MODE_STREAM) && (kbc_at_dev_queue_pos(dev, 1) >= (FIFO_SIZE - packet_size)));
|
||||
int cond = (mouse_capture || video_fullscreen) && mouse_scan && (dev->mode == MODE_STREAM) &&
|
||||
mouse_state_changed() && (kbc_at_dev_queue_pos(dev, 1) < (FIFO_SIZE - packet_size));
|
||||
|
||||
if (!cond && (dev->mode == MODE_STREAM))
|
||||
if (cond)
|
||||
ps2_report_coordinates(dev, 1);
|
||||
|
||||
return cond;
|
||||
return !cond;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -146,7 +146,11 @@ sermouse_transmit_byte(mouse_t *dev, int do_next)
|
||||
serial_write_fifo(dev->serial, dev->buf[dev->buf_pos]);
|
||||
|
||||
if (do_next) {
|
||||
dev->buf_pos = (dev->buf_pos + 1) % dev->buf_len;
|
||||
/* If we have a buffer length of 0, pretend the state is STATE_SKIP_PACKET. */
|
||||
if (dev->buf_len == 0)
|
||||
dev->buf_pos = 0;
|
||||
else
|
||||
dev->buf_pos = (dev->buf_pos + 1) % dev->buf_len;
|
||||
|
||||
if (dev->buf_pos != 0)
|
||||
sermouse_set_period(dev, dev->transmit_period);
|
||||
@@ -747,7 +751,7 @@ sermouse_timer(void *priv)
|
||||
if (!dev->prompt && !dev->continuous)
|
||||
sermouse_transmit_report(dev, (dev->state == STATE_TRANSMIT_REPORT));
|
||||
else
|
||||
dev->state = STATE_IDLE;
|
||||
dev->state = STATE_IDLE;
|
||||
break;
|
||||
case STATE_TRANSMIT_REPORT:
|
||||
case STATE_TRANSMIT:
|
||||
@@ -829,10 +833,6 @@ sermouse_close(void *priv)
|
||||
{
|
||||
mouse_t *dev = (mouse_t *) priv;
|
||||
|
||||
/* Detach serial port from the mouse. */
|
||||
if (dev && dev->serial && dev->serial->sd)
|
||||
memset(dev->serial->sd, 0, sizeof(serial_device_t));
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
@@ -843,7 +843,15 @@ sermouse_init(const device_t *info)
|
||||
mouse_t *dev;
|
||||
void (*rcr_callback)(struct serial_s *serial, void *priv);
|
||||
void (*dev_write)(struct serial_s *serial, void *priv, uint8_t data);
|
||||
void (*transmit_period_callback)(struct serial_s *serial, void *priv, double transmit_period);
|
||||
void (*transmit_period_callback)(struct serial_s *serial, void *priv,
|
||||
double transmit_period);
|
||||
|
||||
if (info->local == MOUSE_TYPE_MSYSTEMSB) {
|
||||
uintptr_t irqbase = ((device_get_config_int("irq") << 16) |
|
||||
(device_get_config_hex16("addr") << 20)) |
|
||||
ns16450_device.local;
|
||||
device_add_params(&ns16450_device, (void*)irqbase);
|
||||
}
|
||||
|
||||
dev = (mouse_t *) calloc(1, sizeof(mouse_t));
|
||||
dev->name = info->name;
|
||||
@@ -858,7 +866,7 @@ sermouse_init(const device_t *info)
|
||||
if (dev->but > 2)
|
||||
dev->flags |= FLAG_3BTN;
|
||||
|
||||
if (info->local == MOUSE_TYPE_MSYSTEMS) {
|
||||
if (info->local == MOUSE_TYPE_MSYSTEMS || info->local == MOUSE_TYPE_MSYSTEMSB) {
|
||||
dev->format = 0;
|
||||
dev->type = info->local;
|
||||
dev->id_len = 1;
|
||||
@@ -889,7 +897,7 @@ sermouse_init(const device_t *info)
|
||||
}
|
||||
}
|
||||
|
||||
dev->port = device_get_config_int("port");
|
||||
dev->port = (info->local == MOUSE_TYPE_MSYSTEMSB) ? (SERIAL_MAX - 1) : device_get_config_int("port");
|
||||
|
||||
/* Attach a serial port to the mouse. */
|
||||
rcr_callback = dev->rts_toggle ? sermouse_callback : NULL;
|
||||
@@ -964,6 +972,78 @@ static const device_config_t msssermouse_config[] = {
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
static const device_config_t mssbusmouse_config[] = {
|
||||
// clang-format off
|
||||
{
|
||||
.name = "addr",
|
||||
.description = "Address",
|
||||
.type = CONFIG_HEX16,
|
||||
.default_string = NULL,
|
||||
.default_int = 0x238,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.selection = {
|
||||
{ .description = "0x338", .value = 0x338 },
|
||||
{ .description = "0x238", .value = 0x238 },
|
||||
{ .description = "0x3f8", .value = 0x3f8 },
|
||||
{ .description = "0x2f8", .value = 0x2f8 },
|
||||
{ .description = "" }
|
||||
},
|
||||
.bios = { { 0 } }
|
||||
},
|
||||
|
||||
{
|
||||
.name = "irq",
|
||||
.description = "IRQ",
|
||||
.type = CONFIG_SELECTION,
|
||||
.default_string = NULL,
|
||||
.default_int = 5,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.selection = {
|
||||
{ .description = "IRQ 2", .value = 2 },
|
||||
{ .description = "IRQ 3", .value = 3 },
|
||||
{ .description = "IRQ 4", .value = 4 },
|
||||
{ .description = "IRQ 5", .value = 5 },
|
||||
{ .description = "IRQ 7", .value = 7 },
|
||||
{ .description = "IRQ 10", .value = 10 },
|
||||
{ .description = "IRQ 11", .value = 11 },
|
||||
{ .description = "IRQ 12", .value = 12 },
|
||||
{ .description = "IRQ 15", .value = 15 },
|
||||
{ .description = "" }
|
||||
},
|
||||
.bios = { { 0 } }
|
||||
},
|
||||
{
|
||||
.name = "buttons",
|
||||
.description = "Buttons",
|
||||
.type = CONFIG_SELECTION,
|
||||
.default_string = NULL,
|
||||
.default_int = 2,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.selection = {
|
||||
{ .description = "Two", .value = 2 },
|
||||
{ .description = "Three", .value = 3 },
|
||||
{ .description = "" }
|
||||
},
|
||||
.bios = { { 0 } }
|
||||
},
|
||||
{
|
||||
.name = "rts_toggle",
|
||||
.description = "RTS toggle",
|
||||
.type = CONFIG_BINARY,
|
||||
.default_string = NULL,
|
||||
.default_int = 0,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.selection = { { 0 } },
|
||||
.bios = { { 0 } }
|
||||
},
|
||||
{ .name = "", .description = "", .type = CONFIG_END }
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
static const device_config_t mssermouse_config[] = {
|
||||
// clang-format off
|
||||
{
|
||||
@@ -1083,6 +1163,20 @@ const device_t mouse_mssystems_device = {
|
||||
.config = msssermouse_config
|
||||
};
|
||||
|
||||
const device_t mouse_mssystems_bus_device = {
|
||||
.name = "Mouse Systems Bus Mouse",
|
||||
.internal_name = "mssystems_bus",
|
||||
.flags = DEVICE_ISA,
|
||||
.local = MOUSE_TYPE_MSYSTEMSB,
|
||||
.init = sermouse_init,
|
||||
.close = sermouse_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = sermouse_speed_changed,
|
||||
.force_redraw = NULL,
|
||||
.config = mssbusmouse_config
|
||||
};
|
||||
|
||||
const device_t mouse_msserial_device = {
|
||||
.name = "Microsoft Serial Mouse",
|
||||
.internal_name = "msserial",
|
||||
|
||||
@@ -30,8 +30,10 @@
|
||||
#include <86box/mem.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/pci.h>
|
||||
#include <86box/plat_fallthrough.h>
|
||||
|
||||
#define PCI_BRIDGE_DEC_21150 0x10110022
|
||||
#define PCI_BRIDGE_DEC_21152 0x10110024
|
||||
#define AGP_BRIDGE_ALI_M5243 0x10b95243
|
||||
#define AGP_BRIDGE_ALI_M5247 0x10b95247
|
||||
#define AGP_BRIDGE_INTEL_440LX 0x80867181
|
||||
@@ -85,6 +87,14 @@ pci_bridge_set_ctl(void *priv, uint8_t ctl)
|
||||
dev->ctl = ctl;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
pci_bridge_get_bus_index(void *priv)
|
||||
{
|
||||
pci_bridge_t *dev = (pci_bridge_t *) priv;
|
||||
|
||||
return dev->bus_index;
|
||||
}
|
||||
|
||||
static void
|
||||
pci_bridge_write(int func, int addr, uint8_t val, void *priv)
|
||||
{
|
||||
@@ -242,12 +252,15 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv)
|
||||
case 0x40:
|
||||
if (dev->local == PCI_BRIDGE_DEC_21150)
|
||||
val &= 0x32;
|
||||
else if (dev->local == PCI_BRIDGE_DEC_21152)
|
||||
val &= 0x12;
|
||||
break;
|
||||
|
||||
case 0x41:
|
||||
if (AGP_BRIDGE_VIA(dev->local))
|
||||
val &= 0x7e;
|
||||
else if (dev->local == PCI_BRIDGE_DEC_21150)
|
||||
else if ((dev->local == PCI_BRIDGE_DEC_21150) ||
|
||||
(dev->local == PCI_BRIDGE_DEC_21152))
|
||||
val &= 0x07;
|
||||
break;
|
||||
|
||||
@@ -257,18 +270,22 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv)
|
||||
break;
|
||||
|
||||
case 0x43:
|
||||
if (dev->local == PCI_BRIDGE_DEC_21150)
|
||||
if ((dev->local == PCI_BRIDGE_DEC_21150) ||
|
||||
(dev->local == PCI_BRIDGE_DEC_21152))
|
||||
val &= 0x03;
|
||||
break;
|
||||
|
||||
case 0x64:
|
||||
if (dev->local == PCI_BRIDGE_DEC_21150)
|
||||
if ((dev->local == PCI_BRIDGE_DEC_21150) ||
|
||||
(dev->local == PCI_BRIDGE_DEC_21152))
|
||||
val &= 0x7e;
|
||||
break;
|
||||
|
||||
case 0x69:
|
||||
if (dev->local == PCI_BRIDGE_DEC_21150)
|
||||
val &= 0x3f;
|
||||
else if (dev->local == PCI_BRIDGE_DEC_21152)
|
||||
val = (val & 0x01) | 0x3e;
|
||||
break;
|
||||
|
||||
case 0x86:
|
||||
@@ -302,6 +319,15 @@ pci_bridge_write(int func, int addr, uint8_t val, void *priv)
|
||||
break;
|
||||
|
||||
case 0xe0:
|
||||
if (AGP_BRIDGE_ALI(dev->local)) {
|
||||
if (!(dev->ctl & 0x20))
|
||||
return;
|
||||
} else if (dev->local == PCI_BRIDGE_DEC_21152)
|
||||
val &= 0x03;
|
||||
else
|
||||
return;
|
||||
break;
|
||||
|
||||
case 0xe1:
|
||||
if (AGP_BRIDGE_ALI(dev->local)) {
|
||||
if (!(dev->ctl & 0x20))
|
||||
@@ -399,6 +425,14 @@ pci_bridge_reset(void *priv)
|
||||
|
||||
/* command and status */
|
||||
switch (dev->local) {
|
||||
case PCI_BRIDGE_DEC_21152:
|
||||
dev->regs[0x08] = 0x03;
|
||||
dev->regs[0x34] = 0xdc;
|
||||
dev->regs[0x69] = 0x3e;
|
||||
dev->regs[0xdc] = 0x01;
|
||||
dev->regs[0xde] = 0x01;
|
||||
dev->regs[0xe2] = 0x80;
|
||||
fallthrough;
|
||||
case PCI_BRIDGE_DEC_21150:
|
||||
dev->regs[0x06] = 0x80;
|
||||
dev->regs[0x07] = 0x02;
|
||||
@@ -487,8 +521,8 @@ static void *
|
||||
pci_bridge_init(const device_t *info)
|
||||
{
|
||||
uint8_t interrupts[4];
|
||||
uint8_t interrupt_count;
|
||||
uint8_t interrupt_mask;
|
||||
uint8_t add_type;
|
||||
uint8_t slot_count;
|
||||
|
||||
pci_bridge_t *dev = (pci_bridge_t *) calloc(1, sizeof(pci_bridge_t));
|
||||
@@ -499,22 +533,27 @@ pci_bridge_init(const device_t *info)
|
||||
|
||||
pci_bridge_reset(dev);
|
||||
|
||||
pci_add_bridge(AGP_BRIDGE(dev->local), pci_bridge_read, pci_bridge_write, dev, &dev->slot);
|
||||
|
||||
interrupt_count = sizeof(interrupts);
|
||||
interrupt_mask = interrupt_count - 1;
|
||||
interrupt_mask = sizeof(interrupts) - 1;
|
||||
if (dev->slot < 32) {
|
||||
for (uint8_t i = 0; i < interrupt_count; i++)
|
||||
for (uint8_t i = 0; i <= interrupt_mask; i++)
|
||||
interrupts[i] = pci_get_int(dev->slot, PCI_INTA + i);
|
||||
}
|
||||
pci_bridge_log("PCI Bridge %d: upstream bus %02X slot %02X interrupts %02X %02X %02X %02X\n",
|
||||
dev->bus_index, (dev->slot >> 5) & 0xff, dev->slot & 31, interrupts[0],
|
||||
interrupts[1], interrupts[2], interrupts[3]);
|
||||
|
||||
if (info->local == PCI_BRIDGE_DEC_21150)
|
||||
if (info->local == PCI_BRIDGE_DEC_21150) {
|
||||
slot_count = 9; /* 9 bus masters */
|
||||
else
|
||||
add_type = PCI_ADD_NORMAL;
|
||||
} else if (info->local == PCI_BRIDGE_DEC_21152) {
|
||||
slot_count = 0; /* 4 bus masters, but slots are added by the Dell machines */
|
||||
add_type = PCI_ADD_BRIDGE;
|
||||
} else {
|
||||
slot_count = 1; /* AGP bridges always have 1 slot */
|
||||
add_type = PCI_ADD_AGPBRIDGE;
|
||||
}
|
||||
|
||||
pci_add_bridge(add_type, pci_bridge_read, pci_bridge_write, dev, &dev->slot);
|
||||
|
||||
for (uint8_t i = 0; i < slot_count; i++) {
|
||||
/* Interrupts for bridge slots are assigned in round-robin: ABCD, BCDA, CDAB and so on. */
|
||||
@@ -547,6 +586,20 @@ const device_t dec21150_device = {
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t dec21152_device = {
|
||||
.name = "DEC 21152 PCI Bridge",
|
||||
.internal_name = "dec21152",
|
||||
.flags = DEVICE_PCI,
|
||||
.local = PCI_BRIDGE_DEC_21152,
|
||||
.init = pci_bridge_init,
|
||||
.close = NULL,
|
||||
.reset = pci_bridge_reset,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
/* AGP bridges */
|
||||
const device_t ali5243_agp_device = {
|
||||
.name = "ALi M5243 AGP Bridge",
|
||||
|
||||
@@ -30,11 +30,14 @@
|
||||
#include "cpu.h"
|
||||
|
||||
uint8_t postcard_codes[POSTCARDS_NUM];
|
||||
char postcard_diags[5] = { 0 };
|
||||
|
||||
static uint16_t postcard_port;
|
||||
static uint8_t postcard_written[POSTCARDS_NUM];
|
||||
static uint8_t postcard_ports_num = 1;
|
||||
static uint8_t postcard_prev_codes[POSTCARDS_NUM];
|
||||
static uint8_t postcard_dell_mode = 0;
|
||||
static char postcard_prev_diags[5] = { 0 };
|
||||
#define UISTR_LEN 32
|
||||
static char postcard_str[UISTR_LEN]; /* UI output string */
|
||||
|
||||
@@ -98,12 +101,22 @@ postcard_setui(void)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
char dell_diags[11] = { 0 };
|
||||
if (postcard_dell_mode) {
|
||||
if (!postcard_written[1])
|
||||
snprintf(dell_diags, sizeof(dell_diags), " ---- ----");
|
||||
else if (postcard_written[1] == 1)
|
||||
snprintf(dell_diags, sizeof(dell_diags), " %s ----", postcard_diags);
|
||||
else
|
||||
snprintf(dell_diags, sizeof(dell_diags), " %s %s", postcard_diags, postcard_prev_diags);
|
||||
}
|
||||
|
||||
if (!postcard_written[0])
|
||||
snprintf(postcard_str, sizeof(postcard_str), "POST: -- --");
|
||||
snprintf(postcard_str, sizeof(postcard_str), "POST: -- --%s", dell_diags);
|
||||
else if (postcard_written[0] == 1)
|
||||
snprintf(postcard_str, sizeof(postcard_str), "POST: %02X --", postcard_codes[0]);
|
||||
snprintf(postcard_str, sizeof(postcard_str), "POST: %02X --%s", postcard_codes[0], dell_diags);
|
||||
else
|
||||
snprintf(postcard_str, sizeof(postcard_str), "POST: %02X %02X", postcard_codes[0], postcard_prev_codes[0]);
|
||||
snprintf(postcard_str, sizeof(postcard_str), "POST: %02X %02X%s", postcard_codes[0], postcard_prev_codes[0], dell_diags);
|
||||
}
|
||||
|
||||
ui_sb_bugui(postcard_str);
|
||||
@@ -122,6 +135,9 @@ postcard_reset(void)
|
||||
memset(postcard_codes, 0x00, POSTCARDS_NUM * sizeof(uint8_t));
|
||||
memset(postcard_prev_codes, 0x00, POSTCARDS_NUM * sizeof(uint8_t));
|
||||
|
||||
memset(postcard_diags, 0x00, 5 * sizeof(char));
|
||||
memset(postcard_prev_diags, 0x00, 5 * sizeof(char));
|
||||
|
||||
postcard_setui();
|
||||
}
|
||||
|
||||
@@ -140,6 +156,35 @@ postcard_write(uint16_t port, uint8_t val, UNUSED(void *priv))
|
||||
postcard_setui();
|
||||
}
|
||||
|
||||
static int
|
||||
postcard_cmp_diags(uint32_t val)
|
||||
{
|
||||
int ret = 0;
|
||||
char *pv = (char *) &val;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
ret = ret || (pv[i] != postcard_diags[3 - i]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
postcard_writel(uint16_t port, uint32_t val, UNUSED(void *priv))
|
||||
{
|
||||
char *pv = (char *) &val;
|
||||
|
||||
if (postcard_written[1] && !postcard_cmp_diags(val))
|
||||
return;
|
||||
|
||||
*(uint32_t *) postcard_prev_diags = *(uint32_t *) postcard_diags;
|
||||
for (int i = 0; i < 4; i++)
|
||||
postcard_diags[i] = pv[3 - i];
|
||||
if (postcard_written[1] < 2)
|
||||
postcard_written[1]++;
|
||||
|
||||
postcard_setui();
|
||||
}
|
||||
|
||||
static void *
|
||||
postcard_init(UNUSED(const device_t *info))
|
||||
{
|
||||
@@ -147,17 +192,22 @@ postcard_init(UNUSED(const device_t *info))
|
||||
|
||||
if (machine_has_bus(machine, MACHINE_BUS_MCA))
|
||||
postcard_port = 0x680; /* MCA machines */
|
||||
else if (strstr(machines[machine].name, " PS/2 ") || strstr(machine_getname_ex(machine), " PS/1 "))
|
||||
else if (strstr(machines[machine].name, " PS/2 ") ||
|
||||
strstr(machine_getname_ex(machine), " PS/1 "))
|
||||
postcard_port = 0x190; /* ISA PS/2 machines */
|
||||
else if (strstr(machines[machine].name, " IBM XT "))
|
||||
postcard_port = 0x60; /* IBM XT */
|
||||
else if (strstr(machines[machine].name, " IBM PCjr")) {
|
||||
postcard_port = 0x10; /* IBM PCjr */
|
||||
postcard_ports_num = 3; /* IBM PCjr error ports 11h and 12h */
|
||||
} else if (strstr(machines[machine].name, " Compaq ") && !machine_has_bus(machine, MACHINE_BUS_PCI))
|
||||
} else if (strstr(machines[machine].name, " Compaq ") &&
|
||||
!strstr(machines[machine].name, " Presario ") &&
|
||||
!strstr(machines[machine].name, " ProSignia "))
|
||||
postcard_port = 0x84; /* ISA Compaq machines */
|
||||
else if (strstr(machines[machine].name, "Olivetti"))
|
||||
postcard_port = 0x378; /* Olivetti machines */
|
||||
else if (!strcmp(machines[machine].internal_name, "isa486c"))
|
||||
postcard_port = 0x5080; /* ASUS ISA-486C */
|
||||
else
|
||||
postcard_port = 0x80; /* AT and clone machines */
|
||||
postcard_log("POST card initializing on port %04Xh\n", postcard_port);
|
||||
@@ -168,6 +218,12 @@ postcard_init(UNUSED(const device_t *info))
|
||||
io_sethandler(postcard_port, postcard_ports_num,
|
||||
NULL, NULL, NULL, postcard_write, NULL, NULL, NULL);
|
||||
|
||||
postcard_dell_mode = strstr(machines[machine].name, " Dell ") &&
|
||||
(machine_get_chipset(machine) >= MACHINE_CHIPSET_INTEL_430FX);
|
||||
if (postcard_dell_mode)
|
||||
io_sethandler(is486 ? 0x00e0 : 0x00e4, 0x0001,
|
||||
NULL, NULL, NULL, NULL, NULL, postcard_writel, NULL);
|
||||
|
||||
return postcard_write;
|
||||
}
|
||||
|
||||
|
||||
@@ -884,10 +884,10 @@ serial_close(void *priv)
|
||||
{
|
||||
serial_t *dev = (serial_t *) priv;
|
||||
|
||||
next_inst--;
|
||||
|
||||
if (com_ports[dev->inst].enabled)
|
||||
if (dev->sd) {
|
||||
memset(dev->sd, 0, sizeof(serial_device_t));
|
||||
fifo_close(dev->rcvr_fifo);
|
||||
}
|
||||
|
||||
free(dev);
|
||||
}
|
||||
@@ -897,7 +897,7 @@ serial_reset(void *priv)
|
||||
{
|
||||
serial_t *dev = (serial_t *) priv;
|
||||
|
||||
if (com_ports[dev->inst].enabled) {
|
||||
if (dev->sd) {
|
||||
timer_disable(&dev->transmit_timer);
|
||||
timer_disable(&dev->timeout_timer);
|
||||
timer_disable(&dev->receive_timer);
|
||||
@@ -930,16 +930,26 @@ static void *
|
||||
serial_init(const device_t *info)
|
||||
{
|
||||
serial_t *dev = (serial_t *) calloc(1, sizeof(serial_t));
|
||||
int orig_inst = next_inst;
|
||||
|
||||
if (info->local & 0xFFF00000)
|
||||
next_inst = SERIAL_MAX - 1;
|
||||
|
||||
dev->inst = next_inst;
|
||||
|
||||
if (com_ports[next_inst].enabled) {
|
||||
if (com_ports[next_inst].enabled || (info->local & 0xFFF00000)) {
|
||||
serial_log("Adding serial port %i...\n", next_inst);
|
||||
dev->type = info->local;
|
||||
memset(&(serial_devices[next_inst]), 0, sizeof(serial_device_t));
|
||||
dev->sd = &(serial_devices[next_inst]);
|
||||
dev->sd->serial = dev;
|
||||
if (next_inst == 6)
|
||||
|
||||
if (info->local & 0xfff00000) {
|
||||
dev->base_address = info->local >> 20;
|
||||
dev->irq = (info->local >> 16) & 0xF;
|
||||
io_sethandler(dev->base_address, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, dev);
|
||||
next_inst = orig_inst;
|
||||
} else if (next_inst == 6)
|
||||
serial_setup(dev, COM7_ADDR, COM7_IRQ);
|
||||
else if (next_inst == 5)
|
||||
serial_setup(dev, COM6_ADDR, COM6_IRQ);
|
||||
@@ -984,7 +994,8 @@ serial_init(const device_t *info)
|
||||
serial_reset_port(dev);
|
||||
}
|
||||
|
||||
next_inst++;
|
||||
if (!(info->local & 0xfff00000))
|
||||
next_inst++;
|
||||
|
||||
return dev;
|
||||
}
|
||||
@@ -998,7 +1009,7 @@ serial_set_next_inst(int ni)
|
||||
void
|
||||
serial_standalone_init(void)
|
||||
{
|
||||
while (next_inst < SERIAL_MAX)
|
||||
while (next_inst < (SERIAL_MAX - 1))
|
||||
device_add_inst(&ns8250_device, next_inst + 1);
|
||||
};
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ serial_passthrough_log(const char *fmt, ...)
|
||||
void
|
||||
serial_passthrough_init(void)
|
||||
{
|
||||
for (uint8_t c = 0; c < SERIAL_MAX; c++) {
|
||||
for (uint8_t c = 0; c < (SERIAL_MAX - 1); c++) {
|
||||
if (serial_passthrough_enabled[c]) {
|
||||
/* Instance n for COM n */
|
||||
device_add_inst(&serial_passthrough_device, c + 1);
|
||||
|
||||
@@ -31,6 +31,7 @@ add_library(hdd OBJECT
|
||||
hdc_ide_opti611.c
|
||||
hdc_ide_cmd640.c
|
||||
hdc_ide_cmd646.c
|
||||
hdc_ide_rz1000.c
|
||||
hdc_ide_sff8038i.c
|
||||
hdc_ide_um8673f.c
|
||||
hdc_ide_w83769f.c
|
||||
|
||||
@@ -395,7 +395,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv)
|
||||
fatal("Write with ECC\n");
|
||||
esdi->status = STAT_READY | STAT_DRQ | STAT_DSC;
|
||||
esdi->pos = 0;
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 1);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 1);
|
||||
break;
|
||||
|
||||
case CMD_VERIFY:
|
||||
@@ -412,7 +412,7 @@ esdi_write(uint16_t port, uint8_t val, void *priv)
|
||||
case CMD_FORMAT:
|
||||
esdi->status = STAT_DRQ;
|
||||
esdi->pos = 0;
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 1);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 1);
|
||||
break;
|
||||
|
||||
case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */
|
||||
@@ -593,6 +593,7 @@ esdi_callback(void *priv)
|
||||
esdi->reset = 0;
|
||||
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -650,7 +651,7 @@ read_error:
|
||||
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
|
||||
esdi->error = ERR_ABRT;
|
||||
irq_raise(esdi);
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
break;
|
||||
} else {
|
||||
if (get_sector(esdi, &addr)) {
|
||||
@@ -658,7 +659,7 @@ read_error:
|
||||
write_error:
|
||||
esdi->status = STAT_READY | STAT_DSC | STAT_ERR;
|
||||
irq_raise(esdi);
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -672,10 +673,10 @@ write_error:
|
||||
esdi->status = STAT_DRQ | STAT_READY | STAT_DSC;
|
||||
esdi->pos = 0;
|
||||
next_sector(esdi);
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 1);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 1);
|
||||
} else {
|
||||
esdi->status = STAT_READY | STAT_DSC;
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -718,7 +719,7 @@ verify_error:
|
||||
break;
|
||||
|
||||
case CMD_FORMAT:
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
if (!drive->present) {
|
||||
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
|
||||
esdi->error = ERR_ABRT;
|
||||
@@ -752,10 +753,12 @@ format_error:
|
||||
esdi->status = STAT_READY | STAT_DSC;
|
||||
irq_raise(esdi);
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
break;
|
||||
|
||||
case CMD_SET_PARAMETERS: /* Initialize Drive Parameters */
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
if (!drive->present) {
|
||||
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
|
||||
esdi->error = ERR_ABRT;
|
||||
@@ -778,10 +781,12 @@ format_error:
|
||||
esdi->error = ERR_ABRT;
|
||||
irq_raise(esdi);
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
break;
|
||||
|
||||
case 0xe0:
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
if (!drive->present) {
|
||||
esdi->status = STAT_READY | STAT_ERR | STAT_DSC;
|
||||
esdi->error = ERR_ABRT;
|
||||
@@ -825,6 +830,7 @@ format_error:
|
||||
}
|
||||
irq_raise(esdi);
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
break;
|
||||
|
||||
case CMD_READ_PARAMETERS:
|
||||
@@ -869,6 +875,7 @@ format_error:
|
||||
irq_raise(esdi);
|
||||
}
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -880,6 +887,7 @@ format_error:
|
||||
esdi->error = ERR_ABRT;
|
||||
irq_raise(esdi);
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -954,6 +962,7 @@ wd1007vse1_init(UNUSED(const device_t *info))
|
||||
timer_add(&esdi->callback_timer, esdi_callback, esdi, 0);
|
||||
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
|
||||
return esdi;
|
||||
}
|
||||
@@ -973,6 +982,7 @@ wd1007vse1_close(void *priv)
|
||||
free(esdi);
|
||||
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
|
||||
@@ -288,6 +288,7 @@ cmd_unsupported(esdi_t *dev)
|
||||
dev->irq_in_progress = 1;
|
||||
set_irq(dev);
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -309,6 +310,7 @@ device_not_present(esdi_t *dev)
|
||||
dev->irq_in_progress = 1;
|
||||
set_irq(dev);
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -330,6 +332,7 @@ rba_out_of_range(esdi_t *dev)
|
||||
dev->irq_in_progress = 1;
|
||||
set_irq(dev);
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -351,6 +354,7 @@ defective_block(esdi_t *dev)
|
||||
dev->irq_in_progress = 1;
|
||||
set_irq(dev);
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -368,6 +372,7 @@ complete_command_status(esdi_t *dev)
|
||||
dev->status_data[5] = (dev->rba - 1) >> 8;
|
||||
dev->status_data[6] = 0; /*Number of blocks requiring error recovery*/
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
}
|
||||
|
||||
#define ESDI_ADAPTER_ONLY() \
|
||||
@@ -696,6 +701,7 @@ esdi_callback(void *priv)
|
||||
dev->irq_in_progress = 1;
|
||||
set_irq(dev);
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
break;
|
||||
|
||||
case CMD_GET_DEV_CONFIG:
|
||||
@@ -744,6 +750,7 @@ esdi_callback(void *priv)
|
||||
dev->irq_in_progress = 1;
|
||||
set_irq(dev);
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
break;
|
||||
|
||||
case CMD_GET_POS_INFO:
|
||||
@@ -764,6 +771,7 @@ esdi_callback(void *priv)
|
||||
dev->irq_in_progress = 1;
|
||||
set_irq(dev);
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
break;
|
||||
|
||||
case 0x10:
|
||||
@@ -817,6 +825,7 @@ esdi_callback(void *priv)
|
||||
dev->irq_in_progress = 1;
|
||||
set_irq(dev);
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_ESDI, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -1208,7 +1208,9 @@ ide_atapi_pio_request(ide_t *ide, uint8_t out)
|
||||
ide->tf->atastat = BSY_STAT;
|
||||
|
||||
if (ide->tf->pos >= dev->packet_len) {
|
||||
ide_log("%i bytes %s, command done\n", ide->tf->pos, out ? "written" : "read");
|
||||
// ide_log("%i bytes %s, command done\n", ide->tf->pos, out ? "written" : "read");
|
||||
ide_log("%i bytes %s, command done, %i sectors left\n", ide->tf->pos, out ? "written" : "read",
|
||||
dev->sector_len);
|
||||
|
||||
ide->tf->pos = dev->request_pos = 0;
|
||||
|
||||
@@ -1262,13 +1264,12 @@ ide_atapi_pio_request(ide_t *ide, uint8_t out)
|
||||
ide_atapi_callback(ide);
|
||||
ide_set_callback(ide, 0.0);
|
||||
} else {
|
||||
ide->sc->packet_status = PHASE_COMPLETE;
|
||||
ide->sc->callback = 0.0;
|
||||
|
||||
if (ide->phase_data_out != NULL)
|
||||
(void) ide->phase_data_out(dev);
|
||||
|
||||
ide_atapi_callback(ide);
|
||||
if ((ide->sc->packet_status == PHASE_COMPLETE) &&
|
||||
(ide->sc->callback == 0.0))
|
||||
ide_atapi_callback(ide);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -1280,10 +1281,9 @@ ide_atapi_pio_request(ide_t *ide, uint8_t out)
|
||||
if (ide->command_stop != NULL)
|
||||
ide->command_stop(dev);
|
||||
|
||||
ide->sc->packet_status = PHASE_COMPLETE;
|
||||
ide->sc->callback = 0.0;
|
||||
|
||||
ide_atapi_callback(ide);
|
||||
if ((ide->sc->packet_status == PHASE_COMPLETE) &&
|
||||
(ide->sc->callback == 0.0))
|
||||
ide_atapi_callback(ide);
|
||||
}
|
||||
} else if (ide->read != NULL)
|
||||
ide->read(dev);
|
||||
@@ -1299,8 +1299,8 @@ ide_atapi_packet_read(ide_t *ide)
|
||||
uint16_t ret = 0;
|
||||
|
||||
if (dev && dev->temp_buffer && (dev->packet_status == PHASE_DATA_IN)) {
|
||||
ide_log("PHASE_DATA_IN read: %i, %i, %i, %i\n",
|
||||
dev->request_pos, dev->max_transfer_len, ide->tf->pos, dev->packet_len);
|
||||
/* ide_log("PHASE_DATA_IN read: %i, %i, %i, %i\n",
|
||||
dev->request_pos, dev->max_transfer_len, ide->tf->pos, dev->packet_len); */
|
||||
|
||||
bufferw = (uint16_t *) dev->temp_buffer;
|
||||
|
||||
@@ -1722,7 +1722,8 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv)
|
||||
break;
|
||||
|
||||
case 0x7: /* Command register */
|
||||
if (ide->tf->atastat & (BSY_STAT | DRQ_STAT))
|
||||
if ((ide->tf->atastat & (BSY_STAT | DRQ_STAT)) &&
|
||||
((val != WIN_SRST) || (ide->type != IDE_ATAPI)))
|
||||
break;
|
||||
|
||||
if ((ide->type == IDE_NONE) || ((ide->type & IDE_SHADOW) && (val != WIN_DRIVE_DIAGNOSTICS)))
|
||||
@@ -1826,7 +1827,7 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv)
|
||||
ide->blockcount = 0;
|
||||
/* Turn on the activity indicator *here* so that it gets turned on
|
||||
less times. */
|
||||
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus_type, 1);
|
||||
ui_sb_update_icon_write(SB_HDD | hdd[ide->hdd_num].bus_type, 1);
|
||||
fallthrough;
|
||||
|
||||
case WIN_WRITE:
|
||||
@@ -2158,7 +2159,8 @@ ide_read_alt_status(UNUSED(const uint16_t addr), void *priv)
|
||||
if (!(addr & 0x0001))
|
||||
ret = ide_status(ide, ide_drives[ch ^ 1], ch);
|
||||
|
||||
ide_log("[%04X:%08X] ide_read_alt_status(%04X, %08X) = %02X\n", CS, cpu_state.pc, addr, priv, ret);
|
||||
// ide_log("[%04X:%08X] ide_read_alt_status(%04X, %08X) = %02X\n", CS, cpu_state.pc, addr, priv, ret);
|
||||
// ide_log("ide_read_alt_status(%04X, %08X) = %02X\n", CS, cpu_state.pc, addr, priv, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -2470,6 +2472,7 @@ ide_callback(void *priv)
|
||||
else if (!ide->tf->lba && (ide->cfg_spt == 0))
|
||||
err = IDNF_ERR;
|
||||
else {
|
||||
ui_sb_update_icon_write(SB_HDD | hdd[ide->hdd_num].bus_type, 1);
|
||||
ret = hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer);
|
||||
ide_irq_raise(ide);
|
||||
ide->tf->secount--;
|
||||
@@ -2477,10 +2480,8 @@ ide_callback(void *priv)
|
||||
ide->tf->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT;
|
||||
ide->tf->pos = 0;
|
||||
ide_next_sector(ide);
|
||||
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus_type, 1);
|
||||
} else {
|
||||
ide->tf->atastat = DRDY_STAT | DSC_STAT;
|
||||
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus_type, 0);
|
||||
}
|
||||
if (ret < 0)
|
||||
err = UNC_ERR;
|
||||
@@ -2512,6 +2513,7 @@ ide_callback(void *priv)
|
||||
return;
|
||||
} else if (ret & 1) {
|
||||
/* DMA successful */
|
||||
ui_sb_update_icon_write(SB_HDD | hdd[ide->hdd_num].bus_type, 1);
|
||||
ret = hdd_image_write(ide->hdd_num, ide_get_sector(ide),
|
||||
ide->sector_pos, ide->sector_buffer);
|
||||
|
||||
@@ -2522,7 +2524,6 @@ ide_callback(void *priv)
|
||||
err = UNC_ERR;
|
||||
|
||||
ide_irq_raise(ide);
|
||||
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus_type, 0);
|
||||
} else {
|
||||
/* Bus master DMA error, abort the command. */
|
||||
ide_log("IDE %i: DMA read aborted (failed)\n", ide->channel);
|
||||
@@ -2560,7 +2561,7 @@ ide_callback(void *priv)
|
||||
ide_next_sector(ide);
|
||||
} else {
|
||||
ide->tf->atastat = DRDY_STAT | DSC_STAT;
|
||||
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus_type, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | hdd[ide->hdd_num].bus_type, 0);
|
||||
}
|
||||
if (ret < 0)
|
||||
err = UNC_ERR;
|
||||
@@ -2594,7 +2595,7 @@ ide_callback(void *priv)
|
||||
err = UNC_ERR;
|
||||
ide_irq_raise(ide);
|
||||
|
||||
ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus_type, 1);
|
||||
ui_sb_update_icon_write(SB_HDD | hdd[ide->hdd_num].bus_type, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -3159,6 +3160,13 @@ ide_init(const device_t *info)
|
||||
ide_board_init(1, HDC_SECONDARY_IRQ, HDC_SECONDARY_BASE, HDC_SECONDARY_SIDE, info->local, info->flags);
|
||||
break;
|
||||
|
||||
case 8 ... 0x0d:
|
||||
ide_board_init(2, -1, 0, 0, info->local, info->flags);
|
||||
|
||||
if (info->local & 1)
|
||||
ide_board_init(3, -1, 0, 0, info->local, info->flags);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -3540,7 +3548,7 @@ const device_t mcide_device = {
|
||||
.name = "MCA McIDE Controller",
|
||||
.internal_name = "ide_mcide",
|
||||
.flags = DEVICE_MCA,
|
||||
.local = 3,
|
||||
.local = 1,
|
||||
.init = mcide_init,
|
||||
.close = mcide_close,
|
||||
.reset = mcide_reset,
|
||||
@@ -3661,3 +3669,17 @@ const device_t ide_qua_pnp_device = {
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t ide_pci_ter_qua_2ch_device = {
|
||||
.name = "PCI IDE Controller (Dual-Channel Tertiary/Quaternary)",
|
||||
.internal_name = "ide_pci_ter_qua_2ch",
|
||||
.flags = DEVICE_PCI,
|
||||
.local = 0x0d,
|
||||
.init = ide_init,
|
||||
.close = ide_close,
|
||||
.reset = ide_reset,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
289
src/disk/hdc_ide_rz1000.c
Normal file
289
src/disk/hdc_ide_rz1000.c
Normal file
@@ -0,0 +1,289 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Implementation of the PC Technology RZ-1000 controller.
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2025 Miran Grca.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include <86box/86box.h>
|
||||
#include <86box/cdrom.h>
|
||||
#include <86box/scsi_device.h>
|
||||
#include <86box/scsi_cdrom.h>
|
||||
#include <86box/dma.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/keyboard.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/pci.h>
|
||||
#include <86box/pic.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/hdc.h>
|
||||
#include <86box/hdc_ide.h>
|
||||
#include <86box/hdc_ide_sff8038i.h>
|
||||
#include <86box/zip.h>
|
||||
#include <86box/mo.h>
|
||||
|
||||
typedef struct rz1000_t {
|
||||
uint8_t vlb_idx;
|
||||
uint8_t id;
|
||||
uint8_t in_cfg;
|
||||
uint8_t channels;
|
||||
uint8_t pci;
|
||||
uint8_t irq_state;
|
||||
uint8_t pci_slot;
|
||||
uint8_t pad0;
|
||||
uint8_t regs[256];
|
||||
uint32_t local;
|
||||
int irq_mode[2];
|
||||
int irq_pin;
|
||||
int irq_line;
|
||||
} rz1000_t;
|
||||
|
||||
static int next_id = 0;
|
||||
|
||||
#ifdef ENABLE_RZ1000_LOG
|
||||
int rz1000_do_log = ENABLE_RZ1000_LOG;
|
||||
|
||||
static void
|
||||
rz1000_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (rz1000_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
# define rz1000_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
static void
|
||||
rz1000_ide_handlers(rz1000_t *dev)
|
||||
{
|
||||
uint16_t main;
|
||||
uint16_t side;
|
||||
|
||||
if (dev->channels & 0x01) {
|
||||
ide_pri_disable();
|
||||
|
||||
main = 0x1f0;
|
||||
side = 0x3f6;
|
||||
|
||||
ide_set_base(0, main);
|
||||
ide_set_side(0, side);
|
||||
|
||||
if (dev->regs[0x04] & 0x01)
|
||||
ide_pri_enable();
|
||||
}
|
||||
|
||||
if (dev->channels & 0x02) {
|
||||
ide_sec_disable();
|
||||
|
||||
main = 0x170;
|
||||
side = 0x376;
|
||||
|
||||
ide_set_base(1, main);
|
||||
ide_set_side(1, side);
|
||||
|
||||
if (dev->regs[0x04] & 0x01)
|
||||
ide_sec_enable();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rz1000_pci_write(int func, int addr, uint8_t val, void *priv)
|
||||
{
|
||||
rz1000_t *dev = (rz1000_t *) priv;
|
||||
|
||||
rz1000_log("rz1000_pci_write(%i, %02X, %02X)\n", func, addr, val);
|
||||
|
||||
if (func == 0x00)
|
||||
switch (addr) {
|
||||
case 0x04:
|
||||
dev->regs[addr] = (val & 0x41);
|
||||
rz1000_ide_handlers(dev);
|
||||
break;
|
||||
case 0x07:
|
||||
dev->regs[addr] &= ~(val & 0x80);
|
||||
break;
|
||||
case 0x09:
|
||||
if ((dev->regs[addr] & 0x0a) == 0x0a) {
|
||||
dev->regs[addr] = (dev->regs[addr] & 0x0a) | (val & 0x05);
|
||||
dev->irq_mode[0] = !!(val & 0x01);
|
||||
dev->irq_mode[1] = !!(val & 0x04);
|
||||
rz1000_ide_handlers(dev);
|
||||
}
|
||||
break;
|
||||
case 0x40 ... 0x4f:
|
||||
dev->regs[addr] = val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
rz1000_pci_read(int func, int addr, void *priv)
|
||||
{
|
||||
rz1000_t *dev = (rz1000_t *) priv;
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
if (func == 0x00)
|
||||
ret = dev->regs[addr];
|
||||
|
||||
rz1000_log("rz1000_pci_read(%i, %02X, %02X)\n", func, addr, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
rz1000_reset(void *priv)
|
||||
{
|
||||
rz1000_t *dev = (rz1000_t *) priv;
|
||||
int i = 0;
|
||||
int min_channel;
|
||||
int max_channel;
|
||||
|
||||
switch (dev->channels) {
|
||||
default:
|
||||
case 0x00:
|
||||
min_channel = max_channel = 0;
|
||||
break;
|
||||
case 0x01:
|
||||
min_channel = 0;
|
||||
max_channel = 1;
|
||||
break;
|
||||
case 0x02:
|
||||
min_channel = 2;
|
||||
max_channel = 3;
|
||||
break;
|
||||
case 0x03:
|
||||
min_channel = 0;
|
||||
max_channel = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < CDROM_NUM; i++) {
|
||||
if ((cdrom[i].bus_type == CDROM_BUS_ATAPI) && (cdrom[i].ide_channel >= min_channel) &&
|
||||
(cdrom[i].ide_channel <= max_channel) && cdrom[i].priv)
|
||||
scsi_cdrom_reset((scsi_common_t *) cdrom[i].priv);
|
||||
}
|
||||
for (i = 0; i < ZIP_NUM; i++) {
|
||||
if ((zip_drives[i].bus_type == ZIP_BUS_ATAPI) && (zip_drives[i].ide_channel >= min_channel) &&
|
||||
(zip_drives[i].ide_channel <= max_channel) && zip_drives[i].priv)
|
||||
zip_reset((scsi_common_t *) zip_drives[i].priv);
|
||||
}
|
||||
for (i = 0; i < MO_NUM; i++) {
|
||||
if ((mo_drives[i].bus_type == MO_BUS_ATAPI) && (mo_drives[i].ide_channel >= min_channel) &&
|
||||
(mo_drives[i].ide_channel <= max_channel) && mo_drives[i].priv)
|
||||
mo_reset((scsi_common_t *) mo_drives[i].priv);
|
||||
}
|
||||
|
||||
memset(dev->regs, 0x00, sizeof(dev->regs));
|
||||
|
||||
rz1000_log("dev->local = %08X\n", dev->local);
|
||||
|
||||
dev->regs[0x00] = 0x42; /* PC Technology */
|
||||
dev->regs[0x01] = 0x10;
|
||||
dev->regs[0x02] = 0x00; /* RZ-1000 */
|
||||
dev->regs[0x03] = 0x10;
|
||||
dev->regs[0x04] = 0x00;
|
||||
dev->regs[0x07] = 0x02; /* DEVSEL timing: 01 medium */
|
||||
dev->regs[0x08] = 0x02; /* Revision 02 */
|
||||
dev->regs[0x09] = dev->local; /* Programming interface */
|
||||
dev->regs[0x0a] = 0x01; /* IDE controller */
|
||||
dev->regs[0x0b] = 0x01; /* Mass storage controller */
|
||||
|
||||
dev->irq_mode[0] = dev->irq_mode[1] = 0;
|
||||
dev->irq_pin = PCI_INTA;
|
||||
dev->irq_line = 14;
|
||||
|
||||
rz1000_ide_handlers(dev);
|
||||
}
|
||||
|
||||
static void
|
||||
rz1000_close(void *priv)
|
||||
{
|
||||
rz1000_t *dev = (rz1000_t *) priv;
|
||||
|
||||
free(dev);
|
||||
|
||||
next_id = 0;
|
||||
}
|
||||
|
||||
static void *
|
||||
rz1000_init(const device_t *info)
|
||||
{
|
||||
rz1000_t *dev = (rz1000_t *) calloc(1, sizeof(rz1000_t));
|
||||
|
||||
dev->id = next_id | 0x60;
|
||||
|
||||
dev->pci = !!(info->flags & DEVICE_PCI);
|
||||
dev->local = info->local;
|
||||
|
||||
dev->channels = ((info->local & 0x60000) >> 17) & 0x03;
|
||||
|
||||
if (dev->channels & 0x02)
|
||||
device_add(&ide_pci_2ch_device);
|
||||
else
|
||||
device_add(&ide_pci_device);
|
||||
|
||||
if (info->local & 0x80000)
|
||||
pci_add_card(PCI_ADD_NORMAL, rz1000_pci_read, rz1000_pci_write, dev, &dev->pci_slot);
|
||||
else
|
||||
pci_add_card(PCI_ADD_IDE, rz1000_pci_read, rz1000_pci_write, dev, &dev->pci_slot);
|
||||
|
||||
if (dev->channels & 0x01)
|
||||
ide_board_set_force_ata3(0, 1);
|
||||
|
||||
if (dev->channels & 0x02)
|
||||
ide_board_set_force_ata3(1, 1);
|
||||
|
||||
next_id++;
|
||||
|
||||
rz1000_reset(dev);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
const device_t ide_rz1000_pci_device = {
|
||||
.name = "PC Technology RZ-1000 PCI",
|
||||
.internal_name = "ide_rz1000_pci",
|
||||
.flags = DEVICE_PCI,
|
||||
.local = 0x60000,
|
||||
.init = rz1000_init,
|
||||
.close = rz1000_close,
|
||||
.reset = rz1000_reset,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t ide_rz1000_pci_single_channel_device = {
|
||||
.name = "PC Technology RZ-1000 PCI",
|
||||
.internal_name = "ide_rz1000_pci_single_channel",
|
||||
.flags = DEVICE_PCI,
|
||||
.local = 0x20000,
|
||||
.init = rz1000_init,
|
||||
.close = rz1000_close,
|
||||
.reset = rz1000_reset,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
@@ -557,6 +557,7 @@ do_callback(void *priv)
|
||||
mfm->reset = 0;
|
||||
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_MFM, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -627,9 +628,9 @@ write_error:
|
||||
mfm->status |= STAT_DRQ;
|
||||
mfm->pos = 0;
|
||||
next_sector(mfm);
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 1);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_MFM, 1);
|
||||
} else
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_MFM, 0);
|
||||
break;
|
||||
|
||||
case CMD_VERIFY:
|
||||
@@ -657,7 +658,7 @@ write_error:
|
||||
|
||||
mfm->status = STAT_READY | STAT_DSC;
|
||||
irq_raise(mfm);
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 1);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_MFM, 1);
|
||||
break;
|
||||
|
||||
case CMD_DIAGNOSE:
|
||||
@@ -772,6 +773,7 @@ mfm_init(UNUSED(const device_t *info))
|
||||
timer_add(&mfm->callback_timer, do_callback, mfm, 0);
|
||||
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_MFM, 0);
|
||||
|
||||
return mfm;
|
||||
}
|
||||
@@ -790,6 +792,7 @@ mfm_close(void *priv)
|
||||
free(mfm);
|
||||
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_MFM, 0);
|
||||
}
|
||||
|
||||
const device_t st506_at_wd1003_device = {
|
||||
|
||||
@@ -580,14 +580,14 @@ st506_callback(void *priv)
|
||||
(void) get_chs(dev, drive);
|
||||
st506_xt_log("ST506: FORMAT_DRIVE(%i) interleave=%i\n",
|
||||
dev->drive_sel, dev->command[4]);
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 1);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_MFM, 1);
|
||||
timer_advance_u64(&dev->timer, ST506_TIME);
|
||||
dev->state = STATE_SEND_DATA;
|
||||
break;
|
||||
|
||||
case STATE_SEND_DATA: /* wrong, but works */
|
||||
if (!get_sector(dev, drive, &addr)) {
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_MFM, 0);
|
||||
st506_error(dev, dev->error);
|
||||
st506_complete(dev);
|
||||
return;
|
||||
@@ -604,7 +604,7 @@ st506_callback(void *priv)
|
||||
break;
|
||||
|
||||
case STATE_SENT_DATA:
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_MFM, 0);
|
||||
st506_complete(dev);
|
||||
break;
|
||||
|
||||
@@ -663,14 +663,14 @@ st506_callback(void *priv)
|
||||
st506_xt_log("ST506: FORMAT_%sTRACK(%i, %i/%i)\n",
|
||||
(dev->command[0] == CMD_FORMAT_BAD_TRACK) ? "BAD_" : "",
|
||||
dev->drive_sel, dev->cylinder, dev->head);
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 1);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_MFM, 1);
|
||||
timer_advance_u64(&dev->timer, ST506_TIME);
|
||||
dev->state = STATE_SEND_DATA;
|
||||
break;
|
||||
|
||||
case STATE_SEND_DATA: /* wrong, but works */
|
||||
if (!get_sector(dev, drive, &addr)) {
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_MFM, 0);
|
||||
st506_error(dev, dev->error);
|
||||
st506_complete(dev);
|
||||
return;
|
||||
@@ -686,7 +686,7 @@ st506_callback(void *priv)
|
||||
break;
|
||||
|
||||
case STATE_SENT_DATA:
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_MFM, 0);
|
||||
st506_complete(dev);
|
||||
break;
|
||||
|
||||
@@ -828,7 +828,7 @@ read_error_sent:
|
||||
return;
|
||||
}
|
||||
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 1);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_MFM, 1);
|
||||
|
||||
/* Set up the data transfer. */
|
||||
dev->buff_pos = 0;
|
||||
@@ -865,7 +865,7 @@ read_error_sent:
|
||||
case STATE_RECEIVED_DATA:
|
||||
if (!get_sector(dev, drive, &addr)) {
|
||||
write_error:
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_MFM, 0);
|
||||
st506_error(dev, dev->error);
|
||||
st506_complete(dev);
|
||||
return;
|
||||
@@ -879,7 +879,7 @@ write_error:
|
||||
}
|
||||
|
||||
if (--dev->count == 0) {
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_MFM, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_MFM, 0);
|
||||
st506_complete(dev);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -385,7 +385,7 @@ do_format(hdc_t *dev, drive_t *drive, dcb_t *dcb)
|
||||
dev->sector = 0;
|
||||
|
||||
/* Activate the status icon. */
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 1);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_XTA, 1);
|
||||
|
||||
do_fmt:
|
||||
/*
|
||||
@@ -426,7 +426,7 @@ do_fmt:
|
||||
}
|
||||
|
||||
/* De-activate the status icon. */
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_XTA, 0);
|
||||
}
|
||||
|
||||
/* Execute the DCB we just received. */
|
||||
@@ -631,7 +631,7 @@ read_error:
|
||||
|
||||
case STATE_RECV:
|
||||
/* Activate the status icon. */
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 1);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_XTA, 1);
|
||||
do_recv:
|
||||
/* Ready to transfer the data in. */
|
||||
dev->state = STATE_RDATA;
|
||||
@@ -680,7 +680,7 @@ do_recv:
|
||||
if (get_sector(dev, drive, &addr)) {
|
||||
write_error:
|
||||
/* De-activate the status icon. */
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_XTA, 0);
|
||||
|
||||
dev->comp |= COMP_ERR;
|
||||
set_intr(dev);
|
||||
@@ -697,7 +697,7 @@ write_error:
|
||||
dev->buf_idx = 0;
|
||||
if (--dev->count == 0) {
|
||||
/* De-activate the status icon. */
|
||||
ui_sb_update_icon(SB_HDD | HDD_BUS_XTA, 0);
|
||||
ui_sb_update_icon_write(SB_HDD | HDD_BUS_XTA, 0);
|
||||
|
||||
set_intr(dev);
|
||||
return;
|
||||
@@ -1106,6 +1106,36 @@ xta_close(void *priv)
|
||||
|
||||
static const device_config_t wdxt150_config[] = {
|
||||
// clang-format off
|
||||
{
|
||||
.name = "bios_rev",
|
||||
.description = "BIOS Revision",
|
||||
.type = CONFIG_BIOS,
|
||||
.default_string = "rev_1",
|
||||
.default_int = 0,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.bios = {
|
||||
{
|
||||
.name = "Revision 1.0",
|
||||
.internal_name = "rev_1",
|
||||
.bios_type = BIOS_NORMAL,
|
||||
.files_no = 1,
|
||||
.local = 0,
|
||||
.size = 8192,
|
||||
.files = { WD_REV_1_BIOS_FILE, "" }
|
||||
},
|
||||
{
|
||||
.name = "Revision 2.0",
|
||||
.internal_name = "rev_2",
|
||||
.bios_type = BIOS_NORMAL,
|
||||
.files_no = 1,
|
||||
.local = 0,
|
||||
.size = 8192,
|
||||
.files = { WD_REV_2_BIOS_FILE, "" }
|
||||
},
|
||||
{ .files_no = 0 }
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = "base",
|
||||
.description = "Address",
|
||||
@@ -1151,36 +1181,6 @@ static const device_config_t wdxt150_config[] = {
|
||||
},
|
||||
.bios = { { 0 } }
|
||||
},
|
||||
{
|
||||
.name = "bios_rev",
|
||||
.description = "BIOS Revision",
|
||||
.type = CONFIG_BIOS,
|
||||
.default_string = "rev_1",
|
||||
.default_int = 0,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.bios = {
|
||||
{
|
||||
.name = "Revision 1.0",
|
||||
.internal_name = "rev_1",
|
||||
.bios_type = BIOS_NORMAL,
|
||||
.files_no = 1,
|
||||
.local = 0,
|
||||
.size = 8192,
|
||||
.files = { WD_REV_1_BIOS_FILE, "" }
|
||||
},
|
||||
{
|
||||
.name = "Revision 2.0",
|
||||
.internal_name = "rev_2",
|
||||
.bios_type = BIOS_NORMAL,
|
||||
.files_no = 1,
|
||||
.local = 0,
|
||||
.size = 8192,
|
||||
.files = { WD_REV_2_BIOS_FILE, "" }
|
||||
},
|
||||
{ .files_no = 0 }
|
||||
},
|
||||
},
|
||||
{ .name = "", .description = "", .type = CONFIG_END }
|
||||
// clang-format off
|
||||
};
|
||||
|
||||
@@ -252,6 +252,37 @@ xtide_at_close(void *priv)
|
||||
|
||||
// clang-format off
|
||||
static const device_config_t xtide_config[] = {
|
||||
{
|
||||
.name = "bios",
|
||||
.description = "BIOS Revision",
|
||||
.type = CONFIG_BIOS,
|
||||
.default_string = "xt",
|
||||
.default_int = 0,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.selection = { { 0 } },
|
||||
.bios = {
|
||||
{
|
||||
.name = "Regular XT",
|
||||
.internal_name = "xt",
|
||||
.bios_type = BIOS_NORMAL,
|
||||
.files_no = 1,
|
||||
.local = 0,
|
||||
.size = 8192,
|
||||
.files = { ROM_PATH_XT, "" }
|
||||
},
|
||||
{
|
||||
.name = "XT+ (V20/V30/8018x)",
|
||||
.internal_name = "xt_plus",
|
||||
.bios_type = BIOS_NORMAL,
|
||||
.files_no = 1,
|
||||
.local = 0,
|
||||
.size = 8192,
|
||||
.files = { ROM_PATH_XTP, "" }
|
||||
},
|
||||
{ .files_no = 0 }
|
||||
},
|
||||
},
|
||||
{
|
||||
.name = "base",
|
||||
.description = "Address",
|
||||
@@ -348,37 +379,6 @@ static const device_config_t xtide_config[] = {
|
||||
},
|
||||
.bios = { { 0 } }
|
||||
},
|
||||
{
|
||||
.name = "bios",
|
||||
.description = "BIOS Revision",
|
||||
.type = CONFIG_BIOS,
|
||||
.default_string = "xt",
|
||||
.default_int = 0,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.selection = { { 0 } },
|
||||
.bios = {
|
||||
{
|
||||
.name = "Regular XT",
|
||||
.internal_name = "xt",
|
||||
.bios_type = BIOS_NORMAL,
|
||||
.files_no = 1,
|
||||
.local = 0,
|
||||
.size = 8192,
|
||||
.files = { ROM_PATH_XT, "" }
|
||||
},
|
||||
{
|
||||
.name = "XT+ (V20/V30/8018x)",
|
||||
.internal_name = "xt_plus",
|
||||
.bios_type = BIOS_NORMAL,
|
||||
.files_no = 1,
|
||||
.local = 0,
|
||||
.size = 8192,
|
||||
.files = { ROM_PATH_XTP, "" }
|
||||
},
|
||||
{ .files_no = 0 }
|
||||
},
|
||||
},
|
||||
{ .name = "", .description = "", .type = CONFIG_END }
|
||||
};
|
||||
|
||||
|
||||
@@ -407,14 +407,14 @@ hdd_zones_init(hard_disk_t *hdd)
|
||||
|
||||
static hdd_preset_t hdd_speed_presets[] = {
|
||||
// clang-format off
|
||||
{ .name = "RAM Disk (max. speed)", .internal_name = "ramdisk", .rcache_num_seg = 16, .rcache_seg_size = 128, .max_multiple = 32 },
|
||||
{ .name = "[1989] 3500 RPM", .internal_name = "1989_3500rpm", .zones = 1, .avg_spt = 35, .heads = 2, .rpm = 3500, .full_stroke_ms = 40, .track_seek_ms = 8, .rcache_num_seg = 1, .rcache_seg_size = 16, .max_multiple = 8 },
|
||||
{ .name = "[1992] 3600 RPM", .internal_name = "1992_3600rpm", .zones = 1, .avg_spt = 45, .heads = 2, .rpm = 3600, .full_stroke_ms = 30, .track_seek_ms = 6, .rcache_num_seg = 4, .rcache_seg_size = 16, .max_multiple = 8 },
|
||||
{ .name = "[1994] 4500 RPM", .internal_name = "1994_4500rpm", .zones = 8, .avg_spt = 80, .heads = 4, .rpm = 4500, .full_stroke_ms = 26, .track_seek_ms = 5, .rcache_num_seg = 4, .rcache_seg_size = 32, .max_multiple = 16 },
|
||||
{ .name = "[1996] 5400 RPM", .internal_name = "1996_5400rpm", .zones = 16, .avg_spt = 135, .heads = 4, .rpm = 5400, .full_stroke_ms = 24, .track_seek_ms = 3, .rcache_num_seg = 4, .rcache_seg_size = 64, .max_multiple = 16 },
|
||||
{ .name = "[1997] 5400 RPM", .internal_name = "1997_5400rpm", .zones = 16, .avg_spt = 185, .heads = 6, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 64, .max_multiple = 32 },
|
||||
{ .name = "[1998] 5400 RPM", .internal_name = "1998_5400rpm", .zones = 16, .avg_spt = 300, .heads = 8, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 32 },
|
||||
{ .name = "[2000] 7200 RPM", .internal_name = "2000_7200rpm", .zones = 16, .avg_spt = 350, .heads = 6, .rpm = 7200, .full_stroke_ms = 15, .track_seek_ms = 2, .rcache_num_seg = 16, .rcache_seg_size = 128, .max_multiple = 32 },
|
||||
{ .name = "[Generic] RAM Disk (max. speed)", .internal_name = "ramdisk", .rcache_num_seg = 16, .rcache_seg_size = 128, .max_multiple = 32 },
|
||||
{ .name = "[Generic] 1989 (3500 RPM)", .internal_name = "1989_3500rpm", .zones = 1, .avg_spt = 35, .heads = 2, .rpm = 3500, .full_stroke_ms = 40, .track_seek_ms = 8, .rcache_num_seg = 1, .rcache_seg_size = 16, .max_multiple = 8 },
|
||||
{ .name = "[Generic] 1992 (3600 RPM)", .internal_name = "1992_3600rpm", .zones = 1, .avg_spt = 45, .heads = 2, .rpm = 3600, .full_stroke_ms = 30, .track_seek_ms = 6, .rcache_num_seg = 4, .rcache_seg_size = 16, .max_multiple = 8 },
|
||||
{ .name = "[Generic] 1994 (4500 RPM)", .internal_name = "1994_4500rpm", .zones = 8, .avg_spt = 80, .heads = 4, .rpm = 4500, .full_stroke_ms = 26, .track_seek_ms = 5, .rcache_num_seg = 4, .rcache_seg_size = 32, .max_multiple = 16 },
|
||||
{ .name = "[Generic] 1996 (5400 RPM)", .internal_name = "1996_5400rpm", .zones = 16, .avg_spt = 135, .heads = 4, .rpm = 5400, .full_stroke_ms = 24, .track_seek_ms = 3, .rcache_num_seg = 4, .rcache_seg_size = 64, .max_multiple = 16 },
|
||||
{ .name = "[Generic] 1997 (5400 RPM)", .internal_name = "1997_5400rpm", .zones = 16, .avg_spt = 185, .heads = 6, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2.5, .rcache_num_seg = 8, .rcache_seg_size = 64, .max_multiple = 32 },
|
||||
{ .name = "[Generic] 1998 (5400 RPM)", .internal_name = "1998_5400rpm", .zones = 16, .avg_spt = 300, .heads = 8, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 32 },
|
||||
{ .name = "[Generic] 2000 (7200 RPM)", .internal_name = "2000_7200rpm", .zones = 16, .avg_spt = 350, .heads = 6, .rpm = 7200, .full_stroke_ms = 15, .track_seek_ms = 2, .rcache_num_seg = 16, .rcache_seg_size = 128, .max_multiple = 32 },
|
||||
{ .name = "[PIO IDE] IBM WDA-L42", .internal_name = "WDAL42", .model = "WDA-L42", .zones = 1, .avg_spt = 85, .heads = 2, .rpm = 3600, .full_stroke_ms = 33, .track_seek_ms = 2.5, .rcache_num_seg = 1, .rcache_seg_size = 32, .max_multiple = 1 },
|
||||
{ .name = "[ATA-1] Conner CP3024", .internal_name = "CP3024", .model = "Conner Peripherals 20MB - CP3024", .zones = 1, .avg_spt = 33, .heads = 2, .rpm = 3500, .full_stroke_ms = 50, .track_seek_ms = 8, .rcache_num_seg = 1, .rcache_seg_size = 8, .max_multiple = 8 }, // Needed for GRiDcase 1520 to work
|
||||
{ .name = "[ATA-1] Conner CP3044", .internal_name = "CP3044", .model = "Conner Peripherals 40MB - CP3044", .zones = 1, .avg_spt = 40, .heads = 2, .rpm = 3500, .full_stroke_ms = 50, .track_seek_ms = 8, .rcache_num_seg = 1, .rcache_seg_size = 8, .max_multiple = 8 }, // Needed for GRiDcase 1520 to work
|
||||
@@ -469,7 +469,7 @@ static hdd_preset_t hdd_speed_presets[] = {
|
||||
{ .name = "[ATA-2] Western Digital Caviar 22000", .internal_name = "AC22000", .model = "WDC AC22000LA", .zones = 8, .avg_spt = 130, .heads = 3, .rpm = 5200, .full_stroke_ms = 33, .track_seek_ms = 3.5, .rcache_num_seg = 4, .rcache_seg_size = 128, .max_multiple = 8 },
|
||||
{ .name = "[ATA-2] Western Digital Caviar 22100", .internal_name = "AC22100", .model = "WDC AC22100H", .zones = 8, .avg_spt = 140, .heads = 4, .rpm = 5200, .full_stroke_ms = 30, .track_seek_ms = 3, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 },
|
||||
{ .name = "[ATA-2] Western Digital Caviar 31200", .internal_name = "AC31200", .model = "WDC AC31200F", .zones = 8, .avg_spt = 210, .heads = 4, .rpm = 4500, .full_stroke_ms = 12, .track_seek_ms = 4, .rcache_num_seg = 8, .rcache_seg_size = 64, .max_multiple = 16 },
|
||||
{ .name = "[ATA-3] Connor CFS1275A", .internal_name = "CFS1275A", .model = "Connor Peripherals 1275MB - CFS1275A", .zones = 4, .avg_spt = 130, .heads = 2, .rpm = 4500, .full_stroke_ms = 25, .track_seek_ms = 3.8, .rcache_num_seg = 4, .rcache_seg_size = 64, .max_multiple = 16 }, // Either ATA-2 or ATA-3
|
||||
{ .name = "[ATA-3] Conner CFS1275A", .internal_name = "CFS1275A", .model = "Conner Peripherals 1275MB - CFS1275A", .zones = 4, .avg_spt = 130, .heads = 2, .rpm = 4500, .full_stroke_ms = 25, .track_seek_ms = 3.8, .rcache_num_seg = 4, .rcache_seg_size = 64, .max_multiple = 16 }, // Either ATA-2 or ATA-3
|
||||
{ .name = "[ATA-3] Fujitsu MPA3017AT", .internal_name = "MPA3017AT", .model = "FUJITSU MPA3017AT", .zones = 5, .avg_spt = 195, .heads = 2, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 3.2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 },
|
||||
{ .name = "[ATA-3] Fujitsu MPA3026AT", .internal_name = "MPA3026AT", .model = "FUJITSU MPA3026AT", .zones = 8, .avg_spt = 195, .heads = 3, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 3.2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 },
|
||||
{ .name = "[ATA-3] Fujitsu MPA3035AT", .internal_name = "MPA3035AT", .model = "FUJITSU MPA3035AT", .zones = 11, .avg_spt = 195, .heads = 4, .rpm = 5400, .full_stroke_ms = 20, .track_seek_ms = 3.2, .rcache_num_seg = 8, .rcache_seg_size = 128, .max_multiple = 16 },
|
||||
|
||||
@@ -584,7 +584,10 @@ mo_data_command_finish(mo_t *dev, int len, const int block_len,
|
||||
mo_command_write_dma(dev);
|
||||
} else {
|
||||
mo_update_request_length(dev, len, block_len);
|
||||
if (direction == 0)
|
||||
if ((dev->drv->bus_type != MO_BUS_SCSI) &&
|
||||
(dev->tf->request_length == 0))
|
||||
mo_command_complete(dev);
|
||||
else if (direction == 0)
|
||||
mo_command_read(dev);
|
||||
else
|
||||
mo_command_write(dev);
|
||||
@@ -625,6 +628,7 @@ mo_cmd_error(mo_t *dev)
|
||||
dev->callback = 50.0 * MO_TIME;
|
||||
mo_set_callback(dev);
|
||||
ui_sb_update_icon(SB_MO | dev->id, 0);
|
||||
ui_sb_update_icon_write(SB_MO | dev->id, 0);
|
||||
mo_log(dev->log, "[%02X] ERROR: %02X/%02X/%02X\n", dev->current_cdb[0], mo_sense_key,
|
||||
mo_asc, mo_ascq);
|
||||
}
|
||||
@@ -641,6 +645,7 @@ mo_unit_attention(mo_t *dev)
|
||||
dev->callback = 50.0 * MO_TIME;
|
||||
mo_set_callback(dev);
|
||||
ui_sb_update_icon(SB_MO | dev->id, 0);
|
||||
ui_sb_update_icon_write(SB_MO | dev->id, 0);
|
||||
mo_log(dev->log, "UNIT ATTENTION\n");
|
||||
}
|
||||
|
||||
@@ -1459,7 +1464,7 @@ mo_command(scsi_common_t *sc, const uint8_t *cdb)
|
||||
mo_data_command_finish(dev, dev->packet_len, dev->drv->sector_size,
|
||||
dev->packet_len, 1);
|
||||
|
||||
ui_sb_update_icon(SB_MO | dev->id,
|
||||
ui_sb_update_icon_write(SB_MO | dev->id,
|
||||
dev->packet_status != PHASE_COMPLETE);
|
||||
} else {
|
||||
mo_set_phase(dev, SCSI_PHASE_STATUS);
|
||||
@@ -1498,7 +1503,7 @@ mo_command(scsi_common_t *sc, const uint8_t *cdb)
|
||||
dev->drv->sector_size,
|
||||
alloc_length, 1);
|
||||
|
||||
ui_sb_update_icon(SB_MO | dev->id,
|
||||
ui_sb_update_icon_write(SB_MO | dev->id,
|
||||
dev->packet_status != PHASE_COMPLETE);
|
||||
} else {
|
||||
mo_set_phase(dev, SCSI_PHASE_STATUS);
|
||||
|
||||
@@ -665,7 +665,10 @@ zip_data_command_finish(zip_t *dev, int len, const int block_len,
|
||||
zip_command_write_dma(dev);
|
||||
} else {
|
||||
zip_update_request_length(dev, len, block_len);
|
||||
if (direction == 0)
|
||||
if ((dev->drv->bus_type != ZIP_BUS_SCSI) &&
|
||||
(dev->tf->request_length == 0))
|
||||
zip_command_complete(dev);
|
||||
else if (direction == 0)
|
||||
zip_command_read(dev);
|
||||
else
|
||||
zip_command_write(dev);
|
||||
@@ -706,6 +709,7 @@ zip_cmd_error(zip_t *dev)
|
||||
dev->callback = 50.0 * ZIP_TIME;
|
||||
zip_set_callback(dev);
|
||||
ui_sb_update_icon(SB_ZIP | dev->id, 0);
|
||||
ui_sb_update_icon_write(SB_ZIP | dev->id, 0);
|
||||
zip_log(dev->log, "[%02X] ERROR: %02X/%02X/%02X\n", dev->current_cdb[0], zip_sense_key,
|
||||
zip_asc, zip_ascq);
|
||||
}
|
||||
@@ -722,6 +726,7 @@ zip_unit_attention(zip_t *dev)
|
||||
dev->callback = 50.0 * ZIP_TIME;
|
||||
zip_set_callback(dev);
|
||||
ui_sb_update_icon(SB_ZIP | dev->id, 0);
|
||||
ui_sb_update_icon_write(SB_ZIP | dev->id, 0);
|
||||
zip_log(dev->log, "UNIT ATTENTION\n", dev->id);
|
||||
}
|
||||
|
||||
@@ -1482,7 +1487,7 @@ zip_command(scsi_common_t *sc, const uint8_t *cdb)
|
||||
zip_data_command_finish(dev, dev->packet_len, 512,
|
||||
dev->packet_len, 1);
|
||||
|
||||
ui_sb_update_icon(SB_ZIP | dev->id,
|
||||
ui_sb_update_icon_write(SB_ZIP | dev->id,
|
||||
dev->packet_status != PHASE_COMPLETE);
|
||||
} else {
|
||||
zip_set_phase(dev, SCSI_PHASE_STATUS);
|
||||
@@ -1523,7 +1528,7 @@ zip_command(scsi_common_t *sc, const uint8_t *cdb)
|
||||
zip_data_command_finish(dev, 512, 512,
|
||||
alloc_length, 1);
|
||||
|
||||
ui_sb_update_icon(SB_ZIP | dev->id,
|
||||
ui_sb_update_icon_write(SB_ZIP | dev->id,
|
||||
dev->packet_status != PHASE_COMPLETE);
|
||||
} else {
|
||||
zip_set_phase(dev, SCSI_PHASE_STATUS);
|
||||
|
||||
@@ -866,7 +866,7 @@ dma16_read(uint16_t addr, UNUSED(void *priv))
|
||||
break;
|
||||
}
|
||||
|
||||
dma_log("dma16_read(%08X) = %02X\n", port, ret);
|
||||
dma_log("dma16_read(%08X) = %02X\n", addr, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
112
src/floppy/fdc.c
112
src/floppy/fdc.c
@@ -278,6 +278,15 @@ fdc_is_mfm(fdc_t *fdc)
|
||||
return fdc->mfm ? 1 : 0;
|
||||
}
|
||||
|
||||
int
|
||||
fdc_is_dma(fdc_t *fdc)
|
||||
{
|
||||
if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->dma)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
fdc_request_next_sector_id(fdc_t *fdc)
|
||||
{
|
||||
@@ -368,6 +377,15 @@ fdc_set_power_down(fdc_t *fdc, uint8_t power_down)
|
||||
fdc->power_down = power_down;
|
||||
}
|
||||
|
||||
void
|
||||
fdc_toggle_flag(fdc_t *fdc, int flag, int on)
|
||||
{
|
||||
if (on)
|
||||
fdc->flags |= flag;
|
||||
else
|
||||
fdc->flags &= ~flag;
|
||||
}
|
||||
|
||||
void
|
||||
fdc_update_max_track(fdc_t *fdc, int max_track)
|
||||
{
|
||||
@@ -395,6 +413,20 @@ fdc_update_rwc(fdc_t *fdc, int drive, int rwc)
|
||||
fdc_rate(fdc, drive);
|
||||
}
|
||||
|
||||
uint8_t
|
||||
fdc_get_media_id(fdc_t *fdc, int id)
|
||||
{
|
||||
uint8_t ret = fdc->media_id & (1 << id);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
fdc_set_media_id(fdc_t *fdc, int id, int set)
|
||||
{
|
||||
fdc->media_id = (fdc->media_id & ~(1 << id)) | (set << id);
|
||||
}
|
||||
|
||||
int
|
||||
fdc_get_boot_drive(fdc_t *fdc)
|
||||
{
|
||||
@@ -446,9 +478,11 @@ fdc_update_drv2en(fdc_t *fdc, int drv2en)
|
||||
void
|
||||
fdc_update_rate(fdc_t *fdc, int drive)
|
||||
{
|
||||
if (((fdc->rwc[drive] == 1) || (fdc->rwc[drive] == 2)) && fdc->enh_mode)
|
||||
if (((fdc->rwc[drive] == 1) || (fdc->rwc[drive] == 2)) &&
|
||||
fdc->enh_mode && !(fdc->flags & FDC_FLAG_SMC661))
|
||||
fdc->bit_rate = 500;
|
||||
else if ((fdc->rwc[drive] == 3) && fdc->enh_mode)
|
||||
else if ((fdc->rwc[drive] == 3) && fdc->enh_mode &&
|
||||
!(fdc->flags & FDC_FLAG_SMC661))
|
||||
fdc->bit_rate = 250;
|
||||
else switch (fdc->rate) {
|
||||
default:
|
||||
@@ -512,7 +546,7 @@ fdc_get_bitcell_period(fdc_t *fdc)
|
||||
static int
|
||||
fdc_get_densel(fdc_t *fdc, int drive)
|
||||
{
|
||||
if (fdc->enh_mode) {
|
||||
if (fdc->enh_mode && !(fdc->flags & FDC_FLAG_SMC661)) {
|
||||
switch (fdc->rwc[drive]) {
|
||||
case 1:
|
||||
case 3:
|
||||
@@ -615,7 +649,10 @@ fdc_io_command_phase1(fdc_t *fdc, int out)
|
||||
}
|
||||
}
|
||||
|
||||
ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 1);
|
||||
if (fdc->processed_cmd == 0x05 || fdc->processed_cmd == 0x09)
|
||||
ui_sb_update_icon_write(SB_FLOPPY | real_drive(fdc, fdc->drive), 1);
|
||||
else
|
||||
ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 1);
|
||||
fdc->stat = out ? 0x10 : 0x50;
|
||||
if ((fdc->flags & FDC_FLAG_PCJR) || !fdc->dma) {
|
||||
fdc->stat |= 0x20;
|
||||
@@ -671,8 +708,10 @@ fdc_soft_reset(fdc_t *fdc)
|
||||
|
||||
fdc->perp &= 0xfc;
|
||||
|
||||
for (int i = 0; i < FDD_NUM; i++)
|
||||
ui_sb_update_icon(SB_FLOPPY | i, 0);
|
||||
for (int i = 0; i < FDD_NUM; i++) {
|
||||
ui_sb_update_icon(SB_FLOPPY | i, 0);
|
||||
ui_sb_update_icon_write(SB_FLOPPY | i, 0);
|
||||
}
|
||||
|
||||
fdc_ctrl_reset(fdc);
|
||||
}
|
||||
@@ -706,6 +745,7 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
timer_set_delay_u64(&fdc->timer, 8 * TIMER_USEC);
|
||||
fdc->interrupt = -1;
|
||||
ui_sb_update_icon(SB_FLOPPY | 0, 0);
|
||||
ui_sb_update_icon_write(SB_FLOPPY | 0, 0);
|
||||
fdc_ctrl_reset(fdc);
|
||||
}
|
||||
if (!fdd_get_flags(0))
|
||||
@@ -741,8 +781,13 @@ fdc_write(uint16_t addr, uint8_t val, void *priv)
|
||||
return;
|
||||
case 3: /* TDR */
|
||||
if (fdc->enh_mode) {
|
||||
drive = real_drive(fdc, fdc->dor & 3);
|
||||
fdc_update_rwc(fdc, drive, (val & 0x30) >> 4);
|
||||
if (fdc->flags & FDC_FLAG_SMC661) {
|
||||
fdc_set_swap(fdc, !!(val & 0x20));
|
||||
fdc_update_densel_force(fdc, (val & 0x18) >> 3);
|
||||
} else {
|
||||
drive = real_drive(fdc, fdc->dor & 3);
|
||||
fdc_update_rwc(fdc, drive, (val & 0x30) >> 4);
|
||||
}
|
||||
}
|
||||
/* Bit 2: FIFO test mode (PS/55 5550-S,T only. Undocumented)
|
||||
The Power-on Self Test of PS/55 writes and verifies 8 bytes of FIFO buffer through I/O 3F5h.
|
||||
@@ -1362,8 +1407,10 @@ fdc_read(uint16_t addr, void *priv)
|
||||
/* PS/55 POST throws an error and halt if ret = 1 or 2, somehow. */
|
||||
} else if (!fdc->enh_mode)
|
||||
ret = 0x20;
|
||||
else if (fdc->flags & FDC_FLAG_SMC661)
|
||||
ret = (fdc->densel_force << 3) | ((!!fdc->swap) << 5) | (fdc->media_id << 6);
|
||||
else
|
||||
ret = fdc->rwc[drive] << 4;
|
||||
ret = (fdc->rwc[drive] << 4) | (fdc->media_id << 6);
|
||||
break;
|
||||
case 4: /*Status*/
|
||||
ret = fdc->stat;
|
||||
@@ -1446,7 +1493,7 @@ fdc_read(uint16_t addr, void *priv)
|
||||
fdc->step = 0;
|
||||
break;
|
||||
default:
|
||||
ret = 0xFF;
|
||||
ret = 0xff;
|
||||
}
|
||||
fdc_log("[%04X:%08X] Read FDC %04X %02X [%i:%02X]\n", CS, cpu_state.pc, addr, ret, drive, fdc->dor & (0x10 << drive));
|
||||
return ret;
|
||||
@@ -1502,6 +1549,7 @@ fdc_poll_common_finish(fdc_t *fdc, int compare, int st5)
|
||||
fdc->res[10] = fdc->params[4];
|
||||
fdc_log("Read/write finish (%02X %02X %02X %02X %02X %02X %02X)\n", fdc->res[4], fdc->res[5], fdc->res[6], fdc->res[7], fdc->res[8], fdc->res[9], fdc->res[10]);
|
||||
ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 0);
|
||||
ui_sb_update_icon_write(SB_FLOPPY | real_drive(fdc, fdc->drive), 0);
|
||||
fdc->paramstogo = 7;
|
||||
dma_set_drq(fdc->dma_ch, 0);
|
||||
}
|
||||
@@ -1545,8 +1593,10 @@ fdc_callback(void *priv)
|
||||
case -5: /*Reset in power down mode */
|
||||
fdc->perp &= 0xfc;
|
||||
|
||||
for (uint8_t i = 0; i < FDD_NUM; i++)
|
||||
for (uint8_t i = 0; i < FDD_NUM; i++) {
|
||||
ui_sb_update_icon(SB_FLOPPY | i, 0);
|
||||
ui_sb_update_icon_write(SB_FLOPPY | i, 0);
|
||||
}
|
||||
|
||||
fdc_ctrl_reset(fdc);
|
||||
|
||||
@@ -1694,7 +1744,10 @@ fdc_callback(void *priv)
|
||||
fdc->sector++;
|
||||
else if (fdc->params[5] == 0)
|
||||
fdc->sector++;
|
||||
ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 1);
|
||||
if (fdc->interrupt == 0x05 || fdc->interrupt == 0x09)
|
||||
ui_sb_update_icon_write(SB_FLOPPY | real_drive(fdc, fdc->drive), 1);
|
||||
else
|
||||
ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 1);
|
||||
switch (fdc->interrupt) {
|
||||
case 5:
|
||||
case 9:
|
||||
@@ -1885,6 +1938,7 @@ fdc_error(fdc_t *fdc, int st5, int st6)
|
||||
break;
|
||||
}
|
||||
ui_sb_update_icon(SB_FLOPPY | real_drive(fdc, fdc->drive), 0);
|
||||
ui_sb_update_icon_write(SB_FLOPPY | real_drive(fdc, fdc->drive), 0);
|
||||
fdc->paramstogo = 7;
|
||||
}
|
||||
|
||||
@@ -2190,9 +2244,13 @@ fdc_set_base(fdc_t *fdc, int base)
|
||||
{
|
||||
int super_io = (fdc->flags & FDC_FLAG_SUPERIO);
|
||||
|
||||
if (base == 0x0000) {
|
||||
fdc->base_address = base;
|
||||
return;
|
||||
}
|
||||
|
||||
if (fdc->flags & FDC_FLAG_NSC) {
|
||||
io_sethandler(base + 2, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
io_sethandler(base + 4, 0x0002, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
io_sethandler(base + 2, 0x0004, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
io_sethandler(base + 7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
} else {
|
||||
if ((fdc->flags & FDC_FLAG_AT) || (fdc->flags & FDC_FLAG_AMSTRAD)) {
|
||||
@@ -2221,10 +2279,12 @@ fdc_remove(fdc_t *fdc)
|
||||
{
|
||||
int super_io = (fdc->flags & FDC_FLAG_SUPERIO);
|
||||
|
||||
if (fdc->base_address == 0x0000)
|
||||
return;
|
||||
|
||||
fdc_log("FDC Removed (%04X)\n", fdc->base_address);
|
||||
if (fdc->flags & FDC_FLAG_NSC) {
|
||||
io_removehandler(fdc->base_address + 2, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
io_removehandler(fdc->base_address + 4, 0x0002, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
io_removehandler(fdc->base_address + 2, 0x0004, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
io_removehandler(fdc->base_address + 7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, fdc);
|
||||
} else {
|
||||
if ((fdc->flags & FDC_FLAG_AT) || (fdc->flags & FDC_FLAG_AMSTRAD)) {
|
||||
@@ -2333,10 +2393,14 @@ fdc_reset(void *priv)
|
||||
|
||||
current_drive = 0;
|
||||
|
||||
for (uint8_t i = 0; i < FDD_NUM; i++)
|
||||
for (uint8_t i = 0; i < FDD_NUM; i++) {
|
||||
ui_sb_update_icon(SB_FLOPPY | i, 0);
|
||||
ui_sb_update_icon_write(SB_FLOPPY | i, 0);
|
||||
}
|
||||
|
||||
fdc->power_down = 0;
|
||||
|
||||
fdc->media_id = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2604,6 +2668,20 @@ const device_t fdc_at_actlow_device = {
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t fdc_at_smc_661_device = {
|
||||
.name = "PC/AT Floppy Drive Controller (SM(s)C FDC37C661/2)",
|
||||
.internal_name = "fdc_at_smc",
|
||||
.flags = 0,
|
||||
.local = FDC_FLAG_AT | FDC_FLAG_SUPERIO | FDC_FLAG_SMC661,
|
||||
.init = fdc_init,
|
||||
.close = fdc_close,
|
||||
.reset = fdc_reset,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t fdc_at_smc_device = {
|
||||
.name = "PC/AT Floppy Drive Controller (SM(s)C FDC37Cxxx)",
|
||||
.internal_name = "fdc_at_smc",
|
||||
|
||||
@@ -2414,16 +2414,28 @@ d86f_turbo_poll(int drive, int side)
|
||||
case STATE_0C_READ_DATA:
|
||||
case STATE_11_SCAN_DATA:
|
||||
case STATE_16_VERIFY_DATA:
|
||||
d86f_turbo_read(drive, side);
|
||||
if (fdc_is_dma(d86f_fdc))
|
||||
for (int i = 0; i < (128 << dev->last_sector.id.n); i++)
|
||||
d86f_turbo_read(drive, side);
|
||||
else
|
||||
d86f_turbo_read(drive, side);
|
||||
break;
|
||||
|
||||
case STATE_05_WRITE_DATA:
|
||||
case STATE_09_WRITE_DATA:
|
||||
d86f_turbo_write(drive, side);
|
||||
if (fdc_is_dma(d86f_fdc))
|
||||
for (int i = 0; i < (128 << dev->last_sector.id.n); i++)
|
||||
d86f_turbo_write(drive, side);
|
||||
else
|
||||
d86f_turbo_write(drive, side);
|
||||
break;
|
||||
|
||||
case STATE_0D_FORMAT_TRACK:
|
||||
d86f_turbo_format(drive, side, (side && (d86f_get_sides(drive) != 2)));
|
||||
if (fdc_is_dma(d86f_fdc))
|
||||
while (dev->state == STATE_0D_FORMAT_TRACK)
|
||||
d86f_turbo_format(drive, side, (side && (d86f_get_sides(drive) != 2)));
|
||||
else
|
||||
d86f_turbo_format(drive, side, (side && (d86f_get_sides(drive) != 2)));
|
||||
return;
|
||||
|
||||
case STATE_IDLE:
|
||||
|
||||
@@ -62,13 +62,18 @@ joystick_standard_read(UNUSED(void *priv))
|
||||
{
|
||||
uint8_t ret = 0xf0;
|
||||
|
||||
for (int js = 0; js < 2; js++) {
|
||||
if (JOYSTICK_PRESENT(0, js)) {
|
||||
if (joystick_state[0][js].button[0])
|
||||
ret &= ~0x10;
|
||||
if (joystick_state[0][js].button[1])
|
||||
ret &= ~0x20;
|
||||
}
|
||||
if (JOYSTICK_PRESENT(0, 0)) {
|
||||
if (joystick_state[0][0].button[0])
|
||||
ret &= ~0x10;
|
||||
if (joystick_state[0][0].button[1])
|
||||
ret &= ~0x20;
|
||||
}
|
||||
|
||||
if (JOYSTICK_PRESENT(0, 1)) {
|
||||
if (joystick_state[0][1].button[0])
|
||||
ret &= ~0x40;
|
||||
if (joystick_state[0][1].button[1])
|
||||
ret &= ~0x80;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
/* Configuration values. */
|
||||
#define GFXCARD_MAX 2
|
||||
#define SERIAL_MAX 7
|
||||
#define SERIAL_MAX 8
|
||||
#define PARALLEL_MAX 4
|
||||
#define SCREEN_RES_X 640
|
||||
#define SCREEN_RES_Y 480
|
||||
@@ -44,8 +44,8 @@
|
||||
/* Max UUID Length */
|
||||
#define MAX_UUID_LEN 64
|
||||
|
||||
/* Default language 0xFFFF = from system, 0x409 = en-US */
|
||||
#define DEFAULT_LANGUAGE 0x0409
|
||||
/* Default language code */
|
||||
#define DEFAULT_LANGUAGE "system"
|
||||
|
||||
#define POSTCARDS_NUM 4
|
||||
#define POSTCARD_MASK (POSTCARDS_NUM - 1)
|
||||
@@ -84,8 +84,6 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/* Global variables. */
|
||||
extern uint32_t lang_sys; /* (-) system language code */
|
||||
|
||||
extern int dump_on_exit; /* (O) dump regs on exit*/
|
||||
extern int start_in_fullscreen; /* (O) start in fullscreen */
|
||||
#ifdef _WIN32
|
||||
@@ -117,13 +115,12 @@ extern int window_remember;
|
||||
extern int vid_resize; /* (C) allow resizing */
|
||||
extern int invert_display; /* (C) invert the display */
|
||||
extern int suppress_overscan; /* (C) suppress overscans */
|
||||
extern uint32_t lang_id; /* (C) language code identifier */
|
||||
extern int lang_id; /* (C) language id */
|
||||
extern int scale; /* (C) screen scale factor */
|
||||
extern int dpi_scale; /* (C) DPI scaling of the emulated screen */
|
||||
extern int vid_api; /* (C) video renderer */
|
||||
extern int vid_cga_contrast; /* (C) video */
|
||||
extern int video_fullscreen; /* (C) video */
|
||||
extern int video_fullscreen_first; /* (C) video */
|
||||
extern int video_fullscreen_scale; /* (C) video */
|
||||
extern int enable_overscan; /* (C) video */
|
||||
extern int force_43; /* (C) video */
|
||||
@@ -174,14 +171,6 @@ extern int pit_mode; /* (C) force setting PIT mode */
|
||||
extern int fm_driver; /* (C) select FM sound driver */
|
||||
extern int hook_enabled; /* (C) Keyboard hook is enabled */
|
||||
|
||||
/* Keyboard variables for future key combination redefinition. */
|
||||
extern uint16_t key_prefix_1_1;
|
||||
extern uint16_t key_prefix_1_2;
|
||||
extern uint16_t key_prefix_2_1;
|
||||
extern uint16_t key_prefix_2_2;
|
||||
extern uint16_t key_uncapture_1;
|
||||
extern uint16_t key_uncapture_2;
|
||||
|
||||
extern char exe_path[2048]; /* path (dir) of executable */
|
||||
extern char usr_path[1024]; /* path (dir) of user data */
|
||||
extern char cfg_path[1024]; /* full path of config file */
|
||||
@@ -246,6 +235,17 @@ extern int framecountx;
|
||||
extern volatile int cpu_thread_run;
|
||||
extern uint8_t postcard_codes[POSTCARDS_NUM];
|
||||
|
||||
// Accelerator key structure, defines, helper functions
|
||||
struct accelKey {
|
||||
char name[64];
|
||||
char desc[64];
|
||||
char seq[64];
|
||||
};
|
||||
#define NUM_ACCELS 8
|
||||
extern struct accelKey acc_keys[NUM_ACCELS];
|
||||
extern struct accelKey def_acc_keys[NUM_ACCELS];
|
||||
extern int FindAccelerator(const char *name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user