Merge branch 'master' into tc1995_pc98x1

This commit is contained in:
Jasmine Iwanek
2025-09-06 20:14:24 -04:00
1844 changed files with 317174 additions and 155650 deletions

View File

@@ -59,6 +59,7 @@ AppDir:
- libqt5widgets5 # if QT:BOOL=ON
- libsixel1 # if CLI:BOOL=ON
- libslirp0
- libsndfile1
- libsndio7.0 # if OPENAL:BOOL=ON
- libvdeplug-dev # -dev also pulls in libvdeplug2. -dev is required to get the proper .so symlink to the library
- libx11-6 # if QT:BOOL=ON
@@ -71,6 +72,7 @@ AppDir:
- libxkbcommon-x11-0 # if QT:BOOL=ON
- qtwayland5 # if QT:BOOL=ON
- zlib1g
- libserialport0
files:
exclude:
- etc
@@ -94,3 +96,4 @@ AppDir:
AppImage:
arch: !ENV '${arch_appimage}'
file_name: !ENV '${appimage_path}'
comp: gzip

7
.ci/Jenkinsfile vendored
View File

@@ -20,11 +20,12 @@ 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 = ['', '-t']
def buildBranch = env.JOB_BASE_NAME.contains('-') ? 1 : 0
def osArchs = [
'Windows': ['32', '64'],
'Linux': ['x86', 'x86_64', 'arm32', 'arm64'],
'Windows': ['64'],
'Linux': ['x86_64', 'arm64'],
'macOS': ['x86_64+x86_64h+arm64']
]
@@ -238,7 +239,7 @@ pipeline {
dir("${env.WORKSPACE_TMP}/output") {
/* Run source tarball creation process. */
def packageName = "${env.JOB_BASE_NAME}-Source$buildSuffix"
if (runBuild("-s \"$packageName\"") == 0) {
if (runBuild("-s \"$packageName\" ${tarballFlags[buildBranch]}") == 0) {
/* Archive resulting artifacts. */
archiveArtifacts artifacts: "$packageName*"
} else {

View File

@@ -48,6 +48,13 @@
# architecture when invoking build.sh (either standalone or as part of an universal build)
# - port and sed are called through sudo to manage dependencies; make sure those are configured
# as NOPASSWD in /etc/sudoers if you're doing unattended builds
# - Binaries are ad-hoc signed by default; specify a keychain name in ~/86box-keychain-name.txt
# and password in ~/86box-keychain-password.txt to sign binaries with the first developer
# certificate found inside that keychain.
# - Notarization uses credentials stored in the same keychain used for signing. To save these
# credentials, you must find the keychain's file path, run notarytool store-credentials with
# --keychain pointed at that path, and specify the profile name you passed to notarytool in
# ~/86box-keychain-notarytool.txt
#
# Define common functions.
@@ -126,6 +133,70 @@ save_buildtag() {
return $?
}
mac_keychain() {
keychain_name=$(cat ~/86box-keychain-name.txt)
if [ -n "$keychain_name" ]
then
echo $keychain_name
security list-keychains -d user -s $(security list-keychains -d user | grep -Fv "/$keychain_name" | sed -e s/\ \*\"//g) "$keychain_name"
security unlock-keychain -p "$(cat ~/86box-keychain-password.txt)" "$keychain_name"
return $?
fi
}
mac_signidentity() {
if keychain_name=$(mac_keychain)
then
if [ -n "$keychain_name" ]
then
cert_name=$(security find-identity -v -p codesigning "$keychain_name" | perl -nle 'print for /([0-9A-F]+) "Developer ID Application: /')
if [ -n "$cert_name" ]
then
echo [-] Using signing certificate [$cert_name] in keychain [$keychain_name] >&2
echo "--keychain $keychain_name -s $cert_name"
return 0
else
err="Keychain [$keychain_name] has no developer certificate"
fi
else
err="No keychain specified"
fi
else
err="Keychain [$keychain_name] failed to unlock"
fi
echo [!] $err, falling back to ad-hoc signing >&2
echo "-s -"
}
mac_notarize() {
if keychain_name=$(mac_keychain)
then
if [ -n "$keychain_name" ]
then
keychain_profile=$(cat ~/86box-keychain-notarytool.txt)
if [ -n "$keychain_profile" ]
then
keychain_path=$(security list-keychains -d user | grep -F "/$keychain_name" | sed -e s/\ \*\"//g)
if [ -n "$keychain_path" ]
then
echo [-] Notarizing with profile [$keychain_profile] in keychain [$keychain_name]
# FIXME: needs a stapling system
xcrun notarytool submit "$1" --keychain-profile "$keychain_profile" --keychain "$keychain_path" --no-wait
return $?
else
err="File path for keychain [$keychain_name] not found"
fi
else
err="No keychain profile specified"
fi
else
err="No keychain specified"
fi
else
err="Keychain [$keychain_name] failed to unlock"
fi
echo [!] $err, skipping notarization
return 1
}
# Set common variables.
project=86Box
cwd=$(pwd)
@@ -208,7 +279,7 @@ cmake_flags_extra=
if [ -z "$package_name" -a -z "$tarball_name" ] || [ -n "$package_name" -a -z "$arch" ]
then
echo '[!] Usage: build.sh -b {package_name} {architecture} [-t] [cmake_flags...]'
echo ' build.sh -s {source_tarball_name}'
echo ' build.sh -s {source_tarball_name} [-t]'
echo 'Dep. tree: build.sh -p [archive_tmp/path/to/binary]'
exit 100
fi
@@ -228,7 +299,10 @@ then
[ ! -d "$cwd" ] && mkdir -p "$cwd"
# Save current HEAD commit to VERSION.
git log --stat -1 > VERSION || rm -f VERSION
if [ $strip -eq 0 ]
then
git log --stat -1 > VERSION || rm -f VERSION
fi
# Archive source.
make_tar "$cwd/$tarball_name.tar"
@@ -469,12 +543,13 @@ then
mv "archive_tmp_universal/$merge_src.app" "$app_bundle_name"
# Sign final app bundle.
arch -"$(uname -m)" codesign --force --deep -s - "$app_bundle_name"
arch -"$(uname -m)" codesign --force --deep $(mac_signidentity) -o runtime --entitlements src/mac/entitlements.plist --timestamp "$app_bundle_name"
# Create zip.
echo [-] Creating artifact archive
cd archive_tmp
zip --symlinks -r "$cwd/$package_name.zip" .
zip_name="$cwd/$package_name.zip"
zip --symlinks -r "$zip_name" .
status=$?
# Check if the archival succeeded.
@@ -484,6 +559,9 @@ then
exit 7
fi
# Notarize the compressed app bundle.
mac_notarize "$zip_name"
# All good.
echo [-] Universal build of [$package_name] for [$arch] with flags [$cmake_flags] successful
exit 0
@@ -522,6 +600,9 @@ then
cmake_flags_extra="$cmake_flags_extra -D MOLTENVK=ON -D \"MOLTENVK_INCLUDE_DIR=$macports\""
fi
# Enable Libserialport
cmake_flags_extra="$cmake_flags_extra -D \"LIBSERIALPORT_ROOT=$macports\""
# Install dependencies only if we're in a new build and/or MacPorts prefix.
if check_buildtag "$(basename "$macports")"
then
@@ -535,6 +616,21 @@ then
sudo sed -i -e 's/-no-feature-vulkan/-feature-vulkan/g' "$qt5_portfile"
sudo sed -i -e 's/configure.env-append MAKE=/configure.env-append VULKAN_SDK=${prefix} MAKE=/g' "$qt5_portfile"
fi
# Patch openal-soft to use 1.23.1 on all targets instead of 1.24.2 on >=10.13 only,
# to prevent a symlink mismatch from having different versions on x86_64 and arm64.
# See: https://github.com/macports/macports-ports/commit/9b4903fc9c76769d476079e404c9a3b8a225f8aa
# https://github.com/macports/macports-ports/commit/788deb64dc0695e8d04afb32ed904947f2a7591b
openal_portfile="$macports/var/macports/sources/rsync.macports.org/macports/release/tarballs/ports/audio/openal-soft/Portfile"
sudo sed -i -e 's/if {${os.platform} ne "darwin" ||/if {0 \&\&/g' "$openal_portfile"
# Patch wget to remove libproxy support, as it depends on shared-mime-info which
# fails to build for a 10.13 target, which we have to do despite wget only being
# a host dependency. MacPorts issue 69406 strongly implies this will not be fixed.
wget_portfile="$macports/var/macports/sources/rsync.macports.org/macports/release/tarballs/ports/net/wget/Portfile"
sudo sed -i -e 's/--enable-libproxy/--disable-libproxy/g' "$wget_portfile"
sudo sed -i -e 's/port:libproxy//g' "$wget_portfile"
while :
do
# Attempt to install dependencies.
@@ -582,7 +678,7 @@ else
grep -q " bullseye " /etc/apt/sources.list || echo [!] WARNING: System not running the expected Debian version
# Establish general dependencies.
pkgs="cmake ninja-build pkg-config git wget p7zip-full extra-cmake-modules wayland-protocols tar gzip file appstream"
pkgs="cmake ninja-build pkg-config git wget p7zip-full extra-cmake-modules wayland-protocols tar gzip file appstream qttranslations5-l10n python3-pip python3-venv squashfs-tools"
if [ "$(dpkg --print-architecture)" = "$arch_deb" ]
then
pkgs="$pkgs build-essential"
@@ -605,7 +701,7 @@ else
# ...and the ones we do want listed. Non-dev packages fill missing spots on the list.
libpkgs=""
longest_libpkg=0
for pkg in libc6-dev libstdc++6 libopenal-dev libfreetype6-dev libx11-dev libsdl2-dev libpng-dev librtmidi-dev qtdeclarative5-dev libwayland-dev libevdev-dev libxkbcommon-x11-dev libglib2.0-dev libslirp-dev libfaudio-dev libaudio-dev libjack-jackd2-dev libpipewire-0.3-dev libsamplerate0-dev libsndio-dev libvdeplug-dev libfluidsynth-dev
for pkg in libc6-dev libstdc++6 libopenal-dev libfreetype6-dev libx11-dev libsdl2-dev libpng-dev librtmidi-dev qtdeclarative5-dev libwayland-dev libevdev-dev libxkbcommon-x11-dev libglib2.0-dev libslirp-dev libfaudio-dev libaudio-dev libjack-jackd2-dev libpipewire-0.3-dev libsamplerate0-dev libsndio-dev libvdeplug-dev libfluidsynth-dev libsndfile1-dev libserialport-dev
do
libpkgs="$libpkgs $pkg:$arch_deb"
length=$(echo -n $pkg | sed 's/-dev$//' | sed "s/qtdeclarative/qt/" | wc -c)
@@ -884,7 +980,7 @@ then
fi
# Sign app bundle, unless we're in an universal build.
[ $skip_archive -eq 0 ] && codesign --force --deep -s - "archive_tmp/"*".app"
[ $skip_archive -eq 0 ] && codesign --force --deep $(mac_signidentity) -o runtime --entitlements src/mac/entitlements.plist --timestamp "archive_tmp/"*".app"
elif [ "$BUILD_TAG" = "precondition" ]
then
# Continue with no app bundle on a dry build.
@@ -1083,7 +1179,8 @@ elif is_mac
then
# Create zip.
cd archive_tmp
zip --symlinks -r "$cwd/$package_name.zip" .
zip_name="$cwd/$package_name.zip"
zip --symlinks -r "$zip_name" .
status=$?
else
# Determine AppImage runtime architecture.
@@ -1120,55 +1217,32 @@ EOF
# Copy line.
echo "$line" >> AppImageBuilder-generated.yml
# Workaround for appimage-builder issues 272 and 283 (i686 and armhf are also missing)
if [ "$arch_appimage" != "x86_64" -a "$line" = " files:" ]
then
# Some mild arbitrary code execution with a dummy package...
[ ! -d /runtime ] && sudo apt-get -y -o 'DPkg::Post-Invoke::=mkdir -p /runtime; chmod 777 /runtime' install libsixel1 > /dev/null 2>&1
echo " include:" >> AppImageBuilder-generated.yml
for loader in "/lib/$libdir/ld-linux"*.so.*
do
for loader_copy in "$loader" "/lib/$(basename "$loader")"
do
if [ ! -e "/runtime/compat$loader_copy" ]
then
mkdir -p "/runtime/compat$(dirname "$loader_copy")"
ln -s "$loader" "/runtime/compat$loader_copy"
fi
echo " - /runtime/compat$loader_copy" >> AppImageBuilder-generated.yml
done
done
fi
done < .ci/AppImageBuilder.yml
# Download appimage-builder if necessary.
appimage_builder_url="https://github.com/AppImageCrafters/appimage-builder/releases/download/v1.1.0/appimage-builder-1.1.0-$(uname -m).AppImage"
appimage_builder_binary="$cache_dir/$(basename "$appimage_builder_url")"
if [ ! -e "$appimage_builder_binary" ]
appimage_builder_commit=22fefa298f9cee922a651a6f65a46fe0ccbfa34e # from issue 376
appimage_builder_dir="$cache_dir/appimage-builder-$appimage_builder_commit"
if [ ! -x "$appimage_builder_dir/bin/appimage-builder" ]
then
rm -rf "$cache_dir/"*".AppImage" # remove old versions
wget -qO "$appimage_builder_binary" "$appimage_builder_url"
rm -rf "$cache_dir/appimage-builder-"* # remove old versions
python3 -m venv "$appimage_builder_dir" # venv to solve some Debian setuptools headaches
"$appimage_builder_dir/bin/pip" install -U "git+https://github.com/AppImageCrafters/appimage-builder.git@$appimage_builder_commit"
fi
# Symlink appimage-builder binary and global cache directory.
# Symlink appimage-builder global cache directory.
rm -rf appimage-builder.AppImage appimage-builder-cache "$project-"*".AppImage" # also remove any dangling AppImages which may interfere with the renaming process
ln -s "$appimage_builder_binary" appimage-builder.AppImage
chmod u+x appimage-builder.AppImage
mkdir -p "$cache_dir/appimage-builder-cache"
ln -s "$cache_dir/appimage-builder-cache" appimage-builder-cache
# Run appimage-builder in extract-and-run mode for Docker compatibility.
# Run appimage-builder from the virtual environment created above.
# --appdir is a workaround for appimage-builder issue 270 reported by us.
for retry in 1 2 3 4 5
do
project="$project" project_id="$project_id" project_version="$project_version" project_icon="$project_icon" arch_deb="$arch_deb" \
arch_appimage="$arch_appimage" appimage_path="$cwd/$package_name.AppImage" APPIMAGE_EXTRACT_AND_RUN=1 ./appimage-builder.AppImage \
arch_appimage="$arch_appimage" appimage_path="$cwd/$package_name.AppImage" "$appimage_builder_dir/bin/appimage-builder" \
--recipe AppImageBuilder-generated.yml --appdir "$(grep -oP '^\s+path: \K(.+)' AppImageBuilder-generated.yml)"
status=$?
[ $status -eq 0 ] && break
[ $status -eq 127 ] && rm -rf /tmp/appimage_extracted_*
done
# Remove appimage-builder binary on failure, just in case it's corrupted.
@@ -1182,6 +1256,9 @@ then
exit 7
fi
# Notarize the compressed app bundle if we're on macOS.
is_mac && mac_notarize "$zip_name"
# All good.
echo [-] Build of [$package_name] for [$arch] with flags [$cmake_flags] successful
exit 0

View File

@@ -15,3 +15,5 @@ fluidsynth
ghostscript
libslirp
vde2
libsndfile
libserialport

View File

@@ -12,3 +12,6 @@ libslirp
fluidsynth
qt5-static
qt5-translations
vulkan-headers
libsndfile
libserialport

View File

@@ -5,34 +5,11 @@ indent_style = space
indent_size = 4
tab_width = 4
# Disabled for now since not all editors support setting a tab_width value different from indent_size
# Relevant VSCode extension issue: https://github.com/editorconfig/editorconfig-vscode/issues/190
# [*.rc]
# indent_style = space
# indent_size = 4
# tab_width = 4
# [Makefile.*]
# indent_style = space
# indent_size = 4
# tab_width = 4
[*.manifest]
indent_style = space
indent_size = 2
[*.yml]
indent_style = space
indent_size = 2
[**/CMakeLists.txt]
indent_style = space
indent_size = 4
[*.cmake]
indent_style = space
indent_size = 4
[*.json]
indent_style = space
indent_size = 4
[*.ui]
indent_size = 1

16
.gitattributes vendored
View File

@@ -3,12 +3,28 @@
# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
# Code
*.c text
*.cc text
*.cpp text
*.h text
*.hpp text
# CMake scripts
CMakeLists.txt text
*.cmake text
# Windows resource scripts and manifests
*.rc text
*.manifest text
# Translation files
*.po text
# Qt XML files
*.ui text
*.ts text
*.qrc text
# Declare files that will always have CRLF line endings on checkout.

View File

@@ -6,7 +6,15 @@ body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
## Thanks for taking the time to fill out this bug report!
- type: checkboxes
attributes:
label: Checklist
options:
- label: I **have searched** the issue tracker and **was unable** to find an [open](../issues?q=is%3Aissue+is%3Aopen) or [closed](../issues?q=is%3Aissue+is%3Aclosed) issue matching what I'm seeing.
required: true
- label: I **have verified** that the issue is happening in the **[latest nightly build](https://ci.86box.net/job/86Box/lastSuccessfulBuild/artifact/)**, or the latest commit, if building from source.
required: true
- type: textarea
attributes:
label: What happened?
@@ -25,20 +33,13 @@ body:
attributes:
label: Operating system
description: What is your host operating system?
placeholder: e.g. Windows 10
validations:
required: true
- type: input
attributes:
label: CPU
description: What is your host CPU?
placeholder: e.g. AMD Ryzen 5 5600G
placeholder: e.g. Windows 11 24H2
validations:
required: true
- type: input
attributes:
label: 86Box version
description: What version of 86Box are you running? (Saying "Latest from Jenkins" is not helpful.)
description: What version of 86Box are you running? (Please ensure you have updated to the [latest build](https://ci.86box.net/job/86Box/lastSuccessfulBuild/artifact/) before reporting. Merely saying "Latest from Jenkins" is not helpful.)
placeholder: e.g. v4.0 build 5000
validations:
required: true
@@ -47,13 +48,13 @@ body:
label: Build architecture
description: 86Box for what architecture are you using?
options:
- Linux - ARM (32-bit)
- Linux - ARM (64-bit)
- Linux - x64 (64-bit)
- Linux - x86 (32-bit)
- macOS - Universal (Intel and Apple Silicon)
- Windows - x64 (64-bit)
- macOS - Universal (Intel and Apple Silicon)
- Linux - x64 (64-bit)
- Linux - ARM (64-bit)
- Windows - x86 (32-bit)
- Linux - ARM (32-bit)
- Linux - x86 (32-bit)
validations:
required: true
- type: checkboxes
@@ -63,18 +64,7 @@ body:
options:
- label: New recompiler
- label: Debug build
- type: dropdown
attributes:
label: Download source
description: Where did you download 86Box from?
options:
- Official website (Jenkins, GitHub)
- Manager auto-update
- I built 86Box myself (please tell us more about your build configuration)
- I got 86Box from a third party repository (please tell us where)
validations:
required: true
- type: textarea
attributes:
label: Additional context
description: Is there anything else you want to tell us?
description: Is there anything else you want to tell us? If you build 86Box from source, please post your build configuration here.

View File

@@ -1,8 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Machine Request
url: https://github.com/86Box/86Box/issues/3577#issue-comment-box
about: Please submit machine addition requests under this tracking issue.
url: https://github.com/86Box/86Box/discussions/4823#issue-comment-box
about: Please submit machine addition requests in this discussion thread.
- name: Feature Request or Question
url: https://github.com/86Box/86Box/discussions
about: Please submit feature requests and ask questions here.

View File

@@ -1,116 +0,0 @@
name: MSYS2 Makefile (Windows, Legacy)
on:
push:
paths:
- src/**
- .github/workflows/c-cpp.yml
- "!**/CMakeLists.txt"
pull_request:
paths:
- src/**
- .github/workflows/c-cpp.yml
- "!**/CMakeLists.txt"
jobs:
msys2:
# Negative condition disables the job
if: false
name: "Win32 GUI, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, ${{ matrix.environment.msystem }}"
runs-on: windows-2022
defaults:
run:
shell: msys2 {0}
strategy:
fail-fast: true
matrix:
build:
# - name: Regular
# debug: n
# dev: n
- name: Debug
debug: y
dev: n
slug: -Debug
- name: Dev
debug: y
dev: y
slug: -Dev
dynarec:
- name: ODR
new: n
slug: -ODR
- name: NDR
new: y
slug: -NDR
environment:
# - msystem: MSYS
# clang: n
# x64: y
- msystem: MINGW32
prefix: mingw-w64-i686
clang: n
x64: n
- msystem: MINGW64
prefix: mingw-w64-x86_64
clang: n
x64: y
# - msystem: CLANG32
# prefix: mingw-w64-clang-i686
# clang: y
# x64: n
# - msystem: CLANG64
# prefix: mingw-w64-clang-x86_64
# clang: y
# x64: y
- msystem: UCRT64
prefix: mingw-w64-ucrt-x86_64
clang: n
x64: y
steps:
- name: Prepare MSYS2 environment
uses: msys2/setup-msys2@v2
with:
release: false
update: true
msystem: ${{ matrix.environment.msystem }}
install: >-
make
pacboy: >-
gcc:p
clang:p
pkg-config:p
freetype:p
SDL2:p
zlib:p
libpng:p
openal:p
rtmidi:p
libslirp:p
fluidsynth:p
libvncserver:p
- name: Checkout repository
uses: actions/checkout@v4
- name: make
run: >-
make -fwin/Makefile.mingw -j
DEV_BUILD=${{ matrix.build.dev }}
DEBUG=${{ matrix.build.debug }}
NEW_DYNAREC=${{ matrix.dynarec.new }}
CLANG=${{ matrix.environment.clang }}
X64=${{ matrix.environment.x64 }}
working-directory: ./src
- name: Upload artifact
uses: actions/upload-artifact@v3
with:
name: '86Box${{ matrix.dynarec.slug }}${{ matrix.build.slug }}-Windows-${{ matrix.environment.msystem }}-gha${{ github.run_number }}'
path: src/86Box.exe

View File

@@ -8,7 +8,8 @@ on:
- cmake/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- .github/workflows/cmake.yml
- "!.github/workflows/**"
- .github/workflows/cmake_linux.yml
- vcpkg.json
- "!**/Makefile*"
@@ -18,20 +19,18 @@ on:
- cmake/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- .github/workflows/**
- .github/workflows/cmake.yml
- "!.github/workflows/**"
- .github/workflows/cmake_linux.yml
- vcpkg.json
- "!**/Makefile*"
jobs:
linux:
name: "${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, x86_64"
runs-on: ubuntu-22.04
name: "${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, ${{ matrix.environment.arch }}"
env:
BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed
runs-on: ${{ matrix.environment.runner }}
strategy:
fail-fast: true
@@ -40,10 +39,10 @@ jobs:
# - name: Regular
# preset: regular
- name: Debug
preset: debug
preset: dev_debug
slug: -Debug
- name: Dev
preset: experimental
preset: development
slug: -Dev
dynarec:
- name: ODR
@@ -55,16 +54,47 @@ jobs:
ui:
- name: SDL GUI
qt: off
qt6: off
static: on
- name: Qt GUI
- name: Qt 5 GUI
qt: on
slug: -Qt
qt6: off
slug: -Qt5
packages: >-
qtbase5-dev
qtbase5-private-dev
qttools5-dev
qttranslations5-l10n
libevdev-dev
libxkbcommon-x11-dev
- name: Qt 6 GUI
qt: on
qt6: on
slug: -Qt6
packages: >-
qt6-base-dev
qt6-base-private-dev
qt6-tools-dev
qt6-tools-dev-tools
qt6-l10n-tools
qt6-translations-l10n
libevdev-dev
libxkbcommon-x11-dev
libvulkan-dev
environment:
- arch: x86_64
toolchain: ./cmake/flags-gcc-x86_64.cmake
slug: "-x86_64"
runner: ubuntu-22.04
- arch: arm64
toolchain: ./cmake/flags-gcc-aarch64.cmake
slug: -arm64
runner: ubuntu-22.04-arm
exclude:
- dynarec:
new: off
environment:
arch: arm64
steps:
- name: Install dependencies
@@ -80,7 +110,8 @@ jobs:
libopenal-dev
libslirp-dev
libfluidsynth-dev
libvncserver-dev
libvdeplug-dev
libserialport-dev
${{ matrix.ui.packages }}
- name: Checkout repository
@@ -88,35 +119,25 @@ jobs:
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@v2
- name: Configure CMake
run: >-
cmake -G Ninja -S . -B build --preset ${{ matrix.build.preset }}
--toolchain ./cmake/flags-gcc-x86_64.cmake
--toolchain ${{ matrix.environment.toolchain }}
-D NEW_DYNAREC=${{ matrix.dynarec.new }}
-D CMAKE_INSTALL_PREFIX=./build/artifacts
-D QT=${{ matrix.ui.qt }}
-D USE_QT6=${{ matrix.ui.qt6 }}
- name: Build
run: |
build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} cmake --build build
- name: Run sonar-scanner
# if: 0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: |
sonar-scanner --define sonar.cfamily.build-wrapper-output="${{ env.BUILD_WRAPPER_OUT_DIR }}"
cmake --build build
- name: Generate package
run: |
cmake --install build
- name: Upload artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: '86Box${{ matrix.ui.slug }}${{ matrix.dynarec.slug }}${{ matrix.build.slug }}-UbuntuJammy-x86_64-gha${{ github.run_number }}'
name: '86Box${{ matrix.ui.slug }}${{ matrix.dynarec.slug }}${{ matrix.build.slug }}-UbuntuJammy${{ matrix.environment.slug }}-gha${{ github.run_number }}'
path: build/artifacts/**

View File

@@ -8,7 +8,8 @@ on:
- cmake/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- .github/workflows/cmake.yml
- "!.github/workflows/**"
- .github/workflows/cmake_macos.yml
- vcpkg.json
- "!**/Makefile*"
@@ -18,20 +19,18 @@ on:
- cmake/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- .github/workflows/**
- .github/workflows/cmake.yml
- "!.github/workflows/**"
- .github/workflows/cmake_macos.yml
- vcpkg.json
- "!**/Makefile*"
jobs:
macos12:
macos13-x86_64:
name: "${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, x86_64"
runs-on: macos-12
env:
BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed
runs-on: macos-13
strategy:
fail-fast: true
@@ -40,10 +39,10 @@ jobs:
# - name: Regular
# preset: regular
- name: Debug
preset: debug
preset: dev_debug
slug: -Debug
- name: Dev
preset: experimental
preset: development
slug: -Dev
dynarec:
- name: ODR
@@ -56,33 +55,23 @@ 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
ninja
freetype
sdl2
libpng
rtmidi
openal-soft
fluidsynth
libvncserver
libslirp
vde
libserialport
${{ matrix.ui.packages }}
- name: Checkout repository
@@ -90,9 +79,6 @@ jobs:
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@v2
- name: Configure CMake
run: >-
cmake -G Ninja -S . -B build --preset ${{ matrix.build.preset }}
@@ -103,25 +89,93 @@ jobs:
-D Qt5_ROOT=$(brew --prefix qt@5)
-D Qt5LinguistTools_ROOT=$(brew --prefix qt@5)
-D OpenAL_ROOT=$(brew --prefix openal-soft)
-D LIBSERIALPORT_ROOT=$(brew --prefix libserialport)
- name: Build
run: |
build-wrapper-macosx-x86 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} cmake --build build
- name: Run sonar-scanner
if: 0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: |
sonar-scanner --define sonar.cfamily.build-wrapper-output="${{ env.BUILD_WRAPPER_OUT_DIR }}"
run: cmake --build build
- name: Generate package
run: |
cmake --install build
run: cmake --install build
- name: Upload artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: '86Box${{ matrix.ui.slug }}${{ matrix.dynarec.slug }}${{ matrix.build.slug }}-macOS-x86_64-gha${{ github.run_number }}'
path: build/artifacts/**
macos14-arm64:
name: "${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, arm64"
runs-on: macos-14
strategy:
fail-fast: true
matrix:
build:
# - name: Regular
# preset: regular
- name: Debug
preset: dev_debug
slug: -Debug
- name: Dev
preset: development
slug: -Dev
dynarec:
# - name: ODR
# new: off
# slug: -ODR
- name: NDR
new: on
slug: -NDR
ui:
- name: SDL GUI
qt: off
static: on
- name: Qt GUI
qt: on
slug: -Qt
packages: >-
qt@5
steps:
- name: Install dependencies
run: >-
brew install
sdl2
rtmidi
openal-soft
fluidsynth
libslirp
vde
libserialport
${{ matrix.ui.packages }}
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: Configure CMake
run: >-
cmake -G Ninja -S . -B build --preset ${{ matrix.build.preset }}
--toolchain ./cmake/llvm-macos-aarch64.cmake
-D NEW_DYNAREC=${{ matrix.dynarec.new }}
-D CMAKE_INSTALL_PREFIX=./build/artifacts
-D QT=${{ matrix.ui.qt }}
-D Qt5_ROOT=$(brew --prefix qt@5)
-D Qt5LinguistTools_ROOT=$(brew --prefix qt@5)
-D OpenAL_ROOT=$(brew --prefix openal-soft)
-D LIBSERIALPORT_ROOT=$(brew --prefix libserialport)
- name: Build
run: cmake --build build
- name: Generate package
run: cmake --install build
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: '86Box${{ matrix.ui.slug }}${{ matrix.dynarec.slug }}${{ matrix.build.slug }}-macOS-arm64-gha${{ github.run_number }}'
path: build/artifacts/**

View File

@@ -1,163 +0,0 @@
name: CMake (Windows, vcpkg/LLVM)
on:
push:
paths:
- src/**
- cmake/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- .github/workflows/cmake.yml
- vcpkg.json
- "!**/Makefile*"
pull_request:
paths:
- src/**
- cmake/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- .github/workflows/**
- .github/workflows/cmake.yml
- vcpkg.json
- "!**/Makefile*"
jobs:
llvm-windows:
name: "${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, ${{ matrix.target.name }}"
if: 0
runs-on: windows-2022
env:
BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed
VCPKG_BINARY_SOURCES: 'clear;nuget,GitHub,readwrite'
strategy:
fail-fast: true
matrix:
build:
# - name: Regular
# preset: regular
- name: Debug
preset: debug
slug: -Debug
- name: Dev
preset: experimental
slug: -Dev
dynarec:
- name: ODR
new: off
slug: -ODR
- name: NDR
new: on
slug: -NDR
ui:
- name: Win32 GUI
qt: off
- name: Qt GUI
qt: on
slug: -Qt
target:
- name: x86
triplet: x86-windows-static
toolchain: ./cmake/llvm-win32-i686.cmake
vcvars: x64_x86
- name: x64
triplet: x64-windows-static
toolchain: ./cmake/llvm-win32-x86_64.cmake
vcvars: x64
# - name: ARM
# triplet: arm-windows-static
# toolchain: ./cmake/llvm-win32-arm.cmake
# vcvars: x64_arm
- name: ARM64
triplet: arm64-windows-static
toolchain: ./cmake/llvm-win32-aarch64.cmake
vcvars: x64_arm64
exclude:
- dynarec:
new: off
target:
name: ARM64
steps:
- name: Prepare VS environment
uses: ilammy/msvc-dev-cmd@v1
with:
arch: ${{ matrix.target.vcvars }}
- name: Add LLVM to path
run: echo "C:/Program Files/LLVM/bin" >> $env:GITHUB_PATH
- name: Download Ninja
run: >
Invoke-WebRequest https://github.com/ninja-build/ninja/releases/download/v1.11.1/ninja-win.zip -OutFile ninja-win.zip &&
Expand-Archive ninja-win.zip -DestinationPath .
- name: Setup NuGet Credentials
run: >
& (C:/vcpkg/vcpkg --vcpkg-root "${{ env.VCPKG_ROOT }}" fetch nuget | tail -n 2)
sources add
-source "https://nuget.pkg.github.com/86Box/index.json"
-storepasswordincleartext
-name "GitHub"
-username "86Box"
-password "${{ secrets.GITHUB_TOKEN }}"
- name: Fix MSVC atomic headers
run: dir "C:/Program Files/Microsoft Visual Studio/2022/*/VC/Tools/MSVC/*/include" -include stdatomic.h -recurse | del
- 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@v2
- name: Configure CMake
run: >
cmake -G Ninja -S . -B build --preset ${{ matrix.build.preset }}
--toolchain C:/vcpkg/scripts/buildsystems/vcpkg.cmake
-D NEW_DYNAREC=${{ matrix.dynarec.new }} -D QT=${{ matrix.ui.qt }}
-D CMAKE_INSTALL_PREFIX=./build/artifacts
-D VCPKG_CHAINLOAD_TOOLCHAIN_FILE=${{ github.workspace }}/${{ matrix.target.toolchain }}
-D VCPKG_TARGET_TRIPLET=${{ matrix.target.triplet }}
-D VCPKG_HOST_TRIPLET=x64-windows
-D VCPKG_USE_HOST_TOOLS=ON
- name: Fix Qt
if: matrix.ui.qt == 'on'
run: |
$qtTargetsPath = "${{ github.workspace }}/build/vcpkg_installed/${{ matrix.target.triplet }}/share/Qt6/Qt6Targets.cmake"
(Get-Content $qtTargetsPath) -replace "^.*-Zc:__cplusplus;-permissive-.*$","#$&" | Set-Content $qtTargetsPath
- name: Reconfigure CMake
if: matrix.ui.qt == 'on'
run: |
cmake clean 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
- 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: Generate package
run: |
cmake --install build
- name: Upload artifact
uses: actions/upload-artifact@v3
with:
name: '86Box${{ matrix.ui.slug }}${{ matrix.dynarec.slug }}${{ matrix.build.slug }}-Windows-LLVM-${{ matrix.target.name }}-gha${{ github.run_number }}'
path: build/artifacts/**

View File

@@ -8,7 +8,8 @@ on:
- cmake/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- .github/workflows/cmake.yml
- "!.github/workflows/**"
- .github/workflows/cmake_windows_msys2.yml
- vcpkg.json
- "!**/Makefile*"
@@ -18,20 +19,18 @@ on:
- cmake/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- .github/workflows/**
- .github/workflows/cmake.yml
- "!.github/workflows/**"
- .github/workflows/cmake_windows_msys2.yml
- vcpkg.json
- "!**/Makefile*"
jobs:
msys2:
name: "${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, ${{ matrix.environment.msystem }}"
runs-on: windows-2022
name: "${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, ${{ matrix.environment.msystem }}"
env:
BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed
runs-on: ${{ matrix.environment.runner }}
defaults:
run:
@@ -44,10 +43,10 @@ jobs:
# - name: Regular
# preset: regular
- name: Debug
preset: debug
preset: dev_debug
slug: -Debug
- name: Dev
preset: experimental
preset: development
slug: -Dev
dynarec:
- name: ODR
@@ -62,33 +61,41 @@ jobs:
static: on
slug: -Qt
packages: >-
qt5-static:p
# qt5-base:p
# qt5-tools:p
qt5-base:p
qt5-tools:p
vulkan-headers:p
environment:
# - msystem: MSYS
# toolchain: ./cmake/flags-gcc-x86_64.cmake
- msystem: MINGW32
prefix: mingw-w64-i686
toolchain: ./cmake/flags-gcc-i686.cmake
# slug: "-MSYS64"
- msystem: MINGW64
prefix: mingw-w64-x86_64
toolchain: ./cmake/flags-gcc-x86_64.cmake
# - msystem: CLANG32
# prefix: mingw-w64-clang-i686
# toolchain: ./cmake/llvm-win32-i686.cmake
slug: "-64"
runner: windows-2022
# - 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: "CLANG64"
# - msystem: UCRT64
# prefix: mingw-w64-ucrt-x86_64
# toolchain: ./cmake/flags-gcc-x86_64.cmake
# slug: "UCRT64"
- 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: >-
@@ -104,43 +111,31 @@ jobs:
rtmidi:p
libslirp:p
fluidsynth:p
libvncserver:p
${{ matrix.ui.packages }}
libserialport:p
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@v2
- name: Configure CMake
run: >-
cmake -G Ninja -S . -B build --preset ${{ matrix.build.preset }}
--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: 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 }}"
run: cmake --build build
- name: Generate package
run: cmake --install build
- name: Upload artifact
uses: actions/upload-artifact@v3
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/**

View File

@@ -3,34 +3,43 @@ name: CodeQL Analysis (Linux)
on:
push:
branches: [ "master" ]
paths:
- src/**
- cmake/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- .github/workflows/codeql.yml
- "!.github/workflows/**"
- .github/workflows/codeql_linux.yml
- vcpkg.json
- "!**/Makefile*"
pull_request:
branches: [ "master" ]
paths:
- src/**
- cmake/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- .github/workflows/**
- .github/workflows/codeql.yml
- "!.github/workflows/**"
- .github/workflows/codeql_linux.yml
- vcpkg.json
- "!**/Makefile*"
schedule:
- cron: '22 11 * * 0'
jobs:
analyze-linux:
name: "Analyze Linux GCC 11 (${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, x86_64)"
name: "Analyze (${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, x86_64)"
runs-on: ubuntu-22.04
env:
BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed
permissions:
actions: read
contents: read
@@ -43,12 +52,12 @@ jobs:
build:
# - name: Regular
# preset: regular
# - name: Debug
# preset: debug
# slug: -Debug
- name: Dev
preset: experimental
slug: -Dev
- name: Debug
preset: dev_debug
slug: -Debug
# - name: Dev
# preset: development
# slug: -Dev
dynarec:
- name: ODR
new: off
@@ -59,6 +68,7 @@ jobs:
ui:
- name: SDL GUI
qt: off
static: on
- name: Qt GUI
qt: on
slug: -Qt
@@ -66,6 +76,7 @@ jobs:
qtbase5-dev
qtbase5-private-dev
qttools5-dev
qttranslations5-l10n
libevdev-dev
libxkbcommon-x11-dev
@@ -83,14 +94,20 @@ jobs:
libopenal-dev
libslirp-dev
libfluidsynth-dev
libvncserver-dev
libvdeplug-dev
libserialport-dev
${{ matrix.ui.packages }}
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: Install Build Wrapper
uses: SonarSource/sonarqube-scan-action/install-build-wrapper@v5
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
config-file: ./.github/codeql/codeql-config.yml
@@ -104,9 +121,23 @@ jobs:
-D QT=${{ matrix.ui.qt }}
- name: Build
run: cmake --build build
run: |
build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} cmake --build build
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"
- name: SonarQube Scan
if: matrix.build.preset == 'dev_debug' && matrix.dynarec.new == 'on' && matrix.ui.qt == 'on' && env.SONAR_TOKEN != ''
# if: 0
uses: SonarSource/sonarqube-scan-action@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
# SONAR_ROOT_CERT: ${{ secrets.SONAR_ROOT_CERT }}
with:
# Consult https://docs.sonarsource.com/sonarqube-server/latest/analyzing-source-code/scanners/sonarscanner/ for more information and options
args: >
--define sonar.cfamily.compile-commands="${{ env.BUILD_WRAPPER_OUT_DIR }}/compile_commands.json"

View File

@@ -3,33 +3,42 @@ name: CodeQL Analysis (macos)
on:
push:
branches: [ "master" ]
paths:
- src/**
- cmake/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- .github/workflows/codeql.yml
- "!.github/workflows/**"
- .github/workflows/codeql_macos.yml
- vcpkg.json
- "!**/Makefile*"
pull_request:
branches: [ "master" ]
paths:
- src/**
- cmake/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- .github/workflows/**
- .github/workflows/codeql.yml
- "!.github/workflows/**"
- .github/workflows/codeql_macos.yml
- vcpkg.json
- "!**/Makefile*"
schedule:
- cron: '22 11 * * 0'
jobs:
analyze-macos12:
analyze-macos13-x86_64:
name: "${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, x86_64"
name: "Analyze (${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, x86_64)"
runs-on: macos-12
runs-on: macos-13
env:
BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed
permissions:
actions: read
@@ -43,12 +52,12 @@ jobs:
build:
# - name: Regular
# preset: regular
# - name: Debug
# preset: debug
# slug: -Debug
- name: Dev
preset: experimental
slug: -Dev
- name: Debug
preset: dev_debug
slug: -Debug
# - name: Dev
# preset: development
# slug: -Dev
dynarec:
- name: ODR
new: off
@@ -69,21 +78,25 @@ jobs:
- name: Install dependencies
run: >-
brew install
ninja
freetype
sdl2
libpng
rtmidi
openal-soft
fluidsynth
libvncserver
libslirp
vde
libserialport
${{ matrix.ui.packages }}
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: Install Build Wrapper
uses: SonarSource/sonarqube-scan-action/install-build-wrapper@v5
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
config-file: ./.github/codeql/codeql-config.yml
@@ -98,11 +111,26 @@ jobs:
-D Qt5_ROOT=$(brew --prefix qt@5)
-D Qt5LinguistTools_ROOT=$(brew --prefix qt@5)
-D OpenAL_ROOT=$(brew --prefix openal-soft)
-D LIBSERIALPORT_ROOT=$(brew --prefix libserialport)
- name: Build
run: cmake --build build
run: |
build-wrapper-macosx-x86 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} cmake --build build
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"
- name: SonarQube Scan
# if: matrix.build.preset == 'dev_debug' && matrix.dynarec.new == 'on' && matrix.ui.qt == 'on' && env.SONAR_TOKEN != ''
if: 0
uses: SonarSource/sonarqube-scan-action@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
# SONAR_ROOT_CERT: ${{ secrets.SONAR_ROOT_CERT }}
with:
# Consult https://docs.sonarsource.com/sonarqube-server/latest/analyzing-source-code/scanners/sonarscanner/ for more information and options
args: >
--define sonar.cfamily.compile-commands="${{ env.BUILD_WRAPPER_OUT_DIR }}/compile_commands.json"

View File

@@ -3,33 +3,42 @@ name: CodeQL Analysis (Windows, msys2)
on:
push:
branches: [ "master" ]
paths:
- src/**
- cmake/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- .github/workflows/codeql.yml
- "!.github/workflows/**"
- .github/workflows/codeql_windows_msys2.yml
- vcpkg.json
- "!**/Makefile*"
pull_request:
branches: [ "master" ]
paths:
- src/**
- cmake/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- .github/workflows/**
- .github/workflows/codeql.yml
- "!.github/workflows/**"
- .github/workflows/codeql_windows_msys2.yml
- vcpkg.json
- "!**/Makefile*"
schedule:
- cron: '22 11 * * 0'
jobs:
analyze-msys2:
name: "${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, ${{ matrix.environment.msystem }}"
name: "Analyze (${{ matrix.ui.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
permissions:
actions: read
@@ -47,12 +56,12 @@ jobs:
build:
# - name: Regular
# preset: regular
# - name: Debug
# preset: debug
# slug: -Debug
- name: Dev
preset: experimental
slug: -Dev
- name: Debug
preset: dev_debug
slug: -Debug
# - name: Dev
# preset: development
# slug: -Dev
dynarec:
- name: ODR
new: off
@@ -61,9 +70,6 @@ jobs:
new: on
slug: -NDR
ui:
- name: Win32 GUI
qt: off
static: on
- name: Qt GUI
qt: on
static: off
@@ -71,30 +77,41 @@ jobs:
packages: >-
qt5-base:p
qt5-tools:p
vulkan-headers:p
environment:
# - msystem: MSYS
# toolchain: ./cmake/flags-gcc-x86_64.cmake
- msystem: MINGW32
prefix: mingw-w64-i686
toolchain: ./cmake/flags-gcc-i686.cmake
# slug: "-MSYS64"
- msystem: MINGW64
prefix: mingw-w64-x86_64
toolchain: ./cmake/flags-gcc-x86_64.cmake
# - msystem: CLANG32
# prefix: mingw-w64-clang-i686
# toolchain: ./cmake/llvm-win32-i686.cmake
slug: "-64"
runner: windows-2022
# - 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: "CLANG64"
# runner: windows-2022
# - msystem: UCRT64
# prefix: mingw-w64-ucrt-x86_64
# toolchain: ./cmake/flags-gcc-x86_64.cmake
# slug: "UCRT64"
# 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: >-
@@ -110,14 +127,20 @@ jobs:
rtmidi:p
libslirp:p
fluidsynth:p
libvncserver:p
libserialport:p
${{ matrix.ui.packages }}
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 Build Wrapper
# uses: SonarSource/sonarqube-scan-action/install-build-wrapper@v5
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
config-file: ./.github/codeql/codeql-config.yml
@@ -131,11 +154,27 @@ jobs:
-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: cmake --build build
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"
- name: SonarQube Scan
# if: matrix.build.preset == 'dev_debug' && matrix.dynarec.new == 'on' && matrix.ui.qt == 'on' && env.SONAR_TOKEN != ''
if: 0
uses: SonarSource/sonarqube-scan-action@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
# SONAR_ROOT_CERT: ${{ secrets.SONAR_ROOT_CERT }}
with:
# Consult https://docs.sonarsource.com/sonarqube-server/latest/analyzing-source-code/scanners/sonarscanner/ for more information and options
args: >
--define sonar.cfamily.compile-commands="${{ env.BUILD_WRAPPER_OUT_DIR }}/compile_commands.json"

6
.gitignore vendored
View File

@@ -59,3 +59,9 @@ CMakeLists.txt.user
# MacOS Finder stuff
.DS_Store
# clangd
.cache
# Jetbrains CLion
.idea

View File

@@ -1,16 +1,17 @@
#
# 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.
# 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.
# This file is part of the 86Box distribution.
#
# CMake build script.
# CMake build script.
#
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
#
# Copyright 2020-2021 David Hrdlička.
# Copyright 2020-2021 David Hrdlička.
# Copyright 2021-2025 Jasmine Iwanek.
#
cmake_minimum_required(VERSION 3.16)
@@ -35,7 +36,7 @@ if(MUNT_EXTERNAL)
endif()
project(86Box
VERSION 4.1
VERSION 5.1
DESCRIPTION "Emulator of x86-based systems"
HOMEPAGE_URL "https://86box.net"
LANGUAGES C CXX)
@@ -122,43 +123,68 @@ set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON)
# Optional features
#
# Option Description Def.
# ------ ----------- ----
option(RELEASE "Release build" OFF)
option(DYNAREC "Dynamic recompiler" ON)
option(OPENAL "OpenAL" ON)
option(RTMIDI "RtMidi" ON)
option(FLUIDSYNTH "FluidSynth" ON)
option(MUNT "MUNT" ON)
option(VNC "VNC renderer" OFF)
option(DINPUT "DirectInput" OFF)
option(CPPTHREADS "C++11 threads" ON)
option(NEW_DYNAREC "Use the PCem v15 (\"new\") dynamic recompiler" OFF)
option(MINITRACE "Enable Chrome tracing using the modified minitrace library" OFF)
option(GDBSTUB "Enable GDB stub server for debugging" OFF)
option(DEV_BRANCH "Development branch" OFF)
option(QT "Qt GUI" ON)
option(DISCORD "Discord Rich Presence support" ON)
# Option Description Def.
# ------ ----------- ----
option(RELEASE "Release build" OFF)
option(DYNAREC "Dynamic recompiler" ON)
option(OPENAL "OpenAL" ON)
option(RTMIDI "RtMidi" ON)
option(FLUIDSYNTH "FluidSynth" ON)
option(MUNT "MUNT" ON)
option(VNC "VNC renderer" OFF)
option(MINITRACE "Enable Chrome tracing using the modified minitrace library" OFF)
option(GDBSTUB "Enable GDB stub server for debugging" OFF)
option(DEV_BRANCH "Development branch" OFF)
option(DISCORD "Discord Rich Presence support" ON)
option(DEBUGREGS486 "Enable debug register opeartion on 486+ CPUs" OFF)
option(LIBASAN "Enable compilation with the addresss sanitizer" OFF)
if((ARCH STREQUAL "arm64") OR (ARCH STREQUAL "arm"))
set(NEW_DYNAREC ON)
else()
option(NEW_DYNAREC "Use the PCem v15 (\"new\") dynamic recompiler" OFF)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "NetBSD")
option(AUDIO4 "Use audio(4) as sound backend" ON)
else()
set(AUDIO4 OFF)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
option(SNDIO "Use sndio as sound backend" ON)
else()
set(SNDIO OFF)
endif()
if(WIN32)
set(QT ON)
option(CPPTHREADS "C++11 threads" OFF)
else()
option(QT "Qt GUI" ON)
option(CPPTHREADS "C++11 threads" ON)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
SET(CMAKE_EXE_LINKER_FLAGS "-Wl,-z,wxneeded")
endif()
# Development branch features
#
# 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(CYRIX_6X86 "Cyrix 6x86" ON "DEV_BRANCH" OFF)
cmake_dependent_option(DESKPRO386 "Compaq Deskpro 386" 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(PAS16 "Pro Audio Spectrum 16" ON "DEV_BRANCH" OFF)
cmake_dependent_option(SIO_DETECT "Super I/O Detection Helper" ON "DEV_BRANCH" OFF)
cmake_dependent_option(VGAWONDER "ATI VGA Wonder (ATI-18800)" ON "DEV_BRANCH" OFF)
cmake_dependent_option(XL24 "ATI VGA Wonder XL24 (ATI-28800-6)" ON "DEV_BRANCH" OFF)
# Option Description Def. Condition Otherwise
# ------ ----------- ---- ------------ ---------
cmake_dependent_option(AMD_K5 "AMD K5" 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(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(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)
cmake_dependent_option(WACOM "Wacom Input Devices" ON "DEV_BRANCH" OFF)
cmake_dependent_option(XL24 "ATI VGA Wonder XL24 (ATI-28800-6)" ON "DEV_BRANCH" OFF)
cmake_dependent_option(NETSWITCH "Network Switch Support" ON "DEV_BRANCH" OFF)
# Ditto but for Qt
if(QT)
@@ -196,7 +222,15 @@ if(NOT EMU_BUILD_NUM)
set(EMU_BUILD_NUM 0)
endif()
if(NOT EMU_COPYRIGHT_YEAR)
set(EMU_COPYRIGHT_YEAR 2024)
set(EMU_COPYRIGHT_YEAR 2025)
endif()
# Libasan
if(LIBASAN)
add_compile_options(-fsanitize=address)
add_link_options(-fsanitize=address)
endif()
set(CMAKE_TOP_LEVEL_PROCESSED TRUE)
add_subdirectory(src)

View File

@@ -43,17 +43,23 @@
"name": "development",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"DEV_BRANCH": "ON",
"NEW_DYNAREC": "OFF"
"DEV_BRANCH": "ON"
},
"inherits": "base"
},
{
"name": "experimental",
"name": "dev_debug",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"DEV_BRANCH": "ON",
"NEW_DYNAREC": "ON"
"DEV_BRANCH": "ON"
},
"inherits": "base"
},
{
"name": "ultra_debug",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "UltraDebug",
"DEV_BRANCH": "ON"
},
"inherits": "base"
},
@@ -70,7 +76,8 @@
"Qt5_DIR": "/opt/homebrew/opt/qt@5/lib/cmake/Qt5",
"MOLTENVK_DIR": "/opt/homebrew/opt/molten-vk",
"Qt5LinguistTools_DIR": "/opt/homebrew/opt/qt@5/lib/cmake/Qt5LinguistTools",
"OpenAL_ROOT": "/opt/homebrew/opt/openal-soft"
"OpenAL_ROOT": "/opt/homebrew/opt/openal-soft",
"LIBSERIALPORT_ROOT": "/opt/homebrew/opt/libserialport"
},
"inherits": "regular"
},
@@ -88,6 +95,7 @@
"MOLTENVK_DIR": "/opt/homebrew/opt/molten-vk",
"Qt5LinguistTools_DIR": "/opt/homebrew/opt/qt@5/lib/cmake/Qt5LinguistTools",
"OpenAL_ROOT": "/opt/homebrew/opt/openal-soft",
"LIBSERIALPORT_ROOT": "/opt/homebrew/opt/libserialport",
"CMAKE_CXX_FLAGS_DEBUG": "-g -O0 -DENABLE_VDE_LOG",
"CMAKE_C_FLAGS_DEBUG": "-g -O0 -DENABLE_VDE_LOG"
},

View File

@@ -26,15 +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)
* [Linbox-qt5](https://github.com/Dungeonseeker/linbox-qt5) by Dungeonseeker (Linux focused, should work on Windows though untested)
* [86Box Manager X](https://github.com/RetBox/86BoxManagerX) by [xafero](https://github.com/xafero) (Cross platform Port of 86Box Manager using Avalonia)
* [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
---------------
@@ -44,17 +47,21 @@ 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!
[![Visit our IRC channel](https://kiwiirc.com/buttons/irc.ringoflightning.net/86Box.png)](https://kiwiirc.com/client/irc.ringoflightning.net/?nick=86box|?#86Box)
[![Visit our Discord server](https://discordapp.com/api/guilds/262614059009048590/embed.png)](https://discord.gg/QXK9XTv)
Contributions
---------
-------------
We welcome all contributions to the project, as long as the [contribution guidelines](CONTRIBUTING.md) are followed.
Building
---------
For instructions on how to build 86Box from source, see the [build guide](https://86box.readthedocs.io/en/latest/dev/buildguide.html).
Licensing
---------

18
SECURITY.md Normal file
View File

@@ -0,0 +1,18 @@
# Security Policy
## Supported Versions
| Version | Supported |
| --------- | ------------------ |
| >= master | :white_check_mark: |
| < master | :x: |
Each version is supported in the form of patch releases until the next version is merged into master.
## Reporting a Vulnerability
To report a vulnerability, either open an issue here on GitHub or join our Discord server. If it is
accepted, that means we have begun working on it and it will be fixed if it is at all possible. If it
is declined, then that means we have either determined it to not actually be a vulnerability or we
have determined it is not feasible to fix it. On GitHub, we are going to notify you when a decision
taken, and if accepted, when it is fixed. On Discord, you get live updates.

View File

@@ -26,12 +26,6 @@ then
fi
shift
# Extract version components.
newversion_maj=$(echo "$newversion" | cut -d. -f1)
newversion_min=$(echo "$newversion" | cut -d. -f2)
newversion_patch=$(echo "$newversion" | cut -d. -f3)
[ -z "$newversion_patch" ] && newversion_patch=0
if [ -z "${romversion}" ]; then
# Get the latest ROM release from the GitHub API.
romversion=$(curl --silent "https://api.github.com/repos/86Box/roms/releases/latest" |
@@ -62,12 +56,6 @@ patch_file() {
}
patch_file CMakeLists.txt VERSION 's/^(\s*VERSION ).+/\1'"$newversion"'/'
patch_file vcpkg.json version-string 's/(^\s*"version-string"\s*:\s*")[^"]+/\1'"$newversion"'/'
patch_file src/include_make/*/version.h EMU_VERSION 's/(#\s*define\s+EMU_VERSION\s+")[^"]+/\1'"$newversion"'/'
patch_file src/include_make/*/version.h EMU_VERSION_MAJ 's/(#\s*define\s+EMU_VERSION_MAJ\s+)[0-9]+/\1'"$newversion_maj"'/'
patch_file src/include_make/*/version.h EMU_VERSION_MIN 's/(#\s*define\s+EMU_VERSION_MIN\s+)[0-9]+/\1'"$newversion_min"'/'
patch_file src/include_make/*/version.h EMU_VERSION_PATCH 's/(#\s*define\s+EMU_VERSION_PATCH\s+)[0-9]+/\1'"$newversion_patch"'/'
patch_file src/include_make/*/version.h COPYRIGHT_YEAR 's/(#\s*define\s+COPYRIGHT_YEAR\s+)[0-9]+/\1'"$(date +%Y)"'/'
patch_file src/include_make/*/version.h EMU_DOCS_URL 's/(#\s*define\s+EMU_DOCS_URL\s+"https:\/\/[^\/]+\/en\/v)[^\/]+/\1'"$newversion_maj.$newversion_min"'/'
patch_file src/unix/assets/*.spec Version 's/(Version:\s+)[0-9].+/\1'"$newversion"'/'
patch_file src/unix/assets/*.spec '%global romver' 's/(^%global\ romver\s+)[0-9]{8}/\1'"$romversion"'/'
patch_file src/unix/assets/*.spec 'changelog version' 's/(^[*]\s.*>\s+)[0-9].+/\1'"$newversion"-1'/'

View File

@@ -20,6 +20,8 @@ string(APPEND CMAKE_C_FLAGS_RELEASE_INIT " -g0 -O3")
string(APPEND CMAKE_CXX_FLAGS_RELEASE_INIT " -g0 -O3")
string(APPEND CMAKE_C_FLAGS_DEBUG_INIT " -ggdb -Og")
string(APPEND CMAKE_CXX_FLAGS_DEBUG_INIT " -ggdb -Og")
string(APPEND CMAKE_C_FLAGS_ULTRADEBUG_INIT " -O0 -ggdb -g3")
string(APPEND CMAKE_CXX_FLAGS_ULTRADEBUG_INIT " -O0 -ggdb -g3")
string(APPEND CMAKE_C_FLAGS_OPTIMIZED_INIT " -march=native -mtune=native -O3 -ffp-contract=fast -flto")
string(APPEND CMAKE_CXX_FLAGS_OPTIMIZED_INIT " -march=native -mtune=native -O3 -ffp-contract=fast -flto")
@@ -28,7 +30,7 @@ foreach(LANG C;CXX)
set(CMAKE_${LANG}_FLAGS "$ENV{${LANG}FLAGS} ${CMAKE_${LANG}_FLAGS_INIT}" CACHE STRING "Flags used by the ${LANG} compiler during all build types.")
mark_as_advanced(CMAKE_${LANG}_FLAGS)
foreach(CONFIG RELEASE;DEBUG;OPTIMIZED)
foreach(CONFIG RELEASE;DEBUG;ULTRADEBUG;OPTIMIZED)
set(CMAKE_${LANG}_FLAGS_${CONFIG} "${CMAKE_${LANG}_FLAGS_${CONFIG}_INIT}" CACHE STRING "Flags used by the ${LANG} compiler during ${CONFIG} builds.")
mark_as_advanced(CMAKE_${LANG}_FLAGS_${CONFIG})
endforeach()

View 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)

View 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
View File

@@ -1,5 +1,5 @@
86box (4.1) UNRELEASED; urgency=medium
86box (5.1) UNRELEASED; urgency=medium
* Bump release.
-- Jasmine Iwanek <jriwanek@gmail.com> Mon, 16 Oct 2023 20:24:46 +0200
-- Jasmine Iwanek <jriwanek@gmail.com> Wed, 27 Aug 2025 19:39:16 +0200

6
debian/control vendored
View File

@@ -13,9 +13,11 @@ Build-Depends: cmake (>= 3.21),
libsdl2-dev,
libslirp-dev,
libxkbcommon-x11-dev,
libsndfile-dev,
ninja-build,
qttools5-dev,
qtbase5-private-dev
qtbase5-private-dev,
libserialport-dev
Standards-Version: 4.6.0
Homepage: https://86box.net/
#Vcs-Browser: https://salsa.debian.org/debian/86box
@@ -31,4 +33,4 @@ Recommends: libpcap0.8-dev
Description: An emulator for classic IBM PC clones
86Box is a low level x86 emulator that runs older operating systems and software
designed for IBM PC systems and compatibles from 1981 through
fairly recent system designs based on the PCI bus.
fairly recent system designs based on the PCI bus.

File diff suppressed because it is too large Load Diff

View File

@@ -12,16 +12,43 @@
# dob205
#
# Copyright 2020-2022 David Hrdlička.
# Copyright 2021 dob205.
# Copyright 2021 dob205.
# Copyright 2024 Jasmine Iwanek.
#
if(NOT CMAKE_TOP_LEVEL_PROCESSED)
message(FATAL_ERROR "Incorrect source directory specified. Delete your build directory and retry with the top-level directory instead")
endif()
if(APPLE)
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
endif()
add_executable(86Box 86box.c config.c log.c random.c timer.c io.c acpi.c apm.c
dma.c ddma.c nmi.c pic.c pit.c pit_fast.c port_6x.c port_92.c ppi.c pci.c
mca.c usb.c fifo.c fifo8.c device.c nvr.c nvr_at.c nvr_ps2.c
machine_status.c ini.c)
add_executable(86Box
86box.c
config.c
timer.c
io.c
acpi.c
apm.c
dma.c
ddma.c
nmi.c
pic.c
pit.c
pit_fast.c
port_6x.c
port_92.c
ppi.c
pci.c
mca.c
usb.c
device.c
nvr.c
nvr_at.c
nvr_ps2.c
machine_status.c
)
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
add_compile_definitions(_FILE_OFFSET_BITS=64 _LARGEFILE_SOURCE=1 _LARGEFILE64_SOURCE=1)
@@ -48,21 +75,24 @@ if(DYNAREC)
add_compile_definitions(USE_DYNAREC)
endif()
if(DEV_BRANCH)
add_compile_definitions(DEV_BRANCH)
endif()
if(DISCORD)
add_compile_definitions(DISCORD)
target_sources(86Box PRIVATE discord.c)
endif()
if(DEBUGREGS486)
add_compile_definitions(USE_DEBUG_REGS_486)
endif()
if(VNC)
find_package(LibVNCServer)
if(LibVNCServer_FOUND)
add_compile_definitions(USE_VNC)
add_library(vnc OBJECT vnc.c vnc_keymap.c)
target_link_libraries(86Box vnc LibVNCServer::vncserver)
add_library(vnc OBJECT
vnc.c
vnc_keymap.c
)
target_link_libraries(86Box vnc LibVNCServer::vncserver)
if(WIN32)
target_link_libraries(86Box ws2_32)
endif()
@@ -73,8 +103,12 @@ if(INSTRUMENT)
add_compile_definitions(USE_INSTRUMENT)
endif()
target_link_libraries(86Box cpu chipset mch dev mem fdd game cdrom zip mo hdd
net print scsi sio snd vid voodoo plat ui)
target_link_libraries(86Box cpu chipset mch dev mem fdd game cdrom rdisk mo hdd
net print scsi sio snd utils vid voodoo plat ui)
if(HAIKU)
target_link_libraries(86Box be)
endif()
if(WIN32 AND ARCH STREQUAL "i386")
if(MINGW)
@@ -119,16 +153,6 @@ if(APPLE)
target_link_libraries(86Box Freetype::Freetype)
endif()
find_package(SDL2 REQUIRED)
include_directories(${SDL2_INCLUDE_DIRS})
if(STATIC_BUILD AND TARGET SDL2::SDL2-static)
target_link_libraries(86Box SDL2::SDL2-static)
elseif(TARGET SDL2::SDL2)
target_link_libraries(86Box SDL2::SDL2)
else()
target_link_libraries(86Box ${SDL2_LIBRARIES})
endif()
find_package(PNG REQUIRED)
include_directories(${PNG_INCLUDE_DIRS})
target_link_libraries(86Box PNG::PNG)
@@ -139,8 +163,10 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR}/include)
include_directories(include)
if(NEW_DYNAREC)
include_directories(cpu codegen_new)
else()
elseif(DYNAREC)
include_directories(cpu codegen)
else()
include_directories(cpu)
endif()
add_subdirectory(cdrom)
@@ -149,7 +175,7 @@ add_subdirectory(chipset)
add_subdirectory(cpu)
if(NEW_DYNAREC)
add_subdirectory(codegen_new)
else()
elseif(DYNAREC)
add_subdirectory(codegen)
endif()
@@ -189,7 +215,6 @@ elseif(APPLE AND NOT QT)
COMPONENT Runtime)
endif()
# Install the PDB file on Windows builds
if(MSVC)
# CMake fully supports PDB files on MSVC-compatible compilers
@@ -219,16 +244,20 @@ add_subdirectory(printer)
add_subdirectory(sio)
add_subdirectory(scsi)
add_subdirectory(sound)
add_subdirectory(utils)
add_subdirectory(video)
if (APPLE)
add_subdirectory(mac)
endif()
if (QT)
add_subdirectory(qt)
elseif(WIN32)
add_subdirectory(win)
else()
add_compile_definitions(USE_SDL_UI)
add_subdirectory(unix)
endif()
if(CMAKE_SYSTEM_NAME MATCHES "NetBSD")
add_custom_command(TARGET 86Box POST_BUILD COMMAND paxctl ARGS +m $<TARGET_FILE:86Box> COMMENT "Disable PaX MPROTECT")
endif()

View File

@@ -1,200 +0,0 @@
#
# 86Box A hypervisor and IBM PC system emulator that specializes in
# running old operating systems and software designed for IBM
# PC systems and compatibles from 1981 through fairly recent
# system designs based on the PCI bus.
#
# This file is part of the 86Box distribution.
#
# Prefix for localizing the general Makefile.mingw for local
# settings, so we can avoid changing the main one for all of
# our local setups.
#
# Authors: Fred N. van Kempen, <decwiz@yahoo.com>
#
#########################################################################
# Anything here will override defaults in Makefile.MinGW. #
#########################################################################
# Name of the executable.
#PROG := 86box.exe
# Various compile-time options.
# -DROM_TRACE=0xc800 traces ROM access from segment C800
# -DIO_TRACE=0x66 traces I/O on port 0x66
# -DIO_CATCH enables I/O range catch logs
STUFF :=
# Add feature selections here.
# -DANSI_CFG forces the config file to ANSI encoding.
# Root logging:
# -DENABLE_ACPI_LOG=N sets logging level at N.
# -DENABLE_APM_LOG=N sets logging level at N.
# -DENABLE_BUGGER_LOG=N sets logging level at N.
# -DENABLE_CONFIG_LOG=N sets logging level at N.
# -DENABLE_DDMA_LOG=N sets logging level at N.
# -DENABLE_DEVICE_LOG=N sets logging level at N.
# -DENABLE_DMA_LOG=N sets logging level at N.
# -DENABLE_IO_LOG=N sets logging level at N.
# -DENABLE_IOAPIC_LOG=N sets logging level at N.
# -DENABLE_ISAMEM_LOG=N sets logging level at N.
# -DENABLE_ISARTC_LOG=N sets logging level at N.
# -DENABLE_KEYBOARD_AT_LOG=N sets logging level at N.
# -DENABLE_KEYBOARD_XT_LOG=N sets logging level at N.
# -DENABLE_LM75_LOG=N sets logging level at N.
# -DENABLE_LM78_LOG=N sets logging level at N.
# -DENABLE_MEM_LOG=N sets logging level at N.
# -DENABLE_MOUSE_LOG=N sets logging level at N.
# -DENABLE_MOUSE_BUS_LOG=N sets logging level at N.
# -DENABLE_MOUSE_PS2_LOG=N sets logging level at N.
# -DENABLE_MOUSE_SERIAL_LOG=N sets logging level at N.
# -DENABLE_NVR_LOG=N sets logging level at N.
# -DENABLE_PC_LOG=N sets logging level at N.
# -DENABLE_PCI_LOG=N sets logging level at N.
# -DENABLE_PIC_LOG=N sets logging level at N.
# -DENABLE_PIT_LOG=N sets logging level at N.
# -DENABLE_POSTCARD_LOG=N sets logging level at N.
# -DENABLE_ROM_LOG=N sets logging level at N.
# -DENABLE_SERIAL_LOG=N sets logging level at N.
# -DENABLE_SMBUS_LOG=N sets logging level at N.
# -DENABLE_SMBUS_PIIX4_LOG=N sets logging level at N.
# -DENABLE_SPD_LOG=N sets logging level at N.
# -DENABLE_USB_LOG=N sets logging level at N.
# -DENABLE_VNC_LOG=N sets logging level at N.
# -DENABLE_VNC_KEYMAP_LOG=N sets logging level at N.
# cdrom/ logging:
# -DENABLE_CDROM_LOG=N sets logging level at N.
# -DENABLE_CDROM_IMAGE_LOG=N sets logging level at N.
# -DENABLE_CDROM_IMAGE_BACKEND_LOG=N sets logging level at N.
# chipset/ logging:
# -DENABLE_I420EX_LOG=N sets logging level at N.
# -DENABLE_NEAT_LOG=N sets logging level at N.
# -DENABLE_OPTI495_LOG=N sets logging level at N.
# -DENABLE_OPTI895_LOG=N sets logging level at N.
# -DENABLE_PIIX_LOG=N sets logging level at N.
# -DENABLE_SIO_LOG=N sets logging level at N.
# -DENABLE_SIS_85C496_LOG=N sets logging level at N.
# codegen/, codegen_new/, cpu/ logging:
# -DENABLE_X86SEG_LOG=N sets logging level at N.
# cpu/ logging:
# -DENABLE_386_LOG=N sets logging level at N.
# -DENABLE_386_COMMON_LOG=N sets logging level at N.
# -DENABLE_386_DYNAREC_LOG=N sets logging level at N.
# -DENABLE_808X_LOG=N sets logging level at N.
# -DENABLE_CPU_LOG=N sets logging level at N.
# -DENABLE_FPU_LOG=N sets logging level at N.
# disk/ logging:
# -DENABLE_ESDI_AT_LOG=N sets logging level at N.
# -DENABLE_ESDI_MCA_LOG=N sets logging level at N.
# -DENABLE_HDC_LOG=N sets logging level at N.
# -DENABLE_HDD_IMAGE_LOG=N sets logging level at N.
# -DENABLE_IDE_LOG=N sets logging level at N.
# -DENABLE_MO_LOG=N sets logging level at N.
# -DENABLE_SFF_LOG=N sets logging level at N.
# -DENABLE_ST506_AT_LOG=N sets logging level at N.
# -DENABLE_ST506_XT_LOG=N sets logging level at N.
# -DENABLE_XTA_LOG=N sets logging level at N.
# -DENABLE_ZIP_LOG=N sets logging level at N.
# floppy/ logging:
# -DENABLE_D86F_LOG=N sets logging level at N.
# -DENABLE_FDC_LOG=N sets logging level at N.
# -DENABLE_FDD_LOG=N sets logging level at N.
# -DENABLE_FDI_LOG=N sets logging level at N.
# -DENABLE_FDI2RAW_LOG=N sets logging level at N.
# -DENABLE_IMD_LOG=N sets logging level at N.
# -DENABLE_IMG_LOG=N sets logging level at N.
# -DENABLE_JSON_LOG=N sets logging level at N.
# -DENABLE_MFM_LOG=N sets logging level at N.
# -DENABLE_TD0_LOG=N sets logging level at N.
# machine/ logging:
# -DENABLE_AMSTRAD_LOG=N sets logging level at N.
# -DENABLE_EUROPC_LOG=N sets logging level at N.
# -DENABLE_M24VID_LOG=N sets logging level at N.
# -DENABLE_MACHINE_LOG=N sets logging level at N.
# -DENABLE_PS1_HDC_LOG=N sets logging level at N.
# -DENABLE_PS2_MCA_LOG=N sets logging level at N.
# -DENABLE_TANDY_LOG=N sets logging level at N.
# -DENABLE_T1000_LOG=N sets logging level at N.
# -DENABLE_T3100E_LOG=N sets logging level at N.
# network/ logging:
# -DENABLE_3COM503_LOG=N sets logging level at N.
# -DENABLE_DP8390_LOG=N sets logging level at N.
# -DENABLE_NETWORK_LOG=N sets logging level at N.
# -DENABLE_NE2K_LOG=N sets logging level at N.
# -DENABLE_PCAP_LOG=N sets logging level at N.
# -DENABLE_PCNET_LOG=N sets logging level at N.
# -DENABLE_SLIRP_LOG=N sets logging level at N.
# -DENABLE_WD_LOG=N sets logging level at N.
# printer/ logging:
# -DENABLE_ESCP_LOG=N sets logging level at N.
# scsi/ logging:
# -DENABLE_AHA154X_LOG=N sets logging level at N.
# -DENABLE_BUSLOGIC_LOG=N sets logging level at N.
# -DENABLE_NCR5380_LOG=N sets logging level at N.
# -DENABLE_NCR53C8XX_LOG=N sets logging level at N.
# -DENABLE_SCSI_CDROM_LOG=N sets logging level at N.
# -DENABLE_SCSI_DISK_LOG=N sets logging level at N.
# -DENABLE_SPOCK_LOG=N sets logging level at N.
# -DENABLE_X54X_LOG=N sets logging level at N.
# sound/ logging:
# -DENABLE_ADLIB_LOG=N sets logging level at N.
# -DENABLE_AUDIOPCI_LOG=N sets logging level at N.
# -DENABLE_EMU8K_LOG=N sets logging level at N.
# -DENABLE_MPU401_LOG=N sets logging level at N.
# -DENABLE_PAS16_LOG=N sets logging level at N.
# -DENABLE_SB_LOG=N sets logging level at N.
# -DENABLE_SB_DSP_LOG=N sets logging level at N.
# -DENABLE_SOUND_LOG=N sets logging level at N.
# video/ logging:
# -DENABLE_ATI28800_LOG=N sets logging level at N.
# -DENABLE_MACH64_LOG=N sets logging level at N.
# -DENABLE_COMPAQ_CGA_LOG=N sets logging level at N.
# -DENABLE_ET4000W32_LOG=N sets logging level at N.
# -DENABLE_HT216_LOG=N sets logging level at N.
# -DENABLE_ICD2061_LOG=N sets logging level at N.
# -DENABLE_IM1024_LOG=N sets logging level at N.
# -DENABLE_PGC_LOG=N sets logging level at N.
# -DENABLE_S3_VIRGE_LOG=N sets logging level at N.
# -DENABLE_VID_TABLE_LOG=N sets logging level at N.
# -DENABLE_VIDEO_LOG=N sets logging level at N.
# -DENABLE_VOODOO_LOG=N sets logging level at N.
# win/ logging:
# -DENABLE_WIN_LOG=N sets logging level at N.
# -DENABLE_DISCORD_LOG=N sets logging level at N.
# -DENABLE_DYNLD_LOG=N sets logging level at N.
# -DENABLE_JOYSTICK_LOG=N sets logging level at N.
# -DENABLE_SDL_LOG=N sets logging level at N.
# -DENABLE_SETTINGS_LOG=N sets logging level at N.
EXTRAS :=
AUTODEP := n
DEBUG := n
OPTIM := n
X64 := n
RELEASE := n
USB := n
VNC := n
RDP := n
DEV_BUILD := n
DEV_BRANCH := n
CIRRUS := n
NE1000 := n
NV_RIVA := n
OPENAL := y
FLUIDSYNTH := y
MUNT := y
PAS16 := n
DYNAREC := y
#########################################################################
# Include the master Makefile.MinGW for the rest. #
#########################################################################
include win/Makefile.mingw
# End of Makefile.local.

File diff suppressed because it is too large Load Diff

View File

@@ -122,7 +122,7 @@ const device_t apm_device = {
.init = apm_init,
.close = apm_close,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
@@ -136,7 +136,7 @@ const device_t apm_pci_device = {
.init = apm_init,
.close = apm_close,
.reset = apm_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
@@ -150,7 +150,7 @@ const device_t apm_pci_acpi_device = {
.init = apm_init,
.close = apm_close,
.reset = apm_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL

View File

@@ -9,8 +9,36 @@
# CMake build script.
#
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
# Jasmine Iwanek, <jriwanek@gmail.com>
#
# Copyright 2020-2021 David Hrdlička.
# Copyright 2024 Jasmine Iwanek.
#
add_library(cdrom OBJECT cdrom.c cdrom_image_backend.c cdrom_image_viso.c cdrom_image.c cdrom_mitsumi.c)
find_package(PkgConfig REQUIRED)
pkg_check_modules(SNDFILE REQUIRED IMPORTED_TARGET sndfile)
add_library(cdrom OBJECT
cdrom.c
cdrom_image.c
cdrom_image_viso.c
cdrom_mke.c
)
if(NOT WIN32)
target_include_directories(86Box PRIVATE PkgConfig::SNDFILE)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
target_include_directories(cdrom PRIVATE /usr/local/include)
endif()
target_link_libraries(86Box PkgConfig::SNDFILE)
if(CDROM_MITSUMI)
target_compile_definitions(cdrom PRIVATE USE_CDROM_MITSUMI)
target_sources(cdrom PRIVATE cdrom_mitsumi.c)
endif()
if (WIN32)
# MSYS2
target_link_libraries(86Box -static ${SNDFILE_STATIC_LIBRARIES})
endif()

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -8,9 +8,7 @@
*
* Virtual ISO CD-ROM image back-end.
*
*
*
* Authors: RichardG <richardg867@gmail.com>
* Authors: RichardG, <richardg867@gmail.com>
*
* Copyright 2022 RichardG.
*/
@@ -23,7 +21,9 @@
#define __STDC_FORMAT_MACROS
#include <ctype.h>
#include <inttypes.h>
#ifdef IMAGE_VISO_LOG
#include <stdarg.h>
#endif
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -31,43 +31,51 @@
#include <sys/stat.h>
#include <time.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/bswap.h>
#include <86box/cdrom_image_backend.h>
#include <86box/cdrom.h>
#include <86box/cdrom_image.h>
#include <86box/cdrom_image_viso.h>
#include <86box/log.h>
#include <86box/path.h>
#include <86box/plat.h>
#include <86box/bswap.h>
#include <86box/plat_dir.h>
#include <86box/version.h>
#include <86box/timer.h>
#include <86box/nvr.h>
#ifndef S_ISDIR
# define S_ISDIR(m) (((m) &S_IFMT) == S_IFDIR)
#endif
#define VISO_SKIP(p, n) \
{ \
memset(p, 0x00, n); \
p += n; \
#ifdef _WIN32
# define stat _stat64
typedef struct __stat64 stat_t;
#else
typedef struct stat stat_t;
#endif
#define VISO_SKIP(p, n) \
{ \
memset((p), 0x00, (n)); \
(p) += (n); \
}
#define VISO_TIME_VALID(t) ((t) > 0)
/* ISO 9660 defines "both endian" data formats, which
are stored as little endian followed by big endian. */
#define VISO_LBE_16(p, x) \
{ \
*((uint16_t *) p) = cpu_to_le16(x); \
p += 2; \
*((uint16_t *) p) = cpu_to_be16(x); \
p += 2; \
#define VISO_LBE_16(p, x) \
{ \
*((uint16_t *) (p)) = cpu_to_le16((x)); \
(p) += 2; \
*((uint16_t *) (p)) = cpu_to_be16((x)); \
(p) += 2; \
}
#define VISO_LBE_32(p, x) \
{ \
*((uint32_t *) p) = cpu_to_le32(x); \
p += 4; \
*((uint32_t *) p) = cpu_to_be32(x); \
p += 4; \
#define VISO_LBE_32(p, x) \
{ \
*((uint32_t *) (p)) = cpu_to_le32((x)); \
(p) += 4; \
*((uint32_t *) (p)) = cpu_to_be32((x)); \
(p) += 4; \
}
#define VISO_SECTOR_SIZE COOKED_SECTOR_SIZE
@@ -106,7 +114,7 @@ typedef struct _viso_entry_ {
};
uint16_t pt_idx;
struct stat stats;
stat_t stats;
struct _viso_entry_ *parent, *next, *next_dir, *first_child;
@@ -131,29 +139,30 @@ static const char rr_eid[] = "RRIP_1991A"; /* identifiers used in ER field for
static const char rr_edesc[] = "THE ROCK RIDGE INTERCHANGE PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICS.";
static int8_t tz_offset = 0;
#ifdef ENABLE_CDROM_IMAGE_VISO_LOG
int cdrom_image_viso_do_log = ENABLE_CDROM_IMAGE_VISO_LOG;
#ifdef IMAGE_VISO_LOG
int image_viso_do_log = IMAGE_VISO_LOG;
void
cdrom_image_viso_log(const char *fmt, ...)
image_viso_log(void *priv, const char *fmt, ...)
{
va_list ap;
if (cdrom_image_viso_do_log) {
if (image_viso_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
log_out(priv, fmt, ap);
va_end(ap);
}
}
#else
# define cdrom_image_viso_log(fmt, ...)
# define image_viso_log(priv, fmt, ...)
#endif
static size_t
viso_pread(void *ptr, uint64_t offset, size_t size, size_t count, FILE *fp)
viso_pread(void *ptr, const uint64_t offset, const size_t size,
const size_t count, FILE *fp)
{
uint64_t cur_pos = ftello64(fp);
size_t ret = 0;
const uint64_t cur_pos = ftello64(fp);
size_t ret = 0;
if (fseeko64(fp, offset, SEEK_SET) != -1)
ret = fread(ptr, size, count, fp);
fseeko64(fp, cur_pos, SEEK_SET);
@@ -161,10 +170,11 @@ viso_pread(void *ptr, uint64_t offset, size_t size, size_t count, FILE *fp)
}
static size_t
viso_pwrite(const void *ptr, uint64_t offset, size_t size, size_t count, FILE *fp)
viso_pwrite(const void *ptr, const uint64_t offset, const size_t size,
const size_t count, FILE *fp)
{
uint64_t cur_pos = ftello64(fp);
size_t ret = 0;
const uint64_t cur_pos = ftello64(fp);
size_t ret = 0;
if (fseeko64(fp, offset, SEEK_SET) != -1)
ret = fwrite(ptr, size, count, fp);
fseeko64(fp, cur_pos, SEEK_SET);
@@ -436,24 +446,36 @@ static int
viso_fill_time(uint8_t *data, time_t time, int format, int longform)
{
uint8_t *p = data;
struct tm *time_s = localtime(&time);
if (!time_s) {
/* localtime will return NULL if the time_t is negative (Windows)
or way too far into 64-bit space (Linux). Fall back to epoch. */
time_t epoch = 0;
time_s = localtime(&epoch);
if (UNLIKELY(!time_s))
fatal("VISO: localtime(0) = NULL\n");
struct tm time_s_buf;
struct tm *time_s = NULL;
time_t epoch = 0;
/* Force year clamping if the timestamp is known to be outside the supported ranges. */
#ifdef _WIN32
if (localtime_s(&time_s_buf, &time) == 0)
time_s = &time_s_buf;
#else
time_s = localtime_r(&time, &time_s_buf);
#endif
if (!time_s) {
/* localtime may return NULL if time is negative or out of range */
#ifdef _WIN32
if (localtime_s(&time_s_buf, &epoch) == 0)
time_s = &time_s_buf;
#else
time_s = localtime_r(&epoch, &time_s_buf);
#endif
if (!time_s)
fatal("VISO: localtime fallback to epoch failed\n");
/* Force year clamping for out-of-range times */
if (time < (longform ? -62135596800LL : -2208988800LL)) /* 0001-01-01 00:00:00 : 1900-01-01 00:00:00 */
time_s->tm_year = -1901;
else if (time > (longform ? 253402300799LL : 5869583999LL)) /* 9999-12-31 23:59:59 : 2155-12-31 23:59:59 */
time_s->tm_year = 8100;
}
/* Clamp year to the supported ranges, and assume the
OS returns valid numbers in the other struct fields. */
/* Clamp year within supported ranges */
if (time_s->tm_year < (longform ? -1900 : 0)) {
time_s->tm_year = longform ? -1900 : 0;
time_s->tm_mon = time_s->tm_hour = time_s->tm_min = time_s->tm_sec = 0;
@@ -466,18 +488,18 @@ viso_fill_time(uint8_t *data, time_t time, int format, int longform)
time_s->tm_min = time_s->tm_sec = 59;
}
/* Convert timestamp. */
/* Convert timestamp */
if (longform) {
p += sprintf((char *) p, "%04u%02u%02u%02u%02u%02u00",
1900 + time_s->tm_year, 1 + time_s->tm_mon, time_s->tm_mday,
p += sprintf((char *)p, "%04u%02u%02u%02u%02u%02u00",
1900 + (unsigned)time_s->tm_year, 1 + time_s->tm_mon, time_s->tm_mday,
time_s->tm_hour, time_s->tm_min, time_s->tm_sec);
} else {
*p++ = time_s->tm_year; /* year since 1900 */
*p++ = 1 + time_s->tm_mon; /* month */
*p++ = time_s->tm_mday; /* day */
*p++ = time_s->tm_hour; /* hour */
*p++ = time_s->tm_min; /* minute */
*p++ = time_s->tm_sec; /* second */
*p++ = (uint8_t)time_s->tm_year; /* year since 1900 */
*p++ = (uint8_t)(1 + time_s->tm_mon); /* month */
*p++ = (uint8_t)time_s->tm_mday; /* day */
*p++ = (uint8_t)time_s->tm_hour; /* hour */
*p++ = (uint8_t)time_s->tm_min; /* minute */
*p++ = (uint8_t)time_s->tm_sec; /* second */
}
if (format & VISO_FORMAT_ISO)
*p++ = tz_offset; /* timezone (ISO only) */
@@ -496,10 +518,6 @@ viso_fill_dir_record(uint8_t *data, viso_entry_t *entry, viso_t *viso, int type)
*p++ = 0; /* extended attribute length */
VISO_SKIP(p, 8); /* sector offset */
VISO_LBE_32(p, entry->stats.st_size); /* size (filled in later if this is a directory) */
#ifdef _WIN32
if (entry->stats.st_mtime < 0)
pclog("VISO: Warning: Windows returned st_mtime %lld on file [%s]\n", (long long) entry->stats.st_mtime, entry->path);
#endif
p += viso_fill_time(p, entry->stats.st_mtime, viso->format, 0); /* time */
*p++ = S_ISDIR(entry->stats.st_mode) ? 0x02 : 0x00; /* flags */
@@ -671,9 +689,9 @@ viso_read(void *priv, uint8_t *buffer, uint64_t seek, size_t count)
/* Handle reads in a sector by sector basis. */
while (count > 0) {
/* Determine the current sector, offset and remainder. */
uint32_t sector = seek / viso->sector_size;
uint32_t sector_offset = seek % viso->sector_size;
uint32_t sector_remain = MIN(count, viso->sector_size - sector_offset);
size_t sector = seek / viso->sector_size;
size_t sector_offset = seek % viso->sector_size;
size_t sector_remain = MIN(count, viso->sector_size - sector_offset);
/* Handle sector. */
if (sector < viso->metadata_sectors) {
@@ -690,22 +708,22 @@ viso_read(void *priv, uint8_t *buffer, uint64_t seek, size_t count)
/* Close any existing FIFO entry's file. */
viso_entry_t *other_entry = viso->file_fifo[viso->file_fifo_pos];
if (other_entry && other_entry->file) {
cdrom_image_viso_log("VISO: Closing [%s]", other_entry->path);
image_viso_log(viso->tf.log, "Closing [%s]...\n", other_entry->path);
fclose(other_entry->file);
other_entry->file = NULL;
cdrom_image_viso_log("\n");
image_viso_log(viso->tf.log, "Done\n");
}
/* Open file. */
cdrom_image_viso_log("VISO: Opening [%s]", entry->path);
image_viso_log(viso->tf.log, "Opening [%s]...\n", entry->path);
if ((entry->file = fopen(entry->path, "rb"))) {
cdrom_image_viso_log("\n");
image_viso_log(viso->tf.log, "Done\n");
/* Add this entry to the FIFO. */
viso->file_fifo[viso->file_fifo_pos++] = entry;
viso->file_fifo_pos &= (sizeof(viso->file_fifo) / sizeof(viso->file_fifo[0])) - 1;
} else {
cdrom_image_viso_log(" => failed\n");
image_viso_log(viso->tf.log, "Failed\n");
/* Clear any existing FIFO entry. */
viso->file_fifo[viso->file_fifo_pos] = NULL;
@@ -713,8 +731,11 @@ viso_read(void *priv, uint8_t *buffer, uint64_t seek, size_t count)
}
/* Read data. */
if (entry->file && (fseeko64(entry->file, seek - entry->data_offset, SEEK_SET) != -1))
read = fread(buffer, 1, sector_remain, entry->file);
if (!entry->file || (fseeko64(entry->file, seek - entry->data_offset, SEEK_SET) == -1))
return -1;
read = fread(buffer, 1, sector_remain, entry->file);
if (sector_remain && !read)
return -1;
}
/* Fill remainder with 00 bytes if needed. */
@@ -749,12 +770,12 @@ viso_close(void *priv)
if (viso == NULL)
return;
cdrom_image_viso_log("VISO: close()\n");
image_viso_log(viso->tf.log, "close()\n");
/* De-allocate everything. */
if (tf->fp)
fclose(tf->fp);
#ifndef ENABLE_CDROM_IMAGE_VISO_LOG
#ifndef ENABLE_IMAGE_VISO_LOG
remove(nvr_path(viso->tf.fn));
#endif
@@ -773,21 +794,31 @@ viso_close(void *priv)
if (viso->entry_map)
free(viso->entry_map);
if (tf->log != NULL)
log_close(tf->log);
free(viso);
}
track_file_t *
viso_init(const char *dirname, int *error)
viso_init(const uint8_t id, const char *dirname, int *error)
{
cdrom_image_viso_log("VISO: init()\n");
/* Initialize our data structure. */
viso_t *viso = (viso_t *) calloc(1, sizeof(viso_t));
uint8_t *data = NULL;
uint8_t *p;
*error = 1;
if (viso == NULL)
goto end;
char n[1024] = { 0 };
sprintf(n, "CD-ROM %i VISO ", id + 1);
viso->tf.log = log_open(n);
image_viso_log(viso->tf.log, "init()\n");
viso->sector_size = VISO_SECTOR_SIZE;
viso->format = VISO_FORMAT_ISO | VISO_FORMAT_JOLIET | VISO_FORMAT_RR;
viso->use_version_suffix = (viso->format & VISO_FORMAT_ISO); /* cleared later if required */
@@ -798,7 +829,7 @@ viso_init(const char *dirname, int *error)
goto end;
/* Open temporary file. */
#ifdef ENABLE_CDROM_IMAGE_VISO_LOG
#ifdef ENABLE_IMAGE_VISO_LOG
strcpy(viso->tf.fn, "viso-debug.iso");
#else
plat_tempfile(viso->tf.fn, "viso", ".tmp");
@@ -808,7 +839,7 @@ viso_init(const char *dirname, int *error)
goto end;
/* Set up directory traversal. */
cdrom_image_viso_log("VISO: Traversing directories:\n");
image_viso_log(viso->tf.log, "Traversing directories:\n");
viso_entry_t *entry;
viso_entry_t *last_entry;
viso_entry_t *dir;
@@ -830,12 +861,12 @@ viso_init(const char *dirname, int *error)
strcpy(dir->path, dirname);
if (stat(dirname, &dir->stats) != 0) {
/* Use a blank structure if stat failed. */
memset(&dir->stats, 0x00, sizeof(struct stat));
memset(&dir->stats, 0x00, sizeof(stat_t));
}
if (!S_ISDIR(dir->stats.st_mode)) /* root is not a directory */
goto end;
dir->parent = dir; /* for the root's path table and .. entries */
cdrom_image_viso_log("[%08X] %s => [root]\n", dir, dir->path);
image_viso_log(viso->tf.log, "[%08X] %s => [root]\n", dir, dir->path);
/* Traverse directories, starting with the root. */
viso_entry_t **dir_entries = NULL;
@@ -879,13 +910,14 @@ viso_init(const char *dirname, int *error)
/* Stat the current directory or parent directory. */
if (stat(children_count ? dir->parent->path : dir->path, &entry->stats) != 0) {
/* Use a blank structure if stat failed. */
memset(&entry->stats, 0x00, sizeof(struct stat));
memset(&entry->stats, 0x00, sizeof(stat_t));
}
/* Set basename. */
strcpy(entry->name_short, children_count ? ".." : ".");
cdrom_image_viso_log("[%08X] %s => %s\n", entry, dir->path, entry->name_short);
image_viso_log(viso->tf.log, "[%08X] %s => %s\n", entry,
dir->path, entry->name_short);
}
/* Iterate through this directory's children again, making the entries. */
@@ -893,12 +925,16 @@ viso_init(const char *dirname, int *error)
rewinddir(dirp);
while ((readdir_entry = readdir(dirp))) {
/* Ignore . and .. pseudo-directories. */
if ((readdir_entry->d_name[0] == '.') && ((readdir_entry->d_name[1] == '\0') || (*((uint16_t *) &readdir_entry->d_name[1]) == '.')))
if ((readdir_entry->d_name[0] == '.') &&
((readdir_entry->d_name[1] == '\0') ||
(*((uint16_t *) &readdir_entry->d_name[1]) == '.')))
continue;
/* Add and fill entry. */
entry = dir_entries[children_count++] = (viso_entry_t *) calloc(1, sizeof(viso_entry_t) + dir_path_len + strlen(readdir_entry->d_name) + 2);
if (!entry)
entry = dir_entries[children_count++] =
(viso_entry_t *) calloc(1, sizeof(viso_entry_t) +
dir_path_len + strlen(readdir_entry->d_name) + 2);
if (entry == NULL)
break;
entry->parent = dir;
strcpy(entry->path, dir->path);
@@ -909,7 +945,7 @@ viso_init(const char *dirname, int *error)
/* Stat this child. */
if (stat(entry->path, &entry->stats) != 0) {
/* Use a blank structure if stat failed. */
memset(&entry->stats, 0x00, sizeof(struct stat));
memset(&entry->stats, 0x00, sizeof(stat_t));
}
/* Handle file size and El Torito boot code. */
@@ -968,10 +1004,12 @@ have_eltorito_entry:
continue;
}
cdrom_image_viso_log("[%08X] %s => [%-12s] %s\n", entry, dir->path, entry->name_short, entry->basename);
image_viso_log(viso->tf.log, "[%08X] %s => [%-12s] %s\n", entry,
dir->path, entry->name_short, entry->basename);
}
} else {
cdrom_image_viso_log("VISO: Failed to enumerate [%s], will be empty\n", dir->path);
image_viso_log(viso->tf.log, "Failed to enumerate [%s], will be empty\n",
dir->path);
}
/* Add terminator. */
@@ -1008,8 +1046,15 @@ next_dir:
the timezone offset for descriptors and file times to use. */
tzset();
time_t now = time(NULL);
if (viso->format & VISO_FORMAT_ISO) /* timezones are ISO only */
tz_offset = (now - mktime(gmtime(&now))) / (3600 / 4);
struct tm now_tm;
if (viso->format & VISO_FORMAT_ISO) { /* timezones are ISO only */
#ifdef _WIN32
gmtime_s(&now_tm, &now); // Windows: output first param, input second
#else
gmtime_r(&now, &now_tm); // POSIX: input first param, output second
#endif
tz_offset = (now - mktime(&now_tm)) / (3600 / 4);
}
/* Get root directory basename for the volume ID. */
const char *basename = path_get_filename(viso->root_dir->path);
@@ -1125,13 +1170,17 @@ next_dir:
/* Write El Torito boot descriptor. This is an awkward spot for
that, but the spec requires it to be the second descriptor. */
if (!i && eltorito_entry) {
cdrom_image_viso_log("VISO: Writing El Torito boot descriptor for entry [%08X]\n", eltorito_entry);
image_viso_log(viso->tf.log, "Writing El Torito boot descriptor for "
"entry [%08X]\n", eltorito_entry);
p = data;
if (!(viso->format & VISO_FORMAT_ISO))
VISO_LBE_32(p, ftello64(viso->tf.fp) / viso->sector_size); /* sector offset (HSF only) */
*p++ = 0; /* type */
memcpy(p, (viso->format & VISO_FORMAT_ISO) ? "CD001" : "CDROM", 5); /* standard ID */
/* Sector offset (HSF only). */
VISO_LBE_32(p, ftello64(viso->tf.fp) / viso->sector_size);
/* Type. */
*p++ = 0;
/* Standard ID. */
memcpy(p, (viso->format & VISO_FORMAT_ISO) ? "CD001" : "CDROM", 5);
p += 5;
*p++ = 1; /* version */
@@ -1232,7 +1281,7 @@ next_dir:
/* Write each path table. */
for (int i = 0; i <= ((max_vd << 1) | 1); i++) {
cdrom_image_viso_log("VISO: Generating path table #%d:\n", i);
image_viso_log(viso->tf.log, "Generating path table #%d:\n", i);
/* Save this path table's start offset. */
uint64_t pt_start = ftello64(viso->tf.fp);
@@ -1253,7 +1302,9 @@ next_dir:
continue;
}
cdrom_image_viso_log("[%08X] %s => %s\n", dir, dir->path, ((i & 2) || (dir == viso->root_dir)) ? dir->basename : dir->name_short);
image_viso_log(viso->tf.log, "[%08X] %s => %s\n", dir,
dir->path, ((i & 2) || (dir == viso->root_dir)) ? dir->basename :
dir->name_short);
/* Save this directory's path table index and offset. */
dir->pt_idx = pt_idx;
@@ -1321,7 +1372,7 @@ next_dir:
/* Write directory records for each type. */
int dir_type = VISO_DIR_CURRENT_ROOT;
for (int i = 0; i <= max_vd; i++) {
cdrom_image_viso_log("VISO: Generating directory record set #%d:\n", i);
image_viso_log(viso->tf.log, "Generating directory record set #%d:\n", i);
/* Go through directories. */
dir = viso->root_dir;
@@ -1364,8 +1415,10 @@ next_dir:
if ((entry == eltorito_entry) || (entry == eltorito_dir))
goto next_entry;
cdrom_image_viso_log("[%08X] %s => %s\n", entry, dir->path,
((dir_type == VISO_DIR_PARENT) ? ".." : ((dir_type < VISO_DIR_PARENT) ? "." : (i ? entry->basename : entry->name_short))));
image_viso_log(viso->tf.log, "[%08X] %s => %s\n", entry, dir->path,
((dir_type == VISO_DIR_PARENT) ? ".." :
((dir_type < VISO_DIR_PARENT) ? "." :
(i ? entry->basename : entry->name_short))));
/* Fill directory record. */
viso_fill_dir_record(data, entry, viso, dir_type);
@@ -1432,7 +1485,8 @@ next_entry:
/* Allocate entry map for sector->file lookups. */
size_t orig_sector_size = viso->sector_size;
while (1) {
cdrom_image_viso_log("VISO: Allocating entry map for %d %d-byte sectors\n", viso->entry_map_size, viso->sector_size);
image_viso_log(viso->tf.log, "Allocating entry map for %zu %zu-byte sectors\n",
viso->entry_map_size, viso->sector_size);
viso->entry_map = (viso_entry_t **) calloc(viso->entry_map_size, sizeof(viso_entry_t *));
if (viso->entry_map) {
/* Successfully allocated. */
@@ -1444,7 +1498,7 @@ next_entry:
/* If we don't have enough memory, double the sector size. */
viso->sector_size *= 2;
if (viso->sector_size == 0) /* give up if sectors become too large */
if ((viso->sector_size < VISO_SECTOR_SIZE) || (viso->sector_size > (1 << 30))) /* give up if sectors become too large */
goto end;
/* Go through files, recalculating the entry map size. */
@@ -1473,7 +1527,7 @@ next_entry:
viso->all_sectors = viso->metadata_sectors;
/* Go through files, assigning sectors to them. */
cdrom_image_viso_log("VISO: Assigning sectors to files:\n");
image_viso_log(viso->tf.log, "Assigning sectors to files:\n");
size_t base_factor = viso->sector_size / orig_sector_size;
viso_entry_t *prev_entry = viso->root_dir;
viso_entry_t **entry_map_p = viso->entry_map;
@@ -1515,10 +1569,11 @@ next_entry:
entry->data_offset = ((uint64_t) viso->all_sectors) * viso->sector_size;
/* Determine how many sectors this file will take. */
uint32_t size = entry->stats.st_size / viso->sector_size;
size_t size = entry->stats.st_size / viso->sector_size;
if (entry->stats.st_size % viso->sector_size)
size++; /* round up to the next sector */
cdrom_image_viso_log("[%08X] %s => %" PRIu32 " + %" PRIu32 " sectors\n", entry, entry->path, viso->all_sectors, size);
image_viso_log(viso->tf.log, "[%08X] %s => %zu + %zu sectors\n", entry,
entry->path, viso->all_sectors, size);
/* Allocate sectors to this file. */
viso->all_sectors += size;
@@ -1537,20 +1592,21 @@ next_entry:
viso_pwrite(data, viso->vol_size_offsets[i], 8, 1, viso->tf.fp);
/* Metadata processing is finished, read it back to memory. */
cdrom_image_viso_log("VISO: Reading back %d %d-byte sectors of metadata\n", viso->metadata_sectors, viso->sector_size);
image_viso_log(viso->tf.log, "Reading back %zu %zu-byte sectors of metadata\n",
viso->metadata_sectors, viso->sector_size);
viso->metadata = (uint8_t *) calloc(viso->metadata_sectors, viso->sector_size);
if (!viso->metadata)
if (viso->metadata == NULL)
goto end;
fseeko64(viso->tf.fp, 0, SEEK_SET);
uint64_t metadata_size = viso->metadata_sectors * viso->sector_size;
uint64_t metadata_remain = metadata_size;
size_t metadata_size = viso->metadata_sectors * viso->sector_size;
size_t metadata_remain = metadata_size;
while (metadata_remain > 0)
metadata_remain -= fread(viso->metadata + (metadata_size - metadata_remain), 1, MIN(metadata_remain, viso->sector_size), viso->tf.fp);
/* We no longer need the temporary file; close and delete it. */
fclose(viso->tf.fp);
viso->tf.fp = NULL;
#ifndef ENABLE_CDROM_IMAGE_VISO_LOG
#ifndef ENABLE_IMAGE_VISO_LOG
remove(nvr_path(viso->tf.fn));
#endif
@@ -1561,16 +1617,20 @@ end:
/* Set the function pointers. */
viso->tf.priv = viso;
if (!*error) {
cdrom_image_viso_log("VISO: Initialized\n");
image_viso_log(viso->tf.log, "Initialized\n");
viso->tf.read = viso_read;
viso->tf.get_length = viso_get_length;
viso->tf.close = viso_close;
return &viso->tf;
} else {
cdrom_image_viso_log("VISO: 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;
}
}

View File

@@ -8,11 +8,11 @@
*
* Mitsumi CD-ROM emulation for the ISA bus.
*
*
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Jasmine Iwanek, <jriwanek@gmail.com>
*
* Copyright 2022 Miran Grca.
* Copyright 2022 Miran Grca.
* Copyright 2024-2025 Jasmine Iwanek.
*/
#include <inttypes.h>
#include <stdarg.h>
@@ -33,10 +33,6 @@
#include <86box/plat.h>
#include <86box/sound.h>
#define MCD_DEFAULT_IOPORT 0x310
#define MCD_DEFAULT_IRQ 5
#define MCD_DEFAULT_DMA 5
#define RAW_SECTOR_SIZE 2352
#define COOKED_SECTOR_SIZE 2048
@@ -116,15 +112,9 @@ typedef struct mcd_t {
int cur_toc_track;
int pos;
int newstat;
} mcd_t;
/* The addresses sent from the guest are absolute, ie. a LBA of 0 corresponds to a MSF of 00:00:00. Otherwise, the counter displayed by the guest is wrong:
there is a seeming 2 seconds in which audio plays but counter does not move, while a data track before audio jumps to 2 seconds before the actual start
of the audio while audio still plays. With an absolute conversion, the counter is fine. */
#ifdef MSFtoLBA
#undef MSFtoLBA
#endif
#define MSFtoLBA(m, s, f) ((((m * 60) + s) * 75) + f)
cdrom_t *cdrom_dev;
} mcd_t;
#define CD_BCD(x) (((x) % 10) | (((x) / 10) << 4))
#define CD_DCB(x) ((((x) &0xf0) >> 4) * 10 + ((x) &0x0f))
@@ -147,14 +137,16 @@ mitsumi_cdrom_log(const char *fmt, ...)
# define mitsumi_cdrom_log(fmt, ...)
#endif
static int
mitsumi_cdrom_is_ready(const mcd_t *dev)
{
return (dev->cdrom_dev->image_path[0] != 0x00);
}
static void
mitsumi_cdrom_reset(mcd_t *dev)
{
cdrom_t cdrom;
cdrom.host_drive = 0;
dev->stat = cdrom.host_drive ? (STAT_READY | STAT_CHANGE) : 0;
dev->stat = mitsumi_cdrom_is_ready(dev) ? (STAT_READY | STAT_CHANGE) : 0;
dev->cmdrd_count = 0;
dev->cmdbuf_count = 0;
dev->buf_count = 0;
@@ -172,12 +164,11 @@ mitsumi_cdrom_reset(mcd_t *dev)
static int
mitsumi_cdrom_read_sector(mcd_t *dev, int first)
{
cdrom_t cdrom;
uint8_t status;
int ret;
int ret = 0;
if (dev->drvmode == DRV_MODE_CDDA) {
status = cdrom_mitsumi_audio_play(&cdrom, dev->readmsf, dev->readcount);
status = cdrom_mitsumi_audio_play(dev->cdrom_dev, dev->readmsf, dev->readcount);
if (status == 1)
return status;
else
@@ -191,15 +182,15 @@ mitsumi_cdrom_read_sector(mcd_t *dev, int first)
dev->data = 0;
return 0;
}
cdrom_stop(&cdrom);
ret = cdrom_readsector_raw(&cdrom, dev->buf, cdrom.seek_pos, 0, 2, 0x10, (int *) &dev->readcount, 0);
if (!ret)
cdrom_stop(dev->cdrom_dev);
ret = cdrom_readsector_raw(dev->cdrom_dev, dev->buf, dev->cdrom_dev->seek_pos, 0, 2, 0x10, (int *) &dev->readcount, 0);
if (ret <= 0)
return 0;
if (dev->mode & 0x40) {
dev->buf[12] = CD_BCD((dev->readmsf >> 16) & 0xff);
dev->buf[13] = CD_BCD((dev->readmsf >> 8) & 0xff);
}
dev->readmsf = cdrom_lba_to_msf_accurate(cdrom.seek_pos + 1);
dev->readmsf = cdrom_lba_to_msf_accurate(dev->cdrom_dev->seek_pos + 1);
dev->buf_count = dev->dmalen + 1;
dev->buf_idx = 0;
dev->data = 1;
@@ -220,7 +211,7 @@ static uint8_t
mitsumi_cdrom_in(uint16_t port, void *priv)
{
mcd_t *dev = (mcd_t *) priv;
uint8_t ret;
uint8_t ret = 0xff;
pclog("Mitsumi CD-ROM IN=%03x\n", port);
switch (port & 1) {
@@ -255,14 +246,13 @@ mitsumi_cdrom_in(uint16_t port, void *priv)
break;
}
return 0xff;
return ret;
}
static void
mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv)
{
mcd_t *dev = (mcd_t *) priv;
cdrom_t cdrom;
pclog("Mitsumi CD-ROM OUT=%03x, val=%02x\n", port, val);
switch (port & 1) {
@@ -344,19 +334,19 @@ mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv)
break;
}
if (!dev->cmdrd_count)
dev->stat = cdrom.host_drive ? (STAT_READY | (dev->change ? STAT_CHANGE : 0)) : 0;
dev->stat = mitsumi_cdrom_is_ready(dev) ? (STAT_READY | (dev->change ? STAT_CHANGE : 0)) : 0;
return;
}
dev->cmd = val;
dev->cmdbuf_idx = 0;
dev->cmdrd_count = 0;
dev->cmdbuf_count = 1;
dev->cmdbuf[0] = cdrom.host_drive ? (STAT_READY | (dev->change ? STAT_CHANGE : 0)) : 0;
dev->cmdbuf[0] = mitsumi_cdrom_is_ready(dev) ? (STAT_READY | (dev->change ? STAT_CHANGE : 0)) : 0;
dev->data = 0;
switch (val) {
case CMD_GET_INFO:
if (cdrom.host_drive) {
cdrom_get_track_buffer(&cdrom, &(dev->cmdbuf[1]));
if (mitsumi_cdrom_is_ready(dev)) {
cdrom_get_track_buffer(dev->cdrom_dev, &(dev->cmdbuf[1]));
dev->cmdbuf_count = 10;
dev->readcount = 0;
} else {
@@ -365,8 +355,8 @@ mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv)
}
break;
case CMD_GET_Q:
if (cdrom.host_drive) {
cdrom_get_q(&cdrom, &(dev->cmdbuf[1]), &dev->cur_toc_track, dev->mode & MODE_GET_TOC);
if (mitsumi_cdrom_is_ready(dev)) {
cdrom_get_q(cdrom, &(dev->cmdbuf[1]), &dev->cur_toc_track, dev->mode & MODE_GET_TOC);
dev->cmdbuf_count = 11;
dev->readcount = 0;
} else {
@@ -382,7 +372,7 @@ mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv)
break;
case CMD_STOPCDDA:
case CMD_STOP:
cdrom_stop(&cdrom);
cdrom_stop(dev->cdrom_dev);
dev->drvmode = DRV_MODE_STOP;
dev->cur_toc_track = 0;
break;
@@ -391,7 +381,7 @@ mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv)
break;
case CMD_READ1X:
case CMD_READ2X:
if (cdrom.host_drive) {
if (mitsumi_cdrom_is_ready(dev)) {
dev->readcount = 0;
dev->drvmode = (val == CMD_READ1X) ? DRV_MODE_CDDA : DRV_MODE_READ;
dev->cmdrd_count = 6;
@@ -407,7 +397,7 @@ mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv)
dev->cmdbuf_count = 3;
break;
case CMD_EJECT:
cdrom_stop(&cdrom);
cdrom_stop(dev->cdrom_dev);
cdrom_eject(0);
dev->readcount = 0;
break;
@@ -436,15 +426,25 @@ mitsumi_cdrom_out(uint16_t port, uint8_t val, void *priv)
static void *
mitsumi_cdrom_init(UNUSED(const device_t *info))
{
mcd_t *dev;
mcd_t *dev = calloc(1, sizeof(mcd_t));
dev = malloc(sizeof(mcd_t));
memset(dev, 0x00, sizeof(mcd_t));
for (uint8_t i = 0; i < CDROM_NUM; i++) {
if (cdrom[i].bus_type == CDROM_BUS_MITSUMI) {
dev->cdrom_dev = &cdrom[i];
break;
}
}
dev->irq = MCD_DEFAULT_IRQ;
dev->dma = MCD_DEFAULT_DMA;
if (!dev->cdrom_dev)
return NULL;
io_sethandler(MCD_DEFAULT_IOPORT, 3,
dev->cdrom_dev->priv = &dev;
uint16_t base = device_get_config_hex16("base");
dev->irq = device_get_config_int("irq");
dev->dma = device_get_config_int("dma");
io_sethandler(base, 3,
mitsumi_cdrom_in, NULL, NULL, mitsumi_cdrom_out, NULL, NULL, dev);
mitsumi_cdrom_reset(dev);
@@ -463,16 +463,74 @@ mitsumi_cdrom_close(void *priv)
}
}
static const device_config_t mitsumi_config[] = {
// clang-format off
{
.name = "base",
.description = "Address",
.type = CONFIG_HEX16,
.default_string = NULL,
.default_int = 0x310,
.file_filter = NULL,
.spinner = { 0 },
.selection = {
{ .description = "300H", .value = 0x300 },
{ .description = "310H", .value = 0x310 },
{ .description = "320H", .value = 0x320 },
{ .description = "340H", .value = 0x340 },
{ .description = "350H", .value = 0x350 },
{ NULL }
},
.bios = { { 0 } }
},
{
.name = "irq",
.description = "IRQ",
.type = CONFIG_SELECTION,
.default_string = NULL,
.default_int = 5,
.file_filter = NULL,
.spinner = { 0 },
.selection = {
{ .description = "IRQ 3", .value = 3 },
{ .description = "IRQ 5", .value = 5 },
{ .description = "IRQ 9", .value = 9 },
{ .description = "IRQ 10", .value = 10 },
{ .description = "IRQ 11", .value = 11 },
{ .description = "" }
},
.bios = { { 0 } }
},
{
.name = "dma",
.description = "DMA",
.type = CONFIG_SELECTION,
.default_string = NULL,
.default_int = 5,
.file_filter = NULL,
.spinner = { 0 },
.selection = {
{ .description = "DMA 5", .value = 5 },
{ .description = "DMA 6", .value = 6 },
{ .description = "DMA 7", .value = 7 },
{ .description = "" }
},
.bios = { { 0 } }
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format off
};
const device_t mitsumi_cdrom_device = {
.name = "Mitsumi CD-ROM interface",
.internal_name = "mcd",
.flags = DEVICE_ISA | DEVICE_AT,
.local = 1,
.flags = DEVICE_ISA16,
.local = 0,
.init = mitsumi_cdrom_init,
.close = mitsumi_cdrom_close,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
.config = mitsumi_config
};

1078
src/cdrom/cdrom_mke.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -358,8 +358,7 @@ ct_82c100_init(UNUSED(const device_t *info))
{
ct_82c100_t *dev;
dev = (ct_82c100_t *) malloc(sizeof(ct_82c100_t));
memset(dev, 0x00, sizeof(ct_82c100_t));
dev = (ct_82c100_t *) calloc(1, sizeof(ct_82c100_t));
ct_82c100_reset(dev);
@@ -393,7 +392,7 @@ const device_t ct_82c100_device = {
.init = ct_82c100_init,
.close = ct_82c100_close,
.reset = ct_82c100_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL

View File

@@ -9,19 +9,88 @@
# CMake build script.
#
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
# Jasmine Iwanek, <jriwanek@gmail.com>
#
# Copyright 2020-2021 David Hrdlička.
# Copyright 2024 Jasmine Iwanek.
#
add_library(chipset OBJECT 82c100.c acc2168.c cs8230.c ali1429.c ali1435.c ali1489.c
ali1531.c ali1541.c ali1543.c ali1621.c ali6117.c headland.c ims8848.c intel_82335.c
compaq_386.c contaq_82c59x.c cs4031.c intel_420ex.c intel_4x0.c intel_i450kx.c
intel_sio.c intel_piix.c ../ioapic.c neat.c opti283.c opti291.c opti391.c opti495.c
opti602.c opti822.c opti895.c opti5x7.c scamp.c scat.c sis_85c310.c sis_85c4xx.c
sis_85c496.c sis_85c50x.c sis_5511.c sis_5571.c via_vt82c49x.c via_vt82c505.c
sis_85c310.c sis_85c4xx.c sis_85c496.c sis_85c50x.c gc100.c stpc.c umc_8886.c
umc_hb4.c via_apollo.c via_pipc.c vl82c480.c wd76c10.c)
if(OLIVETTI)
target_sources(chipset PRIVATE olivetti_eva.c)
endif()
add_library(chipset OBJECT
82c100.c
acc2036.c
acc2168.c
cs8220.c
cs8230.c
ali1429.c
ali1435.c
ali1489.c
ali1531.c
ali1541.c
ali1543.c
ali1621.c
ali6117.c
ali1409.c
compaq.c
compaq_386.c
contaq_82c59x.c
cs4031.c
grid1520.c
gc100.c
headland.c
ims8848.c
intel_82335.c
intel_420ex.c
intel_4x0.c
intel_i450kx.c
intel_sio.c
intel_piix.c
isa486c.c
../ioapic.c
laserxt.c
neat.c
olivetti_eva.c
opti283.c
opti291.c
opti391.c
opti495.c
opti498.c
opti499.c
opti602.c
opti822.c
opti895.c
opti5x7.c
philips.c
sanyo.c
scamp.c
scat.c
sis_85c310.c
sis_85c4xx.c
sis_85c496.c
sis_85c50x.c
sis_5511.c
sis_5571.c
sis_5581.c
sis_5591.c
sis_5600.c
sis_5511_h2p.c
sis_5571_h2p.c
sis_5581_h2p.c
sis_5591_h2p.c
sis_5600_h2p.c
sis_5513_p2i.c
sis_5513_ide.c
sis_5572_usb.c
sis_5595_pmu.c
sis_55xx.c
sl82c461.c
stpc.c
via_vt82c49x.c
via_vt82c505.c
umc_8886.c
umc_hb4.c
umc_8890.c
via_apollo.c
via_pipc.c
vl82c480.c
wd76c10.c
)

346
src/chipset/acc2036.c Normal file
View File

@@ -0,0 +1,346 @@
/*
* 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 ACC 2036 chipset.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2025 Miran Grca.
*/
#include <inttypes.h>
#include <stdint.h>
#include <stdio.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/port_92.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;
mem_mapping_t mapping;
} ram_page_t;
typedef struct {
uint8_t reg;
uint8_t regs[32];
ram_page_t ram_mid_pages[24];
ram_page_t ems_pages[4];
} acc2036_t;
static uint8_t
acc2036_mem_read(uint32_t addr, void *priv)
{
ram_page_t *dev = (ram_page_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
acc2036_mem_readw(uint32_t addr, void *priv)
{
ram_page_t *dev = (ram_page_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
acc2036_mem_write(uint32_t addr, uint8_t val, void *priv)
{
ram_page_t *dev = (ram_page_t *) priv;
addr = (addr - dev->virt) + dev->phys;
if (addr < (mem_size << 10))
ram[addr] = val;
}
static void
acc2036_mem_writew(uint32_t addr, uint16_t val, void *priv)
{
ram_page_t *dev = (ram_page_t *) priv;
addr = (addr - dev->virt) + dev->phys;
if (addr < (mem_size << 10))
*(uint16_t *) &(ram[addr]) = val;
}
static void
acc2036_recalc(acc2036_t *dev)
{
uint32_t ems_bases[4] = { 0x000c0000, 0x000c8000, 0x000d0000, 0x000e0000 };
int start_i = (ems_bases[dev->regs[0x0c] & 0x03] - 0x000a0000) >> 14;
int end_i = start_i + 3;
for (int i = 0; i < 24; i++) {
ram_page_t *rp = &dev->ram_mid_pages[i];
mem_mapping_disable(&rp->mapping);
}
for (int i = 0; i < 4; i++) {
ram_page_t *ep = &dev->ems_pages[i];
mem_mapping_disable(&ep->mapping);
}
for (int i = 0; i < 24; i++) {
ram_page_t *rp = &dev->ram_mid_pages[i];
if ((dev->regs[0x03] & 0x08) && (i >= start_i) && (i <= end_i)) {
/* EMS */
ram_page_t *ep = &dev->ems_pages[i - start_i];
mem_mapping_disable(&rp->mapping);
mem_mapping_set_addr(&ep->mapping, ep->virt, 0x000040000);
mem_mapping_set_exec(&ep->mapping, ram + ep->phys);
mem_set_mem_state_both(ep->virt, 0x00004000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
} else {
int master_write;
int master_read;
int bit;
int ew_flag;
int er_flag;
int flags;
uint8_t val;
mem_mapping_set_addr(&rp->mapping, rp->virt, 0x000040000);
mem_mapping_set_exec(&rp->mapping, ram + rp->phys);
if ((i >= 8) && (i <= 15)) {
/* 0C0000-0DFFFF */
master_write = dev->regs[0x02] & 0x08;
master_read = dev->regs[0x02] & 0x04;
bit = ((i - 8) >> 1);
val = dev->regs[0x0d] & (1 << bit);
if (i >= 12) {
ew_flag = (dev->regs[0x07] & 0x80) ? MEM_WRITE_EXTANY : MEM_WRITE_EXTERNAL;
er_flag = (dev->regs[0x07] & 0x80) ? MEM_READ_EXTANY : MEM_READ_EXTERNAL;
} else {
ew_flag = (dev->regs[0x07] & 0x40) ? MEM_WRITE_EXTANY : MEM_WRITE_EXTERNAL;
er_flag = (dev->regs[0x07] & 0x40) ? MEM_READ_EXTANY : MEM_READ_EXTERNAL;
}
flags = (val && master_write) ? MEM_WRITE_INTERNAL : ew_flag;
flags |= (val && master_read) ? MEM_READ_INTERNAL : er_flag;
mem_set_mem_state_both(rp->virt, 0x00004000, flags);
} else if (i > 15) {
/* 0E0000-0FFFFF */
master_write = dev->regs[0x02] & 0x02;
master_read = dev->regs[0x02] & 0x01;
bit = ((i - 8) >> 2);
val = dev->regs[0x0c] & (1 << bit);
if (i >= 20) {
ew_flag = MEM_WRITE_EXTANY;
er_flag = MEM_READ_EXTANY;
} else {
ew_flag = (dev->regs[0x0c] & 0x10) ? MEM_WRITE_EXTANY : MEM_WRITE_EXTERNAL;
er_flag = (dev->regs[0x0c] & 0x10) ? MEM_READ_EXTANY : MEM_READ_EXTERNAL;
}
flags = (val && master_write) ? MEM_WRITE_INTERNAL : ew_flag;
flags |= (val && master_read) ? MEM_READ_INTERNAL : er_flag;
mem_set_mem_state_both(rp->virt, 0x00004000, flags);
}
}
}
if (dev->regs[0x00] & 0x40)
mem_set_mem_state_both(0x00fe0000, 0x00010000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
else
mem_set_mem_state_both(0x00fe0000, 0x00010000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
for (int i = 0x01; i <= 0x06; i++) {
uint32_t base = 0x00fe0000 - (i * 0x00010000);
if (dev->regs[i] & 0x40)
mem_set_mem_state_both(base, 0x00008000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
else
mem_set_mem_state_both(base, 0x00008000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
if (dev->regs[i] & 0x80)
mem_set_mem_state_both(base + 0x00008000, 0x00008000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
else
mem_set_mem_state_both(base + 0x00008000, 0x00008000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
}
mem_remap_top(0);
if (dev->regs[0x03] & 0x10) {
if (dev->regs[0x02] & 0x0c)
mem_remap_top(128);
else if (dev->regs[0x02] & 0x03)
mem_remap_top(256);
else
mem_remap_top(384);
}
flushmmucache_nopc();
}
static uint8_t
acc2036_in(uint16_t port, void *priv) {
acc2036_t *dev = (acc2036_t *) priv;
uint8_t reg = dev->reg - 0x20;
uint8_t ret = 0xff;
if (port & 0x0001) switch (dev->reg) {
default:
break;
case 0x20 ... 0x2e:
case 0x31 ... 0x3f:
ret = dev->regs[reg];
break;
} else
ret = dev->reg;
return ret;
}
static void
acc2036_out(uint16_t port, uint8_t val, void *priv) {
acc2036_t *dev = (acc2036_t *) priv;
uint8_t reg = dev->reg - 0x20;
if (port & 0x0001) switch (dev->reg) {
default:
break;
case 0x20 ... 0x23:
dev->regs[reg] = val;
acc2036_recalc(dev);
break;
case 0x24 ... 0x2b:
dev->regs[reg] = val;
dev->ems_pages[(reg - 0x04) >> 1].phys = ((dev->regs[reg & 0xfe] & 0x1f) << 19) |
((dev->regs[reg | 0x01] & 0x1f) << 14);
acc2036_recalc(dev);
break;
case 0x2c: case 0x2d:
dev->regs[reg] = val;
acc2036_recalc(dev);
break;
case 0x2e:
dev->regs[reg] = val | 0x10;
break;
case 0x31:
dev->regs[reg] = val;
mem_a20_alt = (val & 0x01);
mem_a20_recalc();
flushmmucache();
if (val & 0x02) {
softresetx86(); /* Pulse reset! */
cpu_set_edx();
flushmmucache();
}
break;
case 0x32 ... 0x3f:
dev->regs[reg] = val;
break;
} else
dev->reg = val;
}
static void
acc2036_close(void *priv)
{
acc2036_t *dev = (acc2036_t *) priv;
free(dev);
}
static void *
acc2036_init(UNUSED(const device_t *info))
{
acc2036_t *dev = (acc2036_t *) calloc(1, sizeof(acc2036_t));
for (int i = 0; i < 24; i++) {
ram_page_t *rp = &dev->ram_mid_pages[i];
rp->virt = 0x000a0000 + (i << 14);
rp->phys = 0x000a0000 + (i << 14);
mem_mapping_add(&rp->mapping, rp->virt, 0x00004000,
acc2036_mem_read, acc2036_mem_readw, NULL,
acc2036_mem_write, acc2036_mem_writew, NULL,
ram + rp->phys, MEM_MAPPING_INTERNAL, rp);
}
for (int i = 0; i < 4; i++) {
ram_page_t *ep = &dev->ems_pages[i];
ep->virt = 0x000d0000 + (i << 14);
ep->phys = 0x00000000 + (i << 14);
mem_mapping_add(&ep->mapping, ep->virt, 0x00004000,
acc2036_mem_read, acc2036_mem_readw, NULL,
acc2036_mem_write, acc2036_mem_writew, NULL,
ram + ep->phys, MEM_MAPPING_INTERNAL, ep);
mem_mapping_disable(&ep->mapping);
}
mem_mapping_disable(&ram_mid_mapping);
dev->regs[0x00] = 0x02;
dev->regs[0x0e] = 0x10;
dev->regs[0x11] = 0x01;
dev->regs[0x13] = 0x40;
dev->regs[0x15] = 0x40;
dev->regs[0x17] = 0x40;
dev->regs[0x19] = 0x40;
dev->regs[0x1b] = 0x40;
dev->regs[0x1c] = 0x22;
dev->regs[0x1d] = 0xc4;
dev->regs[0x1f] = 0x30;
acc2036_recalc(dev);
mem_a20_alt = 0x01;
mem_a20_recalc();
flushmmucache();
io_sethandler(0x00f2, 0x0002,
acc2036_in, NULL, NULL, acc2036_out, NULL, NULL, dev);
device_add(&port_92_device);
return dev;
}
const device_t acc2036_device = {
.name = "ACC 2036",
.internal_name = "acc2036",
.flags = 0,
.local = 0,
.init = acc2036_init,
.close = acc2036_close,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -184,8 +184,7 @@ acc2168_close(void *priv)
static void *
acc2168_init(UNUSED(const device_t *info))
{
acc2168_t *dev = (acc2168_t *) malloc(sizeof(acc2168_t));
memset(dev, 0, sizeof(acc2168_t));
acc2168_t *dev = (acc2168_t *) calloc(1, sizeof(acc2168_t));
device_add(&port_92_device);
io_sethandler(0x00f2, 0x0002, acc2168_read, NULL, NULL, acc2168_write, NULL, NULL, dev);
@@ -201,7 +200,7 @@ const device_t acc2168_device = {
.init = acc2168_init,
.close = acc2168_close,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL

343
src/chipset/ali1409.c Normal file
View File

@@ -0,0 +1,343 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Implementation of the ALi M1409 chipset.
*
* Note: This chipset has no datasheet, everything were done via
* reverse engineering.
*
*
*
* Authors: Jose Phillips, <jose@latinol.com>
* Sarah Walker, <https://pcem-emulator.co.uk/>
*
* Copyright 2024 Jose Phillips.
* Copyright 2008-2018 Sarah Walker.
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include "cpu.h"
#include <86box/timer.h>
#include <86box/io.h>
#include <86box/device.h>
#include <86box/apm.h>
#include <86box/mem.h>
#include <86box/fdd.h>
#include <86box/fdc.h>
#include <86box/smram.h>
#include <86box/chipset.h>
#include <86box/plat_unused.h>
#ifdef ENABLE_ALI1409_LOG
int ali1409_do_log = ENABLE_ALI1409_LOG;
static void
ali1409_log(const char *fmt, ...)
{
va_list ap;
if (ali1409_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define ali1409_log(fmt, ...)
#endif
typedef struct ali_1409_t {
uint8_t index;
uint8_t cfg_locked;
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("[%04X:%08X] [W] %04X = %02X\n", CS, cpu_state.pc, addr, val);
if (addr & 0x0001) {
if (dev->cfg_locked) {
if ((dev->last_reg == 0x14) && (val == 0x09))
dev->cfg_locked = 0;
dev->last_reg = val;
return;
}
/* 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);
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 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;
}
static uint8_t
ali1409_read(uint16_t addr, void *priv)
{
const ali1409_t *dev = (ali1409_t *) priv;
uint8_t ret = 0xff;
if (dev->cfg_locked)
ret = 0xff;
else if (addr & 0x0001) {
if (dev->index < 0x44)
ret = dev->regs[dev->index];
} else
ret = dev->index;
ali1409_log("[%04X:%08X] [R] %04X = %02X\n", CS, cpu_state.pc, addr, ret);
return ret;
}
static void
ali1409_close(void *priv)
{
ali1409_t *dev = (ali1409_t *) priv;
free(dev);
}
static void *
ali1409_init(UNUSED(const device_t *info))
{
ali1409_t *dev = (ali1409_t *) calloc(1, sizeof(ali1409_t));
dev->cfg_locked = 1;
ali1409_log("Bus speed: %i\n", cpu_busspeed);
io_sethandler(0x0022, 0x0002, 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;
}
const device_t ali1409_device = {
.name = "ALi M1409",
.internal_name = "ali1409",
.flags = 0,
.local = 0,
.init = ali1409_init,
.close = ali1409_close,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -331,8 +331,7 @@ ali1429_defaults(ali1429_t *dev)
static void *
ali1429_init(const device_t *info)
{
ali1429_t *dev = (ali1429_t *) malloc(sizeof(ali1429_t));
memset(dev, 0, sizeof(ali1429_t));
ali1429_t *dev = (ali1429_t *) calloc(1, sizeof(ali1429_t));
dev->cfg_locked = 1;
GREEN = info->local;
@@ -358,7 +357,7 @@ const device_t ali1429_device = {
.init = ali1429_init,
.close = ali1429_close,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
@@ -372,7 +371,7 @@ const device_t ali1429g_device = {
.init = ali1429_init,
.close = ali1429_close,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL

View File

@@ -282,8 +282,7 @@ ali1435_close(void *priv)
static void *
ali1435_init(UNUSED(const device_t *info))
{
ali1435_t *dev = (ali1435_t *) malloc(sizeof(ali1435_t));
memset(dev, 0, sizeof(ali1435_t));
ali1435_t *dev = (ali1435_t *) calloc(1, sizeof(ali1435_t));
dev->cfg_locked = 1;
@@ -308,7 +307,7 @@ const device_t ali1435_device = {
.init = ali1435_init,
.close = ali1435_close,
.reset = ali1435_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL

View File

@@ -28,9 +28,10 @@
#include <86box/timer.h>
#include <86box/io.h>
#include <86box/device.h>
#include <86box/keyboard.h>
#include <86box/hdc_ide.h>
#include <86box/hdc.h>
#include <86box/machine.h>
#include <86box/mem.h>
#include <86box/nmi.h>
#include <86box/pic.h>
@@ -470,8 +471,7 @@ ali1489_close(void *priv)
static void *
ali1489_init(UNUSED(const device_t *info))
{
ali1489_t *dev = (ali1489_t *) malloc(sizeof(ali1489_t));
memset(dev, 0, sizeof(ali1489_t));
ali1489_t *dev = (ali1489_t *) calloc(1, sizeof(ali1489_t));
/* M1487/M1489
22h Index Port
@@ -486,6 +486,9 @@ ali1489_init(UNUSED(const device_t *info))
dev->port_92 = device_add(&port_92_pci_device);
dev->smram = smram_add();
if (machine_get_kbc_device(machine) == NULL)
device_add_params(&kbc_at_device, (void *) KBC_VEN_ALI);
ali1489_defaults(dev);
return dev;
@@ -499,7 +502,7 @@ const device_t ali1489_device = {
.init = ali1489_init,
.close = ali1489_close,
.reset = ali1489_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL

View File

@@ -22,6 +22,7 @@
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include "cpu.h"
#include <86box/timer.h>
#include <86box/device.h>
@@ -225,12 +226,8 @@ ali1531_write(UNUSED(int func), int addr, uint8_t val, void *priv)
ali1531_shadow_recalc(val, dev);
break;
case 0x50:
case 0x51:
case 0x52:
case 0x54:
case 0x55:
case 0x56:
case 0x50 ... 0x52:
case 0x54 ... 0x56:
dev->pci_conf[addr] = val;
break;
@@ -247,8 +244,7 @@ ali1531_write(UNUSED(int func), int addr, uint8_t val, void *priv)
dev->pci_conf[addr] = val & 0x86;
break;
case 0x59:
case 0x5a:
case 0x59 ... 0x5a:
case 0x5c:
dev->pci_conf[addr] = val;
break;
@@ -270,8 +266,7 @@ ali1531_write(UNUSED(int func), int addr, uint8_t val, void *priv)
spd_write_drbs_interleaved(dev->pci_conf, 0x60, 0x6f, 1);
break;
case 0x70:
case 0x71:
case 0x70 ... 0x71:
dev->pci_conf[addr] = val;
break;
@@ -283,8 +278,7 @@ ali1531_write(UNUSED(int func), int addr, uint8_t val, void *priv)
dev->pci_conf[addr] = val & 0x2b;
break;
case 0x76:
case 0x77:
case 0x76 ... 0x77:
dev->pci_conf[addr] = val;
break;
@@ -376,8 +370,7 @@ ali1531_close(void *priv)
static void *
ali1531_init(UNUSED(const device_t *info))
{
ali1531_t *dev = (ali1531_t *) malloc(sizeof(ali1531_t));
memset(dev, 0, sizeof(ali1531_t));
ali1531_t *dev = (ali1531_t *) calloc(1, sizeof(ali1531_t));
pci_add_card(PCI_ADD_NORTHBRIDGE, ali1531_read, ali1531_write, dev, &dev->pci_slot);
@@ -396,7 +389,7 @@ const device_t ali1531_device = {
.init = ali1531_init,
.close = ali1531_close,
.reset = ali1531_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL

View File

@@ -22,6 +22,7 @@
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include "cpu.h"
#include <86box/timer.h>
#include <86box/device.h>
@@ -643,8 +644,7 @@ ali1541_close(void *priv)
static void *
ali1541_init(UNUSED(const device_t *info))
{
ali1541_t *dev = (ali1541_t *) malloc(sizeof(ali1541_t));
memset(dev, 0, sizeof(ali1541_t));
ali1541_t *dev = (ali1541_t *) calloc(1, sizeof(ali1541_t));
pci_add_card(PCI_ADD_NORTHBRIDGE, ali1541_read, ali1541_write, dev, &dev->pci_slot);
@@ -665,7 +665,7 @@ const device_t ali1541_device = {
.init = ali1541_init,
.close = ali1541_close,
.reset = ali1541_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL

View File

@@ -22,6 +22,7 @@
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include "cpu.h"
#include <86box/timer.h>
#include <86box/device.h>
#include <86box/io.h>
@@ -197,6 +198,7 @@ ali1533_write(int func, int addr, uint8_t val, void *priv)
case 0x44: /* Set IRQ Line for Primary IDE if it's on native mode */
dev->pci_conf[addr] = val & 0xdf;
soft_reset_pci = !!(val & 0x80);
pci_set_mirq_level(PCI_MIRQ0, !(val & 0x10));
pci_set_mirq_level(PCI_MIRQ2, !(val & 0x10));
ali1543_log("INTAJ = IRQ %i\n", ali1533_irq_routing[val & 0x0f]);
pci_set_mirq_routing(PCI_MIRQ0, ali1533_irq_routing[val & 0x0f]);
@@ -412,11 +414,13 @@ ali1533_write(int func, int addr, uint8_t val, void *priv)
case 0x74: /* USB IRQ Routing - we cheat and use MIRQ4 */
dev->pci_conf[addr] = val & 0xdf;
/* TODO: MIRQ level/edge control - if bit 4 = 1, it's level */
pci_set_mirq_level(PCI_MIRQ4, !(val & 0x10));
pci_set_mirq_routing(PCI_MIRQ4, ali1533_irq_routing[val & 0x0f]);
break;
case 0x75: /* Set IRQ Line for Secondary IDE if it's on native mode */
dev->pci_conf[addr] = val & 0x1f;
pci_set_mirq_level(PCI_MIRQ1, !(val & 0x10));
pci_set_mirq_level(PCI_MIRQ3, !(val & 0x10));
ali1543_log("INTBJ = IRQ %i\n", ali1533_irq_routing[val & 0x0f]);
pci_set_mirq_routing(PCI_MIRQ1, ali1533_irq_routing[val & 0x0f]);
@@ -704,7 +708,7 @@ ali5229_chip_reset(ali1543_t *dev)
ali5229_write(0, 0x09, 0xfa, dev);
ali5229_write(0, 0x52, 0x00, dev);
ali5229_write(0, 0x50, 0x00, dev);
ali5229_write(0, 0x50, 0x02, dev);
sff_set_slot(dev->ide_controller[0], dev->ide_slot);
sff_set_slot(dev->ide_controller[1], dev->ide_slot);
@@ -717,7 +721,7 @@ static void
ali5229_write(int func, int addr, uint8_t val, void *priv)
{
ali1543_t *dev = (ali1543_t *) priv;
ali1543_log("M5229: dev->ide_conf[%02x] = %02x\n", addr, val);
ali1543_log("M5229: [W] dev->ide_conf[%02x] = %02x\n", addr, val);
if (func > 0)
return;
@@ -756,6 +760,10 @@ ali5229_write(int func, int addr, uint8_t val, void *priv)
ali5229_ide_irq_handler(dev);
break;
case 0x0d: /* LT - Latency Timer */
dev->ide_conf[addr] = val;
break;
/* Primary Base Address */
case 0x10:
case 0x11:
@@ -776,9 +784,9 @@ ali5229_write(int func, int addr, uint8_t val, void *priv)
/* Datasheet erratum: the PCI BAR's actually have different sizes. */
if (addr == 0x20)
dev->ide_conf[addr] = (val & 0xe0) | 0x01;
else if ((addr & 0x43) == 0x00)
else if ((addr & 0x07) == 0x00)
dev->ide_conf[addr] = (val & 0xf8) | 0x01;
else if ((addr & 0x43) == 0x40)
else if ((addr & 0x07) == 0x04)
dev->ide_conf[addr] = (val & 0xfc) | 0x01;
else
dev->ide_conf[addr] = val;
@@ -887,13 +895,15 @@ ali5229_read(int func, int addr, void *priv)
if (dev->ide_dev_enable && (func == 0)) {
ret = dev->ide_conf[addr];
if ((addr == 0x09) && !(dev->ide_conf[0x50] & 0x02))
ret &= 0x0f;
ret = (ret & 0x0f) | 0x80;
else if (addr == 0x50)
ret = (ret & 0xfe) | (dev->ide_dev_enable ? 0x01 : 0x00);
else if (addr == 0x75)
ret = ide_read_ali_75();
else if (addr == 0x76)
ret = ide_read_ali_76();
ali1543_log("M5229: [R] dev->ide_conf[%02x] = %02x\n", addr, ret);
}
return ret;
@@ -1590,8 +1600,7 @@ ali1543_close(void *priv)
static void *
ali1543_init(const device_t *info)
{
ali1543_t *dev = (ali1543_t *) malloc(sizeof(ali1543_t));
memset(dev, 0, sizeof(ali1543_t));
ali1543_t *dev = (ali1543_t *) calloc(1, sizeof(ali1543_t));
/* Device 02: M1533 Southbridge */
pci_add_card(PCI_ADD_SOUTHBRIDGE, ali1533_read, ali1533_write, dev, &dev->pci_slot);
@@ -1664,7 +1673,7 @@ const device_t ali1543_device = {
.init = ali1543_init,
.close = ali1543_close,
.reset = ali1543_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
@@ -1678,7 +1687,7 @@ const device_t ali1543c_device = {
.init = ali1543_init,
.close = ali1543_close,
.reset = ali1543_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL

View File

@@ -669,8 +669,7 @@ ali1621_close(void *priv)
static void *
ali1621_init(UNUSED(const device_t *info))
{
ali1621_t *dev = (ali1621_t *) malloc(sizeof(ali1621_t));
memset(dev, 0, sizeof(ali1621_t));
ali1621_t *dev = (ali1621_t *) calloc(1, sizeof(ali1621_t));
pci_add_card(PCI_ADD_NORTHBRIDGE, ali1621_read, ali1621_write, dev, &dev->pci_slot);
@@ -692,7 +691,7 @@ const device_t ali1621_device = {
.init = ali1621_init,
.close = ali1621_close,
.reset = ali1621_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL

View File

@@ -26,6 +26,7 @@
#include <86box/io.h>
#include <86box/pci.h>
#include <86box/pic.h>
#include "cpu.h"
#include <86box/timer.h>
#include <86box/pit.h>
#include <86box/device.h>
@@ -466,12 +467,12 @@ ali6117_init(const device_t *info)
ali6117_log("ALI6117: init()\n");
ali6117_t *dev = (ali6117_t *) malloc(sizeof(ali6117_t));
memset(dev, 0, sizeof(ali6117_t));
ali6117_t *dev = (ali6117_t *) calloc(1, sizeof(ali6117_t));
dev->local = info->local;
device_add(&ide_isa_device);
if (!(dev->local & 0x08))
device_add(&ide_isa_device);
ali6117_setup(dev);
@@ -493,12 +494,12 @@ ali6117_init(const device_t *info)
const device_t ali1217_device = {
.name = "ALi M1217",
.internal_name = "ali1217",
.flags = DEVICE_AT,
.flags = DEVICE_ISA16,
.local = 0x8,
.init = ali6117_init,
.close = ali6117_close,
.reset = ali6117_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
@@ -507,12 +508,12 @@ const device_t ali1217_device = {
const device_t ali6117d_device = {
.name = "ALi M6117D",
.internal_name = "ali6117d",
.flags = DEVICE_AT,
.flags = DEVICE_ISA16,
.local = 0x2,
.init = ali6117_init,
.close = ali6117_close,
.reset = ali6117_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL

135
src/chipset/compaq.c Normal file
View File

@@ -0,0 +1,135 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Emulation of the Compaq 386 memory controller.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2023 Miran Grca.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include <math.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/io.h>
#include <86box/timer.h>
#include <86box/pit.h>
#include <86box/mem.h>
#include <86box/rom.h>
#include <86box/device.h>
#include <86box/keyboard.h>
#include <86box/fdd.h>
#include <86box/fdc.h>
#include <86box/fdc_ext.h>
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
#include <86box/machine.h>
#include <86box/video.h>
#include <86box/vid_cga.h>
#include <86box/vid_cga_comp.h>
#include <86box/plat_unused.h>
#include <86box/chipset.h>
/* Compaq Deskpro 386 remaps RAM from 0xA0000-0xFFFFF to 0xFA0000-0xFFFFFF */
typedef struct cpq_t {
mem_mapping_t ram_mapping;
} cpq_t;
static uint8_t
read_ram(uint32_t addr, UNUSED(void *priv))
{
addr = (addr & 0x7ffff) + 0x80000;
addreadlookup(mem_logical_addr, addr);
return (ram[addr]);
}
static uint16_t
read_ramw(uint32_t addr, UNUSED(void *priv))
{
addr = (addr & 0x7ffff) + 0x80000;
addreadlookup(mem_logical_addr, addr);
return (*(uint16_t *) &ram[addr]);
}
static uint32_t
read_raml(uint32_t addr, UNUSED(void *priv))
{
addr = (addr & 0x7ffff) + 0x80000;
addreadlookup(mem_logical_addr, addr);
return (*(uint32_t *) &ram[addr]);
}
static void
write_ram(uint32_t addr, uint8_t val, UNUSED(void *priv))
{
addr = (addr & 0x7ffff) + 0x80000;
addwritelookup(mem_logical_addr, addr);
mem_write_ramb_page(addr, val, &pages[addr >> 12]);
}
static void
write_ramw(uint32_t addr, uint16_t val, UNUSED(void *priv))
{
addr = (addr & 0x7ffff) + 0x80000;
addwritelookup(mem_logical_addr, addr);
mem_write_ramw_page(addr, val, &pages[addr >> 12]);
}
static void
write_raml(uint32_t addr, uint32_t val, UNUSED(void *priv))
{
addr = (addr & 0x7ffff) + 0x80000;
addwritelookup(mem_logical_addr, addr);
mem_write_raml_page(addr, val, &pages[addr >> 12]);
}
static void
compaq_close(void *priv)
{
cpq_t *dev = (cpq_t *) priv;
free(dev);
}
static void *
compaq_init(UNUSED(const device_t *info))
{
cpq_t *dev = (cpq_t *) calloc(1, sizeof(cpq_t));
mem_remap_top(384);
mem_mapping_add(&dev->ram_mapping, 0xfa0000, 0x60000,
read_ram, read_ramw, read_raml,
write_ram, write_ramw, write_raml,
0xa0000 + ram, MEM_MAPPING_INTERNAL, NULL);
return dev;
}
const device_t compaq_device = {
.name = "Compaq Memory Control",
.internal_name = "compaq",
.flags = 0,
.local = 0,
.init = compaq_init,
.close = compaq_close,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -37,6 +37,7 @@
#include <86box/vid_cga.h>
#include <86box/vid_cga_comp.h>
#include <86box/plat_unused.h>
#include <86box/chipset.h>
#define RAM_DIAG_L_BASE_MEM_640KB 0x00
#define RAM_DIAG_L_BASE_MEM_INV 0x10
@@ -746,6 +747,23 @@ compaq_386_init(UNUSED(const device_t *info))
return dev;
}
static void
compaq_genoa_outw(uint16_t port, uint16_t val, void *priv)
{
if (port == 0x0c02)
cpq_write_regs(0x80c00000, val, priv);
}
static void *
compaq_genoa_init(UNUSED(const device_t *info))
{
void *cpq = device_add(&compaq_386_device);
io_sethandler(0x0c02, 2, NULL, NULL, NULL, NULL, compaq_genoa_outw, NULL, cpq);
return ram;
}
const device_t compaq_386_device = {
.name = "Compaq 386 Memory Control",
.internal_name = "compaq_386",
@@ -754,7 +772,21 @@ const device_t compaq_386_device = {
.init = compaq_386_init,
.close = compaq_386_close,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t compaq_genoa_device = {
.name = "Compaq Genoa Memory Control",
.internal_name = "compaq_genoa",
.flags = 0,
.local = 0,
.init = compaq_genoa_init,
.close = NULL,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL

View File

@@ -322,8 +322,7 @@ contaq_82c59x_close(void *priv)
static void *
contaq_82c59x_init(const device_t *info)
{
contaq_82c59x_t *dev = (contaq_82c59x_t *) malloc(sizeof(contaq_82c59x_t));
memset(dev, 0x00, sizeof(contaq_82c59x_t));
contaq_82c59x_t *dev = (contaq_82c59x_t *) calloc(1, sizeof(contaq_82c59x_t));
dev->green = info->local;
@@ -359,7 +358,7 @@ const device_t contaq_82c596a_device = {
.init = contaq_82c59x_init,
.close = contaq_82c59x_close,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
@@ -373,7 +372,7 @@ const device_t contaq_82c597_device = {
.init = contaq_82c59x_init,
.close = contaq_82c59x_close,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL

View File

@@ -164,8 +164,7 @@ cs4031_close(void *priv)
static void *
cs4031_init(UNUSED(const device_t *info))
{
cs4031_t *dev = (cs4031_t *) malloc(sizeof(cs4031_t));
memset(dev, 0, sizeof(cs4031_t));
cs4031_t *dev = (cs4031_t *) calloc(1, sizeof(cs4031_t));
dev->port_92 = device_add(&port_92_device);
@@ -185,7 +184,7 @@ const device_t cs4031_device = {
.init = cs4031_init,
.close = cs4031_close,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL

289
src/chipset/cs8220.c Normal file
View 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
};

View File

@@ -157,8 +157,7 @@ cs8230_close(void *priv)
static void *
cs8230_init(UNUSED(const device_t *info))
{
cs8230_t *cs8230 = (cs8230_t *) malloc(sizeof(cs8230_t));
memset(cs8230, 0, sizeof(cs8230_t));
cs8230_t *cs8230 = (cs8230_t *) calloc(1, sizeof(cs8230_t));
io_sethandler(0x0022, 0x0002, cs8230_read, NULL, NULL, cs8230_write, NULL, NULL, cs8230);
@@ -178,7 +177,7 @@ const device_t cs8230_device = {
.init = cs8230_init,
.close = cs8230_close,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL

View File

@@ -137,8 +137,7 @@ et6000_close(void *priv)
static void *
et6000_init(UNUSED(const device_t *info))
{
et6000_t *dev = (et6000_t *) malloc(sizeof(et6000_t));
memset(dev, 0, sizeof(et6000_t));
et6000_t *dev = (et6000_t *) calloc(1, sizeof(et6000_t));
/* Port 92h */
device_add(&port_92_device);
@@ -162,7 +161,7 @@ const device_t et6000_device = {
.init = et6000_init,
.close = et6000_close,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL

View File

@@ -27,6 +27,7 @@
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/nmi.h>
#include "cpu.h"
#include <86box/timer.h>
#include <86box/pit.h>
#include <86box/mem.h>
@@ -208,8 +209,7 @@ gc100_close(void *priv)
static void *
gc100_init(const device_t *info)
{
gc100_t *dev = (gc100_t *) malloc(sizeof(gc100_t));
memset(dev, 0, sizeof(gc100_t));
gc100_t *dev = (gc100_t *) calloc(1, sizeof(gc100_t));
dev->reg[0x2] = 0xff;
dev->reg[0x3] = 0x0;
@@ -238,7 +238,7 @@ const device_t gc100_device = {
.init = gc100_init,
.close = gc100_close,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
@@ -252,7 +252,7 @@ const device_t gc100a_device = {
.init = gc100_init,
.close = gc100_close,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL

333
src/chipset/grid1520.c Normal file
View File

@@ -0,0 +1,333 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Implementation of the GRiD GRiDcase 1520
*
* The GRiDcase 1520 is a 286-based portable.
* These are HDDs supported by GRiD1520 (and probably other 15XX) BIOS
* "CP3022",5
* "CP3024",5, 615,4,17 BIOS table type 2
* "CP344",6,
* "CP3044",9, 980,5,17 BIOS table type 17
* "CP3042",9
* "CP3104",7, 776,8,33 extended type 224 (separate entry outside BIOS table)
* The only way to run unpatched BIOS is to run exactly that (or larger)
* geometry and report model name correctly in response to IDENTYIFY command.
* Alternatively you can use RomBuster to patch the BIOS.
* https://classicbits.net/coding-and-software/my-software/rombuster/
*/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/timer.h>
#include <86box/device.h>
#include <86box/fdd.h>
#include <86box/fdc.h>
#include <86box/fdc_ext.h>
#include <86box/io.h>
#include <86box/keyboard.h>
#include <86box/machine.h>
#include <86box/mem.h>
#include <86box/rom.h>
#include <86box/vid_cga.h>
#include <86box/plat_unused.h>
#include <86box/chipset.h>
#define GRID_APPROM_SELECT 0x440
#define GRID_APPROM_ENABLE 0x405
/*
approm mapping regs?
XXX_7FA equ 7FAh
XXX_7F8 equ 7F8h
XXX_7F9 equ 7F9h
XXX_BD0 equ 0BD0h
XXX_BD1 equ 0BD1h
*/
#define GRID_EMS_PAGE_0 0x0258
#define GRID_EMS_PAGE_1 0x4258
#define GRID_EMS_PAGE_2 0x8258
#define GRID_EMS_PAGE_3 0xC258
#define GRID_TURBO 0x416
#define GRID_UNUSED_424 0x424
#define GRID_426 0x426
#define GRID_HIGH_ENABLE 0xFFF
#define GRID_ROM_SUBSYSTEM 0x6F8
// EMS window
#define GRID_EMS_BASE 0xE0000
#define GRID_EMS_PAGE_SIZE 0x4000
#define GRID_EMS_PAGE_MASK 0x3FFF
#define GRID_EMS_PAGE_SHIFT 14
// physical base of extended memory
#define GRID_EXTENDED_BASE 0xA0000
#define GRID_1M 0x100000
typedef struct {
uint8_t grid_unknown;
uint8_t grid_unused_424;
uint8_t grid_426;
uint8_t grid_high_enable;
uint8_t grid_ems_page[4];
mem_mapping_t grid_ems_mapping[4];
uint8_t grid_turbo;
uint8_t grid_rom_enable;
uint8_t grid_rom_select;
} grid_t;
static uint32_t get_grid_ems_paddr(grid_t *dev, uint32_t addr) {
uint32_t slot = (addr >> GRID_EMS_PAGE_SHIFT) & 0x3;
uint32_t paddr = addr;
if (dev->grid_ems_page[slot] & 0x80)
paddr = GRID_EXTENDED_BASE + ((uint32_t)(dev->grid_ems_page[slot] & 0x7F) << GRID_EMS_PAGE_SHIFT) + (addr & GRID_EMS_PAGE_MASK);
return paddr;
}
static void grid_ems_mem_write8(uint32_t addr, uint8_t val, void *priv) {
grid_t *dev = (grid_t *) priv;
addr = get_grid_ems_paddr(dev, addr);
if (addr < (mem_size << 10))
ram[addr] = val;
}
static uint8_t grid_ems_mem_read8(uint32_t addr, void *priv) {
grid_t *dev = (grid_t *) priv;
uint8_t val = 0xFF;
addr = get_grid_ems_paddr(dev, addr);
if (addr < (mem_size << 10))
val = ram[addr];
return val;
}
static void grid_ems_mem_write16(uint32_t addr, uint16_t val, void *priv) {
grid_t *dev = (grid_t *) priv;
addr = get_grid_ems_paddr(dev, addr);
if (addr < (mem_size << 10))
*(uint16_t *)&(ram[addr]) = val;
}
static uint16_t grid_ems_mem_read16(uint32_t addr, void *priv) {
grid_t *dev = (grid_t *) priv;
uint16_t val = 0xFFFF;
addr = get_grid_ems_paddr(dev, addr);
if (addr < (mem_size << 10))
val = *(uint16_t *)&(ram[addr]);
return val;
}
static void grid_ems_update_mapping(grid_t *dev, uint32_t slot) {
uint32_t vaddr = GRID_EMS_BASE + (slot << GRID_EMS_PAGE_SHIFT);
if (dev->grid_ems_page[slot] & 0x80) {
uint32_t paddr;
mem_mapping_enable(&dev->grid_ems_mapping[slot]);
paddr = get_grid_ems_paddr(dev, vaddr);
mem_mapping_set_exec(&dev->grid_ems_mapping[slot], ram + paddr);
} else {
mem_mapping_disable(&dev->grid_ems_mapping[slot]);
}
}
static void grid_io_write(uint16_t port, uint8_t val, void *priv) {
grid_t *dev = (grid_t *) priv;
switch (port) {
case GRID_426:
dev->grid_426 = val;
break;
case GRID_UNUSED_424:
dev->grid_unused_424 = val;
break;
case GRID_ROM_SUBSYSTEM:
case GRID_ROM_SUBSYSTEM+1:
case GRID_ROM_SUBSYSTEM+2:
case GRID_ROM_SUBSYSTEM+3:
case GRID_ROM_SUBSYSTEM+4:
case GRID_ROM_SUBSYSTEM+5:
case GRID_ROM_SUBSYSTEM+6:
case GRID_ROM_SUBSYSTEM+7:
break;
case GRID_APPROM_SELECT:
dev->grid_rom_select = val;
break;
case GRID_APPROM_ENABLE:
dev->grid_rom_enable = val;
break;
case GRID_TURBO:
if ((dev->grid_turbo ^ val) & 1) {
dev->grid_turbo = val;
if (dev->grid_turbo)
cpu_dynamic_switch(cpu);
else
cpu_dynamic_switch(0); /* 286/6 */
}
break;
case GRID_EMS_PAGE_0:
case GRID_EMS_PAGE_1:
case GRID_EMS_PAGE_2:
case GRID_EMS_PAGE_3: {
uint32_t slot = (port >> 14) & 0x3;
if (dev->grid_ems_page[slot] == val)
break; // no change
dev->grid_ems_page[slot] = val;
if (dev->grid_high_enable & 0x1)
break; // XMS is enabled
grid_ems_update_mapping(dev, slot);
flushmmucache();
break;
}
case GRID_HIGH_ENABLE: {
if (((val ^ dev->grid_high_enable) & 0x1) == 0)
break; // no change
dev->grid_high_enable = val;
if (dev->grid_high_enable & 0x1) {
for (uint8_t i = 0; i < 4; i++)
mem_mapping_disable(&dev->grid_ems_mapping[i]);
mem_mapping_enable(&ram_high_mapping);
} else {
mem_mapping_disable(&ram_high_mapping);
for (uint8_t i = 0; i < 4; i++)
grid_ems_update_mapping(dev, i);
}
flushmmucache();
break;
}
default:
break;
}
}
static uint8_t grid_io_read(uint16_t port, void *priv) {
grid_t *dev = (grid_t *) priv;
switch (port) {
case GRID_426:
return dev->grid_426;
break;
case GRID_UNUSED_424:
return dev->grid_unused_424;
break;
case GRID_ROM_SUBSYSTEM:
return 0x99;
break;
case GRID_ROM_SUBSYSTEM+1:
case GRID_ROM_SUBSYSTEM+2:
case GRID_ROM_SUBSYSTEM+3:
case GRID_ROM_SUBSYSTEM+4:
case GRID_ROM_SUBSYSTEM+5:
case GRID_ROM_SUBSYSTEM+6:
case GRID_ROM_SUBSYSTEM+7:
break;
case GRID_APPROM_SELECT:
return dev->grid_rom_select;
case GRID_APPROM_ENABLE:
return dev->grid_rom_enable;
case GRID_TURBO:
return dev->grid_turbo;
case GRID_HIGH_ENABLE:
return dev->grid_high_enable;
case GRID_EMS_PAGE_0:
case GRID_EMS_PAGE_1:
case GRID_EMS_PAGE_2:
case GRID_EMS_PAGE_3: {
uint32_t slot = (port >> 14) & 0x3;
return dev->grid_ems_page[slot];
}
default:
break;
}
return 0xff;
}
static void *
grid_init(UNUSED(const device_t *info))
{
grid_t *dev = calloc(1, sizeof(grid_t));
io_sethandler(GRID_ROM_SUBSYSTEM, 0x0008, grid_io_read, NULL, NULL, grid_io_write, NULL, NULL, dev);
io_sethandler(GRID_UNUSED_424, 0x0001, grid_io_read, NULL, NULL, grid_io_write, NULL, NULL, dev);
io_sethandler(GRID_426, 0x0001, grid_io_read, NULL, NULL, grid_io_write, NULL, NULL, dev);
io_sethandler(GRID_APPROM_SELECT, 0x0001, grid_io_read, NULL, NULL, grid_io_write, NULL, NULL, dev);
io_sethandler(GRID_APPROM_ENABLE, 0x0001, grid_io_read, NULL, NULL, grid_io_write, NULL, NULL, dev);
io_sethandler(GRID_TURBO, 0x0001, grid_io_read, NULL, NULL, grid_io_write, NULL, NULL, dev);
dev->grid_turbo = 0x1;
io_sethandler(GRID_HIGH_ENABLE, 0x0001, grid_io_read, NULL, NULL, grid_io_write, NULL, NULL, dev);
io_sethandler(GRID_EMS_PAGE_0, 0x0001, grid_io_read, NULL, NULL, grid_io_write, NULL, NULL, dev);
io_sethandler(GRID_EMS_PAGE_1, 0x0001, grid_io_read, NULL, NULL, grid_io_write, NULL, NULL, dev);
io_sethandler(GRID_EMS_PAGE_2, 0x0001, grid_io_read, NULL, NULL, grid_io_write, NULL, NULL, dev);
io_sethandler(GRID_EMS_PAGE_3, 0x0001, grid_io_read, NULL, NULL, grid_io_write, NULL, NULL, dev);
dev->grid_high_enable = 1;
for (uint8_t slot = 0; slot < 4; slot++) {
dev->grid_ems_page[slot] = 0;
mem_mapping_add(&dev->grid_ems_mapping[slot], GRID_EMS_BASE + (slot << GRID_EMS_PAGE_SHIFT), GRID_EMS_PAGE_SIZE, grid_ems_mem_read8, grid_ems_mem_read16, NULL,
grid_ems_mem_write8, grid_ems_mem_write16, NULL, ram + GRID_EXTENDED_BASE + (slot << GRID_EMS_PAGE_SHIFT), MEM_MAPPING_EXTERNAL, dev);
mem_mapping_disable(&dev->grid_ems_mapping[slot]);
}
flushmmucache();
return dev;
}
static void grid_close(void *priv) {
grid_t *dev = (grid_t *) priv;
free(dev);
}
static void grid_reset(void *priv) {
grid_t *dev = (grid_t *) priv;
dev->grid_high_enable = 1;
mem_mapping_enable(&ram_high_mapping);
dev->grid_turbo = 0x1;
for (uint8_t slot = 0; slot < 4; slot++) {
dev->grid_ems_page[slot] = 0;
mem_mapping_disable(&dev->grid_ems_mapping[slot]);
}
flushmmucache();
dev->grid_unknown = 0;
dev->grid_unused_424 = 0;
dev->grid_426 = 0;
dev->grid_rom_enable = 0;
dev->grid_rom_select = 0;
}
const device_t grid1520_device = {
.name = "GRiDcase 1520 chipset",
.internal_name = "grid1520",
.flags = 0,
.local = 0,
.init = grid_init,
.close = grid_close,
.reset = grid_reset,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -594,8 +594,7 @@ headland_init(const device_t *info)
headland_t *dev;
int ht386 = 0;
dev = (headland_t *) malloc(sizeof(headland_t));
memset(dev, 0x00, sizeof(headland_t));
dev = (headland_t *) calloc(1, sizeof(headland_t));
dev->has_cri = (info->local & HEADLAND_HAS_CRI);
dev->has_sleep = (info->local & HEADLAND_HAS_SLEEP);
@@ -699,7 +698,7 @@ const device_t headland_gc10x_device = {
.init = headland_init,
.close = headland_close,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
@@ -713,7 +712,7 @@ const device_t headland_gc113_device = {
.init = headland_init,
.close = headland_close,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
@@ -727,7 +726,7 @@ const device_t headland_ht18a_device = {
.init = headland_init,
.close = headland_close,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
@@ -741,7 +740,7 @@ const device_t headland_ht18b_device = {
.init = headland_init,
.close = headland_close,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
@@ -755,7 +754,7 @@ const device_t headland_ht18c_device = {
.init = headland_init,
.close = headland_close,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
@@ -769,7 +768,7 @@ const device_t headland_ht21c_d_device = {
.init = headland_init,
.close = headland_close,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
@@ -783,7 +782,7 @@ const device_t headland_ht21e_device = {
.init = headland_init,
.close = headland_close,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL

View File

@@ -381,8 +381,7 @@ ims8848_close(void *priv)
static void *
ims8848_init(UNUSED(const device_t *info))
{
ims8848_t *dev = (ims8848_t *) malloc(sizeof(ims8848_t));
memset(dev, 0, sizeof(ims8848_t));
ims8848_t *dev = (ims8848_t *) calloc(1, sizeof(ims8848_t));
device_add(&port_92_device);
@@ -416,7 +415,7 @@ const device_t ims8848_device = {
.init = ims8848_init,
.close = ims8848_close,
.reset = ims8848_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL

View File

@@ -533,8 +533,7 @@ i420ex_speed_changed(void *priv)
static void *
i420ex_init(const device_t *info)
{
i420ex_t *dev = (i420ex_t *) malloc(sizeof(i420ex_t));
memset(dev, 0, sizeof(i420ex_t));
i420ex_t *dev = (i420ex_t *) calloc(1, sizeof(i420ex_t));
dev->smram = smram_add();
@@ -579,7 +578,7 @@ const device_t i420ex_device = {
.init = i420ex_init,
.close = i420ex_close,
.reset = i420ex_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = i420ex_speed_changed,
.force_redraw = NULL,
.config = NULL
@@ -593,7 +592,7 @@ const device_t i420ex_ide_device = {
.init = i420ex_init,
.close = i420ex_close,
.reset = i420ex_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = i420ex_speed_changed,
.force_redraw = NULL,
.config = NULL

View File

@@ -493,16 +493,40 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case 0x52: /* Cache Control Register */
switch (dev->type) {
default:
/*
420TX/ZX:
Bit 7-6: 0, 0 = 64 kB,
0, 1 = 128 kB,
1, 0 = 256 kB,
1, 1 = 512 kB.
Bit 5: 1 = L2 cache present, 0 = L2 cache absent.
Bit 1: 1 = Write back cache, 0 = write through cache.
Bit 0: 1 = L2 cache enable, 0 = L2 cache disable.
*/
case INTEL_420TX:
case INTEL_420ZX:
case INTEL_430NX:
regs[0x52] = (regs[0x52] & 0xe0) | (val & 0x1f);
cpu_cache_ext_enabled = val & 0x01;
cpu_update_waitstates();
break;
case INTEL_430LX:
regs[0x52] = (regs[0x52] & 0xe0) | (val & 0x1b);
cpu_cache_ext_enabled = val & 0x01;
cpu_update_waitstates();
break;
case INTEL_430FX:
case INTEL_430VX:
case INTEL_430TX:
regs[0x52] = (val & 0xfb);
regs[0x52] = (regs[0x52] & 0x04) | (val & 0xfb);
cpu_cache_ext_enabled = ((val & 0x03) == 0x01);
cpu_update_waitstates();
break;
case INTEL_430NX:
case INTEL_430HX:
regs[0x52] = val;
cpu_cache_ext_enabled = ((val & 0x03) == 0x01);
cpu_update_waitstates();
break;
case INTEL_440FX:
regs[0x52] = val;
break;
@@ -989,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;
@@ -1017,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)
@@ -1553,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);
@@ -1584,11 +1613,9 @@ i4x0_close(void *priv)
static void *
i4x0_init(const device_t *info)
{
i4x0_t *dev = (i4x0_t *) malloc(sizeof(i4x0_t));
i4x0_t *dev = (i4x0_t *) calloc(1, sizeof(i4x0_t));
uint8_t *regs;
memset(dev, 0, sizeof(i4x0_t));
dev->smram_low = smram_add();
dev->smram_high = smram_add();
@@ -1630,11 +1657,16 @@ i4x0_init(const device_t *info)
0x00 = None, 0x01 = 64 kB, 0x41 = 128 kB, 0x81 = 256 kB, 0xc1 = 512 kB,
If bit 0 is set, then if bit 2 is also set, the cache is write back,
otherwise it's write through. */
regs[0x52] = 0xc3; /* 512 kB writeback cache */
regs[0x52] = 0xe0; /* 512 kB writeback cache */
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;
@@ -1943,7 +1975,7 @@ const device_t i420tx_device = {
.init = i4x0_init,
.close = i4x0_close,
.reset = i4x0_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
@@ -1957,7 +1989,7 @@ const device_t i420zx_device = {
.init = i4x0_init,
.close = i4x0_close,
.reset = i4x0_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
@@ -1971,7 +2003,7 @@ const device_t i430lx_device = {
.init = i4x0_init,
.close = i4x0_close,
.reset = i4x0_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
@@ -1985,7 +2017,7 @@ const device_t i430nx_device = {
.init = i4x0_init,
.close = i4x0_close,
.reset = i4x0_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
@@ -1999,7 +2031,7 @@ const device_t i430fx_device = {
.init = i4x0_init,
.close = i4x0_close,
.reset = i4x0_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
@@ -2013,7 +2045,7 @@ const device_t i430fx_rev02_device = {
.init = i4x0_init,
.close = i4x0_close,
.reset = i4x0_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
@@ -2027,7 +2059,7 @@ const device_t i430hx_device = {
.init = i4x0_init,
.close = i4x0_close,
.reset = i4x0_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
@@ -2041,7 +2073,7 @@ const device_t i430vx_device = {
.init = i4x0_init,
.close = i4x0_close,
.reset = i4x0_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
@@ -2055,7 +2087,7 @@ const device_t i430tx_device = {
.init = i4x0_init,
.close = i4x0_close,
.reset = i4x0_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
@@ -2069,7 +2101,7 @@ const device_t i440fx_device = {
.init = i4x0_init,
.close = i4x0_close,
.reset = i4x0_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
@@ -2083,7 +2115,7 @@ const device_t i440lx_device = {
.init = i4x0_init,
.close = i4x0_close,
.reset = i4x0_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
@@ -2097,7 +2129,7 @@ const device_t i440ex_device = {
.init = i4x0_init,
.close = i4x0_close,
.reset = i4x0_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
@@ -2111,7 +2143,7 @@ const device_t i440bx_device = {
.init = i4x0_init,
.close = i4x0_close,
.reset = i4x0_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
@@ -2125,7 +2157,7 @@ const device_t i440bx_no_agp_device = {
.init = i4x0_init,
.close = i4x0_close,
.reset = i4x0_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
@@ -2139,7 +2171,7 @@ const device_t i440gx_device = {
.init = i4x0_init,
.close = i4x0_close,
.reset = i4x0_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
@@ -2153,7 +2185,7 @@ const device_t i440zx_device = {
.init = i4x0_init,
.close = i4x0_close,
.reset = i4x0_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL

View File

@@ -171,8 +171,7 @@ intel_82335_close(void *priv)
static void *
intel_82335_init(UNUSED(const device_t *info))
{
intel_82335_t *dev = (intel_82335_t *) malloc(sizeof(intel_82335_t));
memset(dev, 0, sizeof(intel_82335_t));
intel_82335_t *dev = (intel_82335_t *) calloc(1, sizeof(intel_82335_t));
memset(dev->regs, 0, sizeof(dev->regs));
@@ -209,7 +208,7 @@ const device_t intel_82335_device = {
.init = intel_82335_init,
.close = intel_82335_close,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL

View File

@@ -799,8 +799,8 @@ i450kx_close(void *priv)
static void *
i450kx_init(UNUSED(const device_t *info))
{
i450kx_t *dev = (i450kx_t *) malloc(sizeof(i450kx_t));
memset(dev, 0, sizeof(i450kx_t));
i450kx_t *dev = (i450kx_t *) calloc(1, sizeof(i450kx_t));
pci_add_card(PCI_ADD_NORTHBRIDGE, pb_read, pb_write, dev, &dev->pb_slot); /* Device 19h: Intel 450KX PCI Bridge PB */
pci_add_card(PCI_ADD_NORTHBRIDGE_SEC, mc_read, mc_write, dev, &dev->mc_slot); /* Device 14h: Intel 450KX Memory Controller MC */
@@ -824,7 +824,7 @@ const device_t i450kx_device = {
.init = i450kx_init,
.close = i450kx_close,
.reset = i450kx_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL

View File

@@ -47,6 +47,7 @@
#include <86box/hdc_ide.h>
#include <86box/hdc_ide_sff8038i.h>
#include <86box/usb.h>
#include <86box/lpt.h>
#include <86box/machine.h>
#include <86box/smbus.h>
#include <86box/chipset.h>
@@ -59,7 +60,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 +67,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 +156,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 +172,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 +195,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 +472,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)
@@ -599,14 +611,21 @@ piix_write(int func, int addr, uint8_t val, void *priv)
pci_set_mirq_routing(PCI_MIRQ0 + (addr & 0x01), val & 0xf);
if (dev->type == 3) {
if (val & 0x20)
sff_set_irq_mode(dev->bm[1], IRQ_MODE_MIRQ_0);
else
sff_set_irq_mode(dev->bm[1], IRQ_MODE_LEGACY);
else
sff_set_irq_mode(dev->bm[1], IRQ_MODE_MIRQ_0);
}
piix_log("MIRQ%i is %s\n", addr & 0x01, (val & 0x20) ? "disabled" : "enabled");
}
break;
case 0x76:
if (dev->type > 1)
fregs[addr] = val & 0x87;
else if (dev->type <= 4)
fregs[addr] = val & 0x8f;
if ((dev->type == 1) && machine_has_jumpered_ecp_dma(machine, MACHINE_DMA_USE_MBDMA))
lpt1_dma(((val & 0x08) || ((val & 0x07) == 0x04)) ? 0xff : (val & 0x07));
break;
case 0x77:
if (dev->type > 1)
fregs[addr] = val & 0x87;
@@ -738,6 +757,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 +768,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 +948,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 +1200,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 +1218,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 +1234,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 +1350,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
@@ -1538,8 +1550,7 @@ piix_speed_changed(void *priv)
static void *
piix_init(const device_t *info)
{
piix_t *dev = (piix_t *) malloc(sizeof(piix_t));
memset(dev, 0, sizeof(piix_t));
piix_t *dev = (piix_t *) calloc(1, sizeof(piix_t));
dev->type = info->local & 0x0f;
/* If (dev->type == 4) and (dev->rev & 0x08), then this is PIIX4E. */
@@ -1618,47 +1629,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
@@ -1674,7 +1654,7 @@ const device_t piix_device = {
.init = piix_init,
.close = piix_close,
.reset = piix_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = piix_speed_changed,
.force_redraw = NULL,
.config = NULL
@@ -1688,7 +1668,7 @@ const device_t piix_no_mirq_device = {
.init = piix_init,
.close = piix_close,
.reset = piix_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = piix_speed_changed,
.force_redraw = NULL,
.config = NULL
@@ -1702,7 +1682,7 @@ const device_t piix_rev02_device = {
.init = piix_init,
.close = piix_close,
.reset = piix_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = piix_speed_changed,
.force_redraw = NULL,
.config = NULL
@@ -1716,7 +1696,7 @@ const device_t piix3_device = {
.init = piix_init,
.close = piix_close,
.reset = piix_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = piix_speed_changed,
.force_redraw = NULL,
.config = NULL
@@ -1730,7 +1710,7 @@ const device_t piix3_ioapic_device = {
.init = piix_init,
.close = piix_close,
.reset = piix_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = piix_speed_changed,
.force_redraw = NULL,
.config = NULL
@@ -1744,7 +1724,7 @@ const device_t piix4_device = {
.init = piix_init,
.close = piix_close,
.reset = piix_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = piix_speed_changed,
.force_redraw = NULL,
.config = NULL
@@ -1758,7 +1738,7 @@ const device_t piix4e_device = {
.init = piix_init,
.close = piix_close,
.reset = piix_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = piix_speed_changed,
.force_redraw = NULL,
.config = NULL
@@ -1772,7 +1752,7 @@ const device_t slc90e66_device = {
.init = piix_init,
.close = piix_close,
.reset = piix_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = piix_speed_changed,
.force_redraw = NULL,
.config = NULL

View File

@@ -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:
@@ -508,8 +524,7 @@ sio_speed_changed(void *priv)
static void *
sio_init(const device_t *info)
{
sio_t *dev = (sio_t *) malloc(sizeof(sio_t));
memset(dev, 0, sizeof(sio_t));
sio_t *dev = (sio_t *) calloc(1, sizeof(sio_t));
pci_add_card(PCI_ADD_SOUTHBRIDGE, sio_read, sio_write, dev, &dev->pci_slot);
@@ -568,7 +583,7 @@ const device_t sio_device = {
.init = sio_init,
.close = sio_close,
.reset = sio_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = sio_speed_changed,
.force_redraw = NULL,
.config = NULL
@@ -582,7 +597,7 @@ const device_t sio_zb_device = {
.init = sio_init,
.close = sio_close,
.reset = sio_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = sio_speed_changed,
.force_redraw = NULL,
.config = NULL

131
src/chipset/isa486c.c Normal file
View 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
};

473
src/chipset/laserxt.c Normal file
View File

@@ -0,0 +1,473 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Implementation of the VTech LaserXT chipset.
*
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com>
* Jasmine Iwanek, <jriwanek@gmail.com>
*
* Copyright 2008-2025 Sarah Walker.
* Copyright 2016-2025 Miran Grca.
* Copyright 2017-2025 Fred N. van Kempen.
* Copyright 2025 Jasmine Iwanek.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/io.h>
#include <86box/mem.h>
#include <86box/nmi.h>
#include <86box/timer.h>
#include <86box/pit.h>
#include <86box/rom.h>
#include <86box/machine.h>
#include <86box/device.h>
#include <86box/timer.h>
#include <86box/fdd.h>
#include <86box/fdc.h>
#include <86box/fdc_ext.h>
#include <86box/gameport.h>
#include <86box/keyboard.h>
#include <86box/plat_unused.h>
#define EMS_TOTAL_MAX 0x00100000
typedef struct
{
uint8_t page;
uint8_t ctrl;
uint32_t phys;
uint32_t virt;
mem_mapping_t mapping;
uint8_t *ram;
void *parent;
} lxt_ems_t;
typedef struct
{
int ems_base_idx;
lxt_ems_t ems[4];
uint16_t io_base;
uint32_t base;
uint32_t mem_size;
uint8_t *ram;
void *parent;
} lxt_ems_board_t;
typedef struct
{
int is_lxt3;
lxt_ems_board_t *ems_boards[2];
} lxt_t;
static void
ems_update_virt(lxt_ems_t *dev, uint8_t new_page)
{
lxt_ems_board_t *board = (lxt_ems_board_t *) dev->parent;
lxt_t *lxt = (lxt_t *) board->parent;
dev->page = new_page;
if (new_page & 0x80) {
if (lxt->is_lxt3) {
/* Point invalid pages at 1 MB which is outside the maximum. */
if ((new_page & 0x7f) >= 0x40)
dev->virt = EMS_TOTAL_MAX;
else
dev->virt = ((new_page & 0x7f) << 14);
} else
dev->virt = ((new_page & 0x0f) << 14) + ((new_page & 0x40) << 12);
if (dev->virt >= board->mem_size)
dev->virt = EMS_TOTAL_MAX;
} else
dev->virt = EMS_TOTAL_MAX;
dev->ram = board->ram + dev->virt;
if ((new_page & 0x80) && (dev->virt != EMS_TOTAL_MAX)) {
mem_mapping_enable(&dev->mapping);
mem_mapping_set_exec(&dev->mapping, dev->ram);
mem_mapping_set_p(&dev->mapping, dev->ram);
} else
mem_mapping_disable(&dev->mapping);
flushmmucache();
}
static void
lxt_ems_out(uint16_t port, uint8_t val, void *priv)
{
lxt_ems_board_t *dev = (lxt_ems_board_t *) priv;
uint8_t reg = port >> 14;
uint32_t saddrs[8] = { 0xc4000, 0xc8000, 0xcc000, 0xd0000,
0xd4000, 0xd8000, 0xdc000, 0xe0000 };
uint32_t saddr;
if (port & 0x0001) {
dev->ems[reg].ctrl = val;
if (reg < 0x03) {
dev->ems_base_idx = (dev->ems_base_idx & ~(0x04 >> (2 - reg))) |
((dev->ems[reg].ctrl & 0x80) >> (7 - reg));
saddr = saddrs[dev->ems_base_idx];
for (uint8_t i = 0; i < 4; i++) {
uint32_t base = saddr + (i * 0x4000);
mem_mapping_set_addr(&dev->ems[i].mapping, base, 0x4000);
if (!(dev->ems[i].page & 0x80) || (dev->ems[i].virt == EMS_TOTAL_MAX))
mem_mapping_disable(&dev->ems[i].mapping);
}
}
flushmmucache();
} else if (!(port & 0x0001)) {
dev->ems[reg].page = val;
ems_update_virt(&dev->ems[reg], val);
}
}
static uint8_t
lxt_ems_in(uint16_t port, void *priv)
{
lxt_ems_board_t *dev = (lxt_ems_board_t *) priv;
uint8_t reg = port >> 14;
uint8_t ret = 0xff;
if (port & 0x0001)
ret = dev->ems[reg].ctrl;
else
ret = dev->ems[reg].page;
return ret;
}
static void
lxt_ems_write(uint32_t addr, uint8_t val, void *priv)
{
uint8_t *mem = (uint8_t *) priv;
mem[addr & 0x3fff] = val;
}
static void
lxt_ems_writew(uint32_t addr, uint16_t val, void *priv)
{
uint8_t *mem = (uint8_t *) priv;
*(uint16_t *) &(mem[addr & 0x3fff]) = val;
}
static uint8_t
lxt_ems_read(uint32_t addr, void *priv)
{
uint8_t *mem = (uint8_t *) priv;
uint8_t ret = 0xff;
ret = mem[addr & 0x3fff];
return ret;
}
static uint16_t
lxt_ems_readw(uint32_t addr, void *priv)
{
uint8_t *mem = (uint8_t *) priv;
uint16_t ret = 0xff;
ret = *(uint16_t *) &(mem[addr & 0x3fff]);
return ret;
}
static lxt_ems_board_t *
lxt_ems_init(lxt_t *parent, int en, uint16_t io, uint32_t mem)
{
lxt_ems_board_t *dev = (lxt_ems_board_t *) calloc(1, sizeof(lxt_ems_board_t));
if (en) {
dev->parent = parent;
if (io != 0x0000) {
io_sethandler(io , 0x0002, lxt_ems_in, NULL, NULL, lxt_ems_out, NULL, NULL, dev);
io_sethandler(io | 0x4000, 0x0002, lxt_ems_in, NULL, NULL, lxt_ems_out, NULL, NULL, dev);
io_sethandler(io | 0x8000, 0x0002, lxt_ems_in, NULL, NULL, lxt_ems_out, NULL, NULL, dev);
io_sethandler(io | 0xc000, 0x0002, lxt_ems_in, NULL, NULL, lxt_ems_out, NULL, NULL, dev);
}
dev->ram = (uint8_t *) calloc(mem, sizeof(uint8_t));
dev->mem_size = mem;
for (uint8_t i = 0; i < 4; i++) {
uint8_t *ptr = dev->ram + (i << 14);
if (parent->is_lxt3)
mem_mapping_add(&dev->ems[i].mapping, 0xe0000 + (i << 14), 0x4000,
lxt_ems_read, lxt_ems_readw, NULL,
lxt_ems_write, lxt_ems_writew, NULL,
ptr, 0, ptr);
else
mem_mapping_add(&dev->ems[i].mapping, 0xe0000 + (i << 14), 0x4000,
lxt_ems_read, NULL, NULL,
lxt_ems_write, NULL, NULL,
ptr, 0, ptr);
mem_mapping_disable(&dev->ems[i].mapping);
dev->ems[i].page = 0x7f;
dev->ems[i].ctrl = (i == 3) ? 0x00 : 0x80;
dev->ems[i].parent = dev;
ems_update_virt(&(dev->ems[i]), dev->ems[i].page);
}
}
return dev;
}
static void
lxt_close(void *priv)
{
lxt_t *dev = (lxt_t *) priv;
int ems_boards = (1 - dev->is_lxt3) + 1;
for (int i = 0; i < ems_boards; i++)
if (dev->ems_boards[i] != NULL) {
if (dev->ems_boards[i]->ram != NULL)
free(dev->ems_boards[i]->ram);
free(dev->ems_boards[i]);
}
free(dev);
}
static void *
lxt_init(const device_t *info)
{
lxt_t * dev = (lxt_t *) calloc(1, sizeof(lxt_t));
int ems_boards = (1 - info->local) + 1;
int ems_en[2] = { 0 };
uint16_t ems_io[2] = { 0 };
uint32_t ems_mem[2] = { 0 };
char conf_str[512] = { 0 };
dev->is_lxt3 = info->local;
for (int i = 0; i < ems_boards; i++) {
sprintf(conf_str, "ems_%i_enable", i + 1);
ems_en[i] = device_get_config_int(conf_str);
sprintf(conf_str, "ems_%i_base", i + 1);
ems_io[i] = device_get_config_hex16(conf_str);
sprintf(conf_str, "ems_%i_mem_size", i + 1);
ems_mem[i] = device_get_config_int(conf_str) << 10;
dev->ems_boards[i] = lxt_ems_init(dev, ems_en[i], ems_io[i], ems_mem[i]);
}
mem_set_mem_state(0x0c0000, 0x40000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
return dev;
}
static const device_config_t laserxt_config[] = {
{
.name = "ems_1_base",
.description = "EMS 1 Address",
.type = CONFIG_HEX16,
.default_string = NULL,
.default_int = 0,
.file_filter = NULL,
.spinner = { 0 },
.selection = {
{ .description = "Disabled", .value = 0 },
{ .description = "0x208", .value = 0x208 },
{ .description = "0x218", .value = 0x218 },
{ .description = "0x258", .value = 0x258 },
{ .description = "0x268", .value = 0x268 },
{ .description = "0x2A8", .value = 0x2a8 },
{ .description = "0x2B8", .value = 0x2b8 },
{ .description = "0x2E8", .value = 0x2e8 },
{ .description = "" }
},
.bios = { { 0 } }
},
{
.name = "ems_2_base",
.description = "EMS 2 Address",
.type = CONFIG_HEX16,
.default_string = NULL,
.default_int = 0,
.file_filter = NULL,
.spinner = { 0 },
.selection = {
{ .description = "Disabled", .value = 0 },
{ .description = "0x208", .value = 0x208 },
{ .description = "0x218", .value = 0x218 },
{ .description = "0x258", .value = 0x258 },
{ .description = "0x268", .value = 0x268 },
{ .description = "0x2A8", .value = 0x2a8 },
{ .description = "0x2B8", .value = 0x2b8 },
{ .description = "0x2E8", .value = 0x2e8 },
{ .description = "" }
},
.bios = { { 0 } }
},
{
.name = "ems_1_mem_size",
.description = "EMS 1 Memory Size",
.type = CONFIG_SPINNER,
.default_string = NULL,
.default_int = 0,
.file_filter = NULL,
.spinner = {
.min = 0,
.max = 512,
.step = 32
},
.selection = { { 0 } },
.bios = { { 0 } }
},
{
.name = "ems_2_mem_size",
.description = "EMS 2 Memory Size",
.type = CONFIG_SPINNER,
.default_string = NULL,
.default_int = 0,
.file_filter = NULL,
.spinner = {
.min = 0,
.max = 512,
.step = 32
},
.selection = { { 0 } },
.bios = { { 0 } }
},
{
.name = "ems_1_enable",
.description = "Enable EMS 1",
.type = CONFIG_BINARY,
.default_string = NULL,
.default_int = 0,
.file_filter = NULL,
.spinner = { 0 },
.selection = { { 0 } },
.bios = { { 0 } }
},
{
.name = "ems_2_enable",
.description = "Enable EMS 2",
.type = CONFIG_BINARY,
.default_string = NULL,
.default_int = 0,
.file_filter = NULL,
.spinner = { 0 },
.selection = { { 0 } },
.bios = { { 0 } }
},
{ .name = "", .description = "", .type = CONFIG_END }
};
const device_t laserxt_device = {
.name = "VTech Laser Turbo XT",
.internal_name = "laserxt",
.flags = 0,
.local = 0,
.init = lxt_init,
.close = lxt_close,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = laserxt_config
};
static const device_config_t lxt3_config[] = {
{
.name = "ems_1_base",
.description = "EMS Address",
.type = CONFIG_HEX16,
.default_string = NULL,
.default_int = 0,
.file_filter = NULL,
.spinner = { 0 },
.selection = {
{ .description = "Disabled", .value = 0 },
{ .description = "0x208", .value = 0x208 },
{ .description = "0x218", .value = 0x218 },
{ .description = "0x258", .value = 0x258 },
{ .description = "0x268", .value = 0x268 },
{ .description = "0x2A8", .value = 0x2a8 },
{ .description = "0x2B8", .value = 0x2b8 },
{ .description = "0x2E8", .value = 0x2e8 },
{ .description = "" }
},
.bios = { { 0 } }
},
{
.name = "ems_1_mem_size",
.description = "EMS Memory Size",
.type = CONFIG_SPINNER,
.default_string = NULL,
.default_int = 0,
.file_filter = NULL,
.spinner = {
.min = 0,
.max = 1024,
.step = 32
},
.selection = { { 0 } },
.bios = { { 0 } }
},
{
.name = "ems_1_enable",
.description = "Enable EMS",
.type = CONFIG_BINARY,
.default_string = NULL,
.default_int = 0,
.file_filter = NULL,
.spinner = { 0 },
.selection = { { 0 } },
.bios = { { 0 } }
},
{ .name = "", .description = "", .type = CONFIG_END }
};
const device_t lxt3_device = {
.name = "VTech Laser Turbo XT",
.internal_name = "laserxt",
.flags = 0,
.local = 1,
.init = lxt_init,
.close = lxt_close,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = lxt3_config
};

File diff suppressed because it is too large Load Diff

View File

@@ -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;
@@ -134,8 +132,7 @@ olivetti_eva_close(void *priv)
static void *
olivetti_eva_init(UNUSED(const device_t *info))
{
olivetti_eva_t *dev = (olivetti_eva_t *) malloc(sizeof(olivetti_eva_t));
memset(dev, 0, sizeof(olivetti_eva_t));
olivetti_eva_t *dev = (olivetti_eva_t *) calloc(1, sizeof(olivetti_eva_t));
/* GA98 registers */
dev->reg_065 = 0x00;
@@ -144,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);
@@ -153,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;
}
@@ -171,7 +161,7 @@ const device_t olivetti_eva_device = {
.init = olivetti_eva_init,
.close = olivetti_eva_close,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL

View File

@@ -16,6 +16,7 @@
* Copyright 2021 Tiseno100.
* Copyright 2021 Miran Grca.
*/
#include <math.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
@@ -31,6 +32,7 @@
#include <86box/mem.h>
#include <86box/plat_fallthrough.h>
#include <86box/plat_unused.h>
#include <86box/port_92.h>
#include <86box/chipset.h>
#ifdef ENABLE_OPTI283_LOG
@@ -157,7 +159,20 @@ opti283_shadow_recalc(opti283_t *dev)
rom = dev->regs[0x11] & (1 << ((i >> 2) + 4));
opti283_log("OPTI 283: %i/%08X: %i, %i, %i\n", i, base, (i >= 4) ? (1 << (i - 4)) : (1 << (i + 4)), (1 << (i >> 2)), (1 << ((i >> 2) + 4)));
if (sh_enable && rom) {
if (sh_copy) {
if (base >= 0x000e0000)
shadowbios_write |= 1;
if (base >= 0x000d0000)
dev->shadow_high |= 1;
if (base >= 0xe0000) {
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
opti283_log("OPTI 283: %08X-%08X READ_EXTANY, WRITE_INTERNAL\n", base, base + 0x3fff);
} else {
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL);
opti283_log("OPTI 283: %08X-%08X READ_EXTERNAL, WRITE_INTERNAL\n", base, base + 0x3fff);
}
} else if (sh_enable && rom) {
if (base >= 0x000e0000)
shadowbios |= 1;
if (base >= 0x000d0000)
@@ -170,13 +185,8 @@ opti283_shadow_recalc(opti283_t *dev)
if (base >= 0x000e0000)
shadowbios_write |= 1;
if (sh_copy) {
mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
opti283_log("OPTI 283: %08X-%08X READ_INTERNAL, WRITE_INTERNAL\n", base, base + 0x3fff);
} else {
mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL);
opti283_log("OPTI 283: %08X-%08X READ_INTERNAL, WRITE_EXTERNAL\n", base, base + 0x3fff);
}
mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
opti283_log("OPTI 283: %08X-%08X READ_INTERNAL, WRITE_INTERNAL\n", base, base + 0x3fff);
}
} else {
if (base >= 0xe0000) {
@@ -215,34 +225,53 @@ opti283_write(uint16_t addr, uint8_t val, void *priv)
opti283_t *dev = (opti283_t *) priv;
switch (addr) {
default:
break;
case 0x22:
dev->index = val;
break;
case 0x23:
if (dev->index == 0x01)
dev->regs[dev->index] = val;
break;
case 0x24:
opti283_log("OPTi 283: dev->regs[%02x] = %02x\n", dev->index, val);
switch (dev->index) {
case 0x10:
dev->regs[dev->index] = val;
default:
break;
case 0x14:
case 0x10:
dev->regs[dev->index] = (dev->regs[dev->index] & 0x80) | (val & 0x7f);
break;
case 0x14: {
double bus_clk;
switch (val & 0x01) {
default:
case 0x00:
bus_clk = cpu_busspeed / 6.0;
break;
case 0x01:
bus_clk = cpu_busspeed / 4.0;
break;
}
cpu_set_isa_speed((int) round(bus_clk));
reset_on_hlt = !!(val & 0x40);
fallthrough;
}
case 0x11:
case 0x12:
case 0x13:
dev->regs[dev->index] = val;
opti283_shadow_recalc(dev);
break;
default:
break;
}
break;
default:
dev->index = 0xff;
break;
}
}
@@ -250,11 +279,17 @@ opti283_write(uint16_t addr, uint8_t val, void *priv)
static uint8_t
opti283_read(uint16_t addr, void *priv)
{
const opti283_t *dev = (opti283_t *) priv;
uint8_t ret = 0xff;
opti283_t *dev = (opti283_t *) priv;
uint8_t ret = 0xff;
if (addr == 0x24)
if ((addr == 0x23) && (dev->index == 0x01))
ret = dev->regs[dev->index];
else if (addr == 0x24) {
if ((dev->index >= 0x10) && (dev->index <= 0x14))
ret = dev->regs[dev->index];
dev->index = 0xff;
}
return ret;
}
@@ -270,10 +305,10 @@ opti283_close(void *priv)
static void *
opti283_init(UNUSED(const device_t *info))
{
opti283_t *dev = (opti283_t *) malloc(sizeof(opti283_t));
memset(dev, 0x00, sizeof(opti283_t));
opti283_t *dev = (opti283_t *) calloc(1, sizeof(opti283_t));
io_sethandler(0x0022, 0x0001, opti283_read, NULL, NULL, opti283_write, NULL, NULL, dev);
io_sethandler(0x0023, 0x0001, opti283_read, NULL, NULL, opti283_write, NULL, NULL, dev);
io_sethandler(0x0024, 0x0001, opti283_read, NULL, NULL, opti283_write, NULL, NULL, dev);
dev->regs[0x10] = 0x3f;
@@ -296,6 +331,10 @@ opti283_init(UNUSED(const device_t *info))
opti283_shadow_recalc(dev);
cpu_set_isa_speed((int) round(cpu_busspeed / 6.0));
device_add(&port_92_device);
return dev;
}
@@ -307,7 +346,7 @@ const device_t opti283_device = {
.init = opti283_init,
.close = opti283_close,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL

View File

@@ -138,8 +138,7 @@ opti291_close(void *priv)
static void *
opti291_init(UNUSED(const device_t *info))
{
opti291_t *dev = (opti291_t *) malloc(sizeof(opti291_t));
memset(dev, 0, sizeof(opti291_t));
opti291_t *dev = (opti291_t *) calloc(1, sizeof(opti291_t));
io_sethandler(0x022, 0x0001, opti291_read, NULL, NULL, opti291_write, NULL, NULL, dev);
io_sethandler(0x024, 0x0001, opti291_read, NULL, NULL, opti291_write, NULL, NULL, dev);
@@ -161,7 +160,7 @@ const device_t opti291_device = {
.init = opti291_init,
.close = opti291_close,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL

View File

@@ -54,10 +54,34 @@ typedef struct mem_remapping_t {
} mem_remapping_t;
typedef struct opti391_t {
uint8_t type;
uint8_t reg_base;
uint8_t min_reg;
uint8_t max_reg;
uint16_t shadowed;
uint16_t old_start;
uint8_t index;
uint8_t regs[256];
} opti391_t;
static void
opti391_recalcremap(opti391_t *dev)
{
if (dev->type < 2) {
if ((mem_size > 8192) || (dev->shadowed & 0x0ff0) ||
!(dev->regs[0x01] & 0x0f) || !(dev->regs[0x01] & 0x10)) {
mem_remap_top_ex(0, dev->old_start);
dev->old_start = 1024;
} else {
mem_remap_top_ex(0, dev->old_start);
dev->old_start = (dev->regs[0x01] & 0x0f) * 1024;
mem_remap_top_ex(-256, dev->old_start);
}
}
}
static void
opti391_shadow_recalc(opti391_t *dev)
{
@@ -70,24 +94,25 @@ opti391_shadow_recalc(opti391_t *dev)
shadowbios = shadowbios_write = 0;
/* F0000-FFFFF */
sh_enable = !(dev->regs[0x22] & 0x80);
sh_enable = (dev->regs[0x02] & 0x80);
if (sh_enable)
mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
else
mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED);
dev->shadowed |= 0xf000;
sh_write_internal = (dev->regs[0x26] & 0x40);
sh_write_internal = (dev->regs[0x06] & 0x40);
/* D0000-EFFFF */
for (uint8_t i = 0; i < 8; i++) {
base = 0xd0000 + (i << 14);
if (base >= 0xe0000) {
sh_master = (dev->regs[0x22] & 0x40);
sh_wp = (dev->regs[0x22] & 0x10);
sh_master = (dev->regs[0x02] & 0x20);
sh_wp = (dev->regs[0x02] & 0x08);
} else {
sh_master = (dev->regs[0x22] & 0x20);
sh_wp = (dev->regs[0x22] & 0x08);
sh_master = (dev->regs[0x02] & 0x40);
sh_wp = (dev->regs[0x02] & 0x10);
}
sh_enable = dev->regs[0x23] & (1 << i);
sh_enable = dev->regs[0x03] & (1 << i);
if (sh_master) {
if (sh_enable) {
@@ -95,22 +120,29 @@ opti391_shadow_recalc(opti391_t *dev)
mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED);
else
mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
} else if (sh_write_internal)
dev->shadowed |= (1 << (i + 4));
} else if (sh_write_internal) {
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
else
dev->shadowed |= (1 << (i + 4));
} else {
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
} else if (sh_write_internal)
dev->shadowed &= ~(1 << (i + 4));
}
} else if (sh_write_internal) {
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
else
dev->shadowed |= (1 << (i + 4));
} else {
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
dev->shadowed &= ~(1 << (i + 4));
}
}
/* C0000-CFFFF */
sh_master = !(dev->regs[0x26] & 0x10);
sh_wp = (dev->regs[0x26] & 0x20);
sh_master = (dev->regs[0x06] & 0x10); /* OPTi 391 datasheet erratum! */
sh_wp = (dev->regs[0x06] & 0x20);
for (uint8_t i = 0; i < 4; i++) {
base = 0xc0000 + (i << 14);
sh_enable = dev->regs[0x26] & (1 << i);
sh_enable = dev->regs[0x06] & (1 << i);
if (sh_master) {
if (sh_enable) {
@@ -118,15 +150,24 @@ opti391_shadow_recalc(opti391_t *dev)
mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED);
else
mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
} else if (sh_write_internal)
dev->shadowed |= (1 << i);
} else if (sh_write_internal) {
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
else
dev->shadowed |= (1 << i);
} else {
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
} else if (sh_write_internal)
dev->shadowed &= ~(1 << i);
}
} else if (sh_write_internal) {
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
else
dev->shadowed |= (1 << i);
} else {
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
dev->shadowed &= ~(1 << i);
}
}
opti391_recalcremap(dev);
}
static void
@@ -134,7 +175,12 @@ opti391_write(uint16_t addr, uint8_t val, void *priv)
{
opti391_t *dev = (opti391_t *) priv;
opti391_log("[W] %04X = %02X\n", addr, val);
switch (addr) {
default:
break;
case 0x22:
dev->index = val;
break;
@@ -142,35 +188,92 @@ opti391_write(uint16_t addr, uint8_t val, void *priv)
case 0x24:
opti391_log("OPTi 391: dev->regs[%02x] = %02x\n", dev->index, val);
switch (dev->index) {
case 0x20:
dev->regs[dev->index] = (dev->regs[dev->index] & 0xc0) | (val & 0x3f);
if ((dev->index <= 0x01) && (dev->type < 2)) switch (dev->index) {
case 0x00:
if (!(dev->regs[0x10] & 0x20) && (val & 0x20)) {
softresetx86(); /* Pulse reset! */
cpu_set_edx();
flushmmucache();
}
dev->regs[dev->index + 0x10] = val;
break;
case 0x21:
case 0x24:
case 0x25:
case 0x27:
case 0x28:
case 0x29:
case 0x2a:
case 0x2b:
dev->regs[dev->index] = val;
case 0x01:
dev->regs[dev->index + 0x10] = val;
reset_on_hlt = !!(val & 0x02);
break;
case 0x22:
case 0x23:
case 0x26:
dev->regs[dev->index] = val;
opti391_shadow_recalc(dev);
break;
} else switch (dev->index - dev->reg_base) {
default:
break;
}
break;
default:
case 0x00:
if (dev->type == 2) {
reset_on_hlt = !!(val & 0x02);
if (!(dev->regs[dev->index - dev->reg_base] & 0x01) && (val & 0x01)) {
softresetx86(); /* Pulse reset! */
cpu_set_edx();
flushmmucache();
}
dev->regs[dev->index - dev->reg_base] =
(dev->regs[dev->index - dev->reg_base] & 0xc0) | (val & 0x3f);
}
break;
case 0x01:
dev->regs[dev->index - dev->reg_base] = val;
if (dev->type == 2) {
cpu_cache_ext_enabled = !!(dev->regs[0x01] & 0x10);
cpu_update_waitstates();
} else
opti391_recalcremap(dev);
break;
case 0x05:
if (dev->type == 2)
dev->regs[dev->index - dev->reg_base] = val & 0xf8;
else
dev->regs[dev->index - dev->reg_base] = val;
break;
case 0x04:
case 0x09:
case 0x0a:
case 0x0b:
dev->regs[dev->index - dev->reg_base] = val;
break;
case 0x07:
dev->regs[dev->index - dev->reg_base] = val;
if (dev->type < 2) {
mem_a20_alt = val & 0x08;
mem_a20_recalc();
}
break;
case 0x08:
if (dev->type == 2)
dev->regs[dev->index - dev->reg_base] = val & 0xe3;
else {
dev->regs[dev->index - dev->reg_base] = val;
cpu_cache_ext_enabled = !!(dev->regs[0x02] & 0x40);
cpu_update_waitstates();
}
break;
case 0x0c:
case 0x0d:
if (dev->type < 2)
dev->regs[dev->index - dev->reg_base] = val;
break;
case 0x02:
case 0x03:
case 0x06:
opti391_log("Write %02X: %02X\n", dev->index - dev->reg_base, val);
dev->regs[dev->index - dev->reg_base] = val;
opti391_shadow_recalc(dev);
break;
}
dev->index = 0xff;
break;
}
}
@@ -178,11 +281,19 @@ opti391_write(uint16_t addr, uint8_t val, void *priv)
static uint8_t
opti391_read(uint16_t addr, void *priv)
{
const opti391_t *dev = (opti391_t *) priv;
uint8_t ret = 0xff;
opti391_t *dev = (opti391_t *) priv;
uint8_t ret = 0xff;
if (addr == 0x24)
ret = dev->regs[dev->index];
if (addr == 0x24) {
if ((dev->index <= 0x01) && (dev->type < 2))
ret = dev->regs[dev->index + 0x10];
else if ((dev->index >= dev->min_reg) && (dev->index <= dev->max_reg))
ret = dev->regs[dev->index - dev->reg_base];
dev->index = 0xff;
}
opti391_log("[R] %04X = %02X\n", addr, ret);
return ret;
}
@@ -196,38 +307,102 @@ opti391_close(void *priv)
}
static void *
opti391_init(UNUSED(const device_t *info))
opti391_init(const device_t *info)
{
opti391_t *dev = (opti391_t *) malloc(sizeof(opti391_t));
memset(dev, 0x00, sizeof(opti391_t));
opti391_t *dev = (opti391_t *) calloc(1, sizeof(opti391_t));
io_sethandler(0x0022, 0x0001, opti391_read, NULL, NULL, opti391_write, NULL, NULL, dev);
io_sethandler(0x0024, 0x0001, opti391_read, NULL, NULL, opti391_write, NULL, NULL, dev);
dev->regs[0x21] = 0x84;
dev->regs[0x24] = 0x07;
dev->regs[0x25] = 0xf0;
dev->regs[0x26] = 0x30;
dev->regs[0x27] = 0x91;
dev->regs[0x28] = 0x80;
dev->regs[0x29] = 0x10;
dev->regs[0x2a] = 0x80;
dev->regs[0x2b] = 0x10;
dev->type = info->local;
if (info->local == 2) {
dev->reg_base = 0x20;
dev->min_reg = 0x20;
dev->max_reg = 0x2b;
dev->regs[0x02] = 0x84;
dev->regs[0x04] = 0x07;
dev->regs[0x05] = 0xf0;
dev->regs[0x06] = 0x30;
dev->regs[0x07] = 0x91;
dev->regs[0x08] = 0x80;
dev->regs[0x09] = 0x10;
dev->regs[0x0a] = 0x80;
dev->regs[0x0b] = 0x10;
} else {
dev->reg_base = 0x0f;
dev->min_reg = 0x10;
dev->max_reg = 0x1c;
dev->regs[0x01] = 0x01;
dev->regs[0x02] = 0xe0;
if (info->local == 1)
/* Guess due to no OPTi 48x datasheet. */
dev->regs[0x04] = 0x07;
else
dev->regs[0x04] = 0x77;
dev->regs[0x05] = 0x60;
dev->regs[0x06] = 0x10;
dev->regs[0x07] = 0x50;
if (info->local == 1) {
/* Guess due to no OPTi 48x datasheet. */
dev->regs[0x09] = 0x80; /* Non-Cacheable Block 1 */
dev->regs[0x0b] = 0x80; /* Non-Cacheable Block 2 */
dev->regs[0x0d] = 0x91; /* Cacheable Area */
} else {
dev->regs[0x09] = 0xe0; /* Non-Cacheable Block 1 */
dev->regs[0x0b] = 0x10; /* Non-Cacheable Block 2 */
dev->regs[0x0d] = 0x80; /* Cacheable Area */
}
dev->regs[0x0a] = 0x10;
dev->regs[0x0c] = 0x10;
}
dev->old_start = 1024;
opti391_shadow_recalc(dev);
return dev;
}
const device_t opti391_device = {
.name = "OPTi 82C391",
.internal_name = "opti391",
const device_t opti381_device = {
.name = "OPTi 82C381",
.internal_name = "opti381",
.flags = 0,
.local = 0,
.init = opti391_init,
.close = opti391_close,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t opti481_device = {
.name = "OPTi 82C481",
.internal_name = "opti481",
.flags = 0,
.local = 1,
.init = opti391_init,
.close = opti391_close,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t opti391_device = {
.name = "OPTi 82C391",
.internal_name = "opti391",
.flags = 0,
.local = 2,
.init = opti391_init,
.close = opti391_close,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL

View File

@@ -8,14 +8,13 @@
*
* Implementation of the OPTi 82C493/82C495 chipset.
*
*
*
* Authors: Tiseno100,
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2020 Tiseno100.
* Copyright 2016-2020 Miran Grca.
*/
#include <math.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
@@ -28,10 +27,13 @@
#include <86box/io.h>
#include <86box/device.h>
#include <86box/mem.h>
#include <86box/plat_fallthrough.h>
#include <86box/port_92.h>
#include <86box/chipset.h>
typedef struct opti495_t {
uint8_t type;
uint8_t max;
uint8_t idx;
uint8_t regs[256];
uint8_t scratch[2];
@@ -55,6 +57,22 @@ opti495_log(const char *fmt, ...)
# define opti495_log(fmt, ...)
#endif
enum {
OPTI493 = 0,
OPTI495,
OPTI495SLC,
OPTI495SX,
OPTI495XLC,
TMAX
};
/* OPTi 82C493: According to The Last Byte, bit 1 of register 22h, while unused, must still be writable. */
static uint8_t masks[TMAX][0x1c] = { { 0x3f, 0xff, 0xff, 0xff, 0xf7, 0xfb, 0x7f, 0x9f, 0xe3, 0xff, 0xe3, 0xff },
{ 0x3a, 0x7f, 0xff, 0xff, 0xf0, 0xfb, 0x7f, 0xbf, 0xe3, 0xff, 0x00, 0x00 },
{ 0x3a, 0x7f, 0xfc, 0xff, 0xf0, 0xfb, 0xff, 0xbf, 0xe3, 0xff, 0x00, 0x00 },
{ 0x3a, 0xff, 0xfd, 0xff, 0xf0, 0xfb, 0x7f, 0xbf, 0xe3, 0xff, 0x00, 0x00 },
{ 0x3a, 0xff, 0xfc, 0xff, 0xf0, 0xfb, 0xff, 0xbf, 0xe3, 0xff, 0x00, 0x00 } };
static void
opti495_recalc(opti495_t *dev)
{
@@ -119,16 +137,25 @@ opti495_write(uint16_t addr, uint8_t val, void *priv)
opti495_t *dev = (opti495_t *) priv;
switch (addr) {
default:
break;
case 0x22:
opti495_log("[%04X:%08X] [W] dev->idx = %02X\n", CS, cpu_state.pc, val);
dev->idx = val;
break;
case 0x24:
if ((dev->idx >= 0x20) && (dev->idx <= 0x2d)) {
dev->regs[dev->idx] = val;
if ((dev->idx >= 0x20) && (dev->idx <= dev->max)) {
opti495_log("[%04X:%08X] [W] dev->regs[%04X] = %02X\n", CS, cpu_state.pc, dev->idx, val);
dev->regs[dev->idx] = val & masks[dev->type][dev->idx - 0x20];
if ((dev->type == OPTI493) && (dev->idx == 0x20))
val |= 0x40;
switch (dev->idx) {
default:
break;
case 0x21:
cpu_cache_ext_enabled = !!(dev->regs[0x21] & 0x10);
cpu_update_waitstates();
@@ -139,36 +166,57 @@ opti495_write(uint16_t addr, uint8_t val, void *priv)
case 0x26:
opti495_recalc(dev);
break;
default:
case 0x25: {
double bus_clk;
switch (val & 0x03) {
default:
case 0x00:
bus_clk = cpu_busspeed / 6.0;
break;
case 0x01:
bus_clk = cpu_busspeed / 4.0;
break;
case 0x02:
bus_clk = cpu_busspeed / 3.0;
break;
case 0x03:
bus_clk = (cpu_busspeed * 2.0) / 5.0;
break;
}
cpu_set_isa_speed((int) round(bus_clk));
break;
}
}
}
dev->idx = 0xff;
break;
case 0xe1:
case 0xe2:
dev->scratch[~addr & 0x01] = val;
break;
default:
break;
}
}
static uint8_t
opti495_read(uint16_t addr, void *priv)
{
uint8_t ret = 0xff;
const opti495_t *dev = (opti495_t *) priv;
uint8_t ret = 0xff;
opti495_t *dev = (opti495_t *) priv;
switch (addr) {
case 0x22:
opti495_log("[%04X:%08X] [R] dev->idx = %02X\n", CS, cpu_state.pc, ret);
break;
case 0x24:
if ((dev->idx >= 0x20) && (dev->idx <= 0x2d)) {
if ((dev->idx >= 0x20) && (dev->idx <= dev->max)) {
ret = dev->regs[dev->idx];
opti495_log("[%04X:%08X] [R] dev->regs[%04X] = %02X\n", CS, cpu_state.pc, dev->idx, ret);
}
dev->idx = 0xff;
break;
case 0xe1:
case 0xe2:
@@ -192,8 +240,7 @@ opti495_close(void *priv)
static void *
opti495_init(const device_t *info)
{
opti495_t *dev = (opti495_t *) malloc(sizeof(opti495_t));
memset(dev, 0, sizeof(opti495_t));
opti495_t *dev = (opti495_t *) calloc(1, sizeof(opti495_t));
device_add(&port_92_device);
@@ -202,8 +249,11 @@ opti495_init(const device_t *info)
dev->scratch[0] = dev->scratch[1] = 0xff;
if (info->local == 1) {
dev->type = info->local;
if (info->local >= OPTI495) {
/* 85C495 */
dev->max = 0x29;
dev->regs[0x20] = 0x02;
dev->regs[0x21] = 0x20;
dev->regs[0x22] = 0xe4;
@@ -214,6 +264,7 @@ opti495_init(const device_t *info)
dev->regs[0x29] = 0x10;
} else {
/* 85C493 */
dev->max = 0x2b;
dev->regs[0x20] = 0x40;
dev->regs[0x22] = 0x84;
dev->regs[0x24] = 0x87;
@@ -229,6 +280,8 @@ opti495_init(const device_t *info)
io_sethandler(0x00e1, 0x0002, opti495_read, NULL, NULL, opti495_write, NULL, NULL, dev);
cpu_set_isa_speed((int) round(cpu_busspeed / 6.0));
return dev;
}
@@ -236,25 +289,39 @@ const device_t opti493_device = {
.name = "OPTi 82C493",
.internal_name = "opti493",
.flags = 0,
.local = 0,
.local = OPTI493,
.init = opti495_init,
.close = opti495_close,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t opti495_device = {
const device_t opti495slc_device = {
.name = "OPTi 82C495",
.internal_name = "opti495",
.internal_name = "opti495slc",
.flags = 0,
.local = 1,
.local = OPTI495SLC,
.init = opti495_init,
.close = opti495_close,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t opti495sx_device = {
.name = "OPTi 82C495SX",
.internal_name = "opti495sx",
.flags = 0,
.local = OPTI495SX,
.init = opti495_init,
.close = opti495_close,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL

360
src/chipset/opti498.c Normal file
View File

@@ -0,0 +1,360 @@
/*
* 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 OPTi 82C498 chipset.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2025 Miran Grca.
*/
#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/plat_fallthrough.h>
#include <86box/plat_unused.h>
#include <86box/port_92.h>
#include <86box/chipset.h>
#ifdef ENABLE_OPTI498_LOG
int opti498_do_log = ENABLE_OPTI498_LOG;
static void
opti498_log(const char *fmt, ...)
{
va_list ap;
if (opti498_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define opti498_log(fmt, ...)
#endif
typedef struct mem_remapping_t {
uint32_t phys;
uint32_t virt;
} mem_remapping_t;
typedef struct opti498_t {
uint8_t index;
/* 0x30 for 496/497, 0x70 for 498. */
uint8_t reg_base;
uint8_t shadow_high;
uint8_t regs[256];
mem_remapping_t mem_remappings[2];
mem_mapping_t mem_mappings[2];
} opti498_t;
static uint8_t
opti498_read_remapped_ram(uint32_t addr, void *priv)
{
const mem_remapping_t *dev = (mem_remapping_t *) priv;
return mem_read_ram((addr - dev->virt) + dev->phys, priv);
}
static uint16_t
opti498_read_remapped_ramw(uint32_t addr, void *priv)
{
const mem_remapping_t *dev = (mem_remapping_t *) priv;
return mem_read_ramw((addr - dev->virt) + dev->phys, priv);
}
static uint32_t
opti498_read_remapped_raml(uint32_t addr, void *priv)
{
const mem_remapping_t *dev = (mem_remapping_t *) priv;
return mem_read_raml((addr - dev->virt) + dev->phys, priv);
}
static void
opti498_write_remapped_ram(uint32_t addr, uint8_t val, void *priv)
{
const mem_remapping_t *dev = (mem_remapping_t *) priv;
mem_write_ram((addr - dev->virt) + dev->phys, val, priv);
}
static void
opti498_write_remapped_ramw(uint32_t addr, uint16_t val, void *priv)
{
const mem_remapping_t *dev = (mem_remapping_t *) priv;
mem_write_ramw((addr - dev->virt) + dev->phys, val, priv);
}
static void
opti498_write_remapped_raml(uint32_t addr, uint32_t val, void *priv)
{
const mem_remapping_t *dev = (mem_remapping_t *) priv;
mem_write_raml((addr - dev->virt) + dev->phys, val, priv);
}
static void
opti498_shadow_recalc(opti498_t *dev)
{
uint32_t base;
uint32_t rbase;
uint8_t sh_enable;
uint8_t sh_mode;
uint8_t rom;
uint8_t sh_copy;
shadowbios = shadowbios_write = 0;
dev->shadow_high = 0;
opti498_log("OPTI 498: %02X %02X %02X %02X\n", dev->regs[0x02], dev->regs[0x03], dev->regs[0x04], dev->regs[0x05]);
if (dev->regs[0x02] & 0x80) {
if (dev->regs[0x04] & 0x02) {
mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
opti498_log("OPTI 498: F0000-FFFFF READ_EXTANY, WRITE_EXTANY\n");
} else {
shadowbios_write = 1;
mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
opti498_log("OPTI 498: F0000-FFFFF READ_EXTANY, WRITE_INTERNAL\n");
}
} else {
shadowbios = 1;
mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED);
opti498_log("OPTI 498: F0000-FFFFF READ_INTERNAL, WRITE_DISABLED\n");
}
sh_copy = dev->regs[0x02] & 0x08;
for (uint8_t i = 0; i < 12; i++) {
base = 0xc0000 + (i << 14);
if (i >= 4)
sh_enable = dev->regs[0x03] & (1 << (i - 4));
else
sh_enable = dev->regs[0x04] & (1 << (i + 4));
sh_mode = dev->regs[0x02] & (1 << (i >> 2));
rom = dev->regs[0x02] & (1 << ((i >> 2) + 4));
opti498_log("OPTI 498: %i/%08X: %i, %i, %i\n", i, base, (i >= 4) ? (1 << (i - 4)) : (1 << (i + 4)), (1 << (i >> 2)), (1 << ((i >> 2) + 4)));
if (sh_copy) {
if (base >= 0x000e0000)
shadowbios_write |= 1;
if (base >= 0x000d0000)
dev->shadow_high |= 1;
if (base >= 0xe0000) {
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
opti498_log("OPTI 498: %08X-%08X READ_EXTANY, WRITE_INTERNAL\n", base, base + 0x3fff);
} else {
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL);
opti498_log("OPTI 498: %08X-%08X READ_EXTERNAL, WRITE_INTERNAL\n", base, base + 0x3fff);
}
} else if (sh_enable && rom) {
if (base >= 0x000e0000)
shadowbios |= 1;
if (base >= 0x000d0000)
dev->shadow_high |= 1;
if (sh_mode) {
mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED);
opti498_log("OPTI 498: %08X-%08X READ_INTERNAL, WRITE_DISABLED\n", base, base + 0x3fff);
} else {
if (base >= 0x000e0000)
shadowbios_write |= 1;
mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
opti498_log("OPTI 498: %08X-%08X READ_INTERNAL, WRITE_INTERNAL\n", base, base + 0x3fff);
}
} else {
if (base >= 0xe0000) {
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_DISABLED);
opti498_log("OPTI 498: %08X-%08X READ_EXTANY, WRITE_DISABLED\n", base, base + 0x3fff);
} else {
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTERNAL | MEM_WRITE_DISABLED);
opti498_log("OPTI 498: %08X-%08X READ_EXTERNAL, WRITE_DISABLED\n", base, base + 0x3fff);
}
}
}
rbase = ((uint32_t) (dev->regs[0x05] & 0x3f)) << 20;
if (rbase > 0) {
dev->mem_remappings[0].virt = rbase;
mem_mapping_set_addr(&dev->mem_mappings[0], rbase, 0x00020000);
if (!dev->shadow_high) {
rbase += 0x00020000;
dev->mem_remappings[1].virt = rbase;
mem_mapping_set_addr(&dev->mem_mappings[1], rbase, 0x00020000);
} else
mem_mapping_disable(&dev->mem_mappings[1]);
} else {
mem_mapping_disable(&dev->mem_mappings[0]);
mem_mapping_disable(&dev->mem_mappings[1]);
}
flushmmucache_nopc();
}
static void
opti498_write(uint16_t addr, uint8_t val, void *priv)
{
opti498_t *dev = (opti498_t *) priv;
uint8_t reg = dev->index - dev->reg_base;
switch (addr) {
default:
break;
case 0x22:
dev->index = val;
break;
case 0x24:
opti498_log("OPTi 498: dev->regs[%02x] = %02x\n", dev->index, val);
if ((reg >= 0x00) && (reg <= 0x0b)) switch (reg) {
default:
break;
case 0x00:
dev->regs[reg] = (dev->regs[reg] & 0xc0) | (val & 0x3f);
break;
case 0x01:
case 0x07 ... 0x0b:
dev->regs[reg] = val;
break;
case 0x02:
case 0x03:
case 0x04:
case 0x05:
dev->regs[reg] = val;
opti498_shadow_recalc(dev);
break;
case 0x06: {
double bus_clk;
dev->regs[reg] = val;
switch (val & 0x03) {
default:
case 0x00:
bus_clk = cpu_busspeed / 8.0;
break;
case 0x01:
bus_clk = cpu_busspeed / 6.0;
break;
case 0x02:
bus_clk = cpu_busspeed / 5.0;
break;
case 0x03:
bus_clk = cpu_busspeed / 4.0;
break;
}
cpu_set_isa_speed((int) round(bus_clk));
reset_on_hlt = !!(val & 0x40);
break;
}
}
dev->index = 0xff;
break;
}
}
static uint8_t
opti498_read(uint16_t addr, void *priv)
{
opti498_t *dev = (opti498_t *) priv;
uint8_t reg = dev->index - dev->reg_base;
uint8_t ret = 0xff;
if (addr == 0x24) {
if ((reg >= 0x00) && (reg <= 0x0b))
ret = dev->regs[reg];
dev->index = 0xff;
}
return ret;
}
static void
opti498_close(void *priv)
{
opti498_t *dev = (opti498_t *) priv;
free(dev);
}
static void *
opti498_init(UNUSED(const device_t *info))
{
opti498_t *dev = (opti498_t *) calloc(1, sizeof(opti498_t));
dev->reg_base = info->local & 0xff;
io_sethandler(0x0022, 0x0001, opti498_read, NULL, NULL, opti498_write, NULL, NULL, dev);
io_sethandler(0x0024, 0x0001, opti498_read, NULL, NULL, opti498_write, NULL, NULL, dev);
dev->regs[0x00] = 0x1f;
dev->regs[0x01] = 0x8f;
dev->regs[0x02] = 0xf0;
dev->regs[0x07] = 0x70;
dev->regs[0x09] = 0x70;
dev->mem_remappings[0].phys = 0x000a0000;
dev->mem_remappings[1].phys = 0x000d0000;
mem_mapping_add(&dev->mem_mappings[0], 0, 0x00020000,
opti498_read_remapped_ram, opti498_read_remapped_ramw, opti498_read_remapped_raml,
opti498_write_remapped_ram, opti498_write_remapped_ramw, opti498_write_remapped_raml,
&ram[dev->mem_remappings[0].phys], MEM_MAPPING_INTERNAL, &dev->mem_remappings[0]);
mem_mapping_disable(&dev->mem_mappings[0]);
mem_mapping_add(&dev->mem_mappings[1], 0, 0x00020000,
opti498_read_remapped_ram, opti498_read_remapped_ramw, opti498_read_remapped_raml,
opti498_write_remapped_ram, opti498_write_remapped_ramw, opti498_write_remapped_raml,
&ram[dev->mem_remappings[1].phys], MEM_MAPPING_INTERNAL, &dev->mem_remappings[1]);
mem_mapping_disable(&dev->mem_mappings[1]);
opti498_shadow_recalc(dev);
cpu_set_isa_speed((int) round(cpu_busspeed / 8.0));
device_add(&port_92_device);
return dev;
}
const device_t opti498_device = {
.name = "OPTi 82C498",
.internal_name = "opti498",
.flags = 0,
.local = 0x70,
.init = opti498_init,
.close = opti498_close,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -16,6 +16,7 @@
* Copyright 2008-2020 Tiseno100.
* Copyright 2016-2020 Miran Grca.
*/
#include <math.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
@@ -38,6 +39,9 @@ typedef struct opti499_t {
uint8_t scratch[2];
} opti499_t;
/* According to The Last Byte, register 2Dh bit 7 must still be writable, even if it is unused. */
static uint8_t masks[0x0e] = { 0x3f, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xe3, 0xff, 0xfb, 0xff, 0x00, 0xff };
#ifdef ENABLE_OPTI499_LOG
int opti499_do_log = ENABLE_OPTI499_LOG;
@@ -84,7 +88,7 @@ opti499_recalc(opti499_t *dev)
shflags = MEM_READ_INTERNAL;
shflags |= (dev->regs[0x22] & ((base >= 0xe0000) ? 0x08 : 0x10)) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
} else {
if (dev->regs[0x2d] && (1 << ((i >> 1) + 2)))
if (dev->regs[0x2d] & (1 << ((i >> 1) + 2)))
shflags = MEM_READ_EXTANY | MEM_WRITE_EXTANY;
else
shflags = MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL;
@@ -101,13 +105,13 @@ opti499_recalc(opti499_t *dev)
shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
} else {
if (dev->regs[0x26] & 0x40) {
if (dev->regs[0x2d] && (1 << (i >> 1)))
if (dev->regs[0x2d] & (1 << (i >> 1)))
shflags = MEM_READ_EXTANY;
else
shflags = MEM_READ_EXTERNAL;
shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
} else {
if (dev->regs[0x2d] && (1 << (i >> 1)))
if (dev->regs[0x2d] & (1 << (i >> 1)))
shflags = MEM_READ_EXTANY | MEM_WRITE_EXTANY;
else
shflags = MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL;
@@ -126,22 +130,47 @@ opti499_write(uint16_t addr, uint8_t val, void *priv)
opti499_t *dev = (opti499_t *) priv;
switch (addr) {
default:
break;
case 0x22:
opti499_log("[%04X:%08X] [W] dev->idx = %02X\n", CS, cpu_state.pc, val);
dev->idx = val;
break;
case 0x24:
if ((dev->idx >= 0x20) && (dev->idx <= 0x2d)) {
if (dev->idx == 0x20)
dev->regs[dev->idx] = (dev->regs[dev->idx] & 0xc0) | (val & 0x3f);
else
dev->regs[dev->idx] = val;
if ((dev->idx >= 0x20) && (dev->idx <= 0x2d) && (dev->idx != 0x2c)) {
opti499_log("[%04X:%08X] [W] dev->regs[%04X] = %02X\n", CS, cpu_state.pc, dev->idx, val);
dev->regs[dev->idx] = val & masks[dev->idx - 0x20];
if (dev->idx == 0x2a)
dev->regs[dev->idx] |= 0x04;
switch (dev->idx) {
case 0x20:
default:
break;
case 0x20: {
double coeff = (val & 0x10) ? 1.0 : 2.0;
double bus_clk;
switch (dev->regs[0x25] & 0x03) {
default:
case 0x00:
bus_clk = (cpu_busspeed * coeff) / 6.0;
break;
case 0x01:
bus_clk = (cpu_busspeed * coeff) / 5.0;
break;
case 0x02:
bus_clk = (cpu_busspeed * coeff) / 4.0;
break;
case 0x03:
bus_clk = (cpu_busspeed * coeff) / 3.0;
break;
}
cpu_set_isa_speed((int) round(bus_clk));
reset_on_hlt = !(val & 0x02);
break;
}
case 0x21:
cpu_cache_ext_enabled = !!(dev->regs[0x21] & 0x10);
@@ -155,19 +184,37 @@ opti499_write(uint16_t addr, uint8_t val, void *priv)
opti499_recalc(dev);
break;
default:
case 0x25: {
double coeff = (dev->regs[0x20] & 0x10) ? 1.0 : 2.0;
double bus_clk;
switch (val & 0x03) {
default:
case 0x00:
bus_clk = (cpu_busspeed * coeff) / 8.0;
break;
case 0x01:
bus_clk = (cpu_busspeed * coeff) / 6.0;
break;
case 0x02:
bus_clk = (cpu_busspeed * coeff) / 5.0;
break;
case 0x03:
bus_clk = (cpu_busspeed * coeff) / 4.0;
break;
}
cpu_set_isa_speed((int) round(bus_clk));
break;
}
}
}
dev->idx = 0xff;
break;
case 0xe1:
case 0xe2:
dev->scratch[~addr & 0x01] = val;
break;
default:
break;
}
}
@@ -178,25 +225,23 @@ opti499_read(uint16_t addr, void *priv)
opti499_t *dev = (opti499_t *) priv;
switch (addr) {
default:
break;
case 0x22:
opti499_log("[%04X:%08X] [R] dev->idx = %02X\n", CS, cpu_state.pc, ret);
break;
case 0x24:
if ((dev->idx >= 0x20) && (dev->idx <= 0x2d)) {
if (dev->idx == 0x2d)
ret = dev->regs[dev->idx] & 0xbf;
else
ret = dev->regs[dev->idx];
if ((dev->idx >= 0x20) && (dev->idx <= 0x2d) && (dev->idx != 0x2c)) {
ret = dev->regs[dev->idx];
opti499_log("[%04X:%08X] [R] dev->regs[%04X] = %02X\n", CS, cpu_state.pc, dev->idx, ret);
}
dev->idx = 0xff;
break;
case 0xe1:
case 0xe2:
ret = dev->scratch[~addr & 0x01];
break;
default:
break;
}
return ret;
@@ -227,7 +272,7 @@ opti499_reset(void *priv)
opti499_recalc(dev);
free(dev);
cpu_set_isa_speed((int) round((cpu_busspeed * 2.0) / 6.0));
}
static void
@@ -241,8 +286,7 @@ opti499_close(void *priv)
static void *
opti499_init(UNUSED(const device_t *info))
{
opti499_t *dev = (opti499_t *) malloc(sizeof(opti499_t));
memset(dev, 0, sizeof(opti499_t));
opti499_t *dev = (opti499_t *) calloc(1, sizeof(opti499_t));
device_add(&port_92_device);
@@ -264,7 +308,7 @@ const device_t opti499_device = {
.init = opti499_init,
.close = opti499_close,
.reset = opti499_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL

View File

@@ -35,7 +35,7 @@
typedef struct opti5x7_t {
uint8_t idx;
uint8_t is_pci;
uint8_t regs[16];
uint8_t regs[18];
} opti5x7_t;
#ifdef ENABLE_OPTI5X7_LOG
@@ -158,7 +158,7 @@ opti5x7_read(uint16_t addr, void *priv)
{
const opti5x7_t *dev = (opti5x7_t *) priv;
return (addr == 0x24) ? dev->regs[dev->idx] : 0xff;
return ((addr == 0x24) && (dev->idx < sizeof(dev->regs))) ? dev->regs[dev->idx] : 0xff;
}
static void
@@ -172,8 +172,7 @@ opti5x7_close(void *priv)
static void *
opti5x7_init(const device_t *info)
{
opti5x7_t *dev = (opti5x7_t *) malloc(sizeof(opti5x7_t));
memset(dev, 0, sizeof(opti5x7_t));
opti5x7_t *dev = (opti5x7_t *) calloc(1, sizeof(opti5x7_t));
dev->is_pci = info->local;
@@ -193,7 +192,7 @@ const device_t opti5x7_device = {
.init = opti5x7_init,
.close = opti5x7_close,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
@@ -207,7 +206,7 @@ const device_t opti5x7_pci_device = {
.init = opti5x7_init,
.close = opti5x7_close,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL

View File

@@ -218,7 +218,7 @@ const device_t opti601_device = {
.init = opti602_init,
.close = opti602_close,
.reset = opti602_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
@@ -232,7 +232,7 @@ const device_t opti602_device = {
.init = opti602_init,
.close = opti602_close,
.reset = opti602_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL

View File

@@ -394,8 +394,7 @@ opti822_close(void *priv)
static void *
opti822_init(UNUSED(const device_t *info))
{
opti822_t *dev = (opti822_t *) malloc(sizeof(opti822_t));
memset(dev, 0, sizeof(opti822_t));
opti822_t *dev = (opti822_t *) calloc(1, sizeof(opti822_t));
pci_add_card(PCI_ADD_NORTHBRIDGE, opti822_pci_read, opti822_pci_write, dev, &dev->pci_slot);
@@ -412,7 +411,7 @@ const device_t opti822_device = {
.init = opti822_init,
.close = opti822_close,
.reset = opti822_reset,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL

View File

@@ -16,6 +16,7 @@
* Copyright 2008-2020 Tiseno100.
* Copyright 2016-2020 Miran Grca.
*/
#include <math.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
@@ -42,6 +43,9 @@ typedef struct opti895_t {
smram_t *smram;
} opti895_t;
static uint8_t masks[0x10] = { 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
0xe3, 0xff, 0xe3, 0xff, 0x00, 0xff, 0xff, 0xff };
#ifdef ENABLE_OPTI895_LOG
int opti895_do_log = ENABLE_OPTI895_LOG;
@@ -153,8 +157,12 @@ opti895_write(uint16_t addr, uint8_t val, void *priv)
}
break;
case 0x24:
if (((dev->idx >= 0x20) && (dev->idx <= 0x2f)) || ((dev->idx >= 0xe0) && (dev->idx <= 0xef))) {
dev->regs[dev->idx] = val;
if (((dev->idx >= 0x20) && (dev->idx <= 0x2f) && (dev->idx != 0x2c)) ||
((dev->idx >= 0xe0) && (dev->idx <= 0xef))) {
if (dev->idx > 0x2f)
dev->regs[dev->idx] = val;
else
dev->regs[dev->idx] = val & masks[dev->idx - 0x20];
opti895_log("dev->regs[%04x] = %08x\n", dev->idx, val);
/* TODO: Registers 0x30-0x3F for OPTi 802GP and 898. */
@@ -175,6 +183,27 @@ opti895_write(uint16_t addr, uint8_t val, void *priv)
smram_state_change(dev->smram, 0, !!(val & 0x80));
break;
case 0x25: {
double bus_clk;
switch (val & 0x03) {
default:
case 0x00:
bus_clk = cpu_busspeed / 6.0;
break;
case 0x01:
bus_clk = cpu_busspeed / 5.0;
break;
case 0x02:
bus_clk = cpu_busspeed / 4.0;
break;
case 0x03:
bus_clk = cpu_busspeed / 3.0;
break;
}
cpu_set_isa_speed((int) round(bus_clk));
break;
}
case 0xe0:
if (!(val & 0x01))
dev->forced_green = 0;
@@ -217,7 +246,8 @@ opti895_read(uint16_t addr, void *priv)
break;
case 0x24:
/* TODO: Registers 0x30-0x3F for OPTi 802GP and 898. */
if (((dev->idx >= 0x20) && (dev->idx <= 0x2f)) || ((dev->idx >= 0xe0) && (dev->idx <= 0xef))) {
if (((dev->idx >= 0x20) && (dev->idx <= 0x2f) && (dev->idx != 0x2c)) ||
((dev->idx >= 0xe0) && (dev->idx <= 0xef))) {
ret = dev->regs[dev->idx];
if (dev->idx == 0xe0)
ret = (ret & 0xf6) | (in_smm ? 0x00 : 0x08) | !!dev->forced_green;
@@ -251,8 +281,7 @@ opti895_close(void *priv)
static void *
opti895_init(const device_t *info)
{
opti895_t *dev = (opti895_t *) malloc(sizeof(opti895_t));
memset(dev, 0, sizeof(opti895_t));
opti895_t *dev = (opti895_t *) calloc(1, sizeof(opti895_t));
device_add(&port_92_device);
@@ -287,6 +316,8 @@ opti895_init(const device_t *info)
smram_enable(dev->smram, 0x00030000, 0x000b0000, 0x00010000, 0, 1);
cpu_set_isa_speed((int) round(cpu_busspeed / 6.0));
return dev;
}
@@ -298,7 +329,7 @@ const device_t opti802g_device = {
.init = opti895_init,
.close = opti895_close,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
@@ -312,7 +343,7 @@ const device_t opti802g_pci_device = {
.init = opti895_init,
.close = opti895_close,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
@@ -326,7 +357,7 @@ const device_t opti895_device = {
.init = opti895_init,
.close = opti895_close,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL

View File

@@ -8,11 +8,9 @@
*
* Emulation of the Philips XT-compatible machines.
*
*
*
* Authors: EngiNerd <webmaster.crrc@yahoo.it>
*
* Copyright 2020-2021 EngiNerd.
* Copyright 2020-2025 EngiNerd.
*/
#include <stdarg.h>
#include <stdint.h>
@@ -23,6 +21,7 @@
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/nmi.h>
#include "cpu.h"
#include <86box/timer.h>
#include <86box/pit.h>
#include <86box/mem.h>
@@ -142,65 +141,8 @@ const device_t philips_device = {
.init = philips_init,
.close = philips_close,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
void
machine_xt_philips_common_init(const machine_t *model)
{
machine_common_init(model);
pit_devs[0].set_out_func(pit_devs[0].data, 1, pit_refresh_timer_xt);
nmi_init();
standalone_gameport_type = &gameport_device;
device_add(&keyboard_pc_device);
device_add(&philips_device);
device_add(&xta_hd20_device);
}
int
machine_xt_p3105_init(const machine_t *model)
{
int ret;
ret = bios_load_linear("roms/machines/p3105/philipsnms9100.bin",
0x000fc000, 16384, 0);
if (bios_only || !ret)
return ret;
machine_xt_philips_common_init(model);
/* On-board FDC cannot be disabled */
device_add(&fdc_xt_device);
return ret;
}
int
machine_xt_p3120_init(const machine_t *model)
{
int ret;
ret = bios_load_linear("roms/machines/p3120/philips_p3120.bin",
0x000f8000, 32768, 0);
if (bios_only || !ret)
return ret;
machine_xt_philips_common_init(model);
device_add(&gc100a_device);
device_add(&fdc_at_device);
return ret;
}

123
src/chipset/sanyo.c Normal file
View File

@@ -0,0 +1,123 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Emulation of the Philips XT-compatible machines.
*
* Authors: EngiNerd <webmaster.crrc@yahoo.it>
*
* Copyright 2020-2025 EngiNerd.
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/nmi.h>
#include "cpu.h"
#include <86box/timer.h>
#include <86box/pit.h>
#include <86box/mem.h>
#include <86box/device.h>
#include <86box/fdd.h>
#include <86box/fdc.h>
#include <86box/fdc_ext.h>
#include <86box/hdc.h>
#include <86box/gameport.h>
#include <86box/ibm_5161.h>
#include <86box/keyboard.h>
#include <86box/rom.h>
#include <86box/machine.h>
#include <86box/chipset.h>
#include <86box/io.h>
#include <86box/video.h>
#include <86box/plat_unused.h>
typedef struct sanyo_t {
uint8_t reg;
} sanyo_t;
#ifdef ENABLE_SANYO_LOG
int sanyo_do_log = ENABLE_SANYO_LOG;
static void
sanyo_log(const char *fmt, ...)
{
va_list ap;
if (sanyo_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define sanyo_log(fmt, ...)
#endif
static void
sanyo_write(uint16_t port, uint8_t val, void *priv)
{
sanyo_t *dev = (sanyo_t *) priv;
dev->reg = val;
cpu_waitstates = !(val & 0x01);
cpu_update_waitstates();
sanyo_log("Sanyo MBC-17 Mainboard: Write %02x at %02x\n", val, port);
}
static uint8_t
sanyo_read(uint16_t port, void *priv)
{
const sanyo_t *dev = (sanyo_t *) priv;
uint8_t ret = 0xff;
ret = dev->reg;
sanyo_log("Sanyo MBC-17 Mainboard: Read %02x at %02x\n", ret, port);
return ret;
}
static void
sanyo_close(void *priv)
{
sanyo_t *dev = (sanyo_t *) priv;
free(dev);
}
static void *
sanyo_init(UNUSED(const device_t *info))
{
sanyo_t *dev = (sanyo_t *) calloc(1, sizeof(sanyo_t));
dev->reg = cpu_waitstates ? 0x00 : 0x01;
io_sethandler(0x0063, 0x01, sanyo_read, NULL, NULL, sanyo_write, NULL, NULL, dev);
return dev;
}
const device_t sanyo_device = {
.name = "Sanyo MBC-17 Mainboard",
.internal_name = "sanyo",
.flags = 0,
.local = 0,
.init = sanyo_init,
.close = sanyo_close,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

File diff suppressed because it is too large Load Diff

View File

@@ -66,15 +66,17 @@ typedef struct ems_page_t {
} ems_page_t;
typedef struct scat_t {
int type;
uint8_t max_reg;
uint8_t reg_2xA;
int indx;
uint8_t regs[256];
uint8_t reg_2xA;
uint8_t regs[256];
uint32_t xms_bound;
int external_is_RAS;
int type;
int indx;
int external_is_RAS;
ems_page_t null_page;
ems_page_t page[32];
@@ -1138,14 +1140,21 @@ scat_out(uint16_t port, uint8_t val, void *priv)
if (indx >= 24)
base_addr += 0x30000;
if ((base_addr >= 0x000a0000) && (base_addr < 0x00100000))
mem_set_mem_state(base_addr, 0x00004000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
if ((dev->regs[SCAT_EMS_CONTROL] & 0x80) && (dev->page[indx].regs_2x9 & 0x80)) {
virt_addr = get_addr(dev, base_addr, &dev->page[indx]);
if (virt_addr < ((uint32_t) mem_size << 10))
mem_mapping_set_exec(&dev->ems_mapping[indx], ram + virt_addr);
else
mem_mapping_set_exec(&dev->ems_mapping[indx], NULL);
flushmmucache();
if ((base_addr >= 0x000a0000) && (base_addr < 0x00100000))
mem_set_mem_state(base_addr, 0x00004000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
}
flushmmucache();
}
break;
@@ -1161,6 +1170,9 @@ scat_out(uint16_t port, uint8_t val, void *priv)
if (indx >= 24)
base_addr += 0x30000;
if ((base_addr >= 0x000a0000) && (base_addr < 0x00100000))
mem_set_mem_state(base_addr, 0x00004000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
if (dev->regs[SCAT_EMS_CONTROL] & 0x80) {
if (val & 0x80) {
virt_addr = get_addr(dev, base_addr, &dev->page[indx]);
@@ -1173,6 +1185,9 @@ scat_out(uint16_t port, uint8_t val, void *priv)
else
mem_mapping_set_exec(&dev->ems_mapping[indx], NULL);
mem_mapping_enable(&dev->ems_mapping[indx]);
if ((base_addr >= 0x000a0000) && (base_addr < 0x00100000))
mem_set_mem_state(base_addr, 0x00004000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
} else {
mem_mapping_set_exec(&dev->ems_mapping[indx], ram + base_addr);
mem_mapping_disable(&dev->ems_mapping[indx]);
@@ -1233,7 +1248,8 @@ scat_in(uint16_t port, void *priv)
break;
default:
ret = dev->regs[dev->indx];
if (dev->indx <= dev->max_reg)
ret = dev->regs[dev->indx];
break;
}
break;
@@ -1387,12 +1403,13 @@ scat_init(const device_t *info)
uint32_t k;
int sx;
dev = (scat_t *) malloc(sizeof(scat_t));
memset(dev, 0x00, sizeof(scat_t));
dev = (scat_t *) calloc(1, sizeof(scat_t));
dev->type = info->local;
sx = (dev->type == 32) ? 1 : 0;
dev->max_reg = sx ? 0x64 : 0x4f;
for (uint32_t i = 0; i < sizeof(dev->regs); i++)
dev->regs[i] = 0xff;
@@ -1490,7 +1507,7 @@ scat_init(const device_t *info)
mem_mapping_add(&dev->ems_mapping[i], (i + 28) << 14, 0x04000,
mem_read_scatb, mem_read_scatw, mem_read_scatl,
mem_write_scatb, mem_write_scatw, mem_write_scatl,
ram + ((i + 28) << 14), 0, &dev->page[i]);
ram + ((i + 28) << 14), MEM_MAPPING_INTERNAL, &dev->page[i]);
mem_mapping_disable(&dev->ems_mapping[i]);
}
} else {
@@ -1503,7 +1520,7 @@ scat_init(const device_t *info)
mem_read_scatb, mem_read_scatw, mem_read_scatl,
mem_write_scatb, mem_write_scatw, mem_write_scatl,
ram + ((i + (i >= 24 ? 28 : 16)) << 14),
0, &dev->page[i]);
MEM_MAPPING_INTERNAL, &dev->page[i]);
}
}
@@ -1541,7 +1558,7 @@ const device_t scat_device = {
.init = scat_init,
.close = scat_close,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
@@ -1555,7 +1572,7 @@ const device_t scat_4_device = {
.init = scat_init,
.close = scat_close,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
@@ -1569,7 +1586,7 @@ const device_t scat_sx_device = {
.init = scat_init,
.close = scat_close,
.reset = NULL,
{ .available = NULL },
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL

View File

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

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

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

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

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

1387
src/chipset/sis_5513_p2i.c Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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

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

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

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

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

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

187
src/chipset/sis_5581.c Normal file
View File

@@ -0,0 +1,187 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Implementation of the SiS 5581/5582 Pentium PCI/ISA Chipset.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2024 Miran Grca.
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/io.h>
#include <86box/timer.h>
#include <86box/mem.h>
#include <86box/nvr.h>
#include <86box/apm.h>
#include <86box/acpi.h>
#include <86box/keyboard.h>
#include <86box/hdd.h>
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
#include <86box/hdc_ide_sff8038i.h>
#include <86box/pci.h>
#include <86box/pic.h>
#include <86box/pit.h>
#include <86box/pit_fast.h>
#include <86box/plat.h>
#include <86box/plat_unused.h>
#include <86box/port_92.h>
#include <86box/smram.h>
#include <86box/spd.h>
#include <86box/sis_55xx.h>
#include <86box/chipset.h>
#ifdef ENABLE_SIS_5581_LOG
int sis_5581_do_log = ENABLE_SIS_5581_LOG;
static void
sis_5581_log(const char *fmt, ...)
{
va_list ap;
if (sis_5581_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define sis_5581_log(fmt, ...)
#endif
typedef struct sis_5581_t {
uint8_t nb_slot;
uint8_t sb_slot;
void *h2p;
void *p2i;
void *ide;
void *usb;
sis_55xx_common_t *sis;
} sis_5581_t;
static void
sis_5581_write(int func, int addr, uint8_t val, void *priv)
{
const sis_5581_t *dev = (sis_5581_t *) priv;
sis_5581_log("SiS 5581: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
if (func == 0x00)
sis_5581_host_to_pci_write(addr, val, dev->h2p);
}
static uint8_t
sis_5581_read(int func, int addr, void *priv)
{
const sis_5581_t *dev = (sis_5581_t *) priv;
uint8_t ret = 0xff;
if (func == 0x00)
ret = sis_5581_host_to_pci_read(addr, dev->h2p);
sis_5581_log("SiS 5581: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
return ret;
}
static void
sis_5582_write(int func, int addr, uint8_t val, void *priv)
{
const sis_5581_t *dev = (sis_5581_t *) priv;
sis_5581_log("SiS 5582: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
switch (func) {
case 0x00:
sis_5513_pci_to_isa_write(addr, val, dev->p2i);
break;
case 0x01:
sis_5513_ide_write(addr, val, dev->ide);
break;
case 0x02:
sis_5572_usb_write(addr, val, dev->usb);
break;
}
}
static uint8_t
sis_5582_read(int func, int addr, void *priv)
{
const sis_5581_t *dev = (sis_5581_t *) priv;
uint8_t ret = 0xff;
switch (func) {
case 0x00:
ret = sis_5513_pci_to_isa_read(addr, dev->p2i);
break;
case 0x01:
ret = sis_5513_ide_read(addr, dev->ide);
break;
case 0x02:
ret = sis_5572_usb_read(addr, dev->usb);
break;
}
sis_5581_log("SiS 5582: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
return ret;
}
static void
sis_5581_close(void *priv)
{
sis_5581_t *dev = (sis_5581_t *) priv;
free(dev);
}
static void *
sis_5581_init(UNUSED(const device_t *info))
{
sis_5581_t *dev = (sis_5581_t *) calloc(1, sizeof(sis_5581_t));
/* Device 0: SiS 5581 */
pci_add_card(PCI_ADD_NORTHBRIDGE, sis_5581_read, sis_5581_write, dev, &dev->nb_slot);
/* Device 1: SiS 5582 */
pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_5582_read, sis_5582_write, dev, &dev->sb_slot);
dev->sis = device_add(&sis_55xx_common_device);
dev->p2i = device_add_linked(&sis_5582_p2i_device, dev->sis);
dev->h2p = device_add_linked(&sis_5581_h2p_device, dev->sis);
dev->ide = device_add_linked(&sis_5582_ide_device, dev->sis);
dev->usb = device_add_linked(&sis_5582_usb_device, dev->sis);
device_add_params(&kbc_at_device, (void *) KBC_VEN_SIS);
return dev;
}
const device_t sis_5581_device = {
.name = "SiS 5581",
.internal_name = "sis_5581",
.flags = DEVICE_PCI,
.local = 0,
.init = sis_5581_init,
.close = sis_5581_close,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

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

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

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

@@ -0,0 +1,213 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Implementation of the SiS 5591/5592 Pentium PCI/ISA Chipset.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2024 Miran Grca.
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/io.h>
#include <86box/timer.h>
#include <86box/mem.h>
#include <86box/nvr.h>
#include <86box/apm.h>
#include <86box/acpi.h>
#include <86box/keyboard.h>
#include <86box/hdd.h>
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
#include <86box/hdc_ide_sff8038i.h>
#include <86box/pci.h>
#include <86box/pic.h>
#include <86box/pit.h>
#include <86box/pit_fast.h>
#include <86box/plat.h>
#include <86box/plat_unused.h>
#include <86box/port_92.h>
#include <86box/smram.h>
#include <86box/spd.h>
#include <86box/sis_55xx.h>
#include <86box/chipset.h>
#ifdef ENABLE_SIS_5591_LOG
int sis_5591_do_log = ENABLE_SIS_5591_LOG;
static void
sis_5591_log(const char *fmt, ...)
{
va_list ap;
if (sis_5591_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define sis_5591_log(fmt, ...)
#endif
typedef struct sis_5591_t {
uint8_t nb_slot;
uint8_t sb_slot;
void *h2p;
void *p2i;
void *ide;
void *usb;
void *pmu;
sis_55xx_common_t *sis;
} sis_5591_t;
static void
sis_5591_write(int func, int addr, uint8_t val, void *priv)
{
const sis_5591_t *dev = (sis_5591_t *) priv;
sis_5591_log("SiS 5591: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
if (func == 0x00)
sis_5591_host_to_pci_write(addr, val, dev->h2p);
else if (func == 0x01)
sis_5513_ide_write(addr, val, dev->ide);
}
static uint8_t
sis_5591_read(int func, int addr, void *priv)
{
const sis_5591_t *dev = (sis_5591_t *) priv;
uint8_t ret = 0xff;
if (func == 0x00)
ret = sis_5591_host_to_pci_read(addr, dev->h2p);
else if (func == 0x01)
ret = sis_5513_ide_read(addr, dev->ide);
sis_5591_log("SiS 5591: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
return ret;
}
static void
sis_5595_write(int func, int addr, uint8_t val, void *priv)
{
const sis_5591_t *dev = (sis_5591_t *) priv;
sis_5591_log("SiS 5595: [W] dev->pci_conf[%02X] = %02X\n", addr, val);
switch (func) {
case 0x00:
sis_5513_pci_to_isa_write(addr, val, dev->p2i);
break;
case 0x01:
sis_5595_pmu_write(addr, val, dev->pmu);
break;
case 0x02:
sis_5572_usb_write(addr, val, dev->usb);
break;
}
}
static uint8_t
sis_5595_read(int func, int addr, void *priv)
{
const sis_5591_t *dev = (sis_5591_t *) priv;
uint8_t ret = 0xff;
switch (func) {
case 0x00:
ret = sis_5513_pci_to_isa_read(addr, dev->p2i);
break;
case 0x01:
ret = sis_5595_pmu_read(addr, dev->pmu);
break;
case 0x02:
ret = sis_5572_usb_read(addr, dev->usb);
break;
}
sis_5591_log("SiS 5592: [R] dev->pci_conf[%02X] = %02X\n", addr, ret);
return ret;
}
static void
sis_5591_close(void *priv)
{
sis_5591_t *dev = (sis_5591_t *) priv;
free(dev);
}
static void *
sis_5591_init(UNUSED(const device_t *info))
{
sis_5591_t *dev = (sis_5591_t *) calloc(1, sizeof(sis_5591_t));
/* Device 0: SiS 5591 */
pci_add_card(PCI_ADD_NORTHBRIDGE, sis_5591_read, sis_5591_write, dev, &dev->nb_slot);
/* Device 1: SiS 5595 */
pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_5595_read, sis_5595_write, dev, &dev->sb_slot);
dev->sis = device_add(&sis_55xx_common_device);
dev->ide = device_add_linked(&sis_5591_5600_ide_device, dev->sis);
if (info->local)
dev->p2i = device_add_linked(&sis_5595_1997_p2i_device, dev->sis);
else
dev->p2i = device_add_linked(&sis_5595_p2i_device, dev->sis);
dev->h2p = device_add_linked(&sis_5591_h2p_device, dev->sis);
dev->usb = device_add_linked(&sis_5595_usb_device, dev->sis);
if (info->local)
dev->pmu = device_add_linked(&sis_5595_1997_pmu_device, dev->sis);
else
dev->pmu = device_add_linked(&sis_5595_pmu_device, dev->sis);
device_add_params(&kbc_at_device, (void *) KBC_VEN_SIS);
return dev;
}
const device_t sis_5591_1997_device = {
.name = "SiS 5591 (1997)",
.internal_name = "sis_5591_1997",
.flags = DEVICE_PCI,
.local = 1,
.init = sis_5591_init,
.close = sis_5591_close,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t sis_5591_device = {
.name = "SiS 5591",
.internal_name = "sis_5591",
.flags = DEVICE_PCI,
.local = 0,
.init = sis_5591_init,
.close = sis_5591_close,
.reset = NULL,
.available = NULL,
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

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

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

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