Merge branch 'master' into fullscreenstaticonqt

This commit is contained in:
Miran Grča
2023-11-08 07:08:51 +01:00
committed by GitHub
1296 changed files with 451357 additions and 336123 deletions

View File

@@ -1,26 +1,35 @@
#
# 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.
#
# Recipe file for appimage-builder.
# Recipe file for appimage-builder.
#
# build.sh processes conditional comments based on CMakeCache
# options at the end of each line. For example, a line ending in:
#
# # if QT:BOOL=ON
#
# will be removed from the dynamically-generated copy of this
# file if "QT" is not a boolean option set to ON, either through
# a -D definition or the option's default value in CMakeLists.
#
#
# Authors: RichardG, <richardg867@gmail.com>
# Authors: RichardG, <richardg867@gmail.com>
#
# Copyright 2022 RichardG.
# Copyright 2022 RichardG.
#
version: 1
AppDir:
path: ./archive_tmp
app_info:
id: !ENV 'net.${project_lower}.${project_lower}'
id: !ENV '${project_id}'
name: !ENV '${project}'
icon: !ENV '${project_lower}'
icon: !ENV '${project_icon}'
version: !ENV '${project_version}'
exec: !ENV 'usr/local/bin/${project}'
exec_args: $@
@@ -28,67 +37,60 @@ AppDir:
arch: !ENV '${arch_deb}'
sources:
- sourceline: 'deb http://deb.debian.org/debian bullseye main'
key_url: 'https://ftp-master.debian.org/keys/archive-key-11.asc'
key_url: 'https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x1f89983e0081fde018f3cc9673a4f27b8dd47936'
- sourceline: 'deb http://security.debian.org/debian-security bullseye-security main'
key_url: 'https://ftp-master.debian.org/keys/archive-key-11.asc'
key_url: 'https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x1f89983e0081fde018f3cc9673a4f27b8dd47936'
- sourceline: 'deb http://deb.debian.org/debian bullseye-updates main'
key_url: 'https://ftp-master.debian.org/keys/archive-key-11-security.asc'
key_url: 'https://keyserver.ubuntu.com/pks/lookup?op=get&search=0xac530d520f2f3269f5e98313a48449044aad5c5d'
include:
- libevdev2
- libfluidsynth2
- libedit2 # if (CLI:BOOL=ON|QT:BOOL=OFF)
- libevdev2 # if QT:BOOL=ON
- libfreetype6
- libgbm1
- libgl1
- libgles2
- libglvnd0
- libglx0
- libgbm1 # if QT:BOOL=ON
- libgl1 # if QT:BOOL=ON
- libgles2 # if QT:BOOL=ON
- libglvnd0 # if QT:BOOL=ON
- libglx0 # if QT:BOOL=ON
- libgomp1
- libgs9
- libpng16-16
- libqt5core5a
- libqt5gui5
- libqt5widgets5
- libqt5core5a # if QT:BOOL=ON
- libqt5gui5 # if QT:BOOL=ON
- libqt5widgets5 # if QT:BOOL=ON
- libsixel1 # if CLI:BOOL=ON
- libslirp0
- libsndio7.0
- libwayland-client0
- libx11-6
- libxcb1
- 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
- libx11-xcb1 # if QT:BOOL=ON
- libxcb1 # if QT:BOOL=ON
- libxcb-render0 # if QT:BOOL=ON
- libxcb-shape0 # if QT:BOOL=ON
- libxcb-shm0 # if QT:BOOL=ON
- libxcb-xfixes0 # if QT:BOOL=ON
- libxkbcommon-x11-0 # if QT:BOOL=ON
- qtwayland5 # if QT:BOOL=ON
- zlib1g
files:
exclude:
- etc
- lib/udev
- opt/libc/usr/share
- usr/bin
- usr/include
- usr/lib/*/libasound.so.*
- usr/lib/cmake
- usr/lib/pkgconfig
- usr/sbin
- usr/share/alsa
- usr/share/apport
- usr/share/bug
- usr/share/color
- usr/share/doc
- usr/share/doc-base
- usr/share/fontconfig
- usr/share/fonts
- usr/share/ghostscript
- usr/share/glib-2.0
- usr/share/info
- usr/share/libinput
- usr/share/libwacom
- usr/share/lintian
- usr/share/locale
- usr/share/man
- usr/share/metainfo
- usr/share/openal
- usr/share/pkgconfig
- usr/share/poppler
- usr/share/readline
- usr/share/rtmidi
- usr/share/sounds
- usr/share/X11
- usr/share/xml
- usr/[!ls]* # * except lib, local, share
- usr/lib/*/libasound.so.* # using our own ALSA can cause issues, and the API is pretty stable anyway
- usr/lib/*.a # produced by library compilation
- usr/lib/cmake # produced by library compilation
- usr/lib/pkgconfig # produced by library compilation
- usr/s[!h]* # s* except share
- usr/share/[!aim]* # * except applications, icons, metainfo
- usr/share/a[!p]* # a* except applications
- usr/share/ap[!p]* # ap* except applications
- usr/share/app[!l]* # app* except applications
- usr/share/i[!c]* # i* except icons
- usr/share/icons/[!h]* # * except hicolor
- usr/share/icons/h[!i]* # h* except hicolor
- usr/share/m[!e]* # m* except metainfo
- usr/share/metainfo/*.metainfo.xml # metainfo for libraries
- var
AppImage:
arch: !ENV '${arch_appimage}'
file_name: !ENV '${appimage_path}'

286
.ci/Jenkinsfile vendored
View File

@@ -1,32 +1,37 @@
/*
* 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.
*
* Jenkins build pipeline definition.
* Jenkins build pipeline definition.
*
*
*
* Authors: RichardG, <richardg867@gmail.com>
* Authors: RichardG, <richardg867@gmail.com>
*
* Copyright 2021 RichardG.
* Copyright 2021-2022 RichardG.
*/
def repository = 'https://github.com/86Box/86Box.git'
def commitBrowser = 'https://github.com/86Box/86Box/commit/%s'
def branch = 'master'
/* ['main builds', 'branch builds'] */
def repository = ['https://github.com/86Box/86Box.git', scm.userRemoteConfigs[0].url]
def commitBrowser = ['https://github.com/86Box/86Box/commit/%s', null]
def branch = ['master', scm.branches[0].name]
def buildType = ['beta', 'alpha']
def buildBranch = env.JOB_BASE_NAME.contains('-') ? 1 : 0
def osArchs = [
'Windows': ['32', '64'],
'Linux': ['x86', 'x86_64', 'arm32', 'arm64']
'Linux': ['x86', 'x86_64', 'arm32', 'arm64'],
'macOS': ['x86_64+x86_64h+arm64']
]
def osFlags = [
'Windows': '',
'Linux': '-D QT=ON'
'Windows': '-D QT=ON',
'Linux': '-D QT=ON',
'macOS': '-D QT=ON'
]
def archNames = [
@@ -38,6 +43,12 @@ def archNames = [
'arm64': 'ARM (64-bit)'
]
def archNamesMac = [
'x86_64': 'Intel',
'arm64': 'Apple Silicon',
'x86_64+arm64': 'Universal (Intel and Apple Silicon)'
]
def dynarecNames = [
'ODR': 'Old Recompiler (recommended)',
'NDR': 'New Recompiler (beta)',
@@ -50,9 +61,8 @@ def dynarecArchs = [
'64': ['ODR', 'NDR'],
'x86_64': ['ODR', 'NDR'],
'arm32': ['NDR'],
'ARM32': ['NDR'],
'arm64': ['NDR'],
'ARM64': ['NDR']
'x86_64+arm64': ['ODR', 'NDR']
]
def dynarecFlags = [
@@ -68,8 +78,7 @@ def dynarecSlugs = [
]
def presets = [
'Regular',
'Debug'
'Regular'
]
def presetSlugs = [
@@ -80,58 +89,77 @@ def presetSlugs = [
def presetFlags = [
'Regular': '-t --preset=regular -D CMAKE_BUILD_TYPE=Release',
'Debug': '--preset=debug -D CMAKE_BUILD_TYPE=Debug',
'Dev': '--preset=experimental -D CMAKE_BUILD_TYPE=Debug -D VNC=OFF'
'Debug': '--preset=debug -D CMAKE_BUILD_TYPE=Debug -D STATIC_BUILD=OFF',
'Dev': '--preset=experimental -D CMAKE_BUILD_TYPE=Debug -D VNC=OFF -D STATIC_BUILD=OFF'
]
def anyFailure = false
def gitClone(repository, branch) {
/* Clean workspace. */
cleanWs()
/* Use stashes to avoid performing multiple clones. */
if (env.GIT_STASHED != 'true') {
/* Perform clone/checkout. */
def scmVars = checkout poll: true,
changelog: true,
scm: [$class: 'GitSCM',
branches: [[name: branch]],
userRemoteConfigs: [[url: repository]]]
/* Perform git clone if stashed data isn't available yet, or if
this is not debian.citadel where stash is faster than clone. */
if (env.GIT_STASHED != 'true' || env.NODE_NAME != 'debian.citadel') {
/* Catch network issues in clone. */
try {
/* Perform clone/checkout, making sure to set poll and changelog only
once to avoid interference from new commits pushed inbetween clones. */
def scmVars = checkout(poll: env.GIT_STASHED != 'true',
changelog: env.GIT_STASHED != 'true',
scm: [$class: 'GitSCM',
branches: [[name: branch]],
userRemoteConfigs: [[url: repository]]])
if (env.GIT_COMMIT == null) {
/* Save the current HEAD commit. */
env.GIT_COMMIT = scmVars.GIT_COMMIT
} else if (env.GIT_COMMIT != scmVars.GIT_COMMIT) {
/* Checkout the commit read from the polling log. */
if (isUnix())
sh "git checkout ${env.GIT_COMMIT} || exit 0"
else
bat "git checkout ${env.GIT_COMMIT} || exit /b 0"
if (env.GIT_COMMIT == null) {
/* Save the current HEAD commit. */
env.GIT_COMMIT = scmVars.GIT_COMMIT
} else if (env.GIT_COMMIT != scmVars.GIT_COMMIT) {
/* Checkout the commit read from the polling log. */
if (isUnix())
sh(returnStatus: true, script: "git checkout ${env.GIT_COMMIT}")
else
bat(returnStatus: true, script: "git checkout ${env.GIT_COMMIT}")
}
println "[-] Using git commit [${env.GIT_COMMIT}]"
/* Stash data if required, marking it as stashed. */
if (env.GIT_STASHED != 'true') {
stash(name: 'git', useDefaultExcludes: false)
env.GIT_STASHED = 'true'
}
/* No need to use stashed data. */
return;
} catch (e) {
/* If clone fails, use stashed data if available, or re-throw exception otherwise. */
if (env.GIT_STASHED != 'true')
throw e;
}
println "[-] Using git commit [${env.GIT_COMMIT}]"
/* Stash data and mark it as stashed. */
stash name: 'git', useDefaultExcludes: false
env.GIT_STASHED = 'true'
} else {
/* Unstash data. */
unstash name: 'git'
}
/* Unstash data. */
unstash(name: 'git')
}
def removeDir(dir) {
if (isUnix())
sh "rm -rf \"$dir\" || exit 0"
return sh(returnStatus: true, script: "rm -rf '$dir'")
else
bat "if exist \"$dir\" rd /s /q \"$dir\" & exit /b 0"
return bat(returnStatus: true, script: "rd /s /q \"$dir\"")
}
def runBuild(args) {
if (isUnix())
sh "chmod u+x \"$WORKSPACE/.ci/build.sh\" && exec \"$WORKSPACE/.ci/build.sh\" $args"
return sh(returnStatus: true, script: "chmod u+x '$WORKSPACE/.ci/build.sh' && exec '$WORKSPACE/.ci/build.sh' $args")
else
bat "C:\\msys64\\msys2_shell.cmd -msys2 -defterm -here -no-start -c 'exec \"\$(cygpath -u \\'%WORKSPACE%\\')/.ci/build.sh\" $args'"
return bat(returnStatus: true, script: "C:\\msys64\\msys2_shell.cmd -msys2 -defterm -here -no-start -c 'exec \"\$(cygpath -u \\'%WORKSPACE%\\')/.ci/build.sh\" $args'")
}
def failStage() {
/* Force this stage to fail. */
catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
def x = 1 / 0
}
}
pipeline {
@@ -142,24 +170,26 @@ pipeline {
}
options {
disableConcurrentBuilds()
quietPeriod(0)
}
parameters {
string(name: 'BUILD_TYPE',
defaultValue: 'beta', /* !!! CHANGE HERE !!! for build type */
description: "Build type to pass on to CMake. Should only be changed for one-off builds, otherwise change the default on .ci/Jenkinsfile")
defaultValue: buildType[buildBranch],
description: "Build type to pass on to CMake (on main builds) or feature branch identifier (on branch builds).")
}
stages {
stage('Source Tarball') {
agent none
failFast false
steps {
script {
/* Extract the polled commit from the polling log, so that git checkout can be used
to avoid JENKINS-20518 race conditions caused by two pushes too close together. */
/* Extract the polled commit from the polling log, so that git checkout
can be used to avoid JENKINS-20518 race conditions caused by the
webhook being triggered more than once in a short period of time.
This is a backup strategy for FilterProxy's webhook queuing. */
node('master') { /* must run on master node to read polling log */
/* Ignore exceptions as this is not really critical. */
try {
@@ -178,78 +208,103 @@ pipeline {
/* Adding to the above, run a git clone as soon as possible on any node
to further avoid race conditions caused by busy node executor delays. */
node {
/* Run git clone. */
gitClone(repository, branch)
retry(10) {
node('!Windows') {
/* Run git clone. */
gitClone(repository[buildBranch], branch[buildBranch])
/* Clean workspace, in case this is running in a non-build node. */
cleanWs()
/* Clean workspace, in case this is running in a non-build node. */
cleanWs()
}
}
/* Determine build metadata. */
def buildFlags = "-D \"BUILD_TYPE=$BUILD_TYPE\" -D \"EMU_BUILD=build ${env.BUILD_NUMBER}\" -D \"EMU_BUILD_NUM=${env.BUILD_NUMBER}\""
def buildSuffix = "-b${env.BUILD_NUMBER}"
if (buildBranch > 0) {
def date = new Date().format("yyyyMMdd")
buildFlags = "-D \"BUILD_TYPE=${buildType[buildBranch]}\" -D \"EMU_BUILD=${env.JOB_BASE_NAME.split('-')[1]} build $date.$BUILD_TYPE\""
buildSuffix = "-$date-$BUILD_TYPE"
}
/* Create source tarball. */
node('Linux') {
try {
/* Run git clone. */
gitClone(repository, branch)
try {
retry(10) {
node('Linux || macOS') {
/* Run git clone. */
gitClone(repository[buildBranch], branch[buildBranch])
/* Switch to temp directory. */
dir("${env.WORKSPACE_TMP}/output") {
/* Run source tarball creation process. */
def packageName = "${env.JOB_BASE_NAME}-Source-b${env.BUILD_NUMBER}"
runBuild("-s \"$packageName\"")
/* Switch to temp directory. */
dir("${env.WORKSPACE_TMP}/output") {
/* Run source tarball creation process. */
def packageName = "${env.JOB_BASE_NAME}-Source$buildSuffix"
if (runBuild("-s \"$packageName\"") == 0) {
/* Archive resulting artifacts. */
archiveArtifacts artifacts: "$packageName*"
} else {
/* Fail this stage. */
failStage()
}
}
/* Archive resulting artifacts. */
archiveArtifacts artifacts: "$packageName*"
}
/* Clean up. */
removeDir("${env.WORKSPACE_TMP}/output")
} catch (e) {
/* Mark that a failure occurred. */
anyFailure = true
/* Force this stage to fail. */
catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
throw e;
/* Clean up. */
removeDir("${env.WORKSPACE_TMP}/output")
}
}
} catch (e) {
/* Fail this stage. */
failStage()
}
/* Build here to avoid creating a redundant parent stage on the stage view. */
osArchs.each { os, thisOsArchs ->
def combinations = [:]
thisOsArchs.each { arch ->
def thisArchDynarecs = dynarecArchs[arch]
def archSlug = arch.replace('+x86_64h', '') /* all instances of arch except the one passed to -b */
def thisArchDynarecs = dynarecArchs[archSlug.toLowerCase()]
if (!thisArchDynarecs)
thisArchDynarecs = ['NoDR']
thisArchDynarecs.each { dynarec ->
presets.each { preset ->
node(os) {
stage("$os $arch $dynarec $preset") {
try {
/* Run git clone. */
gitClone(repository, branch)
def combination = "$os $archSlug $dynarec $preset"
combinations[combination] = {
catchError(buildResult: 'FAILURE', stageResult: 'SUCCESS') {
retry(10) {
node(os) {
stage(combination) {
/* Run git clone. */
gitClone(repository[buildBranch], branch[buildBranch])
/* Switch to output directory. */
dir("${env.WORKSPACE_TMP}/output") {
/* Run build process. */
def packageName = "${env.JOB_BASE_NAME}${dynarecSlugs[dynarec]}${presetSlugs[preset]}-$os-$arch-b${env.BUILD_NUMBER}"
dir("${dynarecNames[dynarec]}/$os - ${archNames[arch]}") {
runBuild("-b \"$packageName\" \"$arch\" ${presetFlags[preset]} ${dynarecFlags[dynarec]} ${osFlags[os]} -D \"BUILD_TYPE=$BUILD_TYPE\" -D \"EMU_BUILD=build ${env.BUILD_NUMBER}\" -D \"EMU_BUILD_NUM=${env.BUILD_NUMBER}\"")
/* Switch to output directory. */
dir("${env.WORKSPACE_TMP}/output") {
/* Run build process. */
def packageName = "${env.JOB_BASE_NAME}${dynarecSlugs[dynarec]}${presetSlugs[preset]}-$os-$archSlug$buildSuffix"
def ret = -1
def archName = archNames[archSlug]
if (os == 'macOS')
archName = archNamesMac[archSlug]
dir(dynarecNames[dynarec]) {
dir("$os - $archName") {
ret = runBuild("-b \"$packageName\" \"$arch\" ${presetFlags[preset]} ${dynarecFlags[dynarec]} ${osFlags[os]} $buildFlags")
if (presets.size() == 1)
writeFile file: '.forcedir', text: ''
}
if ((osArchs.size() == 1) && (thisOsArchs.size() == 1))
writeFile file: '.forcedir', text: ''
}
if (ret == 0) {
/* Archive resulting artifacts. */
archiveArtifacts artifacts: "**/$packageName*, **/.forcedir", defaultExcludes: false
} else {
/* Fail this stage. */
failStage()
}
}
/* Clean up. */
removeDir("${env.WORKSPACE_TMP}/output")
}
/* Archive resulting artifacts. */
archiveArtifacts artifacts: "**/**/$packageName*"
}
/* Clean up. */
removeDir("${env.WORKSPACE_TMP}/output")
} catch (e) {
/* Mark that a failure occurred. */
anyFailure = true
/* Force this stage to fail. */
catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
throw e;
}
}
}
@@ -257,6 +312,7 @@ pipeline {
}
}
}
parallel combinations
}
}
}
@@ -266,14 +322,8 @@ pipeline {
post {
always {
script {
/* Mark build as failed if any step has failed. */
if (anyFailure) {
println "[!] Failing build because a build stage failed"
currentBuild.result = 'FAILURE'
}
/* Send out build notifications. */
if (!env.JOB_BASE_NAME.contains('TestBuildPleaseIgnore')) {
if (commitBrowser[buildBranch]) {
try {
/* Notify Discord. */
def result = currentBuild.currentResult.toLowerCase()
@@ -284,10 +334,10 @@ pipeline {
description: "**Status:** ${result}\n\u2060", /* word joiner character forces a blank line */
enableArtifactsList: false,
showChangeset: true,
scmWebUrl: commitBrowser
scmWebUrl: commitBrowser[buildBranch]
/* Notify IRC, which needs a node for whatever reason. */
node {
node('citadel || rg || master') {
ircNotify()
}
} catch (e) {

966
.ci/build.sh Normal file → Executable file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,17 @@
cmake
pkgconfig
ninja
freetype
libsdl2
libpng
openal-soft
FAudio
rtmidi
vulkan-headers
MoltenVK
qt5
wget
fluidsynth
ghostscript
libslirp
vde2

14
.ci/dependencies_msys.txt Normal file
View File

@@ -0,0 +1,14 @@
ninja
cmake
gcc
pkgconf
openal
freetype
SDL2
zlib
libpng
rtmidi
libslirp
fluidsynth
qt5-static
qt5-translations

View File

@@ -1,160 +0,0 @@
#!/bin/sh
#
# 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.
#
# Script for converting MinGW static libraries into a DLL.
#
#
# Authors: RichardG, <richardg867@gmail.com>
#
# Copyright 2021 RichardG.
#
def_file="static2dll.def"
seen_file="static2dll.seen"
libs_file="static2dll.libs"
find_lib() {
# Try to find a static library's file.
local msystem_lib="/$(echo $MSYSTEM | tr '[:upper:]' '[:lower:]')/lib/lib"
if [ -e "$msystem_lib$1.a" ]
then
echo "$msystem_lib$1.a"
elif [ -e "$msystem_lib$1.dll.a" ]
then
echo "$msystem_lib$1.dll.a"
else
# Return dynamic reference to the library.
echo "-l$1"
return 1
fi
}
add_lib() {
# Always make sure this lib is listed after the last lib that depends on it.
old_libs=$(cat "$libs_file")
rm -f "$libs_file"
for lib in $old_libs
do
[ "$lib" != "$*" ] && echo "$lib" >> "$libs_file"
done
echo "$*" >> "$libs_file"
# Add libstdc++ in the end if required.
if echo "$*" | grep -q "/"
then
grep -Eq -- "__cxa_|__gxx_" "$1" 2> /dev/null && add_lib -static -lstdc++
fi
# Add libiconv for libintl.
if echo "$*" | grep -q "libintl"
then
add_lib $(find_lib iconv)
fi
# Add libuuid for glib.
if echo "$*" | grep -q "libglib"
then
add_lib $(find_lib uuid)
fi
}
run_pkgconfig() {
local cache_file="static2dll.$1.cache"
if [ -e "$cache_file" ]
then
cat "$cache_file"
else
pkg-config --static --libs "$1" 2> /dev/null | tee "$cache_file"
fi
}
parse_pkgconfig() {
# Parse arguments.
local layers=$1
shift
local input_lib_name=$1
shift
# Don't process the same file again.
grep -q '^'$input_lib_name'$' "$seen_file" && return
echo $input_lib_name >> "$seen_file"
echo "$layers" parse_pkgconfig $input_lib_name
# Parse pkg-config arguments.
for arg in $*
do
local arg_base="$(echo $arg | cut -c1-2)"
if [ "x$arg_base" = "x-l" ]
then
# Don't process the same lib again.
local lib_name="$(echo $arg | cut -c3-)"
[ "x$lib_name" == "x$input_lib_name" ] && continue
# Add lib path.
add_lib "$(find_lib $lib_name)"
# Get this lib's dependencies through pkg-config.
local pkgconfig="$(run_pkgconfig "$lib_name")"
[ $? -eq 0 ] && parse_pkgconfig "$layers"'>' "$lib_name" $pkgconfig || echo $lib_name >> "$seen_file"
elif [ "x$(echo $arg_base | cut -c1)" = "x-" ]
then
# Ignore other arguments.
continue
else
# Add lib path.
add_lib "$arg"
fi
done
}
# Parse arguments.
case $1 in
-p) # -p pkg_config_name static_lib_path out_dll
shift
base_pkgconfig=$(run_pkgconfig "$1")
base_path="$2"
base_name="$1"
;;
*) # pc_path static_lib_path out_dll
base_pkgconfig="$(grep ^Libs.private: $1 | cut -d: -f2-)"
base_path="$2"
base_name="$2"
;;
esac
# Check arguments.
if [ -z "$base_pkgconfig" -o -z "$base_path" -o -z "$base_name" ]
then
echo Usage:
echo static2dll.sh -p {pkgconfig_package_name} {static_lib_path} {out_dll_name}
echo static2dll.sh {pc_file_path} {static_lib_path} {out_dll_name}
exit 1
fi
# Produce .def file.
echo LIBRARY $(basename "$3") > "$def_file"
echo EXPORTS >> "$def_file"
nm "$base_path" | grep " [TC] " | sed "/ _/s// /" | awk '{ print $3 }' >> "$def_file"
# Parse dependencies recursively.
rm -f "$seen_file" "$libs_file" "$libs_file.tmp"
touch "$seen_file" "$libs_file"
parse_pkgconfig '>' $base_name $base_pkgconfig
# Produce final DLL.
dllwrap --def "$def_file" -o "$3" -Wl,--allow-multiple-definition "$base_path" $(cat "$libs_file")
status=$?
[ $status -eq 0 ] && rm -f "$def_file" "$seen_file" "$libs_file" "static2dll.*.cache"
# Update final DLL timestamp.
touch -r "$base_path" "$3"
exit $status

19
.clang-format Normal file
View File

@@ -0,0 +1,19 @@
BasedOnStyle: WebKit
AlignAfterOpenBracket: Align
AlignArrayOfStructures: Left
AlignConsecutiveMacros: AcrossEmptyLines
AlignConsecutiveAssignments: Consecutive
AlignConsecutiveBitFields: AcrossEmptyLines
AlignConsecutiveDeclarations: Consecutive
AlignEscapedNewlines: Left
AlignTrailingComments: true
AlwaysBreakAfterReturnType: TopLevelDefinitions
BreakBeforeTernaryOperators: true
IndentCaseLabels: true
IndentCaseBlocks: true
IndentGotoLabels: false
IndentPPDirectives: AfterHash
IndentExternBlock: NoIndent
PointerAlignment: Right
SpaceAfterCStyleCast: true
SortIncludes: false

View File

@@ -1,21 +1,21 @@
[*]
charset = utf-8
end_of_line = lf
indent_style = tab
indent_size = 8
tab_width = 8
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 = 8
# tab_width = 4
# [Makefile.*]
# indent_style = space
# indent_size = 4
# tab_width = 8
# tab_width = 4
[*.manifest]
indent_style = space
@@ -32,3 +32,7 @@ indent_size = 4
[*.cmake]
indent_style = space
indent_size = 4
[*.json]
indent_style = space
indent_size = 4

21
.gitattributes vendored Normal file
View File

@@ -0,0 +1,21 @@
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto
# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
*.c text
*.cc text
*.cpp text
*.h text
*.hpp text
*.rc text
# Declare files that will always have CRLF line endings on checkout.
*.sln text eol=crlf
# Denote all files that are truly binary and should not be modified.
*.ico binary
*.png binary
*.jpg binary
*.dat

View File

@@ -1,32 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. Windows 10]
- 86Box version: [e.g. v3.00 build 3333; saying "Latest from Jenkins" isn't helpful]
- Build information: [i.e. new/old dynarec, architecture and build type]
**Additional context**
Add any other context about the problem here. If you are using an Optimized build, make sure to try the regular build too before filing a bug report!

80
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View File

@@ -0,0 +1,80 @@
name: Bug Report
description: File a bug report
title: "Title"
labels: ["bug"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
- type: textarea
attributes:
label: What happened?
description: Also tell us, what did you expect to happen?
placeholder: Tell us what you see!
validations:
required: true
- type: textarea
attributes:
label: Configuration file
description: Please copy and paste your machine configuration file (`86box.cfg`). This will be automatically formatted into code, so no need for backticks.
render: ini
validations:
required: true
- type: input
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
validations:
required: true
- type: input
attributes:
label: 86Box version
description: What version of 86Box are you running? (Saying "Latest from Jenkins" is not helpful.)
placeholder: e.g. v4.0 build 5000
validations:
required: true
- type: dropdown
attributes:
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)
- Windows - x86 (32-bit)
validations:
required: true
- type: checkboxes
attributes:
label: Build type
description: What type of build are you using?
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?

View File

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

View File

@@ -1,20 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: feature
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

5
.github/codeql/codeql-config.yml vendored Normal file
View File

@@ -0,0 +1,5 @@
name: "86Box CodeQL config"
queries:
- uses: security-extended
# - uses: security-and-quality

9
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,9 @@
version: 2
updates:
# Maintain dependencies for GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"

View File

@@ -1,4 +1,4 @@
name: MinGW64 Makefile
name: MSYS2 Makefile
on:
@@ -15,10 +15,10 @@ on:
- "!**/CMakeLists.txt"
jobs:
build:
name: ${{ matrix.environment.msystem }} Makefile build (DEV_BUILD=${{ matrix.dev-build }}, NEW_DYNAREC=${{ matrix.new-dynarec }})
msys2:
name: "Windows MSYS2 Makefile (Win32 GUI, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, ${{ matrix.environment.msystem }})"
runs-on: windows-latest
runs-on: windows-2022
defaults:
run:
@@ -27,33 +27,88 @@ jobs:
strategy:
fail-fast: true
matrix:
dev-build: ['y', 'n']
new-dynarec: ['y', 'n']
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:
- uses: msys2/setup-msys2@v2
with:
update: true
msystem: ${{ matrix.environment.msystem }}
install: >-
make
${{ matrix.environment.prefix }}-gcc
${{ matrix.environment.prefix }}-pkg-config
${{ matrix.environment.prefix }}-openal
${{ matrix.environment.prefix }}-freetype
${{ matrix.environment.prefix }}-SDL2
${{ matrix.environment.prefix }}-zlib
${{ matrix.environment.prefix }}-libpng
${{ matrix.environment.prefix }}-libvncserver
${{ matrix.environment.prefix }}-rtmidi
- uses: actions/checkout@v2
- name: make
run: make -fwin/makefile.mingw -j DEV_BUILD=${{ matrix.dev-build }} NEW_DYNAREC=${{ matrix.new-dynarec }} X64=${{ matrix.environment.x64 }} VNC=n
working-directory: ./src
- 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

@@ -4,28 +4,34 @@ on:
push:
paths:
- src/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- .github/workflows/cmake.yml
- vcpkg.json
- "!**/Makefile*"
- src/**
- cmake/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- .github/workflows/cmake.yml
- vcpkg.json
- "!**/Makefile*"
pull_request:
paths:
- src/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- .github/workflows/**
- .github/workflows/cmake.yml
- vcpkg.json
- "!**/Makefile*"
- src/**
- cmake/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- .github/workflows/**
- .github/workflows/cmake.yml
- vcpkg.json
- "!**/Makefile*"
jobs:
msys2:
name: MSYS2 ${{ matrix.build.name }} build (${{ matrix.environment.msystem }})
runs-on: windows-latest
msys2:
name: "Windows MSYS2 (${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, ${{ matrix.environment.msystem }})"
runs-on: windows-2022
env:
BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed
defaults:
run:
@@ -35,304 +41,443 @@ jobs:
fail-fast: true
matrix:
build:
- name: Regular ODR
slug: -ODR
preset: regular
target: install/strip
- name: Debug ODR
slug: -ODR-Debug
preset: debug
target: install
- name: Dev ODR
slug: -ODR-Dev
preset: experimental
target: install
- name: Regular NDR
slug: -NDR
preset: regularndr
target: install/strip
- name: Debug NDR
slug: -NDR-Debug
preset: debugndr
target: install
- name: Dev NDR
slug: -NDR-Dev
preset: experimentalndr
target: install
# - 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
static: on
- name: Qt GUI
qt: on
static: on
slug: -Qt
packages: >-
qt5-static:p
# qt5-base:p
# qt5-tools:p
environment:
# - msystem: MSYS
# toolchain: ./cmake/flags-gcc-x86_64.cmake
- msystem: MINGW32
prefix: mingw-w64-i686
toolchain: ./cmake/flags-gcc-i686.cmake
- msystem: MINGW64
prefix: mingw-w64-x86_64
- msystem: UCRT64
prefix: mingw-w64-ucrt-x86_64
toolchain: ./cmake/flags-gcc-x86_64.cmake
# - msystem: CLANG32
# prefix: mingw-w64-clang-i686
- msystem: CLANG64
prefix: mingw-w64-clang-x86_64
# toolchain: ./cmake/llvm-win32-i686.cmake
# - msystem: CLANG64
# prefix: mingw-w64-clang-x86_64
# toolchain: ./cmake/llvm-win32-x86_64.cmake
- msystem: UCRT64
prefix: mingw-w64-ucrt-x86_64
toolchain: ./cmake/flags-gcc-x86_64.cmake
steps:
- uses: msys2/setup-msys2@v2
with:
path-type: inherit
update: true
msystem: ${{ matrix.environment.msystem }}
install: >-
${{ matrix.environment.prefix }}-ninja
${{ matrix.environment.prefix }}-cc
${{ matrix.environment.prefix }}-pkg-config
${{ matrix.environment.prefix }}-openal
${{ matrix.environment.prefix }}-freetype
${{ matrix.environment.prefix }}-SDL2
${{ matrix.environment.prefix }}-zlib
${{ matrix.environment.prefix }}-libpng
${{ matrix.environment.prefix }}-libvncserver
${{ matrix.environment.prefix }}-rtmidi
- uses: actions/checkout@v2
- name: Configure CMake
run: >-
cmake -S . -B build
--preset ${{ matrix.build.preset }}
-D CMAKE_INSTALL_PREFIX=./build/artifacts
-D VNC=OFF
- name: Build
run: cmake --build build --target ${{ matrix.build.target }}
- uses: actions/upload-artifact@v2
with:
name: '86Box${{ matrix.build.slug }}-Windows-${{ matrix.environment.msystem }}-gha${{ github.run_number }}'
path: build/artifacts/**
- name: Prepare MSYS2 environment
uses: msys2/setup-msys2@v2
with:
release: false
update: true
msystem: ${{ matrix.environment.msystem }}
pacboy: >-
ninja:p
cmake:p
gcc:p
pkgconf:p
freetype:p
SDL2:p
zlib:p
libpng:p
openal:p
rtmidi:p
libslirp:p
fluidsynth:p
libvncserver:p
${{ 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 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 }}"
- 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-${{ matrix.environment.msystem }}-gha${{ github.run_number }}'
path: build/artifacts/**
llvm-windows:
name: "Windows vcpkg/LLVM (${{ matrix.build.name }} ${{ matrix.target.name }})"
name: "Windows vcpkg/LLVM (${{ 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 ODR
slug: -ODR
type: Release
dev-build: off
new-dynarec: off
strip: --strip
- name: Debug ODR
slug: -ODR-Debug
type: Debug
dev-build: off
new-dynarec: off
- name: Dev ODR
slug: -ODR-Dev
type: Debug
dev-build: on
new-dynarec: off
- name: Regular NDR
slug: -NDR
type: Release
strip: --strip
dev-build: off
new-dynarec: on
- name: Debug NDR
slug: -NDR-Debug
type: Debug
dev-build: off
new-dynarec: on
- name: Dev NDR
slug: -NDR-Dev
type: Debug
dev-build: on
new-dynarec: on
# - 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: ARM64
triplet: arm64-windows-static
toolchain: cmake/llvm-win32-aarch64.cmake
vcvars: x64_arm64
- 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:
- build:
new-dynarec: off
target:
name: ARM64
- dynarec:
new: off
target:
name: ARM64
steps:
- uses: actions/checkout@v2
- name: Download Ninja
run: >
Invoke-WebRequest https://github.com/ninja-build/ninja/releases/download/v1.10.2/ninja-win.zip -OutFile ninja-win.zip &&
Expand-Archive ninja-win.zip -DestinationPath .
- name: Setup NuGet Credentials
run: >
& (C:/vcpkg/vcpkg 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: vcpkg package restore
if: false
run: vcpkg install freetype libpng openal-soft sdl2 rtmidi --triplet ${{ matrix.target.triplet }}
- name: Configure CMake
run: >
call "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvarsall.bat" ${{ matrix.target.vcvars }}
set PATH=C:/Program Files/LLVM/bin;%PATH%
- name: Prepare VS environment
uses: ilammy/msvc-dev-cmd@v1
with:
arch: ${{ matrix.target.vcvars }}
cmake -S . -B build -G Ninja -D CMAKE_BUILD_TYPE=${{ matrix.build.type }}
-D NEW_DYNAREC=${{ matrix.build.new-dynarec }}
-D CMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake
-D VCPKG_CHAINLOAD_TOOLCHAIN_FILE=${{ github.workspace }}/${{ matrix.target.toolchain }}
-D VCPKG_TARGET_TRIPLET=${{ matrix.target.triplet }}
shell: cmd
- name: Build
run: |
call "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvarsall.bat" ${{ matrix.target.vcvars }}
cmake --build build
shell: cmd
- name: Generate package
run: cmake --install build --prefix ./build/artifacts ${{ matrix.build.strip }}
- uses: actions/upload-artifact@v2
with:
name: '86Box${{ matrix.build.slug }}-Windows-LLVM-${{ matrix.target.name }}-gha${{ github.run_number }}'
path: build/artifacts/**
- 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/**
linux:
name: "Linux GCC 11 (${{ matrix.build.name }} x86_64)"
name: "Linux GCC 11 (${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, x86_64)"
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
env:
BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed
strategy:
fail-fast: true
matrix:
build:
- name: Regular ODR
slug: -ODR
type: Release
dev-build: off
new-dynarec: off
strip: --strip
- name: Debug ODR
slug: -ODR-Debug
type: Debug
dev-build: off
new-dynarec: off
- name: Dev ODR
slug: -ODR-Dev
type: Debug
dev-build: on
new-dynarec: off
- name: Regular NDR
slug: -NDR
type: Release
strip: --strip
dev-build: off
new-dynarec: on
- name: Debug NDR
slug: -NDR-Debug
type: Debug
dev-build: off
new-dynarec: on
- name: Dev NDR
slug: -NDR-Dev
type: Debug
dev-build: on
new-dynarec: on
# - 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: SDL GUI
qt: off
static: on
- name: Qt GUI
qt: on
slug: -Qt
packages: >-
qtbase5-dev
qtbase5-private-dev
qttools5-dev
libevdev-dev
libxkbcommon-x11-dev
steps:
- uses: actions/checkout@v2
- name: Install dependencies
run: sudo apt update && sudo apt install gcc-11 g++-11 libfreetype-dev libsdl2-dev libpng-dev libopenal-dev libc6-dev librtmidi-dev qtbase5-dev qttools5-dev
run: >-
sudo apt update && sudo apt install
build-essential
ninja-build
libfreetype-dev
libsdl2-dev
libpng-dev
libc6-dev
librtmidi-dev
libopenal-dev
libslirp-dev
libfluidsynth-dev
libvncserver-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 sonar-scanner and build-wrapper
uses: SonarSource/sonarcloud-github-c-cpp@v2
- name: Configure CMake
run: >-
cmake -S . -B build
cmake -G Ninja -S . -B build --preset ${{ matrix.build.preset }}
--toolchain ./cmake/flags-gcc-x86_64.cmake
-D NEW_DYNAREC=${{ matrix.dynarec.new }}
-D CMAKE_INSTALL_PREFIX=./build/artifacts
-D DEV_BRANCH=${{ matrix.build.dev-build }}
-D NEW_DYNAREC=${{ matrix.build.new-dynarec }}
-D QT=ON
-D CMAKE_BUILD_TYPE=${{ matrix.build.type }}
-D CMAKE_C_COMPILER=gcc-11 -D CMAKE_CXX_COMPILER=g++-11
-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: 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 }}"
- name: Generate package
run: cmake --install build --prefix ./build/artifacts ${{ matrix.build.strip }}
- uses: actions/upload-artifact@v2
run: |
cmake --install build
- name: Upload artifact
uses: actions/upload-artifact@v3
with:
name: '86Box${{ matrix.build.slug }}-UbuntuFocal-x86_64-gha${{ github.run_number }}'
name: '86Box${{ matrix.ui.slug }}${{ matrix.dynarec.slug }}${{ matrix.build.slug }}-UbuntuJammy-x86_64-gha${{ github.run_number }}'
path: build/artifacts/**
macos11:
name: "macOS 11 (${{ matrix.build.name }} x86_64)"
name: "macOS 11 (${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, x86_64)"
runs-on: macos-11
env:
BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed
strategy:
fail-fast: true
matrix:
build:
- name: Regular ODR
slug: -ODR
type: Release
dev-build: off
new-dynarec: off
strip: --strip
- name: Debug ODR
slug: -ODR-Debug
type: Debug
dev-build: off
new-dynarec: off
- name: Dev ODR
slug: -ODR-Dev
type: Debug
dev-build: on
new-dynarec: off
- name: Regular NDR
slug: -NDR
type: Release
strip: --strip
dev-build: off
new-dynarec: on
- name: Debug NDR
slug: -NDR-Debug
type: Debug
dev-build: off
new-dynarec: on
- name: Dev NDR
slug: -NDR-Dev
type: Debug
dev-build: on
new-dynarec: on
# - 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: SDL GUI
qt: off
static: on
src-packages: >-
libsndfile
- name: Qt GUI
qt: on
slug: -Qt
packages: >-
qt@5
src-packages: >-
libsndfile
steps:
- uses: actions/checkout@v2
- name: Install source dependencies
run: >-
brew reinstall -s
${{ matrix.ui.src-packages }}
- name: Install dependencies
run: brew install freetype sdl2 libpng openal-soft rtmidi qt@5
run: >-
brew install
ninja
freetype
sdl2
libpng
rtmidi
openal-soft
fluidsynth
libvncserver
${{ 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 sonar-scanner and build-wrapper
uses: SonarSource/sonarcloud-github-c-cpp@v2
- name: Configure CMake
run: >-
cmake -S . -B build
--toolchain cmake/flags-gcc-x86_64.cmake
-D DEV_BRANCH=${{ matrix.build.dev-build }}
-D NEW_DYNAREC=${{ matrix.build.new-dynarec }}
-D VNC=OFF
-D CMAKE_BUILD_TYPE=${{ matrix.build.type }}
-D QT=ON
-D Qt5_DIR=/usr/local/Cellar/qt@5/5.15.2_1/lib/cmake/Qt5
-D Qt5LinguistTools_DIR=/usr/local/Cellar/qt@5/5.15.2_1/lib/cmake/Qt5LinguistTools/
cmake -G Ninja -S . -B build --preset ${{ matrix.build.preset }}
--toolchain ./cmake/flags-gcc-x86_64.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)
- name: Build
run: cmake --build 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 }}"
- name: Generate package
run: cmake --install build --prefix ./build/artifacts ${{ matrix.build.strip }}
- uses: actions/upload-artifact@v2
run: |
cmake --install build
- name: Upload artifact
uses: actions/upload-artifact@v3
with:
name: '86Box${{ matrix.build.slug }}-macOS-x86_64-gha${{ github.run_number }}'
name: '86Box${{ matrix.ui.slug }}${{ matrix.dynarec.slug }}${{ matrix.build.slug }}-macOS-x86_64-gha${{ github.run_number }}'
path: build/artifacts/**

309
.github/workflows/codeql.yml vendored Normal file
View File

@@ -0,0 +1,309 @@
name: CodeQL
on:
push:
paths:
- src/**
- cmake/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- .github/workflows/codeql.yml
- vcpkg.json
- "!**/Makefile*"
pull_request:
paths:
- src/**
- cmake/**
- "**/CMakeLists.txt"
- "CMakePresets.json"
- .github/workflows/**
- .github/workflows/codeql.yml
- vcpkg.json
- "!**/Makefile*"
jobs:
analyze-msys2:
name: "Analyze Windows MSYS2 (${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, ${{ matrix.environment.msystem }})"
runs-on: windows-2022
permissions:
actions: read
contents: read
security-events: write
defaults:
run:
shell: msys2 {0}
strategy:
fail-fast: true
matrix:
language: [ 'cpp' ]
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
static: on
- name: Qt GUI
qt: on
static: off
slug: -Qt
packages: >-
qt5-base:p
qt5-tools:p
environment:
# - msystem: MSYS
# toolchain: ./cmake/flags-gcc-x86_64.cmake
- msystem: MINGW32
prefix: mingw-w64-i686
toolchain: ./cmake/flags-gcc-i686.cmake
- 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
# - 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
steps:
- name: Prepare MSYS2 environment
uses: msys2/setup-msys2@v2
with:
release: false
update: true
msystem: ${{ matrix.environment.msystem }}
pacboy: >-
ninja:p
cmake:p
gcc:p
pkgconf:p
freetype:p
SDL2:p
zlib:p
libpng:p
openal:p
rtmidi:p
libslirp:p
fluidsynth:p
libvncserver:p
${{ matrix.ui.packages }}
- name: Checkout repository
uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
config-file: ./.github/codeql/codeql-config.yml
- 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: cmake --build build
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
category: "/language:${{matrix.language}}"
analyze-linux:
name: "Analyze Linux GCC 11 (${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, x86_64)"
runs-on: ubuntu-22.04
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: true
matrix:
language: [ 'cpp' ]
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: SDL GUI
qt: off
- name: Qt GUI
qt: on
slug: -Qt
packages: >-
qtbase5-dev
qtbase5-private-dev
qttools5-dev
libevdev-dev
libxkbcommon-x11-dev
steps:
- name: Install dependencies
run: >-
sudo apt update && sudo apt install
build-essential
ninja-build
libfreetype-dev
libsdl2-dev
libpng-dev
libc6-dev
librtmidi-dev
libopenal-dev
libslirp-dev
libfluidsynth-dev
libvncserver-dev
${{ matrix.ui.packages }}
- name: Checkout repository
uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
config-file: ./.github/codeql/codeql-config.yml
- name: Configure CMake
run: >-
cmake -G Ninja -S . -B build --preset ${{ matrix.build.preset }}
--toolchain ./cmake/flags-gcc-x86_64.cmake
-D NEW_DYNAREC=${{ matrix.dynarec.new }}
-D CMAKE_INSTALL_PREFIX=./build/artifacts
-D QT=${{ matrix.ui.qt }}
- name: Build
run: cmake --build build
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
category: "/language:${{matrix.language}}"
analyze-macos11:
name: "Analyze macOS 11 (${{ matrix.ui.name }}, ${{ matrix.build.name }}, ${{ matrix.dynarec.name }}, x86_64)"
runs-on: macos-11
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: true
matrix:
language: [ 'cpp' ]
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: SDL GUI
qt: off
- name: Qt GUI
qt: on
slug: -Qt
packages: >-
qt@5
steps:
- name: Install dependencies
run: >-
brew install
ninja
freetype
sdl2
libpng
rtmidi
openal-soft
fluidsynth
libvncserver
${{ matrix.ui.packages }}
- name: Checkout repository
uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
config-file: ./.github/codeql/codeql-config.yml
- name: Configure CMake
run: >-
cmake -G Ninja -S . -B build --preset ${{ matrix.build.preset }}
--toolchain ./cmake/flags-gcc-x86_64.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)
- name: Build
run: cmake --build build
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
category: "/language:${{matrix.language}}"

26
.gitignore vendored
View File

@@ -1,8 +1,8 @@
# CMake
/CMakeUserPresets.json
/CMakeCache.txt
/build
CMakeUserPresets.json
CMakeCache.txt
CMakeFiles
/build
Makefile
*.a
/src/*.exe
@@ -26,6 +26,7 @@ Makefile
# Build scripts
/archive_tmp
/archive_tmp_universal
/static2dll.*
/VERSION
*.zip
@@ -33,11 +34,28 @@ Makefile
*.tar.*
*.AppImage
/appimage-builder-cache
/appimage-build
/AppImageBuilder-generated.yml
# Visual Studio Code
/.vs
/.vscode
src/win/RCa04980
/out
# Windows resource compiler
RC*
# Qt Creator
CMakeLists.txt.user
# Debian builder
/debian/*.log
/debian/*.substvars
/debian/.debhelper
/debian/86box
/debian/debhelper-build-stamp
/debian/files
/obj-*-linux-gnu
# MacOS Finder stuff
.DS_Store

10
AUTHORS
View File

@@ -1,5 +1,5 @@
All authors of this emulator are documented in at the top of each file in the source code.
They own portions of the code, or in cases, the entirety of it.
resid-fp and slirp folders have their own exceptions.
All authors of this emulator are documented in at the top of each file in the source code.
They own portions of the code, or in cases, the entirety of it.
resid-fp and slirp folders have their own exceptions.

View File

@@ -10,7 +10,7 @@
#
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
#
# Copyright 2020,2021 David Hrdlička.
# Copyright 2020-2021 David Hrdlička.
#
cmake_minimum_required(VERSION 3.16)
@@ -18,12 +18,16 @@ cmake_minimum_required(VERSION 3.16)
cmake_policy(SET CMP0091 NEW)
cmake_policy(SET CMP0079 NEW)
if(QT)
if(HAIKU)
set(OPENAL ON)
endif()
if(NOT DEFINED QT OR QT)
list(APPEND VCPKG_MANIFEST_FEATURES "qt-ui")
endif()
if(SLIRP_EXTERNAL)
list(APPEND VCPKG_MANIFEST_FEATURES "slirp")
if(NOT DEFINED OPENAL OR OPENAL)
list(APPEND VCPKG_MANIFEST_FEATURES "openal")
endif()
if(MUNT_EXTERNAL)
@@ -31,7 +35,7 @@ if(MUNT_EXTERNAL)
endif()
project(86Box
VERSION 3.2
VERSION 4.0.2
DESCRIPTION "Emulator of x86-based systems"
HOMEPAGE_URL "https://86box.net"
LANGUAGES C CXX)
@@ -57,6 +61,9 @@ if(VCPKG_TOOLCHAIN)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
set(STATIC_BUILD OFF)
endif()
# `vcpkg.json` defaults to Qt6
set(USE_QT6 ON)
endif()
if(WIN32)
@@ -105,7 +112,12 @@ if(WIN32)
add_compile_definitions(_WINSOCK_DEPRECATED_NO_WARNINGS)
endif()
set(CMAKE_CXX_STANDARD 11)
if(NOT (WIN32 OR APPLE OR CMAKE_SYSTEM_NAME STREQUAL "Linux"))
set(DISCORD OFF)
endif()
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON)
# Optional features
@@ -115,44 +127,46 @@ set(CMAKE_FIND_PACKAGE_PREFER_CONFIG ON)
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)
if(NOT WIN32)
option(QT "QT GUI" ON)
else()
option(QT "QT GUI" OFF)
endif()
option(QT "Qt GUI" ON)
option(DISCORD "Discord Rich Presence support" ON)
# 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(MGA "Matrox Mystique graphics adapters" ON "DEV_BRANCH" OFF)
cmake_dependent_option(NO_SIO "Machines without emulated Super I/O chips" 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" OFF "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(TANDY_ISA "Tandy PSG ISA clone boards" ON "DEV_BRANCH" OFF)
cmake_dependent_option(VGAWONDER "ATI VGA Wonder (ATI-18800)" ON "DEV_BRANCH" OFF)
cmake_dependent_option(VNC "VNC renderer" OFF "DEV_BRANCH" OFF)
cmake_dependent_option(XL24 "ATI VGA Wonder XL24 (ATI-28800-6)" ON "DEV_BRANCH" OFF)
# Ditto but for Qt
if (QT)
if(QT)
option(USE_QT6 "Use Qt6 instead of Qt5" OFF)
if(APPLE)
option(MOLTENVK "Use MoltenVK libraries for Vulkan support on macOS. Requires a Vulkan-enabled QT." OFF)
endif()
endif()
# Determine the build type
@@ -175,7 +189,7 @@ elseif(BUILD_TYPE_LOWER STREQUAL "alpha")
add_compile_definitions(ALPHA_BUILD)
endif()
# Variables introduced by richardg867 for versioning stuff
# Versioning variables
if(NOT CMAKE_PROJECT_VERSION_PATCH)
set(CMAKE_PROJECT_VERSION_PATCH 0)
endif()
@@ -183,7 +197,7 @@ if(NOT EMU_BUILD_NUM)
set(EMU_BUILD_NUM 0)
endif()
if(NOT EMU_COPYRIGHT_YEAR)
set(EMU_COPYRIGHT_YEAR 2022)
set(EMU_COPYRIGHT_YEAR 2023)
endif()
add_subdirectory(src)

View File

@@ -1,114 +1,129 @@
{
"version": 3,
"version": 2,
"cmakeMinimumRequired": {
"major": 3,
"minor": 21,
"patch": 0
"minor": 20
},
"configurePresets": [
{
"name": "flags-base",
"name": "base",
"binaryDir": "${sourceDir}/build/${presetName}",
"cacheVariables": {
"CMAKE_CONFIGURATION_TYPES": "Debug;Release;Optimized"
"CMAKE_INSTALL_PREFIX": "${sourceDir}/build/artifacts",
"CMAKE_EXPORT_COMPILE_COMMANDS": true,
"DEV_BRANCH": "OFF",
"NEW_DYNAREC": "OFF",
"QT": "ON"
},
"hidden": true,
"binaryDir": "build"
"generator": "Ninja",
"hidden": true
},
{
"name": "regular",
"inherits": [
"flags-base"
],
"generator": "Ninja",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"DEV_BRANCH": "OFF",
"NEW_DYNAREC": "OFF"
}
},
{
"name": "regularndr",
"inherits": [
"flags-base"
],
"generator": "Ninja",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"DEV_BRANCH": "OFF",
"NEW_DYNAREC": "ON"
}
"CMAKE_BUILD_TYPE": "Release"
},
"inherits": "base"
},
{
"name": "optimized",
"inherits": [
"flags-base"
],
"generator": "Ninja",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Optimized",
"DEV_BRANCH": "OFF",
"NEW_DYNAREC": "OFF"
}
},
{
"name": "optimizedndr",
"inherits": [
"flags-base"
],
"generator": "Ninja",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Optimized",
"DEV_BRANCH": "OFF",
"NEW_DYNAREC": "ON"
}
"CMAKE_BUILD_TYPE": "Optimized"
},
"inherits": "base"
},
{
"name": "debug",
"inherits": [
"flags-base"
],
"generator": "Ninja",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"DEV_BRANCH": "OFF",
"NEW_DYNAREC": "OFF"
}
"CMAKE_BUILD_TYPE": "Debug"
},
"inherits": "base"
},
{
"name": "debugndr",
"inherits": [
"flags-base"
],
"generator": "Ninja",
"name": "development",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"DEV_BRANCH": "OFF",
"NEW_DYNAREC": "ON"
}
"CMAKE_BUILD_TYPE": "Release",
"DEV_BRANCH": "ON",
"NEW_DYNAREC": "OFF"
},
"inherits": "base"
},
{
"name": "experimental",
"inherits": [
"flags-base"
],
"generator": "Ninja",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"DEV_BRANCH": "ON",
"NEW_DYNAREC": "OFF"
}
},
{
"name": "experimentalndr",
"inherits": [
"flags-base"
],
"generator": "Ninja",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"DEV_BRANCH": "ON",
"NEW_DYNAREC": "ON"
}
},
"inherits": "base"
},
{
"name": "llvm-macos-aarch64.cmake",
"displayName": "MacOS clang regular",
"generator": "Ninja",
"binaryDir": "${sourceDir}/out/build/${presetName}",
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "cmake/llvm-macos-aarch64.cmake",
"NEW_DYNAREC": "ON",
"QT": "ON",
"USE_QT6": "OFF",
"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"
},
"inherits": "regular"
},
{
"name": "llvm-macos-aarch64-debug",
"displayName": "MacOS clang debug",
"generator": "Ninja",
"binaryDir": "${sourceDir}/out/build/${presetName}",
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "cmake/llvm-macos-aarch64.cmake",
"NEW_DYNAREC": "ON",
"QT": "ON",
"USE_QT6": "OFF",
"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",
"CMAKE_CXX_FLAGS_DEBUG": "-g -O0 -DENABLE_VDE_LOG",
"CMAKE_C_FLAGS_DEBUG": "-g -O0 -DENABLE_VDE_LOG"
},
"inherits": "debug"
},
{
"name": "flags-gcc-aarch64-debug",
"displayName": "Linux ARM 64 - Debug",
"description": "Linux ARM64 - Debug build",
"generator": "Ninja",
"binaryDir": "${sourceDir}/out/build/${presetName}",
"cacheVariables": {
"NEW_DYNAREC": "ON",
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_TOOLCHAIN_FILE": "cmake/flags-gcc-aarch64.cmake",
"CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}",
"CMAKE_CXX_FLAGS_DEBUG": "-g -O0 -DENABLE_VDE_LOG",
"CMAKE_C_FLAGS_DEBUG": "-g -O0 -DENABLE_VDE_LOG"
},
"inherits": "debug"
},
{
"name": "flags-gcc-aarch64-regular",
"displayName": "Linux ARM 64 - Regular",
"description": "Linux ARM64 - Release build",
"generator": "Ninja",
"binaryDir": "${sourceDir}/out/build/${presetName}",
"cacheVariables": {
"NEW_DYNAREC": "ON",
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_TOOLCHAIN_FILE": "cmake/flags-gcc-aarch64.cmake",
"CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}"
},
"inherits": "regular"
}
]
],
"buildPresets": [],
"testPresets": []
}

13
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,13 @@
# Contribution guidelines
The 86Box project welcomes contributions from anyone, as long as some basic guidelines are followed.
## Emulated hardware
In order to accept new emulated hardware, the following criteria must be met:
* A ROM must be available and be added to [our ROM repository](https://github.com/86Box/roms)
* Documentation must be available or it must be feasible to reverse engineer with a reasonable amount of time and effort
* It must be feasible to implement with a reasonable amount of time and effort
* It has to fall inside the project's scope
## Questions
If you're unsure about any aspect of contributing, don't hesitate to get in touch via any of our official communities linked in our [readme](README.md#community) or [GitHub Discussions](https://github.com/86Box/86Box/discussions).

View File

@@ -1,55 +1,72 @@
86Box [![Build Status](http://ci.86box.net/job/86Box/badge/icon)](http://ci.86box.net/job/86Box)
86Box
=====
[![Build Status](https://ci.86box.net/job/86Box/badge/icon)](https://ci.86box.net/job/86Box/)
[![License](https://img.shields.io/github/license/86Box/86Box)](COPYING) [![Latest release](https://img.shields.io/github/release/86Box/86Box.svg)](https://github.com/86Box/86Box/releases) [![Downloads](https://img.shields.io/github/downloads/86Box/86Box/total.svg)](https://github.com/86Box/86Box/releases)
**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.
Features
--------
* Easy to use interface inspired by mainstream hypervisor software
* Low level emulation of 8086-based processors up to the Pentium with focus on accuracy
* Low level emulation of 8086-based processors up to the Mendocino-era Celeron with focus on accuracy
* Great range of customizability of virtual machines
* Many available systems, such as the very first IBM PC 5150 from 1981, or the more obscure IBM PS/2 line of systems based on the Micro Channel Architecture
* Lots of supported peripherals including video adapters, sound cards, network adapters, hard disk controllers, and SCSI adapters
* MIDI output to Windows built-in MIDI support, FluidSynth, or emulated Roland synthesizers
* Supports running MS-DOS, older Windows versions, OS/2, many Linux distributions, or vintage systems such as BeOS or NEXTSTEP, and applications for these systems
System requirements and recommendations
---------------------------------------
* Intel Core 2 or AMD Athlon 64 processor
* Windows 7 Service Pack 1, Windows 8.1 or Windows 10
* 4 GB of RAM
Minimum system requirements and recommendations
-----------------------------------------------
Performance may vary depending on both host and guest configuration. Most emulation logic is executed in a single thread, therefore generally systems with better IPC (instructions per clock) should be able to emulate higher clock speeds.
* Intel Core 2 or AMD Athlon 64 processor or newer
* Windows version: Windows 7 Service Pack 1 or later
* Linux version: Ubuntu 16.04, Debian 9.0 or other distributions from 2016 onwards
* 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.
It is also recommended to use a manager application with 86Box for easier handling of multiple virtual machines.
* [WinBox for 86Box](https://github.com/86Box/WinBox-for-86Box) by Laci bá'
* The new manager with improved new user experience; installer, automatic updates of emulator files and more.
* [86Box Manager](https://github.com/86Box/86BoxManager) by [daviunic](https://github.com/daviunic) (Overdoze)
* The traditional 86Box manager with simple interface.
However, it is also possible to use 86Box on its own with the `--vmpath`/`-P` command line option.
* [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)
* [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.
Getting started
---------------
See [our documentation](https://86box.readthedocs.io/en/latest/index.html) for an overview of the emulator's features and user interface.
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!
[![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.
Licensing
---------
86Box is released under the [GNU General Public License, version 2](https://www.gnu.org/licenses/old-licenses/gpl-2.0.html) or later. For more information, see the `COPYING` file in the root of the repository.
The emulator can also optionally make use of [munt](https://github.com/munt/munt), [FluidSynth](https://www.fluidsynth.org/), [Ghostscript](https://www.ghostscript.com/) and [Discord Game SDK](https://discord.com/developers/docs/game-sdk/sdk-starter-guide), which are distributed under their respective licenses.
Donations
---------
We do not charge you for the emulator but donations are still welcome:
https://paypal.me/86Box.
<https://paypal.me/86Box>.
You can also support the project on Patreon:
https://www.patreon.com/86box.
<https://www.patreon.com/86box>.

77
bumpversion.sh Normal file
View File

@@ -0,0 +1,77 @@
#!/bin/sh
#
# 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.
#
# Convenience script for changing the emulator's version.
#
#
# Authors: RichardG, <richardg867@gmail.com>
#
# Copyright 2022 RichardG.
#
# Parse arguments.
newversion="$1"
romversion="$2"
if [ -z "$(echo "$newversion" | grep '\.')" ]
then
echo '[!] Usage: bumpversion.sh x.y[.z] [romversion]'
exit 1
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" |
grep '"tag_name":' |
sed -E 's/.*"v([^"]+)".*/\1/')
fi
# Switch to the repository root directory.
cd "$(dirname "$0")" || exit
pretty_date() {
# Ensure we get the date in English.
LANG=en_US.UTF-8 date '+%a %b %d %Y'
}
# Patch files.
patch_file() {
# Stop if the file doesn't exist.
[ ! -e "$1" ] && return
# Patch file.
if sed -i -r -e "$3" "$1"
then
echo "[-] Patched $2 on $1"
else
echo "[!] Patching $2 on $1 failed"
fi
}
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'/'
patch_file src/unix/assets/*.spec 'changelog date' 's/(^[*]\s)[a-zA-Z]{3}\s[a-zA-Z]{3}\s[0-9]{2}\s[0-9]{4}/\1'"$(pretty_date)"'/'
patch_file src/unix/assets/*.metainfo.xml release 's/(<release version=")[^"]+(" date=")[^"]+/\1'"$newversion"'\2'"$(date +%Y-%m-%d)"'/'
patch_file debian/changelog 'changelog date' 's/> .+/> '"$(date -R)"'/'
patch_file debian/changelog 'changelog version' 's/86box \(.+\)/86box \('"$newversion"'\)/'

View File

@@ -1,20 +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.
# 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 toolchain file defining GCC compiler flags
# for AArch64 (ARM64) targets.
# CMake toolchain file defining GCC compiler flags
# for AArch64 (ARM64) targets.
#
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
#
# Copyright 2021 David Hrdlička.
# Copyright 2021 David Hrdlička.
#
string(APPEND CMAKE_C_FLAGS_INIT " -march=armv8-a ${CMAKE_C_FLAGS_INIT}")
string(APPEND CMAKE_CXX_FLAGS_INIT " -march=armv8-a ${CMAKE_CXX_FLAGS_INIT}")
string(APPEND CMAKE_C_FLAGS_INIT " -march=armv8-a")
string(APPEND CMAKE_CXX_FLAGS_INIT " -march=armv8-a")
include(${CMAKE_CURRENT_LIST_DIR}/flags-gcc.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/flags-gcc.cmake)

View File

@@ -1,20 +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.
# 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 toolchain file defining GCC compiler flags
# for ARMv7 targets.
# CMake toolchain file defining GCC compiler flags
# for ARMv7 targets.
#
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
#
# Copyright 2021 David Hrdlička.
# Copyright 2021 David Hrdlička.
#
string(APPEND CMAKE_C_FLAGS_INIT " -march=armv7-a -mfloat-abi=hard ${CMAKE_C_FLAGS_INIT}")
string(APPEND CMAKE_CXX_FLAGS_INIT " -march=armv7-a -mfloat-abi=hard ${CMAKE_CXX_FLAGS_INIT}")
string(APPEND CMAKE_C_FLAGS_INIT " -march=armv7-a+fp -mfloat-abi=hard")
string(APPEND CMAKE_CXX_FLAGS_INIT " -march=armv7-a+fp -mfloat-abi=hard")
include(${CMAKE_CURRENT_LIST_DIR}/flags-gcc.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/flags-gcc.cmake)

View File

@@ -1,20 +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.
# 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 toolchain file defining GCC compiler flags
# for 32-bit x86 targets.
# CMake toolchain file defining GCC compiler flags
# for 32-bit x86 targets.
#
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
#
# Copyright 2021 David Hrdlička.
# Copyright 2021 David Hrdlička.
#
string(APPEND CMAKE_C_FLAGS_INIT " -m32 -march=i686 -msse2 -mfpmath=sse -mstackrealign ${CMAKE_C_FLAGS_INIT}")
string(APPEND CMAKE_CXX_FLAGS_INIT " -m32 -march=i686 -msse2 -mfpmath=sse -mstackrealign ${CMAKE_CXX_FLAGS_INIT}")
string(APPEND CMAKE_C_FLAGS_INIT " -m32 -march=i686 -msse2 -mfpmath=sse -mstackrealign")
string(APPEND CMAKE_CXX_FLAGS_INIT " -m32 -march=i686 -msse2 -mfpmath=sse -mstackrealign")
include(${CMAKE_CURRENT_LIST_DIR}/flags-gcc.cmake)

View File

@@ -1,20 +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.
# 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 toolchain file defining GCC compiler flags
# for 64-bit x86 targets.
# CMake toolchain file defining GCC compiler flags
# for 64-bit x86 targets.
#
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
#
# Copyright 2021 David Hrdlička.
# Copyright 2021 David Hrdlička.
#
string(APPEND CMAKE_C_FLAGS_INIT " -m64 -march=x86-64 -msse2 -mfpmath=sse -mstackrealign ${CMAKE_C_FLAGS_INIT}")
string(APPEND CMAKE_CXX_FLAGS_INIT " -m64 -march=x86-64 -msse2 -mfpmath=sse -mstackrealign ${CMAKE_CXX_FLAGS_INIT}")
string(APPEND CMAKE_C_FLAGS_INIT " -m64 -march=x86-64 -msse2 -mfpmath=sse -mstackrealign")
string(APPEND CMAKE_CXX_FLAGS_INIT " -m64 -march=x86-64 -msse2 -mfpmath=sse -mstackrealign")
include(${CMAKE_CURRENT_LIST_DIR}/flags-gcc.cmake)

View File

@@ -1,20 +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.
# 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 toolchain file defining GCC compiler flags.
# CMake toolchain file defining GCC compiler flags.
#
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
#
# Copyright 2021 David Hrdlička.
# Copyright 2021 David Hrdlička.
#
# Define our flags
string(APPEND CMAKE_C_FLAGS_INIT " -fomit-frame-pointer -Wall -fno-strict-aliasing")
string(APPEND CMAKE_C_FLAGS_INIT " -fomit-frame-pointer -Wall -fno-strict-aliasing -Werror=implicit-int -Werror=implicit-function-declaration -Werror=int-conversion -Werror=strict-prototypes -Werror=old-style-definition")
string(APPEND CMAKE_CXX_FLAGS_INIT " -fomit-frame-pointer -Wall -fno-strict-aliasing")
string(APPEND CMAKE_C_FLAGS_RELEASE_INIT " -g0 -O3")
string(APPEND CMAKE_CXX_FLAGS_RELEASE_INIT " -g0 -O3")
@@ -32,4 +32,4 @@ foreach(LANG C;CXX)
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()
endforeach()
endforeach()

View File

@@ -1,22 +1,22 @@
#
# 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 toolchain file defining Clang compiler flags
# for AArch64 (ARM64)-based Apple Silicon targets.
# CMake toolchain file defining Clang compiler flags
# for AArch64 (ARM64)-based Apple Silicon targets.
#
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
# dob205
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
# dob205
#
# Copyright 2021 David Hrdlička.
# Copyright 2022 dob205.
# Copyright 2021 David Hrdlička.
# Copyright 2022 dob205.
#
string(APPEND CMAKE_C_FLAGS_INIT " -march=armv8.5-a+simd")
string(APPEND CMAKE_CXX_FLAGS_INIT " -march=armv8.5-a+simd")
include(${CMAKE_CURRENT_LIST_DIR}/flags-gcc.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/flags-gcc.cmake)

View File

@@ -1,16 +1,16 @@
#
# 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 toolchain file for Clang on Windows builds (ARM64 target).
# CMake toolchain file for Clang on Windows builds (ARM64 target).
#
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
#
# Copyright 2021 David Hrdlička.
# Copyright 2021 David Hrdlička.
#
include(${CMAKE_CURRENT_LIST_DIR}/flags-gcc-aarch64.cmake)
@@ -27,4 +27,4 @@ set(CMAKE_CXX_COMPILER_TARGET aarch64-pc-windows-msvc)
set(CMAKE_SYSTEM_PROCESSOR ARM64)
# TODO: set the vcpkg target triplet perhaps?
# TODO: set the vcpkg target triplet perhaps?

View File

@@ -0,0 +1,30 @@
#
# 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 for Clang on Windows builds (ARM64 target).
#
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
#
# Copyright 2021 David Hrdlička.
#
include(${CMAKE_CURRENT_LIST_DIR}/flags-gcc-armv7.cmake)
# Use the GCC-compatible Clang executables in order to use our flags
set(CMAKE_C_COMPILER clang)
set(CMAKE_CXX_COMPILER clang++)
# `llvm-rc` is barely usable as of LLVM 13, using MS' rc.exe for now
set(CMAKE_RC_COMPILER rc)
set(CMAKE_C_COMPILER_TARGET arm-pc-windows-msvc)
set(CMAKE_CXX_COMPILER_TARGET arm-pc-windows-msvc)
set(CMAKE_SYSTEM_PROCESSOR ARM)
# TODO: set the vcpkg target triplet perhaps?

View File

@@ -1,16 +1,16 @@
#
# 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 toolchain file for Clang on Windows builds (x86 target).
# CMake toolchain file for Clang on Windows builds (x86 target).
#
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
#
# Copyright 2021 David Hrdlička.
# Copyright 2021 David Hrdlička.
#
include(${CMAKE_CURRENT_LIST_DIR}/flags-gcc-i686.cmake)
@@ -27,4 +27,4 @@ set(CMAKE_CXX_COMPILER_TARGET i686-pc-windows-msvc)
set(CMAKE_SYSTEM_PROCESSOR X86)
# TODO: set the vcpkg target triplet perhaps?
# TODO: set the vcpkg target triplet perhaps?

View File

@@ -1,16 +1,16 @@
#
# 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 toolchain file for Clang on Windows builds (x64/AMD64 target).
# CMake toolchain file for Clang on Windows builds (x64/AMD64 target).
#
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
#
# Copyright 2021 David Hrdlička.
# Copyright 2021 David Hrdlička.
#
include(${CMAKE_CURRENT_LIST_DIR}/flags-gcc-x86_64.cmake)
@@ -27,4 +27,4 @@ set(CMAKE_CXX_COMPILER_TARGET x86_64-pc-windows-msvc)
set(CMAKE_SYSTEM_PROCESSOR AMD64)
# TODO: set the vcpkg target triplet perhaps?
# TODO: set the vcpkg target triplet perhaps?

5
debian/changelog vendored Normal file
View File

@@ -0,0 +1,5 @@
86box (4.0.2) UNRELEASED; urgency=medium
* Bump release.
-- Jasmine Iwanek <jriwanek@gmail.com> Mon, 16 Oct 2023 20:24:46 +0200

29
debian/control vendored Normal file
View File

@@ -0,0 +1,29 @@
Source: 86box
Section: otherosfs
Priority: optional
Maintainer: Mariusz Kurek <mariuszkurek@protonmail.com>
Build-Depends: cmake (>= 3.21),
debhelper-compat (= 13),
libevdev-dev,
libfreetype-dev,
libopenal-dev,
libqt5opengl5-dev,
librtmidi-dev,
libsdl2-dev,
libslirp-dev,
ninja-build,
qttools5-dev
Standards-Version: 4.6.0
Homepage: https://86box.net/
#Vcs-Browser: https://salsa.debian.org/debian/86box
#Vcs-Git: https://salsa.debian.org/debian/86box.git
Rules-Requires-Root: no
Package: 86box
Architecture: amd64 armhf arm64 i386
Depends: ${shlibs:Depends},
${misc:Depends},
sse2-support [i386]
Recommends: libpcap0.8-dev
Description: An emulator for classic IBM PC clones
#TODO: insert long description, indented with spaces

38
debian/copyright vendored Normal file
View File

@@ -0,0 +1,38 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: 86box
Source: https://86box.net/
Files: *
Copyright: <years> <put author's name and email here>
<years> <likewise for another author>
License: GPL-2.0+
Files: debian/*
Copyright: 2022 Mariusz Kurek <mariuszkurek@protonmail.com>
License: GPL-2.0+
License: GPL-2.0+
This package is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
.
This package is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>
.
On Debian systems, the complete text of the GNU General
Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
# Please also look if there are files or directories which have a
# different copyright/license attached and list them here.
# Please avoid picking licenses with terms that are more restrictive than the
# packaged work, as it may make Debian's contributions unacceptable upstream.
#
# If you need, there are some extra license texts available in two places:
# /usr/share/debhelper/dh_make/licenses/
# /usr/share/common-licenses/

41
debian/postinst vendored Normal file
View File

@@ -0,0 +1,41 @@
#!/bin/sh
# postinst script for 86box
#
# see: dh_installdeb(1)
set -e
# summary of how this script can be called:
# * <postinst> `configure' <most-recently-configured-version>
# * <old-postinst> `abort-upgrade' <new version>
# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
# <new-version>
# * <postinst> `abort-remove'
# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
# <failed-install-package> <version> `removing'
# <conflicting-package> <version>
# for details, see https://www.debian.org/doc/debian-policy/ or
# the debian-policy package
case "$1" in
configure)
echo You need ROM files in order to use 86Box. These can be obtained from https://github.com/86Box/roms
echo You can put the roms folder in, for example, /usr/share/86Box/roms or \~/.local/share/86Box/roms
;;
abort-upgrade|abort-remove|abort-deconfigure)
;;
*)
echo "postinst called with unknown argument \`$1'" >&2
exit 1
;;
esac
# dh_installdeb will replace this with shell code automatically
# generated by other debhelper scripts.
#DEBHELPER#
exit 0

42
debian/rules vendored Normal file
View File

@@ -0,0 +1,42 @@
#!/usr/bin/make -f
# See debhelper(7) (uncomment to enable)
# output every command that modifies files on the build system.
#export DH_VERBOSE = 1
ARCH=$(shell dpkg-architecture -qDEB_HOST_ARCH)
ifeq ($(ARCH), $(filter $(ARCH), amd64 i386))
NDR=off
ifeq ($(ARCH),amd64)
TOOLCHAIN=cmake/flags-gcc-x86_64.cmake
else
TOOLCHAIN=cmake/flags-gcc-i686.cmake
endif
else
NDR=on
ifeq ($(ARCH),armhf)
TOOLCHAIN=cmake/flags-gcc-armv7.cmake
else
TOOLCHAIN=cmake/flags-gcc-aarch64.cmake
endif
endif
%:
dh $@ --buildsystem cmake+ninja
override_dh_auto_configure:
dh_auto_configure --buildsystem cmake+ninja -- --preset regular --toolchain $(TOOLCHAIN) -DNEW_DYNAREC=$(NDR)
override_dh_auto_test:
override_dh_auto_install:
dh_auto_install --buildsystem cmake+ninja
for i in 48x48 64x64 72x72 96x96 128x128 192x192 256x256 512x512 ; do \
install -Dm644 src/unix/assets/$$i/net.86box.86Box.png -t debian/86box/usr/share/icons/hicolor/$$i/apps ; \
done
mkdir debian/86box/usr/share/applications
sed 's/^Exec.*/Exec=86Box -P .local\/share\/86Box/' "src/unix/assets/net.86box.86Box.desktop" > "debian/86box/usr/share/applications/net.86box.86Box.desktop"
override_dh_installdocs:
override_dh_installman:

1
debian/source/format vendored Normal file
View File

@@ -0,0 +1 @@
3.0 (quilt)

15
debian/watch vendored Normal file
View File

@@ -0,0 +1,15 @@
# Example watch control file for uscan
# Rename this file to "watch" and then you can run the "uscan" command
# to check for upstream updates and more.
# See uscan(1) for format
# Compulsory line, this is a version 4 file
version=4
# PGP signature mangle, so foo.tar.gz has foo.tar.gz.sig
#opts="pgpsigurlmangle=s%$%.sig%"
# GitHub hosted projects
opts="filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%<project>-$1.tar.gz%" \
https://github.com/86Box/86Box/tags \
(?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian uupdate

12
sonar-project.properties Normal file
View File

@@ -0,0 +1,12 @@
sonar.projectKey=86Box_86Box
sonar.organization=86box
# This is the name and version displayed in the SonarCloud UI.
#sonar.projectName=86Box
#sonar.projectVersion=1.0
# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows.
#sonar.sources=.
# Encoding of the source code. Default is default system encoding
#sonar.sourceEncoding=UTF-8

File diff suppressed because it is too large Load Diff

View File

@@ -1,28 +1,41 @@
#
# 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>
# dob205
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
# dob205
#
# Copyright 2020-2022 David Hrdlička.
# Copyright 2021 dob205.
# Copyright 2020-2022 David Hrdlička.
# Copyright 2021 dob205.
#
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 discord.c nmi.c pic.c pit.c port_6x.c port_92.c ppi.c pci.c
mca.c usb.c fifo8.c device.c nvr.c nvr_at.c nvr_ps2.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)
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
add_compile_definitions(_FILE_OFFSET_BITS=64 _LARGEFILE_SOURCE=1 _LARGEFILE64_SOURCE=1)
endif()
if(CPPTHREADS)
target_sources(86Box PRIVATE thread.cpp)
endif()
if(GDBSTUB)
add_compile_definitions(USE_GDBSTUB)
target_sources(86Box PRIVATE gdbstub.c)
endif()
if(NEW_DYNAREC)
add_compile_definitions(USE_NEW_DYNAREC)
endif()
@@ -39,15 +52,27 @@ if(DEV_BRANCH)
add_compile_definitions(DEV_BRANCH)
endif()
if(DISCORD)
add_compile_definitions(DISCORD)
target_sources(86Box PRIVATE discord.c)
endif()
if(VNC)
add_compile_definitions(USE_VNC)
add_library(vnc OBJECT vnc.c vnc_keymap.c)
target_link_libraries(86Box vnc vncserver)
if (WIN32)
target_link_libraries(86Box ws2_32)
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)
if(WIN32)
target_link_libraries(86Box ws2_32)
endif()
endif()
endif()
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)
@@ -70,39 +95,30 @@ if(APPLE)
# Force using the newest library if it's installed by homebrew
set(CMAKE_FIND_FRAMEWORK LAST)
# setting our compilation target to macOS 10.15 Catalina if targetting Qt6, macOS 10.13 High Sierra otherwise
# setting our compilation target to macOS 10.15 Catalina if targeting Qt6,
# macOS 10.14 Mojave for vulkan support, 10.13 High Sierra otherwise
if (USE_QT6)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15")
else()
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.13")
if(MOLTENVK)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14")
else()
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.13")
endif()
endif()
endif()
find_package(Freetype REQUIRED)
include_directories(${FREETYPE_INCLUDE_DIRS})
if(FREETYPE_INCLUDE_DIR_ft2build)
include_directories(${FREETYPE_INCLUDE_DIR_ft2build})
endif()
if(APPLE)
# Freetype is dynamically loaded by the emulator, however, we link it
# on macOS so it gets copied to the bundle by the installation process
target_link_libraries(86Box Freetype::Freetype)
endif()
if(OPENAL)
if(VCPKG_TOOLCHAIN)
find_package(OpenAL CONFIG REQUIRED)
elseif(MINGW)
find_package(OpenAL MODULE REQUIRED)
else()
find_package(OpenAL REQUIRED)
endif()
if(TARGET OpenAL::OpenAL)
target_link_libraries(86Box OpenAL::OpenAL)
else()
include_directories(${OPENAL_INCLUDE_DIR})
target_link_libraries(86Box ${OPENAL_LIBRARY})
endif()
endif()
find_package(SDL2 REQUIRED)
include_directories(${SDL2_INCLUDE_DIRS})
if(STATIC_BUILD AND TARGET SDL2::SDL2-static)
@@ -117,20 +133,6 @@ find_package(PNG REQUIRED)
include_directories(${PNG_INCLUDE_DIRS})
target_link_libraries(86Box PNG::PNG)
if(VCPKG_TOOLCHAIN)
# vcpkg includes a config file for rtmidi
find_package(RtMidi REQUIRED)
target_link_libraries(86Box RtMidi::rtmidi)
else()
find_package(PkgConfig REQUIRED)
pkg_check_modules(RTMIDI REQUIRED IMPORTED_TARGET rtmidi)
target_link_libraries(86Box PkgConfig::RTMIDI)
if(WIN32)
target_link_libraries(PkgConfig::RTMIDI INTERFACE winmm)
endif()
endif()
configure_file(include/86box/version.h.in include/86box/version.h @ONLY)
include_directories(${CMAKE_CURRENT_BINARY_DIR}/include)
@@ -205,6 +207,7 @@ elseif(WIN32)
OPTIONAL)
endif()
add_subdirectory(device)
add_subdirectory(disk)
add_subdirectory(floppy)
@@ -218,7 +221,7 @@ add_subdirectory(scsi)
add_subdirectory(sound)
add_subdirectory(video)
if (APPLE)
add_subdirectory(mac)
add_subdirectory(mac)
endif()
if (QT)

View File

@@ -1,32 +1,32 @@
#
# 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.
#
# Prefix for localizing the general Makefile.mingw for local
# settings, so we can avoid changing the main one for all of
# our local setups.
# Prefix for localizing the general Makefile.mingw for local
# settings, so we can avoid changing the main one for all of
# our local setups.
#
# Author: Fred N. van Kempen, <decwiz@yahoo.com>
# Authors: Fred N. van Kempen, <decwiz@yahoo.com>
#
#########################################################################
# Anything here will override defaults in Makefile.MinGW. #
# Anything here will override defaults in Makefile.MinGW. #
#########################################################################
# Name of the executable.
#PROG := yourexe
#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 :=
STUFF :=
# Add feature selections here.
# -DANSI_CFG forces the config file to ANSI encoding.
@@ -168,32 +168,31 @@ STUFF :=
# -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 :=
EXTRAS :=
AUTODEP := n
CRASHDUMP := 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
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 the master Makefile.MinGW for the rest. #
#########################################################################
include win/Makefile.mingw

2445
src/acpi.c

File diff suppressed because it is too large Load Diff

146
src/apm.c
View File

@@ -1,18 +1,18 @@
/*
* 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.
*
* Advanced Power Management emulation.
* Advanced Power Management emulation.
*
*
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2019 Miran Grca.
* Copyright 2019 Miran Grca.
*/
#include <stdarg.h>
#include <stdio.h>
@@ -27,145 +27,131 @@
#include <86box/io.h>
#include <86box/apm.h>
#ifdef ENABLE_APM_LOG
int apm_do_log = ENABLE_APM_LOG;
static void
apm_log(const char *fmt, ...)
{
va_list ap;
if (apm_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define apm_log(fmt, ...)
# define apm_log(fmt, ...)
#endif
void
apm_set_do_smi(apm_t *dev, uint8_t do_smi)
{
dev->do_smi = do_smi;
}
static void
apm_out(uint16_t port, uint8_t val, void *p)
apm_out(uint16_t port, uint8_t val, void *priv)
{
apm_t *dev = (apm_t *) p;
apm_t *dev = (apm_t *) priv;
apm_log("[%04X:%08X] APM write: %04X = %02X (BX = %04X, CX = %04X)\n", CS, cpu_state.pc, port, val, BX, CX);
port &= 0x0001;
if (port == 0x0000) {
dev->cmd = val;
if (dev->do_smi)
smi_line = 1;
dev->cmd = val;
if (dev->do_smi)
smi_raise();
} else
dev->stat = val;
dev->stat = val;
}
static uint8_t
apm_in(uint16_t port, void *p)
apm_in(uint16_t port, void *priv)
{
apm_t *dev = (apm_t *) p;
uint8_t ret = 0xff;
const apm_t *dev = (apm_t *) priv;
uint8_t ret = 0xff;
port &= 0x0001;
if (port == 0x0000)
ret = dev->cmd;
ret = dev->cmd;
else
ret = dev->stat;
ret = dev->stat;
apm_log("[%04X:%08X] APM read: %04X = %02X\n", CS, cpu_state.pc, port, ret);
return ret;
}
static void
apm_reset(void *p)
apm_reset(void *priv)
{
apm_t *dev = (apm_t *)p;
apm_t *dev = (apm_t *) priv;
dev->cmd = dev->stat = 0x00;
}
static void
apm_close(void *p)
apm_close(void *priv)
{
apm_t *dev = (apm_t *)p;
apm_t *dev = (apm_t *) priv;
free(dev);
}
static void
*apm_init(const device_t *info)
static void *
apm_init(const device_t *info)
{
apm_t *dev = (apm_t *) malloc(sizeof(apm_t));
memset(dev, 0, sizeof(apm_t));
if (info->local == 0)
io_sethandler(0x00b2, 0x0002, apm_in, NULL, NULL, apm_out, NULL, NULL, dev);
io_sethandler(0x00b2, 0x0002, apm_in, NULL, NULL, apm_out, NULL, NULL, dev);
return dev;
}
const device_t apm_device =
{
"Advanced Power Management",
"apm",
0,
0,
apm_init,
apm_close,
NULL,
{ NULL },
NULL,
NULL,
NULL
const device_t apm_device = {
.name = "Advanced Power Management",
.internal_name = "apm",
.flags = 0,
.local = 0,
.init = apm_init,
.close = apm_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t apm_pci_device =
{
"Advanced Power Management (PCI)",
"apm_pci",
DEVICE_PCI,
0,
apm_init,
apm_close,
apm_reset,
{ NULL },
NULL,
NULL,
NULL
const device_t apm_pci_device = {
.name = "Advanced Power Management (PCI)",
.internal_name = "apm_pci",
.flags = DEVICE_PCI,
.local = 0,
.init = apm_init,
.close = apm_close,
.reset = apm_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t apm_pci_acpi_device =
{
"Advanced Power Management (PCI)",
"apm_pci_acpi",
DEVICE_PCI,
1,
apm_init,
apm_close,
apm_reset,
{ NULL },
NULL,
NULL,
NULL
const device_t apm_pci_acpi_device = {
.name = "Advanced Power Management (PCI)",
.internal_name = "apm_pci_acpi",
.flags = DEVICE_PCI,
.local = 1,
.init = apm_init,
.close = apm_close,
.reset = apm_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -1,27 +1,27 @@
/*
* 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.
*
* Configure-time architecture detection for the CMake build.
* Configure-time architecture detection for the CMake build.
*
*
*
* 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.
*/
#if defined(__arm__) || defined(__TARGET_ARCH_ARM)
#error ARCH arm
# error ARCH arm
#elif defined(__aarch64__) || defined(_M_ARM64)
#error ARCH arm64
# error ARCH arm64
#elif defined(__i386) || defined(__i386__) || defined(_M_IX86)
#error ARCH i386
# error ARCH i386
#elif defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64)
#error ARCH x86_64
# error ARCH x86_64
#endif
#error ARCH unknown

View File

@@ -1,16 +1,16 @@
#
# 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.
#
add_library(cdrom OBJECT cdrom.c cdrom_image_backend.c cdrom_image.c)
add_library(cdrom OBJECT cdrom.c cdrom_image_backend.c cdrom_image_viso.c cdrom_image.c cdrom_mitsumi.c)

File diff suppressed because it is too large Load Diff

View File

@@ -1,26 +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.
* 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.
*
* CD-ROM image support.
* CD-ROM image support.
*
*
*
* Author: RichardG867,
* Miran Grca, <mgrca8@gmail.com>
* bit,
* Authors: RichardG867,
* Miran Grca, <mgrca8@gmail.com>
* bit,
*
* Copyright 2015-2019 Richardg867.
* Copyright 2015-2019 Miran Grca.
* Copyright 2017-2019 bit.
* Copyright 2015-2019 Richardg867.
* Copyright 2015-2019 Miran Grca.
* Copyright 2017-2019 bit.
*/
#define __USE_LARGEFILE64
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#include <inttypes.h>
#include <stdarg.h>
#include <stdio.h>
@@ -31,17 +28,16 @@
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/config.h>
#include <86box/path.h>
#include <86box/plat.h>
#include <86box/scsi_device.h>
#include <86box/cdrom_image_backend.h>
#include <86box/cdrom.h>
#include <86box/cdrom_image.h>
#ifdef ENABLE_CDROM_IMAGE_LOG
int cdrom_image_do_log = ENABLE_CDROM_IMAGE_LOG;
void
cdrom_image_log(const char *fmt, ...)
{
@@ -54,31 +50,28 @@ cdrom_image_log(const char *fmt, ...)
}
}
#else
#define cdrom_image_log(fmt, ...)
# define cdrom_image_log(fmt, ...)
#endif
/* 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. */
#define MSFtoLBA(m,s,f) ((((m * 60) + s) * 75) + f)
#define MSFtoLBA(m, s, f) ((((m * 60) + s) * 75) + f)
static void
image_get_tracks(cdrom_t *dev, int *first, int *last)
{
cd_img_t *img = (cd_img_t *)dev->image;
TMSF tmsf;
cd_img_t *img = (cd_img_t *) dev->image;
TMSF tmsf;
cdi_get_audio_tracks(img, first, last, &tmsf);
}
static void
image_get_track_info(cdrom_t *dev, uint32_t track, int end, track_info_t *ti)
{
cd_img_t *img = (cd_img_t *)dev->image;
TMSF tmsf;
cd_img_t *img = (cd_img_t *) dev->image;
TMSF tmsf;
cdi_get_audio_track_info(img, end, track, &ti->number, &tmsf, &ti->attr);
@@ -87,15 +80,15 @@ image_get_track_info(cdrom_t *dev, uint32_t track, int end, track_info_t *ti)
ti->f = tmsf.fr;
}
static void
image_get_subchannel(cdrom_t *dev, uint32_t lba, subchannel_t *subc)
{
cd_img_t *img = (cd_img_t *)dev->image;
TMSF rel_pos, abs_pos;
cd_img_t *img = (cd_img_t *) dev->image;
TMSF rel_pos;
TMSF abs_pos;
cdi_get_audio_sub(img, lba, &subc->attr, &subc->track, &subc->index,
&rel_pos, &abs_pos);
&rel_pos, &abs_pos);
subc->abs_m = abs_pos.min;
subc->abs_s = abs_pos.sec;
@@ -106,143 +99,140 @@ image_get_subchannel(cdrom_t *dev, uint32_t lba, subchannel_t *subc)
subc->rel_f = rel_pos.fr;
}
static int
image_get_capacity(cdrom_t *dev)
{
cd_img_t *img = (cd_img_t *)dev->image;
int first_track, last_track;
int number, c;
cd_img_t *img = (cd_img_t *) dev->image;
int first_track;
int last_track;
int number;
unsigned char attr;
uint32_t address = 0, lb = 0;
uint32_t address = 0;
uint32_t lb = 0;
if (!img)
return 0;
return 0;
cdi_get_audio_tracks_lba(img, &first_track, &last_track, &lb);
for (c = 0; c <= last_track; c++) {
cdi_get_audio_track_info_lba(img, 0, c + 1, &number, &address, &attr);
if (address > lb)
lb = address;
for (int c = 0; c <= last_track; c++) {
cdi_get_audio_track_info_lba(img, 0, c + 1, &number, &address, &attr);
if (address > lb)
lb = address;
}
return lb;
}
static int
image_is_track_audio(cdrom_t *dev, uint32_t pos, int ismsf)
{
cd_img_t *img = (cd_img_t *)dev->image;
uint8_t attr;
TMSF tmsf;
int m, s, f;
int number, track;
cd_img_t *img = (cd_img_t *) dev->image;
uint8_t attr;
TMSF tmsf;
int m;
int s;
int f;
int number;
int track;
if (!img || (dev->cd_status == CD_STATUS_DATA_ONLY))
return 0;
return 0;
if (ismsf) {
m = (pos >> 16) & 0xff;
s = (pos >> 8) & 0xff;
f = pos & 0xff;
pos = MSFtoLBA(m, s, f) - 150;
m = (pos >> 16) & 0xff;
s = (pos >> 8) & 0xff;
f = pos & 0xff;
pos = MSFtoLBA(m, s, f) - 150;
}
/* GetTrack requires LBA. */
track = cdi_get_track(img, pos);
if (track == -1)
return 0;
return 0;
else {
cdi_get_audio_track_info(img, 0, track, &number, &tmsf, &attr);
return attr == AUDIO_TRACK;
cdi_get_audio_track_info(img, 0, track, &number, &tmsf, &attr);
return attr == AUDIO_TRACK;
}
}
static int
image_is_track_pre(cdrom_t *dev, uint32_t lba)
{
cd_img_t *img = (cd_img_t *)dev->image;
int track;
cd_img_t *img = (cd_img_t *) dev->image;
int track;
/* GetTrack requires LBA. */
track = cdi_get_track(img, lba);
if (track != -1)
return cdi_get_audio_track_pre(img, track);
return cdi_get_audio_track_pre(img, track);
return 0;
}
static int
static int
image_sector_size(struct cdrom *dev, uint32_t lba)
{
cd_img_t *img = (cd_img_t *)dev->image;
cd_img_t *img = (cd_img_t *) dev->image;
return cdi_get_sector_size(img, lba);
}
static int
image_read_sector(struct cdrom *dev, int type, uint8_t *b, uint32_t lba)
{
cd_img_t *img = (cd_img_t *)dev->image;
cd_img_t *img = (cd_img_t *) dev->image;
switch (type) {
case CD_READ_DATA:
return cdi_read_sector(img, b, 0, lba);
case CD_READ_AUDIO:
return cdi_read_sector(img, b, 1, lba);
case CD_READ_RAW:
if (cdi_get_sector_size(img, lba) == 2352)
return cdi_read_sector(img, b, 1, lba);
else
return cdi_read_sector_sub(img, b, lba);
default:
cdrom_image_log("CD-ROM %i: Unknown CD read type\n", dev->id);
return 0;
case CD_READ_DATA:
return cdi_read_sector(img, b, 0, lba);
case CD_READ_AUDIO:
return cdi_read_sector(img, b, 1, lba);
case CD_READ_RAW:
if (cdi_get_sector_size(img, lba) == 2352)
return cdi_read_sector(img, b, 1, lba);
else
return cdi_read_sector_sub(img, b, lba);
default:
cdrom_image_log("CD-ROM %i: Unknown CD read type\n", dev->id);
return 0;
}
}
static int
image_track_type(cdrom_t *dev, uint32_t lba)
{
cd_img_t *img = (cd_img_t *)dev->image;
cd_img_t *img = (cd_img_t *) dev->image;
if (img) {
if (image_is_track_audio(dev, lba, 0))
return CD_TRACK_AUDIO;
else {
if (cdi_is_mode2(img, lba))
return CD_TRACK_MODE2 | cdi_get_mode2_form(img, lba);
}
if (image_is_track_audio(dev, lba, 0))
return CD_TRACK_AUDIO;
else {
if (cdi_is_mode2(img, lba))
return CD_TRACK_MODE2 | cdi_get_mode2_form(img, lba);
}
}
return 0;
}
static void
image_exit(cdrom_t *dev)
{
cd_img_t *img = (cd_img_t *)dev->image;
cd_img_t *img = (cd_img_t *) dev->image;
cdrom_image_log("CDROM: image_exit(%s)\n", dev->image_path);
cdrom_image_log("CDROM: image_exit(%s)\n", dev->image_path);
dev->cd_status = CD_STATUS_EMPTY;
if (img) {
cdi_close(img);
dev->image = NULL;
cdi_close(img);
dev->image = NULL;
}
dev->ops = NULL;
}
static const cdrom_ops_t cdrom_image_ops = {
image_get_tracks,
image_get_track_info,
@@ -254,17 +244,16 @@ static const cdrom_ops_t cdrom_image_ops = {
image_exit
};
static int
image_open_abort(cdrom_t *dev)
{
cdrom_image_close(dev);
dev->ops = NULL;
dev->host_drive = 0;
dev->ops = NULL;
dev->host_drive = 0;
dev->image_path[0] = 0;
return 1;
}
int
cdrom_image_open(cdrom_t *dev, const char *fn)
{
@@ -273,30 +262,32 @@ cdrom_image_open(cdrom_t *dev, const char *fn)
/* Make sure to not STRCPY if the two are pointing
at the same place. */
if (fn != dev->image_path)
strcpy(dev->image_path, fn);
strcpy(dev->image_path, fn);
/* Create new instance of the CDROM_Image class. */
img = (cd_img_t *) malloc(sizeof(cd_img_t));
/* This guarantees that if ops is not NULL, then
neither is the image pointer. */
if (!img)
return image_open_abort(dev);
if (!img)
return image_open_abort(dev);
memset(img, 0, sizeof(cd_img_t));
dev->image = img;
/* Open the image. */
if (!cdi_set_device(img, fn))
return image_open_abort(dev);
int i = cdi_set_device(img, fn);
if (!i)
return image_open_abort(dev);
/* All good, reset state. */
if (! strcasecmp(plat_get_extension((char *) fn), "ISO"))
dev->cd_status = CD_STATUS_DATA_ONLY;
if (i >= 2)
dev->cd_status = CD_STATUS_DATA_ONLY;
else
dev->cd_status = CD_STATUS_STOPPED;
dev->seek_pos = 0;
dev->cd_buflen = 0;
dev->cd_status = CD_STATUS_STOPPED;
dev->is_dir = (i == 3);
dev->seek_pos = 0;
dev->cd_buflen = 0;
dev->cdrom_capacity = image_get_capacity(dev);
cdrom_image_log("CD-ROM capacity: %i sectors (%" PRIi64 " bytes)\n", dev->cdrom_capacity, ((uint64_t) dev->cdrom_capacity) << 11ULL);
@@ -306,12 +297,11 @@ cdrom_image_open(cdrom_t *dev, const char *fn)
return 0;
}
void
cdrom_image_close(cdrom_t *dev)
{
cdrom_image_log("CDROM: image_close(%s)\n", dev->image_path);
if (dev && dev->ops && dev->ops->exit)
dev->ops->exit(dev);
dev->ops->exit(dev);
}

File diff suppressed because it is too large Load Diff

1576
src/cdrom/cdrom_image_viso.c Normal file

File diff suppressed because it is too large Load Diff

478
src/cdrom/cdrom_mitsumi.c Normal file
View File

@@ -0,0 +1,478 @@
/*
* 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.
*
* Mitsumi CD-ROM emulation for the ISA bus.
*
*
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2022 Miran Grca.
*/
#include <inttypes.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/io.h>
#include <86box/pic.h>
#include <86box/dma.h>
#include <86box/cdrom.h>
#include <86box/cdrom_interface.h>
#include <86box/cdrom_mitsumi.h>
#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
enum {
STAT_CMD_CHECK = 0x01,
STAT_PLAY_CDDA = 0x02,
STAT_ERROR = 0x04,
STAT_DISK_CDDA = 0x08,
STAT_SPIN = 0x10,
STAT_CHANGE = 0x20,
STAT_READY = 0x40,
STAT_OPEN = 0x80
};
enum {
CMD_GET_INFO = 0x10,
CMD_GET_Q = 0x20,
CMD_GET_STAT = 0x40,
CMD_SET_MODE = 0x50,
CMD_SOFT_RESET = 0x60,
CMD_STOPCDDA = 0x70,
CMD_CONFIG = 0x90,
CMD_SET_VOL = 0xae,
CMD_READ1X = 0xc0,
CMD_READ2X = 0xc1,
CMD_GET_VER = 0xdc,
CMD_STOP = 0xf0,
CMD_EJECT = 0xf6,
CMD_LOCK = 0xfe
};
enum {
MODE_MUTE = 0x01,
MODE_GET_TOC = 0x04,
MODE_STOP = 0x08,
MODE_ECC = 0x20,
MODE_DATA = 0x40
};
enum {
DRV_MODE_STOP,
DRV_MODE_READ,
DRV_MODE_CDDA
};
enum {
FLAG_NODATA = 2,
FLAG_NOSTAT = 4,
FLAG_UNK = 8, //??
FLAG_OPEN = 16
};
enum {
IRQ_DATAREADY = 1,
IRQ_DATACOMP = 2,
IRQ_ERROR = 4
};
typedef struct mcd_t {
int dma;
int irq;
int change;
int data;
uint8_t stat;
uint8_t buf[RAW_SECTOR_SIZE];
int buf_count;
int buf_idx;
uint8_t cmdbuf[16];
int cmdbuf_count;
int cmdrd_count;
int cmdbuf_idx;
uint8_t mode;
uint8_t cmd;
uint8_t conf;
uint8_t enable_irq;
uint8_t enable_dma;
uint16_t dmalen;
uint32_t readmsf;
uint32_t readcount;
int locked;
int drvmode;
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)
#define CD_BCD(x) (((x) % 10) | (((x) / 10) << 4))
#define CD_DCB(x) ((((x) &0xf0) >> 4) * 10 + ((x) &0x0f))
#ifdef ENABLE_MITSUMI_CDROM_LOG
int mitsumi_cdrom_do_log = ENABLE_MITSUMI_CDROM_LOG;
void
mitsumi_cdrom_log(const char *fmt, ...)
{
va_list ap;
if (mitsumi_cdrom_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define mitsumi_cdrom_log(fmt, ...)
#endif
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->cmdrd_count = 0;
dev->cmdbuf_count = 0;
dev->buf_count = 0;
dev->cur_toc_track = 0;
dev->enable_dma = 0;
dev->enable_irq = 0;
dev->conf = 0;
dev->dmalen = COOKED_SECTOR_SIZE;
dev->locked = 0;
dev->change = 1;
dev->newstat = 1;
dev->data = 0;
}
static int
mitsumi_cdrom_read_sector(mcd_t *dev, int first)
{
cdrom_t cdrom;
uint8_t status;
int ret;
if (dev->drvmode == DRV_MODE_CDDA) {
status = cdrom_mitsumi_audio_play(&cdrom, dev->readmsf, dev->readcount);
if (status == 1)
return status;
else
dev->drvmode = DRV_MODE_READ;
}
if ((dev->enable_irq & IRQ_DATACOMP) && !first) {
picint(1 << dev->irq);
}
if (!dev->readcount) {
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)
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->buf_count = dev->dmalen + 1;
dev->buf_idx = 0;
dev->data = 1;
if (dev->enable_dma) {
while (dev->pos < dev->readcount) {
dma_channel_write(dev->dma, dev->buf[dev->pos]);
dev->pos++;
}
dev->pos = 0;
}
dev->readcount--;
if ((dev->enable_irq & IRQ_DATAREADY) && first)
picint(1 << dev->irq);
return 1;
}
static uint8_t
mitsumi_cdrom_in(uint16_t port, void *priv)
{
mcd_t *dev = (mcd_t *) priv;
uint8_t ret;
pclog("Mitsumi CD-ROM IN=%03x\n", port);
switch (port & 1) {
case 0:
if (dev->cmdbuf_count) {
dev->cmdbuf_count--;
return dev->cmdbuf[dev->cmdbuf_idx++];
} else if (dev->buf_count) {
ret = (dev->buf_idx < RAW_SECTOR_SIZE) ? dev->buf[dev->buf_idx] : 0;
dev->buf_idx++;
dev->buf_count--;
if (!dev->buf_count)
mitsumi_cdrom_read_sector(dev, 0);
pclog("Read port 0: ret = %02x\n", ret);
return ret;
}
pclog("Read port 0: stat = %02x\n", dev->stat);
return dev->stat;
case 1:
ret = 0;
picintc(1 << dev->irq);
if (!dev->buf_count || !dev->data || dev->enable_dma)
ret |= FLAG_NODATA;
if (!dev->cmdbuf_count || !dev->newstat)
ret |= FLAG_NOSTAT;
pclog("Read port 1: ret = %02x\n", ret | FLAG_UNK);
return ret | FLAG_UNK;
case 2:
break;
default:
break;
}
return 0xff;
}
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) {
case 0:
if (dev->cmdrd_count) {
dev->cmdrd_count--;
switch (dev->cmd) {
case CMD_SET_MODE:
dev->mode = val;
dev->cmdbuf[1] = 0;
dev->cmdbuf_count = 2;
break;
case CMD_LOCK:
dev->locked = val & 1;
dev->cmdbuf[1] = 0;
dev->cmdbuf[2] = 0;
dev->cmdbuf_count = 3;
break;
case CMD_CONFIG:
switch (dev->cmdrd_count) {
case 0:
switch (dev->conf) {
case 0x01:
dev->dmalen |= val;
break;
case 0x02:
dev->enable_dma = val;
break;
case 0x10:
dev->enable_irq = val;
break;
default:
break;
}
dev->cmdbuf[1] = 0;
dev->cmdbuf_count = 2;
dev->conf = 0;
break;
case 1:
if (dev->conf == 1) {
dev->dmalen = val << 8;
break;
}
dev->conf = val;
if (dev->conf == 1)
dev->cmdrd_count++;
break;
default:
break;
}
break;
case CMD_READ1X:
case CMD_READ2X:
switch (dev->cmdrd_count) {
case 0:
dev->readcount |= val;
mitsumi_cdrom_read_sector(dev, 1);
dev->cmdbuf_count = 1;
dev->cmdbuf[0] = STAT_SPIN | STAT_READY;
break;
case 1:
dev->readcount |= (val << 8);
break;
case 2:
dev->readcount = (val << 16);
break;
case 5:
dev->readmsf = 0;
fallthrough;
case 4:
case 3:
dev->readmsf |= CD_DCB(val) << ((dev->cmdrd_count - 3) << 3);
break;
default:
break;
}
break;
default:
break;
}
if (!dev->cmdrd_count)
dev->stat = cdrom.host_drive ? (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->data = 0;
switch (val) {
case CMD_GET_INFO:
if (cdrom.host_drive) {
cdrom_get_track_buffer(&cdrom, &(dev->cmdbuf[1]));
dev->cmdbuf_count = 10;
dev->readcount = 0;
} else {
dev->cmdbuf_count = 1;
dev->cmdbuf[0] = STAT_CMD_CHECK;
}
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);
dev->cmdbuf_count = 11;
dev->readcount = 0;
} else {
dev->cmdbuf_count = 1;
dev->cmdbuf[0] = STAT_CMD_CHECK;
}
break;
case CMD_GET_STAT:
dev->change = 0;
break;
case CMD_SET_MODE:
dev->cmdrd_count = 1;
break;
case CMD_STOPCDDA:
case CMD_STOP:
cdrom_stop(&cdrom);
dev->drvmode = DRV_MODE_STOP;
dev->cur_toc_track = 0;
break;
case CMD_CONFIG:
dev->cmdrd_count = 2;
break;
case CMD_READ1X:
case CMD_READ2X:
if (cdrom.host_drive) {
dev->readcount = 0;
dev->drvmode = (val == CMD_READ1X) ? DRV_MODE_CDDA : DRV_MODE_READ;
dev->cmdrd_count = 6;
} else {
dev->cmdbuf_count = 1;
dev->cmdbuf[0] = STAT_CMD_CHECK;
}
break;
case CMD_GET_VER:
dev->cmdbuf[0] = 1;
dev->cmdbuf[1] = 'D';
dev->cmdbuf[2] = 0;
dev->cmdbuf_count = 3;
break;
case CMD_EJECT:
cdrom_stop(&cdrom);
cdrom_eject(0);
dev->readcount = 0;
break;
case CMD_LOCK:
dev->cmdrd_count = 1;
break;
case CMD_SOFT_RESET:
pclog("Soft Reset\n");
mitsumi_cdrom_reset(dev);
break;
default:
dev->cmdbuf[0] = dev->stat | STAT_CMD_CHECK;
break;
}
break;
case 1:
mitsumi_cdrom_reset(dev);
break;
case 2:
break;
default:
break;
}
}
static void *
mitsumi_cdrom_init(UNUSED(const device_t *info))
{
mcd_t *dev;
dev = malloc(sizeof(mcd_t));
memset(dev, 0x00, sizeof(mcd_t));
dev->irq = MCD_DEFAULT_IRQ;
dev->dma = MCD_DEFAULT_DMA;
io_sethandler(MCD_DEFAULT_IOPORT, 3,
mitsumi_cdrom_in, NULL, NULL, mitsumi_cdrom_out, NULL, NULL, dev);
mitsumi_cdrom_reset(dev);
return dev;
}
static void
mitsumi_cdrom_close(void *priv)
{
mcd_t *dev = (mcd_t *) priv;
if (dev) {
free(dev);
dev = NULL;
}
}
const device_t mitsumi_cdrom_device = {
.name = "Mitsumi CD-ROM interface",
.internal_name = "mcd",
.flags = DEVICE_ISA | DEVICE_AT,
.local = 1,
.init = mitsumi_cdrom_init,
.close = mitsumi_cdrom_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -1,24 +1,26 @@
/*
* 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.
*
* Implementation of Chips&Technology's 82C100 chipset.
* Implementation of Chips&Technology's 82C100 chipset.
*
*
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2021 Miran Grca.
* Copyright 2021 Miran Grca.
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/device.h>
#include "cpu.h"
@@ -26,33 +28,30 @@
#include <86box/io.h>
#include <86box/mem.h>
#include <86box/nmi.h>
#include <86box/plat_unused.h>
#include <86box/port_92.h>
#include <86box/rom.h>
#include <86box/chipset.h>
typedef struct
{
int enabled;
uint32_t virt, phys;
typedef struct ems_page_t {
int enabled;
uint32_t virt;
uint32_t phys;
} ems_page_t;
typedef struct
{
uint8_t index, access;
uint16_t ems_io_base;
uint32_t ems_window_base;
uint8_t ems_page_regs[4],
regs[256];
ems_page_t ems_pages[4];
mem_mapping_t ems_mappings[4];
typedef struct ct_82c100_t {
uint8_t index;
uint8_t access;
uint16_t ems_io_base;
uint32_t ems_window_base;
uint8_t ems_page_regs[4];
uint8_t regs[256];
ems_page_t ems_pages[4];
mem_mapping_t ems_mappings[4];
} ct_82c100_t;
#ifdef ENABLE_CT_82C100_LOG
int ct_82c100_do_log = ENABLE_CT82C100_LOG;
int ct_82c100_do_log = ENABLE_CT_82C100_LOG;
static void
ct_82c100_log(const char *fmt, ...)
@@ -60,46 +59,43 @@ ct_82c100_log(const char *fmt, ...)
va_list ap;
if (ct_82c100_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define ct_82c100_log(fmt, ...)
# define ct_82c100_log(fmt, ...)
#endif
static void
ct_82c100_ems_pages_recalc(ct_82c100_t *dev)
{
int i;
uint32_t page_base;
for (i = 0; i < 4; i++) {
page_base = dev->ems_window_base + (i << 14);
if ((i == 1) || (i == 2))
page_base ^= 0xc000;
if (dev->ems_page_regs[i] & 0x80) {
dev->ems_pages[i].virt = page_base;
dev->ems_pages[i].phys = 0xa0000 + (((uint32_t) (dev->ems_page_regs[i] & 0x7f)) << 14);
ct_82c100_log("Enabling EMS page %i: %08X-%08X -> %08X-%08X\n", i,
dev->ems_pages[i].virt, dev->ems_pages[i].virt + 0x00003fff,
dev->ems_pages[i].phys, dev->ems_pages[i].phys + 0x00003fff);
mem_mapping_set_addr(&(dev->ems_mappings[i]), dev->ems_pages[i].virt, 0x4000);
mem_mapping_set_exec(&(dev->ems_mappings[i]), &(ram[dev->ems_pages[i].phys]));
mem_set_mem_state_both(page_base, 0x00004000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
} else {
ct_82c100_log("Disabling EMS page %i\n", i);
mem_mapping_disable(&(dev->ems_mappings[i]));
mem_set_mem_state_both(page_base, 0x00004000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
}
for (uint8_t i = 0; i < 4; i++) {
page_base = dev->ems_window_base + (i << 14);
if ((i == 1) || (i == 2))
page_base ^= 0xc000;
if (dev->ems_page_regs[i] & 0x80) {
dev->ems_pages[i].virt = page_base;
dev->ems_pages[i].phys = 0xa0000 + (((uint32_t) (dev->ems_page_regs[i] & 0x7f)) << 14);
ct_82c100_log("Enabling EMS page %i: %08X-%08X -> %08X-%08X\n", i,
dev->ems_pages[i].virt, dev->ems_pages[i].virt + 0x00003fff,
dev->ems_pages[i].phys, dev->ems_pages[i].phys + 0x00003fff);
mem_mapping_set_addr(&(dev->ems_mappings[i]), dev->ems_pages[i].virt, 0x4000);
mem_mapping_set_exec(&(dev->ems_mappings[i]), &(ram[dev->ems_pages[i].phys]));
mem_set_mem_state_both(page_base, 0x00004000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
} else {
ct_82c100_log("Disabling EMS page %i\n", i);
mem_mapping_disable(&(dev->ems_mappings[i]));
mem_set_mem_state_both(page_base, 0x00004000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
}
}
flushmmucache_nopc();
}
static void
ct_82c100_ems_out(uint16_t port, uint8_t val, void *priv)
{
@@ -110,36 +106,32 @@ ct_82c100_ems_out(uint16_t port, uint8_t val, void *priv)
ct_82c100_ems_pages_recalc(dev);
}
static uint8_t
ct_82c100_ems_in(uint16_t port, void *priv)
{
ct_82c100_t *dev = (ct_82c100_t *) priv;
uint8_t ret = 0xff;
const ct_82c100_t *dev = (ct_82c100_t *) priv;
uint8_t ret = 0xff;
ret = dev->ems_page_regs[port >> 14];
return ret;
}
static void
ct_82c100_ems_update(ct_82c100_t *dev)
{
int i;
for (i = 0; i < 4; i++) {
ct_82c100_log("Disabling EMS I/O handler %i at %04X\n", i, dev->ems_io_base + (i << 14));
io_handler(0, dev->ems_io_base + (i << 14), 1,
ct_82c100_ems_in, NULL, NULL, ct_82c100_ems_out, NULL, NULL, dev);
for (uint8_t i = 0; i < 4; i++) {
ct_82c100_log("Disabling EMS I/O handler %i at %04X\n", i, dev->ems_io_base + (i << 14));
io_handler(0, dev->ems_io_base + (i << 14), 1,
ct_82c100_ems_in, NULL, NULL, ct_82c100_ems_out, NULL, NULL, dev);
}
dev->ems_io_base = 0x0208 + (dev->regs[0x4c] & 0xf0);
for (i = 0; i < 4; i++) {
ct_82c100_log("Enabling EMS I/O handler %i at %04X\n", i, dev->ems_io_base + (i << 14));
io_handler(1, dev->ems_io_base + (i << 14), 1,
ct_82c100_ems_in, NULL, NULL, ct_82c100_ems_out, NULL, NULL, dev);
for (uint8_t i = 0; i < 4; i++) {
ct_82c100_log("Enabling EMS I/O handler %i at %04X\n", i, dev->ems_io_base + (i << 14));
io_handler(1, dev->ems_io_base + (i << 14), 1,
ct_82c100_ems_in, NULL, NULL, ct_82c100_ems_out, NULL, NULL, dev);
}
dev->ems_window_base = 0xc0000 + (((uint32_t) (dev->regs[0x4c] & 0x0f)) << 14);
@@ -147,7 +139,6 @@ ct_82c100_ems_update(ct_82c100_t *dev)
ct_82c100_ems_pages_recalc(dev);
}
static void
ct_82c100_reset(void *priv)
{
@@ -161,7 +152,7 @@ ct_82c100_reset(void *priv)
dev->index = dev->access = 0x00;
/* INTERNAL CONFIGURATION/CONTROL REGISTERS */
dev->regs[0x40] = 0x01; /* Defaults to 8086/V30 mode. */
dev->regs[0x40] = 0x01; /* Defaults to 8086/V30 mode. */
dev->regs[0x43] = 0x30;
dev->regs[0x48] = 0x01;
@@ -171,188 +162,189 @@ ct_82c100_reset(void *priv)
/* ADDITIONAL I/O REGISTERS */
}
static void
ct_82c100_out(uint16_t port, uint8_t val, void *priv)
{
ct_82c100_t *dev = (ct_82c100_t *) priv;
if (port == 0x0022) {
dev->index = val;
dev->access = 1;
dev->index = val;
dev->access = 1;
} else if (port == 0x0023) {
if (dev->access) {
switch (dev->index) {
/* INTERNAL CONFIGURATION/CONTROL REGISTERS */
case 0x40:
dev->regs[0x40] = val & 0xc7;
/* TODO: Clock stuff - needs CPU speed change functionality that's
going to be implemented in 86box v4.0.
Bit 0 is 0 for 8088/V20 and 1 for 8086/V30. */
break;
case 0x41:
dev->regs[0x41] = val & 0xed;
/* TODO: Where is the Software Reset Function that's enabled by
setting bit 6 to 1? */
break;
case 0x42:
dev->regs[0x42] = val & 0x01;
break;
case 0x43:
dev->regs[0x43] = val;
break;
case 0x44:
dev->regs[0x44] = val;
custom_nmi_vector = (custom_nmi_vector & 0xffffff00) | ((uint32_t) val);
break;
case 0x45:
dev->regs[0x45] = val;
custom_nmi_vector = (custom_nmi_vector & 0xffff00ff) | (((uint32_t) val) << 8);
break;
case 0x46:
dev->regs[0x46] = val;
custom_nmi_vector = (custom_nmi_vector & 0xff00ffff) | (((uint32_t) val) << 16);
break;
case 0x47:
dev->regs[0x47] = val;
custom_nmi_vector = (custom_nmi_vector & 0x00ffffff) | (((uint32_t) val) << 24);
break;
case 0x48: case 0x49:
dev->regs[dev->index] = val;
break;
case 0x4b:
dev->regs[0x4b] = val;
use_custom_nmi_vector = !!(val & 0x40);
break;
case 0x4c:
ct_82c100_log("CS4C: %02X\n", val);
dev->regs[0x4c] = val;
ct_82c100_ems_update(dev);
break;
}
dev->access = 0;
}
if (dev->access) {
switch (dev->index) {
/* INTERNAL CONFIGURATION/CONTROL REGISTERS */
case 0x40:
dev->regs[0x40] = val & 0xc7;
/* TODO: Clock stuff - needs CPU speed change functionality that's
going to be implemented in 86box v4.0.
Bit 0 is 0 for 8088/V20 and 1 for 8086/V30. */
break;
case 0x41:
dev->regs[0x41] = val & 0xed;
/* TODO: Where is the Software Reset Function that's enabled by
setting bit 6 to 1? */
break;
case 0x42:
dev->regs[0x42] = val & 0x01;
break;
case 0x43:
dev->regs[0x43] = val;
break;
case 0x44:
dev->regs[0x44] = val;
custom_nmi_vector = (custom_nmi_vector & 0xffffff00) | ((uint32_t) val);
break;
case 0x45:
dev->regs[0x45] = val;
custom_nmi_vector = (custom_nmi_vector & 0xffff00ff) | (((uint32_t) val) << 8);
break;
case 0x46:
dev->regs[0x46] = val;
custom_nmi_vector = (custom_nmi_vector & 0xff00ffff) | (((uint32_t) val) << 16);
break;
case 0x47:
dev->regs[0x47] = val;
custom_nmi_vector = (custom_nmi_vector & 0x00ffffff) | (((uint32_t) val) << 24);
break;
case 0x48:
case 0x49:
dev->regs[dev->index] = val;
break;
case 0x4b:
dev->regs[0x4b] = val;
use_custom_nmi_vector = !!(val & 0x40);
break;
case 0x4c:
ct_82c100_log("CS4C: %02X\n", val);
dev->regs[0x4c] = val;
ct_82c100_ems_update(dev);
break;
default:
break;
}
dev->access = 0;
}
} else if (port == 0x72)
dev->regs[0x72] = val & 0x7e;
dev->regs[0x72] = val & 0x7e;
else if (port == 0x7e)
dev->regs[0x7e] = val;
dev->regs[0x7e] = val;
else if (port == 0x7f) {
/* Bit 3 is Software Controlled Reset, asserted if set. Will be
done in the feature/machine_and_kb branch using hardresetx86(). */
dev->regs[0x7f] = val;
if ((dev->regs[0x41] & 0x40) && (val & 0x08)) {
softresetx86();
cpu_set_edx();
ct_82c100_reset(dev);
}
/* Bit 3 is Software Controlled Reset, asserted if set. Will be
done in the feature/machine_and_kb branch using hardresetx86(). */
dev->regs[0x7f] = val;
if ((dev->regs[0x41] & 0x40) && (val & 0x08)) {
softresetx86();
cpu_set_edx();
ct_82c100_reset(dev);
}
}
}
static uint8_t
ct_82c100_in(uint16_t port, void *priv)
{
ct_82c100_t *dev = (ct_82c100_t *) priv;
uint8_t ret = 0xff;
uint8_t ret = 0xff;
if (port == 0x0022)
ret = dev->index;
ret = dev->index;
else if (port == 0x0023) {
if (dev->access) {
switch (dev->index) {
/* INTERNAL CONFIGURATION/CONTROL REGISTERS */
case 0x40 ... 0x49:
case 0x4b: case 0x4c:
ret = dev->regs[dev->index];
break;
}
dev->access = 0;
}
if (dev->access) {
switch (dev->index) {
/* INTERNAL CONFIGURATION/CONTROL REGISTERS */
case 0x40 ... 0x49:
case 0x4b:
case 0x4c:
ret = dev->regs[dev->index];
break;
default:
break;
}
dev->access = 0;
}
} else if (port == 0x72)
ret = dev->regs[0x72];
ret = dev->regs[0x72];
else if (port == 0x7e)
ret = dev->regs[0x7e];
ret = dev->regs[0x7e];
else if (port == 0x7f)
ret = dev->regs[0x7f];
ret = dev->regs[0x7f];
return ret;
}
static uint8_t
mem_read_emsb(uint32_t addr, void *priv)
{
ems_page_t *page = (ems_page_t *)priv;
uint8_t ret = 0xff;
const ems_page_t *page = (ems_page_t *) priv;
uint8_t ret = 0xff;
#ifdef ENABLE_CT_82C100_LOG
uint32_t old_addr = addr;
#endif
addr = addr - page->virt + page->phys;
if (addr < ((uint32_t)mem_size << 10))
ret = ram[addr];
if (addr < (mem_size << 10))
ret = ram[addr];
ct_82c100_log("mem_read_emsb(%08X = %08X): %02X\n", old_addr, addr, ret);
return ret;
}
static uint16_t
mem_read_emsw(uint32_t addr, void *priv)
{
ems_page_t *page = (ems_page_t *)priv;
uint16_t ret = 0xffff;
const ems_page_t *page = (ems_page_t *) priv;
uint16_t ret = 0xffff;
#ifdef ENABLE_CT_82C100_LOG
uint32_t old_addr = addr;
#endif
addr = addr - page->virt + page->phys;
if (addr < ((uint32_t)mem_size << 10))
ret = *(uint16_t *)&ram[addr];
if (addr < (mem_size << 10))
ret = *(uint16_t *) &ram[addr];
ct_82c100_log("mem_read_emsw(%08X = %08X): %04X\n", old_addr, addr, ret);
return ret;
}
static void
mem_write_emsb(uint32_t addr, uint8_t val, void *priv)
{
ems_page_t *page = (ems_page_t *)priv;
const ems_page_t *page = (ems_page_t *) priv;
#ifdef ENABLE_CT_82C100_LOG
uint32_t old_addr = addr;
#endif
addr = addr - page->virt + page->phys;
if (addr < ((uint32_t)mem_size << 10))
ram[addr] = val;
if (addr < (mem_size << 10))
ram[addr] = val;
ct_82c100_log("mem_write_emsb(%08X = %08X, %02X)\n", old_addr, addr, val);
}
static void
mem_write_emsw(uint32_t addr, uint16_t val, void *priv)
{
ems_page_t *page = (ems_page_t *)priv;
const ems_page_t *page = (ems_page_t *) priv;
#ifdef ENABLE_CT_82C100_LOG
uint32_t old_addr = addr;
#endif
addr = addr - page->virt + page->phys;
if (addr < ((uint32_t)mem_size << 10))
*(uint16_t *)&ram[addr] = val;
if (addr < (mem_size << 10))
*(uint16_t *) &ram[addr] = val;
ct_82c100_log("mem_write_emsw(%08X = %08X, %04X)\n", old_addr, addr, val);
}
static void
ct_82c100_close(void *priv)
{
@@ -361,47 +353,48 @@ ct_82c100_close(void *priv)
free(dev);
}
static void *
ct_82c100_init(const device_t *info)
ct_82c100_init(UNUSED(const device_t *info))
{
ct_82c100_t *dev;
uint32_t i;
dev = (ct_82c100_t *)malloc(sizeof(ct_82c100_t));
dev = (ct_82c100_t *) malloc(sizeof(ct_82c100_t));
memset(dev, 0x00, sizeof(ct_82c100_t));
ct_82c100_reset(dev);
io_sethandler(0x0022, 2,
ct_82c100_in, NULL, NULL, ct_82c100_out, NULL, NULL, dev);
ct_82c100_in, NULL, NULL, ct_82c100_out, NULL, NULL, dev);
io_sethandler(0x0072, 1,
ct_82c100_in, NULL, NULL, ct_82c100_out, NULL, NULL, dev);
ct_82c100_in, NULL, NULL, ct_82c100_out, NULL, NULL, dev);
io_sethandler(0x007e, 2,
ct_82c100_in, NULL, NULL, ct_82c100_out, NULL, NULL, dev);
ct_82c100_in, NULL, NULL, ct_82c100_out, NULL, NULL, dev);
for (i = 0; i < 4; i++) {
mem_mapping_add(&(dev->ems_mappings[i]), (i + 28) << 14, 0x04000,
mem_read_emsb, mem_read_emsw, NULL,
mem_write_emsb, mem_write_emsw, NULL,
ram + 0xa0000 + (i << 14), MEM_MAPPING_INTERNAL, &dev->ems_pages[i]);
mem_mapping_disable(&(dev->ems_mappings[i]));
for (uint8_t i = 0; i < 4; i++) {
mem_mapping_add(&(dev->ems_mappings[i]), (i + 28) << 14, 0x04000,
mem_read_emsb, mem_read_emsw, NULL,
mem_write_emsb, mem_write_emsw, NULL,
ram + 0xa0000 + (i << 14), MEM_MAPPING_INTERNAL, &dev->ems_pages[i]);
mem_mapping_disable(&(dev->ems_mappings[i]));
}
mem_mapping_disable(&ram_mid_mapping);
device_add(&port_92_device);
return(dev);
return dev;
}
const device_t ct_82c100_device = {
"C&T 82C100",
"ct_82c100",
0,
0,
ct_82c100_init, ct_82c100_close, ct_82c100_reset,
{ NULL }, NULL, NULL,
NULL
.name = "C&T 82C100",
.internal_name = "ct_82c100",
.flags = 0,
.local = 0,
.init = ct_82c100_init,
.close = ct_82c100_close,
.reset = ct_82c100_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -1,26 +1,27 @@
#
# 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.
#
add_library(chipset OBJECT 82c100.c acc2168.c cs8230.c ali1429.c ali1489.c ali1531.c ali1541.c ali1543.c
ali1621.c ali6117.c headland.c ims8848.c intel_82335.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 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)
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()
endif()

View File

@@ -1,20 +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.
* 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.
*
* Implementation of the ACC 2046/2168 chipset
* Implementation of the ACC 2046/2168 chipset
*
*
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
* Tiseno100
*
* Copyright 2019 Sarah Walker.
* Copyright 2021 Tiseno100.
* Copyright 2019 Sarah Walker.
* Copyright 2021 Tiseno100.
*/
#include <stdarg.h>
#include <stdint.h>
@@ -30,144 +30,145 @@
#include <86box/io.h>
#include <86box/mem.h>
#include <86box/port_92.h>
#include <86box/plat_unused.h>
#include <86box/chipset.h>
#define ENABLED_SHADOW (MEM_READ_INTERNAL | ((dev->regs[0x02] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL))
#define ENABLED_SHADOW (MEM_READ_INTERNAL | ((dev->regs[0x02] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL))
#define DISABLED_SHADOW (MEM_READ_EXTANY | MEM_WRITE_EXTANY)
#define SHADOW_ADDR ((i <= 1) ? (0xc0000 + (i << 15)) : (0xd0000 + ((i - 2) << 16)))
#define SHADOW_SIZE ((i <= 1) ? 0x8000 : 0x10000)
#define SHADOW_RECALC ((dev->regs[0x02] & (1 << i)) ? ENABLED_SHADOW : DISABLED_SHADOW)
#define SHADOW_ADDR ((i <= 1) ? (0xc0000 + (i << 15)) : (0xd0000 + ((i - 2) << 16)))
#define SHADOW_SIZE ((i <= 1) ? 0x8000 : 0x10000)
#define SHADOW_RECALC ((dev->regs[0x02] & (1 << i)) ? ENABLED_SHADOW : DISABLED_SHADOW)
#ifdef ENABLE_ACC2168_LOG
int acc2168_do_log = ENABLE_ACC2168_LOG;
static void
acc2168_log(const char *fmt, ...)
{
va_list ap;
if (acc2168_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define acc2168_log(fmt, ...)
# define acc2168_log(fmt, ...)
#endif
typedef struct acc2168_t
{
uint8_t reg_idx, regs[256];
typedef struct acc2168_t {
uint8_t reg_idx;
uint8_t regs[256];
} acc2168_t;
static void
acc2168_shadow_recalc(acc2168_t *dev)
{
for (uint32_t i = 0; i < 5; i++)
for (uint8_t i = 0; i < 5; i++)
mem_set_mem_state_both(SHADOW_ADDR, SHADOW_SIZE, SHADOW_RECALC);
}
static void
acc2168_write(uint16_t addr, uint8_t val, void *p)
acc2168_write(uint16_t addr, uint8_t val, void *priv)
{
acc2168_t *dev = (acc2168_t *)p;
acc2168_t *dev = (acc2168_t *) priv;
switch (addr)
{
case 0xf2:
dev->reg_idx = val;
break;
case 0xf3:
acc2168_log("ACC2168: dev->regs[%02x] = %02x\n", dev->reg_idx, val);
switch (dev->reg_idx)
{
case 0x00:
dev->regs[dev->reg_idx] = val;
switch (addr) {
case 0xf2:
dev->reg_idx = val;
break;
case 0xf3:
acc2168_log("ACC2168: dev->regs[%02x] = %02x\n", dev->reg_idx, val);
switch (dev->reg_idx) {
case 0x00:
dev->regs[dev->reg_idx] = val;
break;
case 0x01:
dev->regs[dev->reg_idx] = val & 0xd3;
cpu_update_waitstates();
case 0x01:
dev->regs[dev->reg_idx] = val & 0xd3;
cpu_update_waitstates();
break;
case 0x02:
dev->regs[dev->reg_idx] = val & 0x7f;
acc2168_shadow_recalc(dev);
break;
case 0x03:
dev->regs[dev->reg_idx] = val & 0x1f;
break;
case 0x04:
dev->regs[dev->reg_idx] = val;
cpu_cache_ext_enabled = !!(val & 0x01);
cpu_update_waitstates();
break;
case 0x05:
dev->regs[dev->reg_idx] = val & 0xf3;
break;
case 0x06:
case 0x07:
dev->regs[dev->reg_idx] = val & 0x1f;
break;
case 0x08:
dev->regs[dev->reg_idx] = val & 0x0f;
break;
case 0x09:
dev->regs[dev->reg_idx] = val & 0x03;
break;
case 0x0a:
case 0x0b:
case 0x0c:
case 0x0d:
case 0x0e:
case 0x0f:
case 0x10:
case 0x11:
dev->regs[dev->reg_idx] = val;
break;
case 0x12:
dev->regs[dev->reg_idx] = val & 0xbb;
break;
case 0x18:
dev->regs[dev->reg_idx] = val & 0x77;
break;
case 0x19:
dev->regs[dev->reg_idx] = val & 0xfb;
break;
case 0x1a:
dev->regs[dev->reg_idx] = val;
cpu_cache_int_enabled = !(val & 0x40);
cpu_update_waitstates();
break;
case 0x1b:
dev->regs[dev->reg_idx] = val & 0xef;
break;
default: /* ACC 2168 has way more registers which we haven't documented */
dev->regs[dev->reg_idx] = val;
break;
}
break;
case 0x02:
dev->regs[dev->reg_idx] = val & 0x7f;
acc2168_shadow_recalc(dev);
default:
break;
case 0x03:
dev->regs[dev->reg_idx] = val & 0x1f;
break;
case 0x04:
dev->regs[dev->reg_idx] = val;
cpu_cache_ext_enabled = !!(val & 0x01);
cpu_update_waitstates();
break;
case 0x05:
dev->regs[dev->reg_idx] = val & 0xf3;
break;
case 0x06:
case 0x07:
dev->regs[dev->reg_idx] = val & 0x1f;
break;
case 0x08:
dev->regs[dev->reg_idx] = val & 0x0f;
break;
case 0x09:
dev->regs[dev->reg_idx] = val & 0x03;
break;
case 0x0a:
case 0x0b:
case 0x0c:
case 0x0d:
case 0x0e:
case 0x0f:
case 0x10:
case 0x11:
dev->regs[dev->reg_idx] = val;
break;
case 0x12:
dev->regs[dev->reg_idx] = val & 0xbb;
break;
case 0x18:
dev->regs[dev->reg_idx] = val & 0x77;
break;
case 0x19:
dev->regs[dev->reg_idx] = val & 0xfb;
break;
case 0x1a:
dev->regs[dev->reg_idx] = val;
cpu_cache_int_enabled = !(val & 0x40);
cpu_update_waitstates();
break;
case 0x1b:
dev->regs[dev->reg_idx] = val & 0xef;
break;
default: /* ACC 2168 has way more registers which we haven't documented */
dev->regs[dev->reg_idx] = val;
break;
}
break;
}
}
static uint8_t
acc2168_read(uint16_t addr, void *p)
acc2168_read(uint16_t addr, void *priv)
{
acc2168_t *dev = (acc2168_t *)p;
const acc2168_t *dev = (acc2168_t *) priv;
return (addr == 0xf3) ? dev->regs[dev->reg_idx] : dev->reg_idx;
}
@@ -175,15 +176,15 @@ acc2168_read(uint16_t addr, void *p)
static void
acc2168_close(void *priv)
{
acc2168_t *dev = (acc2168_t *)priv;
acc2168_t *dev = (acc2168_t *) priv;
free(dev);
}
static void *
acc2168_init(const device_t *info)
acc2168_init(UNUSED(const device_t *info))
{
acc2168_t *dev = (acc2168_t *)malloc(sizeof(acc2168_t));
acc2168_t *dev = (acc2168_t *) malloc(sizeof(acc2168_t));
memset(dev, 0, sizeof(acc2168_t));
device_add(&port_92_device);
@@ -193,14 +194,15 @@ acc2168_init(const device_t *info)
}
const device_t acc2168_device = {
"ACC 2046/2168",
"acc2168",
0,
0,
acc2168_init,
acc2168_close,
NULL,
{NULL},
NULL,
NULL,
NULL};
.name = "ACC 2046/2168",
.internal_name = "acc2168",
.flags = 0,
.local = 0,
.init = acc2168_init,
.close = acc2168_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -1,21 +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.
* 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.
*
* Implementation of the ALi M1429 chipset.
* Implementation of the ALi M1429 chipset.
*
* Note: This chipset has no datasheet, everything were done via
* reverse engineering the BIOS of various machines using it.
* Note: This chipset has no datasheet, everything were done via
* reverse engineering the BIOS of various machines using it.
*
* Authors: Tiseno100,
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2020,2021 Tiseno100.
* Copyright 2021,2021 Miran Grca.
*
* Authors: Tiseno100,
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2020-2021 Tiseno100.
* Copyright 2021 Miran Grca.
*/
/*
@@ -64,15 +66,14 @@
Register 20h:
Bits 2-1-0: Bus Clock Speed
0 0 0: 7.1519Mhz (ATCLK2)
0 0 1: CLK2IN/4
0 1 0: CLK2IN/5
0 1 1: CLK2IN/6
1 0 0: CLK2IN/8
1 0 1: CLK2IN/10
1 1 0: CLK2IN/12
0 0 1: CLK2IN/4
0 1 0: CLK2IN/5
0 1 1: CLK2IN/6
1 0 0: CLK2IN/8
1 0 1: CLK2IN/10
1 1 0: CLK2IN/12
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
@@ -94,13 +95,11 @@
#include <86box/smram.h>
#include <86box/chipset.h>
#define GREEN dev->is_g /* Is G Variant */
#define GREEN dev->is_g /* Is G Variant */
#ifdef ENABLE_ALI1429_LOG
int ali1429_do_log = ENABLE_ALI1429_LOG;
static void
ali1429_log(const char *fmt, ...)
{
@@ -113,29 +112,31 @@ ali1429_log(const char *fmt, ...)
}
}
#else
#define ali1429_log(fmt, ...)
# define ali1429_log(fmt, ...)
#endif
typedef struct
{
uint8_t is_g, index, cfg_locked, reg_57h,
regs[90];
typedef struct ali_1429_t {
uint8_t is_g;
uint8_t index;
uint8_t cfg_locked;
uint8_t reg_57h;
uint8_t regs[90];
} ali1429_t;
static void
ali1429_shadow_recalc(ali1429_t *dev)
{
uint32_t base, i, can_write, can_read;
uint32_t base;
uint32_t can_write;
uint32_t can_read;
shadowbios = (dev->regs[0x13] & 0x40) && (dev->regs[0x14] & 0x01);
shadowbios = (dev->regs[0x13] & 0x40) && (dev->regs[0x14] & 0x01);
shadowbios_write = (dev->regs[0x13] & 0x40) && (dev->regs[0x14] & 0x02);
can_write = (dev->regs[0x14] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
can_read = (dev->regs[0x14] & 0x01) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
can_read = (dev->regs[0x14] & 0x01) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
for (i = 0; i < 8; i++) {
for (uint8_t i = 0; i < 8; i++) {
base = 0xc0000 + (i << 15);
if (dev->regs[0x13] & (1 << i))
@@ -147,147 +148,159 @@ ali1429_shadow_recalc(ali1429_t *dev)
flushmmucache_nopc();
}
static void
ali1429_write(uint16_t addr, uint8_t val, void *priv)
{
ali1429_t *dev = (ali1429_t *)priv;
ali1429_t *dev = (ali1429_t *) priv;
switch (addr) {
case 0x22:
dev->index = val;
break;
case 0x22:
dev->index = val;
break;
case 0x23:
case 0x23:
#ifdef ENABLE_ALI1429_LOG
if (dev->index != 0x03)
ali1429_log("M1429: dev->regs[%02x] = %02x\n", dev->index, val);
if (dev->index != 0x03)
ali1429_log("M1429: dev->regs[%02x] = %02x\n", dev->index, val);
#endif
if (dev->index == 0x03)
dev->cfg_locked = !(val == 0xc5);
if (dev->index == 0x03)
dev->cfg_locked = (val != 0xc5);
if (!dev->cfg_locked) {
/* Common M1429 Registers */
switch (dev->index) {
case 0x10: case 0x11:
dev->regs[dev->index] = val;
break;
if (!dev->cfg_locked) {
ali1429_log("M1429: dev->regs[%02x] = %02x\n", dev->index, val);
case 0x12:
dev->regs[dev->index] = val;
if(val & 4)
mem_remap_top(128);
else
mem_remap_top(0);
break;
/* Common M1429 Registers */
switch (dev->index) {
case 0x10:
case 0x11:
dev->regs[dev->index] = val;
break;
case 0x13: case 0x14:
dev->regs[dev->index] = val;
ali1429_shadow_recalc(dev);
break;
case 0x12:
dev->regs[dev->index] = val;
if (val & 4)
mem_remap_top(128);
else
mem_remap_top(0);
break;
case 0x15: case 0x16:
case 0x17:
dev->regs[dev->index] = val;
break;
case 0x13:
case 0x14:
dev->regs[dev->index] = val;
ali1429_shadow_recalc(dev);
break;
case 0x18:
dev->regs[dev->index] = (val & 0x8f) | 0x20;
cpu_cache_ext_enabled = !!(val & 2);
cpu_update_waitstates();
break;
case 0x15:
case 0x16:
case 0x17:
dev->regs[dev->index] = val;
break;
case 0x19: case 0x1a:
case 0x1e:
dev->regs[dev->index] = val;
break;
case 0x18:
dev->regs[dev->index] = (val & 0x8f) | 0x20;
cpu_cache_ext_enabled = !!(val & 2);
cpu_update_waitstates();
break;
case 0x20:
dev->regs[dev->index] = val;
case 0x19:
case 0x1a:
case 0x1e:
dev->regs[dev->index] = val;
break;
switch(val & 7) {
case 0: case 7: /* Illegal */
cpu_set_isa_speed(7159091);
break;
case 0x20:
dev->regs[dev->index] = val;
case 1:
cpu_set_isa_speed(cpu_busspeed / 4);
break;
switch (val & 7) {
case 0:
case 7: /* Illegal */
cpu_set_isa_speed(7159091);
break;
case 2:
cpu_set_isa_speed(cpu_busspeed / 5);
break;
case 1:
cpu_set_isa_speed(cpu_busspeed / 4);
break;
case 3:
cpu_set_isa_speed(cpu_busspeed / 6);
break;
case 2:
cpu_set_isa_speed(cpu_busspeed / 5);
break;
case 4:
cpu_set_isa_speed(cpu_busspeed / 8);
break;
case 3:
cpu_set_isa_speed(cpu_busspeed / 6);
break;
case 5:
cpu_set_isa_speed(cpu_busspeed / 10);
break;
case 4:
cpu_set_isa_speed(cpu_busspeed / 8);
break;
case 6:
cpu_set_isa_speed(cpu_busspeed / 12);
break;
}
break;
case 5:
cpu_set_isa_speed(cpu_busspeed / 10);
break;
case 0x21 ... 0x27:
dev->regs[dev->index] = val;
break;
}
case 6:
cpu_set_isa_speed(cpu_busspeed / 12);
break;
default:
break;
}
break;
/* M1429G Only Registers */
if (GREEN) {
switch (dev->index) {
case 0x30 ... 0x41:
case 0x43: case 0x45:
case 0x4a:
dev->regs[dev->index] = val;
break;
case 0x21 ... 0x27:
dev->regs[dev->index] = val;
break;
default:
break;
}
case 0x57:
dev->reg_57h = val;
break;
}
}
}
break;
/* M1429G Only Registers */
if (GREEN) {
switch (dev->index) {
case 0x30 ... 0x41:
case 0x43:
case 0x45:
case 0x4a:
dev->regs[dev->index] = val;
break;
case 0x57:
dev->reg_57h = val;
break;
default:
break;
}
}
}
break;
default:
break;
}
}
static uint8_t
ali1429_read(uint16_t addr, void *priv)
{
ali1429_t *dev = (ali1429_t *)priv;
uint8_t ret = 0xff;
const ali1429_t *dev = (ali1429_t *) priv;
uint8_t ret = 0xff;
if ((addr == 0x23) && (dev->index >= 0x10) && (dev->index <= 0x4a))
ret = dev->regs[dev->index];
ret = dev->regs[dev->index];
else if ((addr == 0x23) && (dev->index == 0x57))
ret = dev->reg_57h;
ret = dev->reg_57h;
else if (addr == 0x22)
ret = dev->index;
ret = dev->index;
return ret;
}
static void
ali1429_close(void *priv)
{
ali1429_t *dev = (ali1429_t *)priv;
ali1429_t *dev = (ali1429_t *) priv;
free(dev);
}
static void
ali1429_defaults(ali1429_t *dev)
{
@@ -306,28 +319,27 @@ ali1429_defaults(ali1429_t *dev)
/* M1429G Default Registers */
if (GREEN) {
dev->regs[0x31] = 0x88;
dev->regs[0x32] = 0xc0;
dev->regs[0x38] = 0xe5;
dev->regs[0x40] = 0xe3;
dev->regs[0x41] = 2;
dev->regs[0x45] = 0x80;
dev->regs[0x31] = 0x88;
dev->regs[0x32] = 0xc0;
dev->regs[0x38] = 0xe5;
dev->regs[0x40] = 0xe3;
dev->regs[0x41] = 2;
dev->regs[0x45] = 0x80;
}
}
static void *
ali1429_init(const device_t *info)
{
ali1429_t *dev = (ali1429_t *)malloc(sizeof(ali1429_t));
ali1429_t *dev = (ali1429_t *) malloc(sizeof(ali1429_t));
memset(dev, 0, sizeof(ali1429_t));
dev->cfg_locked = 1;
GREEN = info->local;
GREEN = info->local;
/* M1429 Ports:
22h Index Port
23h Data Port
22h Index Port
23h Data Port
*/
io_sethandler(0x0022, 0x0002, ali1429_read, NULL, NULL, ali1429_write, NULL, NULL, dev);
@@ -339,21 +351,29 @@ ali1429_init(const device_t *info)
}
const device_t ali1429_device = {
"ALi M1429",
"ali1429",
0,
0,
ali1429_init, ali1429_close, NULL,
{ NULL }, NULL, NULL,
NULL
.name = "ALi M1429",
.internal_name = "ali1429",
.flags = 0,
.local = 0,
.init = ali1429_init,
.close = ali1429_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t ali1429g_device = {
"ALi M1429G",
"ali1429g",
0,
1,
ali1429_init, ali1429_close, NULL,
{ NULL }, NULL, NULL,
NULL
.name = "ALi M1429G",
.internal_name = "ali1429g",
.flags = 0,
.local = 1,
.init = ali1429_init,
.close = ali1429_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

315
src/chipset/ali1435.c Normal file
View File

@@ -0,0 +1,315 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* Emulation of ALi M1435 chipset that acts as both the
* southbridge.
*
*
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2020 Miran Grca.
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/io.h>
#include <86box/apm.h>
#include <86box/dma.h>
#include <86box/mem.h>
#include <86box/smram.h>
#include <86box/pci.h>
#include <86box/timer.h>
#include <86box/pic.h>
#include <86box/pit.h>
#include <86box/plat_unused.h>
#include <86box/port_92.h>
#include <86box/hdc_ide.h>
#include <86box/hdc.h>
#include <86box/machine.h>
#include <86box/chipset.h>
#include <86box/spd.h>
#define MEM_STATE_SHADOW_R 0x01
#define MEM_STATE_SHADOW_W 0x02
#define MEM_STATE_SMRAM 0x04
typedef struct ali_1435_t {
uint8_t index;
uint8_t cfg_locked;
uint8_t pci_slot;
uint8_t pad;
uint8_t regs[16];
uint8_t pci_regs[256];
} ali1435_t;
#ifdef ENABLE_ALI1435_LOG
int ali1435_do_log = ENABLE_ALI1435_LOG;
static void
ali1435_log(const char *fmt, ...)
{
va_list ap;
if (ali1435_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define ali1435_log(fmt, ...)
#endif
/* NOTE: We cheat here. The real ALi M1435 uses a level to edge triggered IRQ converter
when the most siginificant bit is set. We work around that by manipulating the
emulated PIC's ELCR register. */
static void
ali1435_update_irqs(ali1435_t *dev, int set)
{
uint8_t val;
int reg;
int shift;
int irq;
int irq_map[8] = { -1, 5, 9, 10, 11, 12, 14, 15 };
pic_t *temp_pic;
for (uint8_t i = 0; i < 4; i++) {
reg = 0x80 + (i >> 1);
shift = (i & 1) << 2;
val = (dev->pci_regs[reg] >> shift) & 0x0f;
irq = irq_map[val & 0x07];
if (irq == -1)
continue;
temp_pic = (irq >= 8) ? &pic2 : &pic;
irq &= 7;
if (set && (val & 0x08))
temp_pic->elcr |= (1 << irq);
else
temp_pic->elcr &= ~(1 << irq);
}
}
static void
ali1435_pci_write(int func, int addr, uint8_t val, void *priv)
{
ali1435_t *dev = (ali1435_t *) priv;
int irq;
int irq_map[8] = { -1, 5, 9, 10, 11, 12, 14, 15 };
ali1435_log("ali1435_write(%02X, %02X, %02X)\n", func, addr, val);
if (func > 0)
return;
if ((addr < 0x04) || (addr == 0x06) || ((addr >= 0x08) && (addr <= 0x0b)))
return;
if ((addr >= 0x0f) && (addr < 0x30))
return;
if ((addr >= 0x34) && (addr < 0x40))
return;
switch (addr) {
/* Dummy PCI Config */
case 0x04:
dev->pci_regs[addr] = (val & 0x7f) | 0x07;
break;
case 0x05:
dev->pci_regs[addr] = (val & 0x01);
break;
/* Dummy PCI Status */
case 0x07:
dev->pci_regs[addr] &= ~(val & 0xb8);
break;
case 0x80:
case 0x81:
dev->pci_regs[addr] = val;
ali1435_update_irqs(dev, 0);
irq = irq_map[val & 0x07];
if (irq >= 0) {
ali1435_log("Set IRQ routing: INT %c -> %02X\n", 0x41 + ((addr & 0x01) << 1), irq);
pci_set_irq_routing(PCI_INTA + ((addr & 0x01) << 1), irq);
} else {
ali1435_log("Set IRQ routing: INT %c -> FF\n", 0x41 + ((addr & 0x01) << 1));
pci_set_irq_routing(PCI_INTA + ((addr & 0x01) << 1), PCI_IRQ_DISABLED);
}
irq = irq_map[(val >> 4) & 0x07];
if (irq >= 0) {
ali1435_log("Set IRQ routing: INT %c -> %02X\n", 0x42 + ((addr & 0x01) << 1), irq);
pci_set_irq_routing(PCI_INTB + ((addr & 0x01) << 1), irq);
} else {
ali1435_log("Set IRQ routing: INT %c -> FF\n", 0x42 + ((addr & 0x01) << 1));
pci_set_irq_routing(PCI_INTB + ((addr & 0x01) << 1), PCI_IRQ_DISABLED);
}
ali1435_update_irqs(dev, 1);
break;
default:
dev->pci_regs[addr] = val;
break;
}
}
static uint8_t
ali1435_pci_read(int func, int addr, void *priv)
{
const ali1435_t *dev = (ali1435_t *) priv;
uint8_t ret;
ret = 0xff;
if (func == 0)
ret = dev->pci_regs[addr];
ali1435_log("ali1435_read(%02X, %02X) = %02X\n", func, addr, ret);
return ret;
}
static void
ali1435_write(uint16_t addr, uint8_t val, void *priv)
{
ali1435_t *dev = (ali1435_t *) priv;
switch (addr) {
case 0x22:
dev->index = val;
break;
case 0x23:
if (dev->index == 0x03)
dev->cfg_locked = (val != 0x69);
#ifdef ENABLE_ALI1435_LOG
else
ali1435_log("M1435: dev->regs[%02x] = %02x\n", dev->index, val);
#endif
if (!dev->cfg_locked) {
switch (dev->index) {
/* PCI Mechanism select? */
case 0x00:
dev->regs[dev->index] = val;
ali1435_log("PMC = %i\n", val != 0xc8);
pci_key_write(((val & 0xc8) == 0xc8) ? 0xf0 : 0x00);
break;
/* ???? */
case 0x06:
dev->regs[dev->index] = val;
break;
/* ???? */
case 0x07:
dev->regs[dev->index] = val;
break;
default:
break;
}
}
break;
default:
break;
}
}
static uint8_t
ali1435_read(uint16_t addr, void *priv)
{
const ali1435_t *dev = (ali1435_t *) priv;
uint8_t ret = 0xff;
if ((addr == 0x23) && (dev->index < 0x10))
ret = dev->regs[dev->index];
else if (addr == 0x22)
ret = dev->index;
return ret;
}
static void
ali1435_reset(void *priv)
{
ali1435_t *dev = (ali1435_t *) priv;
memset(dev->regs, 0, 16);
dev->regs[0x00] = 0xff;
dev->cfg_locked = 1;
memset(dev->pci_regs, 0, 256);
dev->pci_regs[0x00] = 0x25;
dev->pci_regs[0x01] = 0x10; /*ALi*/
dev->pci_regs[0x02] = 0x35;
dev->pci_regs[0x03] = 0x14; /*M1435*/
dev->pci_regs[0x04] = 0x07;
dev->pci_regs[0x07] = 0x04;
dev->pci_regs[0x0b] = 0x06;
dev->pci_regs[0x80] = 0x80;
dev->pci_regs[0x81] = 0x00;
pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED);
pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED);
pci_set_irq_routing(PCI_INTC, PCI_IRQ_DISABLED);
pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED);
}
static void
ali1435_close(void *priv)
{
ali1435_t *dev = (ali1435_t *) priv;
free(dev);
}
static void *
ali1435_init(UNUSED(const device_t *info))
{
ali1435_t *dev = (ali1435_t *) malloc(sizeof(ali1435_t));
memset(dev, 0, sizeof(ali1435_t));
dev->cfg_locked = 1;
/* M1435 Ports:
22h Index Port
23h Data Port
*/
io_sethandler(0x0022, 0x0002, ali1435_read, NULL, NULL, ali1435_write, NULL, NULL, dev);
pci_add_card(PCI_ADD_NORTHBRIDGE, ali1435_pci_read, ali1435_pci_write, dev, &dev->pci_slot);
ali1435_reset(dev);
return dev;
}
const device_t ali1435_device = {
.name = "Intel ALi M1435",
.internal_name = "ali1435",
.flags = DEVICE_PCI,
.local = 0x00,
.init = ali1435_init,
.close = ali1435_close,
.reset = ali1435_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -1,20 +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.
* 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.
*
* Implementation of the ALi M1489 chipset.
* Implementation of the ALi M1489 chipset.
*
*
*
* Authors: Tiseno100,
* Miran Grca, <mgrca8@gmail.com>
* Authors: Tiseno100,
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2020,2021 Tiseno100.
* Copyright 2020,2021 Miran Grca.
* Copyright 2020-2021 Tiseno100.
* Copyright 2020-2021 Miran Grca.
*/
#include <stdarg.h>
#include <stdint.h>
@@ -35,83 +35,80 @@
#include <86box/nmi.h>
#include <86box/pic.h>
#include <86box/pci.h>
#include <86box/plat_unused.h>
#include <86box/port_92.h>
#include <86box/smram.h>
#include <86box/chipset.h>
#define DEFINE_SHADOW_PROCEDURE (((dev->regs[0x14] & 0x10) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x14] & 0x20) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY))
#define DISABLED_SHADOW (MEM_READ_EXTANY | MEM_WRITE_EXTANY)
#define DISABLED_SHADOW (MEM_READ_EXTANY | MEM_WRITE_EXTANY)
#ifdef ENABLE_ALI1489_LOG
int ali1489_do_log = ENABLE_ALI1489_LOG;
static void
ali1489_log(const char *fmt, ...)
{
va_list ap;
if (ali1489_do_log)
{
if (ali1489_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define ali1489_log(fmt, ...)
# define ali1489_log(fmt, ...)
#endif
typedef struct ali1489_t {
uint8_t index;
uint8_t ide_index;
uint8_t ide_chip_id;
uint8_t pci_slot;
uint8_t regs[256];
uint8_t pci_conf[256];
uint8_t ide_regs[256];
typedef struct
{
uint8_t index, ide_index, ide_chip_id, pci_slot,
regs[256], pci_conf[256], ide_regs[256];
port_92_t * port_92;
smram_t * smram;
port_92_t *port_92;
smram_t *smram;
} ali1489_t;
static void ali1489_ide_handler(ali1489_t *dev);
static void ali1489_ide_handler(ali1489_t *dev);
static void
ali1489_shadow_recalc(ali1489_t *dev)
{
uint32_t i;
shadowbios = shadowbios_write = 0;
for (i = 0; i < 8; i++) {
if (dev->regs[0x13] & (1 << i)) {
ali1489_log("%06Xh-%06Xh region shadow enabled: read = %i, write = %i\n",
0xc0000 + (i << 14), 0xc3fff + (i << 14), !!(dev->regs[0x14] & 0x10), !!(dev->regs[0x14] & 0x20));
mem_set_mem_state_both(0xc0000 + (i << 14), 0x4000, DEFINE_SHADOW_PROCEDURE);
} else {
ali1489_log("%06Xh-%06Xh region shadow disabled\n", 0xc0000 + (i << 14), 0xc3fff + (i << 14));
mem_set_mem_state_both(0xc0000 + (i << 14), 0x4000, DISABLED_SHADOW);
}
for (uint8_t i = 0; i < 8; i++) {
if (dev->regs[0x13] & (1 << i)) {
ali1489_log("%06Xh-%06Xh region shadow enabled: read = %i, write = %i\n",
0xc0000 + (i << 14), 0xc3fff + (i << 14), !!(dev->regs[0x14] & 0x10), !!(dev->regs[0x14] & 0x20));
mem_set_mem_state_both(0xc0000 + (i << 14), 0x4000, DEFINE_SHADOW_PROCEDURE);
} else {
ali1489_log("%06Xh-%06Xh region shadow disabled\n", 0xc0000 + (i << 14), 0xc3fff + (i << 14));
mem_set_mem_state_both(0xc0000 + (i << 14), 0x4000, DISABLED_SHADOW);
}
}
for (i = 0; i < 4; i++) {
for (uint8_t i = 0; i < 4; i++) {
if (dev->regs[0x14] & (1 << i)) {
ali1489_log("%06Xh-%06Xh region shadow enabled: read = %i, write = %i\n",
0xe0000 + (i << 15), 0xe7fff + (i << 15), !!(dev->regs[0x14] & 0x10), !!(dev->regs[0x14] & 0x20));
mem_set_mem_state_both(0xe0000 + (i << 15), 0x8000, DEFINE_SHADOW_PROCEDURE);
shadowbios |= !!(dev->regs[0x14] & 0x10);
shadowbios_write |= !!(dev->regs[0x14] & 0x20);
ali1489_log("%06Xh-%06Xh region shadow enabled: read = %i, write = %i\n",
0xe0000 + (i << 15), 0xe7fff + (i << 15), !!(dev->regs[0x14] & 0x10), !!(dev->regs[0x14] & 0x20));
mem_set_mem_state_both(0xe0000 + (i << 15), 0x8000, DEFINE_SHADOW_PROCEDURE);
shadowbios |= !!(dev->regs[0x14] & 0x10);
shadowbios_write |= !!(dev->regs[0x14] & 0x20);
} else {
ali1489_log("%06Xh-%06Xh region shadow disabled\n", 0xe0000 + (i << 15), 0xe7fff + (i << 15));
mem_set_mem_state_both(0xe0000 + (i << 15), 0x8000, DISABLED_SHADOW);
}
ali1489_log("%06Xh-%06Xh region shadow disabled\n", 0xe0000 + (i << 15), 0xe7fff + (i << 15));
mem_set_mem_state_both(0xe0000 + (i << 15), 0x8000, DISABLED_SHADOW);
}
}
flushmmucache_nopc();
}
static void
ali1489_smram_recalc(ali1489_t *dev)
{
@@ -120,27 +117,28 @@ ali1489_smram_recalc(ali1489_t *dev)
smram_disable(dev->smram);
switch (dev->regs[0x19] & 0x30) {
case 0x10:
smram_enable(dev->smram, 0xa0000, 0xa0000, 0x20000, (dev->regs[0x19] & 0x08), 1);
break;
case 0x20:
smram_enable(dev->smram, 0xe0000, 0xe0000, 0x10000, (dev->regs[0x19] & 0x08), 1);
break;
case 0x30:
if ((dev->regs[0x35] & 0xc0) == 0x80)
smram_enable(dev->smram, 0x68000, 0xa8000, 0x08000, (dev->regs[0x19] & 0x08), 1);
else
smram_enable(dev->smram, 0x38000, 0xa8000, 0x08000, (dev->regs[0x19] & 0x08), 1);
break;
case 0x10:
smram_enable(dev->smram, 0xa0000, 0xa0000, 0x20000, (dev->regs[0x19] & 0x08), 1);
break;
case 0x20:
smram_enable(dev->smram, 0xe0000, 0xe0000, 0x10000, (dev->regs[0x19] & 0x08), 1);
break;
case 0x30:
if ((dev->regs[0x35] & 0xc0) == 0x80)
smram_enable(dev->smram, 0x68000, 0xa8000, 0x08000, (dev->regs[0x19] & 0x08), 1);
else
smram_enable(dev->smram, 0x38000, 0xa8000, 0x08000, (dev->regs[0x19] & 0x08), 1);
break;
default:
break;
}
if ((dev->regs[0x19] & 0x31) == 0x11) {
/* If SMRAM is enabled and bit 0 is set, code still goes to DRAM. */
mem_set_mem_state_smram_ex(1, 0xa0000, 0x20000, 0x02);
/* If SMRAM is enabled and bit 0 is set, code still goes to DRAM. */
mem_set_mem_state_smram_ex(1, 0xa0000, 0x20000, 0x02);
}
}
static void
ali1489_defaults(ali1489_t *dev)
{
@@ -197,9 +195,9 @@ ali1489_defaults(ali1489_t *dev)
picintc(1 << 10);
picintc(1 << 15);
nmi = 0;
nmi = 0;
smi_line = 0;
in_smm = 0;
in_smm = 0;
pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED);
pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED);
@@ -209,214 +207,222 @@ ali1489_defaults(ali1489_t *dev)
ali1489_ide_handler(dev);
}
static void
ali1489_write(uint16_t addr, uint8_t val, void *priv)
{
ali1489_t *dev = (ali1489_t *)priv;
uint8_t old, irq;
const uint8_t irq_array[16] = { 0, 3, 4, 7, 0, 0, 0, 0, 9, 10, 5, 6, 11, 12, 14, 15 };
ali1489_t *dev = (ali1489_t *) priv;
uint8_t old;
uint8_t irq;
const uint8_t irq_array[16] = { 0, 9, 3, 10, 4, 5, 7, 6, 0, 11, 0, 12, 0, 14, 0, 15 };
switch (addr) {
case 0x22:
dev->index = val;
break;
case 0x23:
/* Check if the configuration registers are unlocked */
if (dev->regs[0x03] == 0xc5) {
switch (dev->index) {
case 0x03: /* Lock Register */
case 0x10: /* DRAM Configuration Register I */
case 0x11: /* DRAM Configuration Register II */
case 0x12: /* ROM Function Register */
dev->regs[dev->index] = val;
break;
case 0x22:
dev->index = val;
break;
case 0x23:
/* Check if the configuration registers are unlocked */
if (dev->regs[0x03] == 0xc5) {
switch (dev->index) {
case 0x03: /* Lock Register */
case 0x10: /* DRAM Configuration Register I */
case 0x11: /* DRAM Configuration Register II */
case 0x12: /* ROM Function Register */
dev->regs[dev->index] = val;
break;
case 0x13: /* Shadow Region Register */
case 0x14: /* Shadow Control Register */
if (dev->index == 0x14)
dev->regs[dev->index] = (val & 0xbf);
else
dev->regs[dev->index] = val;
case 0x13: /* Shadow Region Register */
case 0x14: /* Shadow Control Register */
if (dev->index == 0x14)
dev->regs[dev->index] = (val & 0xbf);
else
dev->regs[dev->index] = val;
ali1489_shadow_recalc(dev);
ali1489_smram_recalc(dev);
break;
ali1489_shadow_recalc(dev);
ali1489_smram_recalc(dev);
break;
case 0x15: /* Cycle Check Point Control Register */
dev->regs[dev->index] = (val & 0xf1);
break;
case 0x15: /* Cycle Check Point Control Register */
dev->regs[dev->index] = (val & 0xf1);
break;
case 0x16: /* Cache Control Register I */
dev->regs[dev->index] = val;
cpu_cache_int_enabled = (val & 0x01);
cpu_cache_ext_enabled = (val & 0x02);
cpu_update_waitstates();
break;
case 0x17: /* Cache Control Register II */
dev->regs[dev->index] = val;
break;
case 0x16: /* Cache Control Register I */
dev->regs[dev->index] = val;
cpu_cache_int_enabled = (val & 0x01);
cpu_cache_ext_enabled = (val & 0x02);
cpu_update_waitstates();
break;
case 0x17: /* Cache Control Register II */
dev->regs[dev->index] = val;
break;
case 0x19: /* SMM Control Register */
dev->regs[dev->index] = val;
ali1489_smram_recalc(dev);
break;
case 0x19: /* SMM Control Register */
dev->regs[dev->index] = val;
ali1489_smram_recalc(dev);
break;
case 0x1a: /* EDO DRAM Configuration Register */
case 0x1b: /* DRAM Timing Control Register */
dev->regs[dev->index] = val;
break;
case 0x1c: /* Memory Data Buffer Direction Control Register */
dev->regs[dev->index] = val & 0x1f;
break;
case 0x1a: /* EDO DRAM Configuration Register */
case 0x1b: /* DRAM Timing Control Register */
dev->regs[dev->index] = val;
break;
case 0x1c: /* Memory Data Buffer Direction Control Register */
dev->regs[dev->index] = val & 0x1f;
break;
case 0x1e: /* Linear Wrapped Burst Order Mode Control Register */
dev->regs[dev->index] = (val & 0x40);
break;
case 0x1e: /* Linear Wrapped Burst Order Mode Control Register */
dev->regs[dev->index] = (val & 0x40);
break;
case 0x20: /* CPU to PCI Buffer Control Register */
dev->regs[dev->index] = val;
break;
case 0x21: /* DEVSELJ Check Point Setting Register */
dev->regs[dev->index] = (val & 0xbb) | 0x04;
break;
case 0x22: /* PCI to CPU W/R Buffer Configuration Register */
dev->regs[dev->index] = (val & 0xfd);
break;
case 0x20: /* CPU to PCI Buffer Control Register */
dev->regs[dev->index] = val;
break;
case 0x21: /* DEVSELJ Check Point Setting Register */
dev->regs[dev->index] = (val & 0xbb) | 0x04;
break;
case 0x22: /* PCI to CPU W/R Buffer Configuration Register */
dev->regs[dev->index] = (val & 0xfd);
break;
case 0x25: /* GP/MEM Address Definition Register I */
case 0x26: /* GP/MEM Address Definition Register II */
case 0x27: /* GP/MEM Address Definition Register III */
dev->regs[dev->index] = val;
break;
case 0x28: /* PCI Arbiter Control Register */
dev->regs[dev->index] = val & 0x3f;
break;
case 0x25: /* GP/MEM Address Definition Register I */
case 0x26: /* GP/MEM Address Definition Register II */
case 0x27: /* GP/MEM Address Definition Register III */
dev->regs[dev->index] = val;
break;
case 0x28: /* PCI Arbiter Control Register */
dev->regs[dev->index] = val & 0x3f;
break;
case 0x29: /* System Clock Register */
dev->regs[dev->index] = val;
case 0x29: /* System Clock Register */
dev->regs[dev->index] = val;
port_92_remove(dev->port_92);
if (val & 0x10)
port_92_add(dev->port_92);
break;
port_92_remove(dev->port_92);
if (val & 0x10)
port_92_add(dev->port_92);
break;
case 0x2a: /* I/O Recovery Register */
dev->regs[dev->index] = val;
break;
case 0x2a: /* I/O Recovery Register */
dev->regs[dev->index] = val;
break;
case 0x2b: /* Turbo Function Register */
dev->regs[dev->index] = (val & 0xbf) | 0x40;
break;
case 0x2b: /* Turbo Function Register */
dev->regs[dev->index] = (val & 0xbf) | 0x40;
break;
case 0x30: /* Power Management Unit Control Register */
old = dev->regs[dev->index];
dev->regs[dev->index] = val;
case 0x30: /* Power Management Unit Control Register */
old = dev->regs[dev->index];
dev->regs[dev->index] = val;
if (((val & 0x14) == 0x14) && !(old & 0x08) && (val & 0x08)) {
switch (dev->regs[0x35] & 0x30) {
case 0x00:
smi_line = 1;
break;
case 0x10:
nmi = 1;
break;
case 0x20:
picint(1 << 15);
break;
case 0x30:
picint(1 << 10);
break;
}
dev->regs[0x35] |= 0x0e;
} else if (!(val & 0x10))
dev->regs[0x35] &= ~0x0f;
break;
if (((val & 0x14) == 0x14) && !(old & 0x08) && (val & 0x08)) {
switch (dev->regs[0x35] & 0x30) {
case 0x00:
smi_raise();
break;
case 0x10:
nmi_raise();
break;
case 0x20:
picint(1 << 15);
break;
case 0x30:
picint(1 << 10);
break;
default:
break;
}
dev->regs[0x35] |= 0x0e;
} else if (!(val & 0x10))
dev->regs[0x35] &= ~0x0f;
break;
case 0x31: /* Mode Timer Monitoring Events Selection Register I */
case 0x32: /* Mode Timer Monitoring Events Selection Register II */
case 0x33: /* SMI Triggered Events Selection Register I */
case 0x34: /* SMI Triggered Events Selection Register II */
dev->regs[dev->index] = val;
break;
case 0x31: /* Mode Timer Monitoring Events Selection Register I */
case 0x32: /* Mode Timer Monitoring Events Selection Register II */
case 0x33: /* SMI Triggered Events Selection Register I */
case 0x34: /* SMI Triggered Events Selection Register II */
dev->regs[dev->index] = val;
break;
case 0x35: /* SMI Status Register */
dev->regs[dev->index] = (dev->regs[dev->index] & 0x0f) | (val & 0xf0);
break;
case 0x35: /* SMI Status Register */
dev->regs[dev->index] = (dev->regs[dev->index] & 0x0f) | (val & 0xf0);
break;
case 0x36: /* IRQ Channel Group Selected Control Register I */
dev->regs[dev->index] = (val & 0xe5);
break;
case 0x37: /* IRQ Channel Group Selected Control Register II */
dev->regs[dev->index] = (val & 0xef);
break;
case 0x36: /* IRQ Channel Group Selected Control Register I */
dev->regs[dev->index] = (val & 0xe5);
break;
case 0x37: /* IRQ Channel Group Selected Control Register II */
dev->regs[dev->index] = (val & 0xef);
break;
case 0x38: /* DRQ Channel Selected Control Register */
case 0x39: /* Mode Timer Setting Register */
case 0x3a: /* Input_device Timer Setting Register */
case 0x3b: /* GP/MEM Timer Setting Register */
case 0x3c: /* LED Flash Control Register */
dev->regs[dev->index] = val;
break;
case 0x38: /* DRQ Channel Selected Control Register */
case 0x39: /* Mode Timer Setting Register */
case 0x3a: /* Input_device Timer Setting Register */
case 0x3b: /* GP/MEM Timer Setting Register */
case 0x3c: /* LED Flash Control Register */
dev->regs[dev->index] = val;
break;
case 0x3d: /* Miscellaneous Register I */
dev->regs[dev->index] = (val & 0x07);
break;
case 0x3d: /* Miscellaneous Register I */
dev->regs[dev->index] = (val & 0x07);
break;
case 0x40: /* Clock Generator Control Feature Register */
dev->regs[dev->index] = (val & 0x3f);
break;
case 0x41: /* Power Control Output Register */
dev->regs[dev->index] = val;
break;
case 0x40: /* Clock Generator Control Feature Register */
dev->regs[dev->index] = (val & 0x3f);
break;
case 0x41: /* Power Control Output Register */
dev->regs[dev->index] = val;
break;
case 0x42: /* PCI INTx Routing Table Mapping Register I */
irq = irq_array[val & 0x0f];
pci_set_irq_routing(PCI_INTA, (irq != 0) ? irq : PCI_IRQ_DISABLED);
irq = irq_array[(val & 0xf0) >> 4];
pci_set_irq_routing(PCI_INTB, (irq != 0) ? irq : PCI_IRQ_DISABLED);
break;
case 0x42: /* PCI INTx Routing Table Mapping Register I */
irq = irq_array[val & 0x0f];
pci_set_irq_routing(PCI_INTA, (irq != 0) ? irq : PCI_IRQ_DISABLED);
irq = irq_array[(val & 0xf0) >> 4];
pci_set_irq_routing(PCI_INTB, (irq != 0) ? irq : PCI_IRQ_DISABLED);
break;
case 0x43: /* PCI INTx Routing Table Mapping Register II */
irq = irq_array[val & 0x0f];
pci_set_irq_routing(PCI_INTC, (irq != 0) ? irq : PCI_IRQ_DISABLED);
irq = irq_array[(val & 0xf0) >> 4];
pci_set_irq_routing(PCI_INTD, (irq != 0) ? irq : PCI_IRQ_DISABLED);
break;
case 0x43: /* PCI INTx Routing Table Mapping Register II */
irq = irq_array[val & 0x0f];
pci_set_irq_routing(PCI_INTC, (irq != 0) ? irq : PCI_IRQ_DISABLED);
irq = irq_array[(val & 0xf0) >> 4];
pci_set_irq_routing(PCI_INTD, (irq != 0) ? irq : PCI_IRQ_DISABLED);
break;
case 0x44: /* PCI INTx Sensitivity Register */
/* TODO: When doing the IRQ and PCI IRQ rewrite, bits 0 to 3 toggle edge/level output. */
dev->regs[dev->index] = val;
break;
}
case 0x44: /* PCI INTx Sensitivity Register */
/* TODO: When doing the IRQ and PCI IRQ rewrite, bits 0 to 3 toggle edge/level output. */
dev->regs[dev->index] = val;
break;
default:
break;
}
if (dev->index != 0x03) {
ali1489_log("M1489: dev->regs[%02x] = %02x\n", dev->index, val);
}
} else if (dev->index == 0x03)
dev->regs[dev->index] = val;
if (dev->index != 0x03) {
ali1489_log("M1489: dev->regs[%02x] = %02x\n", dev->index, val);
}
} else if (dev->index == 0x03)
dev->regs[dev->index] = val;
break;
break;
default:
break;
}
}
static uint8_t
ali1489_read(uint16_t addr, void *priv)
{
uint8_t ret = 0xff;
ali1489_t *dev = (ali1489_t *)priv;
uint8_t ret = 0xff;
const ali1489_t *dev = (ali1489_t *) priv;
switch (addr) {
case 0x23:
/* Avoid conflict with Cyrix CPU registers */
if (((dev->index == 0x20) || (dev->index >= 0xc0)) && cpu_iscyrix)
ret = 0xff;
else if (dev->index == 0x3f)
ret = inb(0x70);
else
ret = dev->regs[dev->index];
break;
case 0x23:
/* Avoid conflict with Cyrix CPU registers */
if (((dev->index == 0x20) || (dev->index >= 0xc0)) && cpu_iscyrix)
ret = 0xff;
else if (dev->index == 0x3f)
ret = inb(0x70);
else
ret = dev->regs[dev->index];
break;
default:
break;
}
ali1489_log("M1489: dev->regs[%02x] (%02x)\n", dev->index, ret);
@@ -424,155 +430,159 @@ ali1489_read(uint16_t addr, void *priv)
return ret;
}
static void
ali1489_pci_write(int func, int addr, uint8_t val, void *priv)
ali1489_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv)
{
ali1489_t *dev = (ali1489_t *)priv;
ali1489_t *dev = (ali1489_t *) priv;
ali1489_log("M1489-PCI: dev->pci_conf[%02x] = %02x\n", addr, val);
switch (addr) {
/* Dummy PCI Config */
case 0x04:
dev->pci_conf[0x04] = val & 0x7f;
break;
/* Dummy PCI Config */
case 0x04:
dev->pci_conf[0x04] = val & 0x7f;
break;
/* Dummy PCI Status */
case 0x07:
dev->pci_conf[0x07] &= ~(val & 0xb8);
break;
/* Dummy PCI Status */
case 0x07:
dev->pci_conf[0x07] &= ~(val & 0xb8);
break;
default:
break;
}
}
static uint8_t
ali1489_pci_read(int func, int addr, void *priv)
ali1489_pci_read(UNUSED(int func), int addr, void *priv)
{
ali1489_t *dev = (ali1489_t *)priv;
uint8_t ret = 0xff;
const ali1489_t *dev = (ali1489_t *) priv;
uint8_t ret = 0xff;
ret = dev->pci_conf[addr];
ali1489_log("M1489-PCI: dev->pci_conf[%02x] (%02x)\n", addr, ret);
return ret;
}
static void
ali1489_ide_handler(ali1489_t *dev)
{
ide_pri_disable();
ide_sec_disable();
if (dev->ide_regs[0x01] & 0x01) {
ide_pri_enable();
if (!(dev->ide_regs[0x35] & 0x40))
ide_sec_enable();
ide_pri_enable();
if (!(dev->ide_regs[0x35] & 0x40))
ide_sec_enable();
}
}
static void
ali1489_ide_write(uint16_t addr, uint8_t val, void *priv)
{
ali1489_t *dev = (ali1489_t *)priv;
ali1489_t *dev = (ali1489_t *) priv;
switch (addr)
{
case 0xf4: /* Usually it writes 30h here */
dev->ide_chip_id = val;
break;
switch (addr) {
case 0xf4: /* Usually it writes 30h here */
dev->ide_chip_id = val;
break;
case 0xf8:
dev->ide_index = val;
break;
case 0xf8:
dev->ide_index = val;
break;
case 0xfc:
if (dev->ide_chip_id != 0x30)
break;
case 0xfc:
if (dev->ide_chip_id != 0x30)
break;
switch(dev->ide_index) {
case 0x01: /* IDE Configuration Register */
dev->ide_regs[dev->ide_index] = val & 0x8f;
ali1489_ide_handler(dev);
break;
case 0x02: /* DBA Data Byte Cative Count for IDE-1 */
case 0x03: /* D0RA Disk 0 Read Active Count for IDE-1 */
case 0x04: /* D0WA Disk 0 Write Active Count for IDE-1 */
case 0x05: /* D1RA Disk 1 Read Active Count for IDE-1 */
case 0x06: /* D1WA Disk 1 Write Active Count for IDE-1 */
case 0x25: /* DBR Data Byte Recovery Count for IDE-1 */
case 0x26: /* D0RR Disk 0 Read Byte Recovery Count for IDE-1 */
case 0x27: /* D0WR Disk 0 Write Byte Recovery Count for IDE-1 */
case 0x28: /* D1RR Disk 1 Read Byte Recovery Count for IDE-1 */
case 0x29: /* D1WR Disk 1 Write Byte Recovery Count for IDE-1 */
case 0x2a: /* DBA Data Byte Cative Count for IDE-2 */
case 0x2b: /* D0RA Disk 0 Read Active Count for IDE-2 */
case 0x2c: /* D0WA Disk 0 Write Active Count for IDE-2 */
case 0x2d: /* D1RA Disk 1 Read Active Count for IDE-2 */
case 0x2e: /* D1WA Disk 1 Write Active Count for IDE-2 */
case 0x2f: /* DBR Data Byte Recovery Count for IDE-2 */
case 0x30: /* D0RR Disk 0 Read Byte Recovery Count for IDE-2 */
case 0x31: /* D0WR Disk 0 Write Byte Recovery Count for IDE-2 */
case 0x32: /* D1RR Disk 1 Read Byte Recovery Count for IDE-2 */
case 0x33: /* D1WR Disk 1 Write Byte Recovery Count for IDE-2 */
dev->ide_regs[dev->ide_index] = val & 0x1f;
break;
case 0x07: /* Buffer Mode Register 1 */
dev->ide_regs[dev->ide_index] = val;
break;
case 0x09: /* IDEPE1 IDE Port Enable Register 1 */
dev->ide_regs[dev->ide_index] = val & 0xc3;
break;
case 0x0a: /* Buffer Mode Register 2 */
dev->ide_regs[dev->ide_index] = val & 0x4f;
break;
case 0x0b: /* IDE Channel 1 Disk 0 Sector Byte Count Register 1 */
case 0x0d: /* IDE Channel 1 Disk 1 Sector Byte Count Register 1 */
case 0x0f: /* IDE Channel 2 Disk 0 Sector Byte Count Register 1 */
case 0x11: /* IDE Channel 2 Disk 1 Sector Byte Count Register 1 */
dev->ide_regs[dev->ide_index] = val & 0x03;
break;
case 0x0c: /* IDE Channel 1 Disk 0 Sector Byte Count Register 2 */
case 0x0e: /* IDE Channel 1 Disk 1 Sector Byte Count Register 2 */
case 0x10: /* IDE Channel 2 Disk 1 Sector Byte Count Register 2 */
case 0x12: /* IDE Channel 2 Disk 1 Sector Byte Count Register 2 */
dev->ide_regs[dev->ide_index] = val & 0x1f;
break;
case 0x35: /* IDEPE3 IDE Port Enable Register 3 */
dev->ide_regs[dev->ide_index] = val;
ali1489_ide_handler(dev);
break;
}
break;
switch (dev->ide_index) {
case 0x01: /* IDE Configuration Register */
dev->ide_regs[dev->ide_index] = val & 0x8f;
ali1489_ide_handler(dev);
break;
case 0x02: /* DBA Data Byte Cative Count for IDE-1 */
case 0x03: /* D0RA Disk 0 Read Active Count for IDE-1 */
case 0x04: /* D0WA Disk 0 Write Active Count for IDE-1 */
case 0x05: /* D1RA Disk 1 Read Active Count for IDE-1 */
case 0x06: /* D1WA Disk 1 Write Active Count for IDE-1 */
case 0x25: /* DBR Data Byte Recovery Count for IDE-1 */
case 0x26: /* D0RR Disk 0 Read Byte Recovery Count for IDE-1 */
case 0x27: /* D0WR Disk 0 Write Byte Recovery Count for IDE-1 */
case 0x28: /* D1RR Disk 1 Read Byte Recovery Count for IDE-1 */
case 0x29: /* D1WR Disk 1 Write Byte Recovery Count for IDE-1 */
case 0x2a: /* DBA Data Byte Cative Count for IDE-2 */
case 0x2b: /* D0RA Disk 0 Read Active Count for IDE-2 */
case 0x2c: /* D0WA Disk 0 Write Active Count for IDE-2 */
case 0x2d: /* D1RA Disk 1 Read Active Count for IDE-2 */
case 0x2e: /* D1WA Disk 1 Write Active Count for IDE-2 */
case 0x2f: /* DBR Data Byte Recovery Count for IDE-2 */
case 0x30: /* D0RR Disk 0 Read Byte Recovery Count for IDE-2 */
case 0x31: /* D0WR Disk 0 Write Byte Recovery Count for IDE-2 */
case 0x32: /* D1RR Disk 1 Read Byte Recovery Count for IDE-2 */
case 0x33: /* D1WR Disk 1 Write Byte Recovery Count for IDE-2 */
dev->ide_regs[dev->ide_index] = val & 0x1f;
break;
case 0x07: /* Buffer Mode Register 1 */
dev->ide_regs[dev->ide_index] = val;
break;
case 0x09: /* IDEPE1 IDE Port Enable Register 1 */
dev->ide_regs[dev->ide_index] = val & 0xc3;
break;
case 0x0a: /* Buffer Mode Register 2 */
dev->ide_regs[dev->ide_index] = val & 0x4f;
break;
case 0x0b: /* IDE Channel 1 Disk 0 Sector Byte Count Register 1 */
case 0x0d: /* IDE Channel 1 Disk 1 Sector Byte Count Register 1 */
case 0x0f: /* IDE Channel 2 Disk 0 Sector Byte Count Register 1 */
case 0x11: /* IDE Channel 2 Disk 1 Sector Byte Count Register 1 */
dev->ide_regs[dev->ide_index] = val & 0x03;
break;
case 0x0c: /* IDE Channel 1 Disk 0 Sector Byte Count Register 2 */
case 0x0e: /* IDE Channel 1 Disk 1 Sector Byte Count Register 2 */
case 0x10: /* IDE Channel 2 Disk 1 Sector Byte Count Register 2 */
case 0x12: /* IDE Channel 2 Disk 1 Sector Byte Count Register 2 */
dev->ide_regs[dev->ide_index] = val & 0x1f;
break;
case 0x35: /* IDEPE3 IDE Port Enable Register 3 */
dev->ide_regs[dev->ide_index] = val;
ali1489_ide_handler(dev);
break;
default:
break;
}
break;
default:
break;
}
}
static uint8_t
ali1489_ide_read(uint16_t addr, void *priv)
{
ali1489_t *dev = (ali1489_t *)priv;
uint8_t ret = 0xff;
const ali1489_t *dev = (ali1489_t *) priv;
uint8_t ret = 0xff;
switch (addr)
{
case 0xf4:
ret = dev->ide_chip_id;
break;
case 0xfc:
ret = dev->ide_regs[dev->ide_index];
ali1489_log("M1489-IDE: dev->regs[%02x] (%02x)\n", dev->ide_index, ret);
break;
switch (addr) {
case 0xf4:
ret = dev->ide_chip_id;
break;
case 0xfc:
ret = dev->ide_regs[dev->ide_index];
ali1489_log("M1489-IDE: dev->regs[%02x] (%02x)\n", dev->ide_index, ret);
break;
default:
break;
}
return ret;
}
static void
ali1489_reset(void *priv)
{
ali1489_t *dev = (ali1489_t *)priv;
ali1489_t *dev = (ali1489_t *) priv;
pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED);
pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED);
@@ -582,21 +592,19 @@ ali1489_reset(void *priv)
ali1489_defaults(dev);
}
static void
ali1489_close(void *priv)
{
ali1489_t *dev = (ali1489_t *)priv;
ali1489_t *dev = (ali1489_t *) priv;
smram_del(dev->smram);
free(dev);
}
static void *
ali1489_init(const device_t *info)
ali1489_init(UNUSED(const device_t *info))
{
ali1489_t *dev = (ali1489_t *)malloc(sizeof(ali1489_t));
ali1489_t *dev = (ali1489_t *) malloc(sizeof(ali1489_t));
memset(dev, 0, sizeof(ali1489_t));
/* M1487/M1489
@@ -614,28 +622,28 @@ ali1489_init(const device_t *info)
io_sethandler(0x0fc, 0x0001, ali1489_ide_read, NULL, NULL, ali1489_ide_write, NULL, NULL, dev);
/* Dummy M1489 PCI device */
dev->pci_slot = pci_add_card(PCI_ADD_NORTHBRIDGE, ali1489_pci_read, ali1489_pci_write, dev);
pci_add_card(PCI_ADD_NORTHBRIDGE, ali1489_pci_read, ali1489_pci_write, dev, &dev->pci_slot);
device_add(&ide_pci_2ch_device);
dev->port_92 = device_add(&port_92_pci_device);
dev->smram = smram_add();
dev->smram = smram_add();
ali1489_defaults(dev);
return dev;
}
const device_t ali1489_device = {
"ALi M1489",
"ali1489",
0,
0,
ali1489_init,
ali1489_close,
ali1489_reset,
{NULL},
NULL,
NULL,
NULL};
.name = "ALi M1489",
.internal_name = "ali1489",
.flags = 0,
.local = 0,
.init = ali1489_init,
.close = ali1489_close,
.reset = ali1489_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -1,19 +1,18 @@
/*
* 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.
*
* Implementation of the ALi M1531B CPU-to-PCI Bridge.
* Implementation of the ALi M1531B CPU-to-PCI Bridge.
*
*
*
* Authors: Tiseno100,
*
* Copyright 2021 Tiseno100.
* Authors: Tiseno100,
*
* Copyright 2021 Tiseno100.
*/
#include <stdarg.h>
#include <stdint.h>
@@ -29,283 +28,298 @@
#include <86box/io.h>
#include <86box/mem.h>
#include <86box/pci.h>
#include <86box/plat_unused.h>
#include <86box/smram.h>
#include <86box/spd.h>
#include <86box/chipset.h>
typedef struct ali1531_t {
uint8_t pci_slot;
uint8_t pad;
uint8_t pad0;
uint8_t pad1;
typedef struct ali1531_t
{
uint8_t pci_conf[256];
smram_t *smram;
} ali1531_t;
#ifdef ENABLE_ALI1531_LOG
int ali1531_do_log = ENABLE_ALI1531_LOG;
static void
ali1531_log(const char *fmt, ...)
{
va_list ap;
if (ali1531_do_log)
{
if (ali1531_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define ali1531_log(fmt, ...)
# define ali1531_log(fmt, ...)
#endif
static void
ali1531_smram_recalc(uint8_t val, ali1531_t *dev)
{
smram_disable_all();
if (val & 1) {
switch (val & 0x0c) {
case 0x00:
ali1531_log("SMRAM: D0000 -> B0000 (%i)\n", val & 2);
smram_enable(dev->smram, 0xd0000, 0xb0000, 0x10000, val & 2, 1);
if (val & 0x10)
mem_set_mem_state_smram_ex(1, 0xd0000, 0x10000, 0x02);
break;
case 0x04:
ali1531_log("SMRAM: A0000 -> A0000 (%i)\n", val & 2);
smram_enable(dev->smram, 0xa0000, 0xa0000, 0x20000, val & 2, 1);
if (val & 0x10)
mem_set_mem_state_smram_ex(1, 0xa0000, 0x20000, 0x02);
break;
case 0x08:
ali1531_log("SMRAM: 30000 -> B0000 (%i)\n", val & 2);
smram_enable(dev->smram, 0x30000, 0xb0000, 0x10000, val & 2, 1);
if (val & 0x10)
mem_set_mem_state_smram_ex(1, 0x30000, 0x10000, 0x02);
break;
}
switch (val & 0x0c) {
case 0x00:
ali1531_log("SMRAM: D0000 -> B0000 (%i)\n", val & 2);
smram_enable(dev->smram, 0xd0000, 0xb0000, 0x10000, val & 2, 1);
if (val & 0x10)
mem_set_mem_state_smram_ex(1, 0xd0000, 0x10000, 0x02);
break;
case 0x04:
ali1531_log("SMRAM: A0000 -> A0000 (%i)\n", val & 2);
smram_enable(dev->smram, 0xa0000, 0xa0000, 0x20000, val & 2, 1);
if (val & 0x10)
mem_set_mem_state_smram_ex(1, 0xa0000, 0x20000, 0x02);
break;
case 0x08:
ali1531_log("SMRAM: 30000 -> B0000 (%i)\n", val & 2);
smram_enable(dev->smram, 0x30000, 0xb0000, 0x10000, val & 2, 1);
if (val & 0x10)
mem_set_mem_state_smram_ex(1, 0x30000, 0x10000, 0x02);
break;
default:
break;
}
}
flushmmucache_nopc();
}
static void
ali1531_shadow_recalc(int cur_reg, ali1531_t *dev)
ali1531_shadow_recalc(UNUSED(int cur_reg), ali1531_t *dev)
{
int i, bit, r_reg, w_reg;
uint32_t base, flags = 0;
int bit;
int r_reg;
int w_reg;
uint32_t base;
uint32_t flags = 0;
shadowbios = shadowbios_write = 0;
for (i = 0; i < 16; i++) {
base = 0x000c0000 + (i << 14);
bit = i & 7;
r_reg = 0x4c + (i >> 3);
w_reg = 0x4e + (i >> 3);
for (uint8_t i = 0; i < 16; i++) {
base = 0x000c0000 + (i << 14);
bit = i & 7;
r_reg = 0x4c + (i >> 3);
w_reg = 0x4e + (i >> 3);
flags = (dev->pci_conf[r_reg] & (1 << bit)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
flags |= ((dev->pci_conf[w_reg] & (1 << bit)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY);
flags = (dev->pci_conf[r_reg] & (1 << bit)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
flags |= ((dev->pci_conf[w_reg] & (1 << bit)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY);
if (base >= 0x000e0000) {
if (dev->pci_conf[r_reg] & (1 << bit))
shadowbios |= 1;
if (dev->pci_conf[w_reg] & (1 << bit))
shadowbios_write |= 1;
}
if (base >= 0x000e0000) {
if (dev->pci_conf[r_reg] & (1 << bit))
shadowbios |= 1;
if (dev->pci_conf[w_reg] & (1 << bit))
shadowbios_write |= 1;
}
ali1531_log("%08X-%08X shadow: R%c, W%c\n", base, base + 0x00003fff,
(dev->pci_conf[r_reg] & (1 << bit)) ? 'I' : 'E', (dev->pci_conf[w_reg] & (1 << bit)) ? 'I' : 'E');
ali1531_log("%08X-%08X shadow: R%c, W%c\n", base, base + 0x00003fff,
(dev->pci_conf[r_reg] & (1 << bit)) ? 'I' : 'E', (dev->pci_conf[w_reg] & (1 << bit)) ? 'I' : 'E');
mem_set_mem_state_both(base, 0x00004000, flags);
}
flushmmucache_nopc();
}
static void
ali1531_write(int func, int addr, uint8_t val, void *priv)
ali1531_write(UNUSED(int func), int addr, uint8_t val, void *priv)
{
ali1531_t *dev = (ali1531_t *)priv;
ali1531_t *dev = (ali1531_t *) priv;
switch (addr) {
case 0x04:
dev->pci_conf[addr] = val;
break;
case 0x05:
dev->pci_conf[addr] = val & 0x01;
break;
case 0x04:
dev->pci_conf[addr] = val;
break;
case 0x05:
dev->pci_conf[addr] = val & 0x01;
break;
case 0x07:
dev->pci_conf[addr] &= ~(val & 0xf8);
break;
case 0x07:
dev->pci_conf[addr] &= ~(val & 0xf8);
break;
case 0x0d:
dev->pci_conf[addr] = val & 0xf8;
break;
case 0x0d:
dev->pci_conf[addr] = val & 0xf8;
break;
case 0x2c: /* Subsystem Vendor ID */
case 0x2d:
case 0x2e:
case 0x2f:
if (dev->pci_conf[0x70] & 0x08)
dev->pci_conf[addr] = val;
break;
case 0x2c: /* Subsystem Vendor ID */
case 0x2d:
case 0x2e:
case 0x2f:
if (dev->pci_conf[0x70] & 0x08)
dev->pci_conf[addr] = val;
break;
case 0x40:
dev->pci_conf[addr] = val & 0xf1;
break;
case 0x40:
dev->pci_conf[addr] = val & 0xf1;
break;
case 0x41:
dev->pci_conf[addr] = (val & 0xd6) | 0x08;
break;
case 0x41:
dev->pci_conf[addr] = (val & 0xd6) | 0x08;
break;
case 0x42: /* L2 Cache */
dev->pci_conf[addr] = val & 0xf7;
cpu_cache_ext_enabled = !!(val & 1);
cpu_update_waitstates();
break;
case 0x42: /* L2 Cache */
dev->pci_conf[addr] = val & 0xf7;
cpu_cache_ext_enabled = !!(val & 1);
cpu_update_waitstates();
break;
case 0x43: /* L1 Cache */
dev->pci_conf[addr] = val;
cpu_cache_int_enabled = !!(val & 1);
cpu_update_waitstates();
break;
case 0x43: /* L1 Cache */
dev->pci_conf[addr] = val;
cpu_cache_int_enabled = !!(val & 1);
cpu_update_waitstates();
break;
case 0x44:
dev->pci_conf[addr] = val;
break;
case 0x45:
dev->pci_conf[addr] = val;
break;
case 0x44:
dev->pci_conf[addr] = val;
break;
case 0x45:
dev->pci_conf[addr] = val;
break;
case 0x46:
dev->pci_conf[addr] = val;
break;
case 0x46:
dev->pci_conf[addr] = val;
break;
case 0x47:
dev->pci_conf[addr] = val & 0xfc;
case 0x47:
dev->pci_conf[addr] = val & 0xfc;
if (mem_size > 0xe00000)
mem_set_mem_state_both(0xe00000, 0x100000, (val & 0x20) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL));
if (mem_size > 0xe00000)
mem_set_mem_state_both(0xe00000, 0x100000, (val & 0x20) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL));
if (mem_size > 0xf00000)
mem_set_mem_state_both(0xf00000, 0x100000, (val & 0x10) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL));
if (mem_size > 0xf00000)
mem_set_mem_state_both(0xf00000, 0x100000, (val & 0x10) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL));
mem_set_mem_state_both(0xa0000, 0x20000, (val & 8) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY));
mem_set_mem_state_both(0x80000, 0x20000, (val & 4) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL));
mem_set_mem_state_both(0xa0000, 0x20000, (val & 8) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY));
mem_set_mem_state_both(0x80000, 0x20000, (val & 4) ? (MEM_READ_EXTANY | MEM_WRITE_EXTANY) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL));
flushmmucache_nopc();
break;
flushmmucache_nopc();
break;
case 0x48: /* SMRAM */
dev->pci_conf[addr] = val;
ali1531_smram_recalc(val, dev);
break;
case 0x48: /* SMRAM */
dev->pci_conf[addr] = val;
ali1531_smram_recalc(val, dev);
break;
case 0x49:
dev->pci_conf[addr] = val & 0x73;
break;
case 0x49:
dev->pci_conf[addr] = val & 0x73;
break;
case 0x4a:
dev->pci_conf[addr] = val;
break;
case 0x4a:
dev->pci_conf[addr] = val;
break;
case 0x4c ... 0x4f: /* Shadow RAM */
dev->pci_conf[addr] = val;
ali1531_shadow_recalc(val, dev);
break;
case 0x4c ... 0x4f: /* Shadow RAM */
dev->pci_conf[addr] = val;
ali1531_shadow_recalc(val, dev);
break;
case 0x50: case 0x51: case 0x52: case 0x54:
case 0x55: case 0x56:
dev->pci_conf[addr] = val;
break;
case 0x50:
case 0x51:
case 0x52:
case 0x54:
case 0x55:
case 0x56:
dev->pci_conf[addr] = val;
break;
case 0x57: /* H2PO */
dev->pci_conf[addr] = val & 0x60;
/* Find where the Shut-down Special cycle is initiated. */
// if (!(val & 0x20))
// outb(0x92, 0x01);
break;
case 0x57: /* H2PO */
dev->pci_conf[addr] = val & 0x60;
/* Find where the Shut-down Special cycle is initiated. */
#if 0
if (!(val & 0x20))
outb(0x92, 0x01);
#endif
break;
case 0x58:
dev->pci_conf[addr] = val & 0x86;
break;
case 0x58:
dev->pci_conf[addr] = val & 0x86;
break;
case 0x59: case 0x5a:
case 0x5c:
dev->pci_conf[addr] = val;
break;
case 0x59:
case 0x5a:
case 0x5c:
dev->pci_conf[addr] = val;
break;
case 0x5b:
dev->pci_conf[addr] = val & 0x4f;
break;
case 0x5b:
dev->pci_conf[addr] = val & 0x4f;
break;
case 0x5d:
dev->pci_conf[addr] = val & 0x53;
break;
case 0x5d:
dev->pci_conf[addr] = val & 0x53;
break;
case 0x5f:
dev->pci_conf[addr] = val & 0x7f;
break;
case 0x5f:
dev->pci_conf[addr] = val & 0x7f;
break;
case 0x60 ... 0x6f: /* DRB's */
dev->pci_conf[addr] = val;
spd_write_drbs_interleaved(dev->pci_conf, 0x60, 0x6f, 1);
break;
case 0x60 ... 0x6f: /* DRB's */
dev->pci_conf[addr] = val;
spd_write_drbs_interleaved(dev->pci_conf, 0x60, 0x6f, 1);
break;
case 0x70: case 0x71:
dev->pci_conf[addr] = val;
break;
case 0x70:
case 0x71:
dev->pci_conf[addr] = val;
break;
case 0x72:
dev->pci_conf[addr] = val & 0x0f;
break;
case 0x72:
dev->pci_conf[addr] = val & 0x0f;
break;
case 0x74:
dev->pci_conf[addr] = val & 0x2b;
break;
case 0x74:
dev->pci_conf[addr] = val & 0x2b;
break;
case 0x76: case 0x77:
dev->pci_conf[addr] = val;
break;
case 0x76:
case 0x77:
dev->pci_conf[addr] = val;
break;
case 0x80:
dev->pci_conf[addr] = val & 0x84;
break;
case 0x80:
dev->pci_conf[addr] = val & 0x84;
break;
case 0x81:
dev->pci_conf[addr] = val & 0x81;
break;
case 0x81:
dev->pci_conf[addr] = val & 0x81;
break;
case 0x83:
dev->pci_conf[addr] = val & 0x10;
break;
case 0x83:
dev->pci_conf[addr] = val & 0x10;
break;
default:
break;
}
}
static uint8_t
ali1531_read(int func, int addr, void *priv)
ali1531_read(UNUSED(int func), int addr, void *priv)
{
ali1531_t *dev = (ali1531_t *)priv;
uint8_t ret = 0xff;
const ali1531_t *dev = (ali1531_t *) priv;
uint8_t ret = 0xff;
ret = dev->pci_conf[addr];
return ret;
}
static void
ali1531_reset(void *priv)
{
ali1531_t *dev = (ali1531_t *)priv;
int i;
ali1531_t *dev = (ali1531_t *) priv;
/* Default Registers */
dev->pci_conf[0x00] = 0xb9;
@@ -341,33 +355,31 @@ ali1531_reset(void *priv)
ali1531_write(0, 0x47, 0x00, dev);
ali1531_write(0, 0x48, 0x00, dev);
for (i = 0; i < 4; i++)
ali1531_write(0, 0x4c + i, 0x00, dev);
for (uint8_t i = 0; i < 4; i++)
ali1531_write(0, 0x4c + i, 0x00, dev);
for (i = 0; i < 16; i += 2) {
ali1531_write(0, 0x60 + i, 0x08, dev);
ali1531_write(0, 0x61 + i, 0x40, dev);
for (uint8_t i = 0; i < 16; i += 2) {
ali1531_write(0, 0x60 + i, 0x08, dev);
ali1531_write(0, 0x61 + i, 0x40, dev);
}
}
static void
ali1531_close(void *priv)
{
ali1531_t *dev = (ali1531_t *)priv;
ali1531_t *dev = (ali1531_t *) priv;
smram_del(dev->smram);
free(dev);
}
static void *
ali1531_init(const device_t *info)
ali1531_init(UNUSED(const device_t *info))
{
ali1531_t *dev = (ali1531_t *)malloc(sizeof(ali1531_t));
ali1531_t *dev = (ali1531_t *) malloc(sizeof(ali1531_t));
memset(dev, 0, sizeof(ali1531_t));
pci_add_card(PCI_ADD_NORTHBRIDGE, ali1531_read, ali1531_write, dev);
pci_add_card(PCI_ADD_NORTHBRIDGE, ali1531_read, ali1531_write, dev, &dev->pci_slot);
dev->smram = smram_add();
@@ -376,17 +388,16 @@ ali1531_init(const device_t *info)
return dev;
}
const device_t ali1531_device = {
"ALi M1531 CPU-to-PCI Bridge",
"ali1531",
DEVICE_PCI,
0,
ali1531_init,
ali1531_close,
ali1531_reset,
{NULL},
NULL,
NULL,
NULL
.name = "ALi M1531 CPU-to-PCI Bridge",
.internal_name = "ali1531",
.flags = DEVICE_PCI,
.local = 0,
.init = ali1531_init,
.close = ali1531_close,
.reset = ali1531_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

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

@@ -1,18 +1,18 @@
/*
* 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.
*
* Implementation of the ALi M6117 SoC.
* Implementation of the ALi M6117 SoC.
*
*
*
* Authors: RichardG, <richardg867@gmail.com>
* Authors: RichardG, <richardg867@gmail.com>
*
* Copyright 2020 RichardG.
* Copyright 2020 RichardG.
*/
#include <stdio.h>
#include <stdint.h>
@@ -30,22 +30,58 @@
#include <86box/pit.h>
#include <86box/device.h>
#include <86box/port_92.h>
#include <86box/usb.h>
#include <86box/hdc.h>
#include <86box/hdc_ide.h>
#include <86box/chipset.h>
#include <86box/plat_fallthrough.h>
typedef struct ali6117_t
{
uint32_t local;
typedef struct ali6117_t {
uint32_t local;
/* Main registers (port 22h/23h) */
uint8_t unlocked;
uint8_t reg_offset;
uint8_t regs[256];
uint8_t unlocked;
uint8_t mode;
uint8_t reg_offset;
uint8_t regs[256];
} ali6117_t;
/* Total size, Bank 0 size, Bank 1 size, Bank 2 size, Bank 3 size. */
static uint32_t ali6117_modes[32][5] = {
// clang-format off
{ 1024, 512, 512, 0, 0 },
{ 2048, 512, 512, 512, 512 },
{ 3072, 512, 512, 2048, 0 },
{ 5120, 512, 512, 2048, 2048 },
{ 9216, 512, 512, 8192, 0 },
{ 1024, 1024, 0, 0, 0 },
{ 2048, 1024, 1024, 0, 0 },
{ 4096, 1024, 1024, 2048, 0 },
{ 6144, 1024, 1024, 2048, 2048 },
{ 10240, 1024, 1024, 8192, 0 },
{ 18432, 1024, 1024, 8192, 8192 },
{ 3072, 1024, 2048, 0, 0 },
{ 5120, 1024, 2048, 2048, 0 },
{ 9216, 1024, 8192, 0, 0 },
{ 2048, 2048, 0, 0, 0 },
{ 4096, 2048, 2048, 0, 0 },
{ 6144, 2048, 2048, 2048, 0 },
{ 8192, 2048, 2048, 2048, 2048 },
{ 12288, 2048, 2048, 8192, 0 },
{ 20480, 2048, 2048, 8192, 8192 },
{ 10240, 2048, 8192, 0, 0 },
{ 18432, 2048, 8192, 8192, 0 },
{ 26624, 2048, 8192, 8192, 8192 },
{ 4096, 4096, 0, 0, 0 },
{ 8192, 4096, 4096, 0, 0 },
{ 24576, 4096, 4096, 8192, 8192 },
{ 12288, 4096, 8192, 0, 0 },
{ 8192, 8192, 0, 0, 0 },
{ 16384, 8192, 8192, 0, 0 },
{ 24576, 8192, 8192, 8192, 0 },
{ 32768, 8192, 8192, 8192, 8192 },
{ 65536, 32768, 32768, 0, 0 }
// clang-format on
};
#ifdef ENABLE_ALI6117_LOG
int ali6117_do_log = ENABLE_ALI6117_LOG;
@@ -56,62 +92,104 @@ ali6117_log(const char *fmt, ...)
va_list ap;
if (ali6117_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define ali6117_log(fmt, ...)
# define ali6117_log(fmt, ...)
#endif
static void
ali6117_recalcmapping(ali6117_t *dev)
{
uint8_t reg, bitpair;
uint32_t base, size;
int state;
uint32_t base;
uint32_t size;
int state;
shadowbios = 0;
shadowbios = 0;
shadowbios_write = 0;
ali6117_log("ALI6117: Shadowing for A0000-BFFFF (reg 12 bit 1) = %s\n", (dev->regs[0x12] & 0x02) ? "on" : "off");
mem_set_mem_state(0xa0000, 0x20000, (dev->regs[0x12] & 0x02) ? (MEM_WRITE_INTERNAL | MEM_READ_INTERNAL) : (MEM_WRITE_EXTANY | MEM_READ_EXTANY));
for (reg = 0; reg <= 1; reg++) {
for (bitpair = 0; bitpair <= 3; bitpair++) {
size = 0x8000;
base = 0xc0000 + (size * ((reg * 4) + bitpair));
ali6117_log("ALI6117: Shadowing for %05X-%05X (reg %02X bp %d wmask %02X rmask %02X) =", base, base + size - 1, 0x14 + reg, bitpair, 1 << ((bitpair * 2) + 1), 1 << (bitpair * 2));
for (uint8_t reg = 0; reg <= 1; reg++) {
for (uint8_t bitpair = 0; bitpair <= 3; bitpair++) {
size = 0x8000;
base = 0xc0000 + (size * ((reg * 4) + bitpair));
ali6117_log("ALI6117: Shadowing for %05X-%05X (reg %02X bp %d wmask %02X rmask %02X) =", base, base + size - 1, 0x14 + reg, bitpair, 1 << ((bitpair * 2) + 1), 1 << (bitpair * 2));
state = 0;
if (dev->regs[0x14 + reg] & (1 << ((bitpair * 2) + 1))) {
ali6117_log(" w on");
state |= MEM_WRITE_INTERNAL;
if (base >= 0xe0000)
shadowbios_write |= 1;
} else {
ali6117_log(" w off");
state |= MEM_WRITE_EXTANY;
}
if (dev->regs[0x14 + reg] & (1 << (bitpair * 2))) {
ali6117_log("; r on\n");
state |= MEM_READ_INTERNAL;
if (base >= 0xe0000)
shadowbios |= 1;
} else {
ali6117_log("; r off\n");
state |= MEM_READ_EXTANY;
}
state = 0;
if (dev->regs[0x14 + reg] & (1 << ((bitpair * 2) + 1))) {
ali6117_log(" w on");
state |= MEM_WRITE_INTERNAL;
if (base >= 0xe0000)
shadowbios_write |= 1;
} else {
ali6117_log(" w off");
state |= MEM_WRITE_EXTANY;
}
if (dev->regs[0x14 + reg] & (1 << (bitpair * 2))) {
ali6117_log("; r on\n");
state |= MEM_READ_INTERNAL;
if (base >= 0xe0000)
shadowbios |= 1;
} else {
ali6117_log("; r off\n");
state |= MEM_READ_EXTANY;
}
mem_set_mem_state(base, size, state);
}
mem_set_mem_state(base, size, state);
}
}
flushmmucache_nopc();
}
static void
ali6117_bank_recalc(ali6117_t *dev)
{
uint32_t bank;
uint32_t addr;
for (uint32_t i = 0x00000000; i < (mem_size << 10); i += 4096) {
if ((i >= 0x000a0000) && (i < 0x00100000))
continue;
if (!is6117 && (i >= 0x00f00000) && (i < 0x01000000))
continue;
if (is6117 && (i >= 0x03f00000) && (i < 0x04000000))
continue;
switch (dev->regs[0x10] & 0xf8) {
case 0xe8:
bank = (i >> 12) & 3;
addr = (i & 0xfff) | ((i >> 14) << 12);
ali6117_log("E8 (%08X): Bank %i, address %08X vs. bank size %08X\n", i, bank, addr, ali6117_modes[dev->mode][bank + 1] * 1024);
if (addr < (ali6117_modes[dev->mode][bank + 1] * 1024))
mem_set_mem_state_both(i, 4096, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
else
mem_set_mem_state_both(i, 4096, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
break;
case 0xf8:
bank = (i >> 12) & 1;
addr = (i & 0xfff) | ((i >> 13) << 12);
ali6117_log("F8 (%08X): Bank %i, address %08X vs. bank size %08X\n", i, bank, addr, ali6117_modes[dev->mode][bank + 1] * 1024);
if (addr < (ali6117_modes[dev->mode][bank + 1] * 1024))
mem_set_mem_state_both(i, 4096, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
else
mem_set_mem_state_both(i, 4096, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
break;
default:
mem_set_mem_state_both(i, 4096, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
break;
}
}
flushmmucache();
}
static void
ali6117_reg_write(uint16_t addr, uint8_t val, void *priv)
@@ -121,184 +199,208 @@ ali6117_reg_write(uint16_t addr, uint8_t val, void *priv)
ali6117_log("ALI6117: reg_write(%04X, %02X)\n", addr, val);
if (addr == 0x22)
dev->reg_offset = val;
dev->reg_offset = val;
else if (dev->reg_offset == 0x13)
dev->unlocked = (val == 0xc5);
dev->unlocked = (val == 0xc5);
else if (dev->unlocked) {
ali6117_log("ALI6117: regs[%02X] = %02X\n", dev->reg_offset, val);
ali6117_log("ALI6117: regs[%02X] = %02X\n", dev->reg_offset, val);
if (!(dev->local & 0x08) || (dev->reg_offset < 0x30)) switch (dev->reg_offset) {
case 0x30: case 0x34: case 0x35: case 0x3e:
case 0x3f: case 0x46: case 0x4c: case 0x6a:
case 0x73:
return; /* read-only registers */
if (!(dev->local & 0x08) || (dev->reg_offset < 0x30))
switch (dev->reg_offset) {
case 0x30:
case 0x34:
case 0x35:
case 0x3e:
case 0x3f:
case 0x46:
case 0x4c:
case 0x6a:
case 0x73:
return; /* read-only registers */
case 0x10:
refresh_at_enable = !(val & 0x02) || !!(dev->regs[0x20] & 0x80);
break;
case 0x10:
refresh_at_enable = !(val & 0x02) || !!(dev->regs[0x20] & 0x80);
dev->regs[dev->reg_offset] = val;
case 0x12:
val &= 0xf7;
/* FALL-THROUGH */
if (dev->local != 0x8) {
if (val & 0x04)
mem_set_mem_state_both(0x00f00000, 0x00100000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
else
mem_set_mem_state_both(0x00f00000, 0x00100000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
case 0x14: case 0x15:
dev->regs[dev->reg_offset] = val;
ali6117_recalcmapping(dev);
break;
ali6117_bank_recalc(dev);
}
break;
case 0x1e:
val &= 0x07;
case 0x12:
val &= 0xf7;
fallthrough;
switch (val) {
/* Half PIT clock. */
case 0x0:
cpu_set_isa_speed(7159091);
break;
case 0x14:
case 0x15:
dev->regs[dev->reg_offset] = val;
ali6117_recalcmapping(dev);
break;
/* Divisors on the input clock PCLK2, which is double the CPU clock. */
case 0x1:
cpu_set_isa_speed(cpu_busspeed / 1.5);
break;
case 0x1e:
val &= 0x07;
case 0x2:
cpu_set_isa_speed(cpu_busspeed / 2);
break;
switch (val) {
/* Half PIT clock. */
case 0x0:
cpu_set_isa_speed(7159091);
break;
case 0x3:
cpu_set_isa_speed(cpu_busspeed / 2.5);
break;
/* Divisors on the input clock PCLK2, which is double the CPU clock. */
case 0x1:
cpu_set_isa_speed(cpu_busspeed / 1.5);
break;
case 0x4:
cpu_set_isa_speed(cpu_busspeed / 3);
break;
case 0x2:
cpu_set_isa_speed(cpu_busspeed / 2);
break;
case 0x5:
cpu_set_isa_speed(cpu_busspeed / 4);
break;
case 0x3:
cpu_set_isa_speed(cpu_busspeed / 2.5);
break;
case 0x6:
cpu_set_isa_speed(cpu_busspeed / 5);
break;
case 0x4:
cpu_set_isa_speed(cpu_busspeed / 3);
break;
case 0x7:
cpu_set_isa_speed(cpu_busspeed / 6);
break;
}
break;
case 0x5:
cpu_set_isa_speed(cpu_busspeed / 4);
break;
case 0x20:
val &= 0xbf;
refresh_at_enable = !(dev->regs[0x10] & 0x02) || !!(val & 0x80);
break;
case 0x6:
cpu_set_isa_speed(cpu_busspeed / 5);
break;
case 0x31:
/* TODO: fast gate A20 (bit 0) */
val &= 0x21;
break;
case 0x7:
cpu_set_isa_speed(cpu_busspeed / 6);
break;
case 0x32:
val &= 0xc1;
break;
default:
break;
}
break;
case 0x33:
val &= 0xfd;
break;
case 0x20:
val &= 0xbf;
refresh_at_enable = !(dev->regs[0x10] & 0x02) || !!(val & 0x80);
break;
case 0x36:
val &= 0xf0;
val |= dev->regs[dev->reg_offset];
break;
case 0x31:
/* TODO: fast gate A20 (bit 0) */
val &= 0x21;
break;
case 0x37:
val &= 0xf5;
break;
case 0x32:
val &= 0xc1;
break;
case 0x3c:
val &= 0x8f;
ide_pri_disable();
ide_set_base(1, (val & 0x01) ? 0x170 : 0x1f0);
ide_set_side(1, (val & 0x01) ? 0x376 : 0x3f6);
ide_pri_enable();
break;
case 0x33:
val &= 0xfd;
break;
case 0x44: case 0x45:
val &= 0x3f;
break;
case 0x36:
val &= 0xf0;
val |= dev->regs[dev->reg_offset];
break;
case 0x4a:
val &= 0xfe;
break;
case 0x37:
val &= 0xf5;
break;
case 0x55:
val &= 0x03;
break;
case 0x3c:
val &= 0x8f;
ide_pri_disable();
ide_set_base(1, (val & 0x01) ? 0x170 : 0x1f0);
ide_set_side(1, (val & 0x01) ? 0x376 : 0x3f6);
ide_pri_enable();
break;
case 0x56:
val &= 0xc7;
break;
case 0x44:
case 0x45:
val &= 0x3f;
break;
case 0x58:
val &= 0xc3;
break;
case 0x4a:
val &= 0xfe;
break;
case 0x59:
val &= 0x60;
break;
case 0x55:
val &= 0x03;
break;
case 0x5b:
val &= 0x1f;
break;
case 0x56:
val &= 0xc7;
break;
case 0x64:
val &= 0xf7;
break;
case 0x58:
val &= 0xc3;
break;
case 0x66:
val &= 0xe3;
break;
case 0x59:
val &= 0x60;
break;
case 0x67:
val &= 0xdf;
break;
case 0x5b:
val &= 0x1f;
break;
case 0x69:
val &= 0x50;
break;
case 0x64:
val &= 0xf7;
break;
case 0x6b:
val &= 0x7f;
break;
case 0x66:
val &= 0xe3;
break;
case 0x6e: case 0x6f:
val &= 0x03;
break;
case 0x67:
val &= 0xdf;
break;
case 0x71:
val &= 0x1f;
break;
}
case 0x69:
val &= 0x50;
break;
dev->regs[dev->reg_offset] = val;
case 0x6b:
val &= 0x7f;
break;
case 0x6e:
case 0x6f:
val &= 0x03;
break;
case 0x71:
val &= 0x1f;
break;
default:
break;
}
dev->regs[dev->reg_offset] = val;
}
}
static uint8_t
ali6117_reg_read(uint16_t addr, void *priv)
{
ali6117_t *dev = (ali6117_t *) priv;
uint8_t ret;
const ali6117_t *dev = (ali6117_t *) priv;
uint8_t ret;
if (addr == 0x22)
ret = dev->reg_offset;
ret = dev->reg_offset;
else
ret = dev->regs[dev->reg_offset];
ret = dev->regs[dev->reg_offset];
ali6117_log("ALI6117: reg_read(%04X) = %02X\n", dev->reg_offset, ret);
return ret;
}
static void
ali6117_reset(void *priv)
{
@@ -316,18 +418,23 @@ ali6117_reset(void *priv)
dev->regs[0x1d] = 0xff;
dev->regs[0x20] = 0x80;
if (dev->local & 0x08) {
dev->regs[0x30] = 0x08;
dev->regs[0x31] = 0x01;
dev->regs[0x34] = 0x04; /* enable internal RTC */
dev->regs[0x35] = 0x20; /* enable internal KBC */
dev->regs[0x36] = dev->local & 0x07; /* M6117D ID */
dev->regs[0x30] = 0x08;
dev->regs[0x31] = 0x01;
dev->regs[0x34] = 0x04; /* enable internal RTC */
dev->regs[0x35] = 0x20; /* enable internal KBC */
dev->regs[0x36] = dev->local & 0x07; /* M6117D ID */
}
cpu_set_isa_speed(7159091);
refresh_at_enable = 1;
}
if (dev->local != 0x8) {
/* On-board memory 15-16M is enabled by default. */
mem_set_mem_state_both(0x00f00000, 0x00100000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
ali6117_bank_recalc(dev);
}
}
static void
ali6117_setup(ali6117_t *dev)
@@ -336,10 +443,9 @@ ali6117_setup(ali6117_t *dev)
/* Main register interface */
io_sethandler(0x22, 2,
ali6117_reg_read, NULL, NULL, ali6117_reg_write, NULL, NULL, dev);
ali6117_reg_read, NULL, NULL, ali6117_reg_write, NULL, NULL, dev);
}
static void
ali6117_close(void *priv)
{
@@ -348,61 +454,66 @@ ali6117_close(void *priv)
ali6117_log("ALI6117: close()\n");
io_removehandler(0x22, 2,
ali6117_reg_read, NULL, NULL, ali6117_reg_write, NULL, NULL, dev);
ali6117_reg_read, NULL, NULL, ali6117_reg_write, NULL, NULL, dev);
free(dev);
}
static void *
ali6117_init(const device_t *info)
{
int last_match = 0;
ali6117_log("ALI6117: init()\n");
ali6117_t *dev = (ali6117_t *) malloc(sizeof(ali6117_t));
memset(dev, 0, sizeof(ali6117_t));
dev->local = info->local;
device_add(&ide_isa_device);
ali6117_setup(dev);
for (int8_t i = 31; i >= 0; i--) {
if ((mem_size >= ali6117_modes[i][0]) && (ali6117_modes[i][0] > last_match)) {
last_match = ali6117_modes[i][0];
dev->mode = i;
}
}
ali6117_reset(dev);
if (!(dev->local & 0x08))
pic_elcr_io_handler(0);
pic_elcr_io_handler(0);
return dev;
}
const device_t ali1217_device =
{
"ALi M1217",
"ali1217",
DEVICE_AT,
0x8,
ali6117_init,
ali6117_close,
ali6117_reset,
{ NULL },
NULL,
NULL,
NULL
const device_t ali1217_device = {
.name = "ALi M1217",
.internal_name = "ali1217",
.flags = DEVICE_AT,
.local = 0x8,
.init = ali6117_init,
.close = ali6117_close,
.reset = ali6117_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t ali6117d_device =
{
"ALi M6117D",
"ali6117d",
DEVICE_AT,
0x2,
ali6117_init,
ali6117_close,
ali6117_reset,
{ NULL },
NULL,
NULL,
NULL
const device_t ali6117d_device = {
.name = "ALi M6117D",
.internal_name = "ali6117d",
.flags = DEVICE_AT,
.local = 0x2,
.init = ali6117_init,
.close = ali6117_close,
.reset = ali6117_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

761
src/chipset/compaq_386.c Normal file
View File

@@ -0,0 +1,761 @@
/*
* 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>
#define RAM_DIAG_L_BASE_MEM_640KB 0x00
#define RAM_DIAG_L_BASE_MEM_INV 0x10
#define RAM_DIAG_L_BASE_MEM_512KB 0x20
#define RAM_DIAG_L_BASE_MEM_256KB 0x30
#define RAM_DIAG_L_BASE_MEM_MASK 0x30
#define RAM_DIAG_L_PERMA_BITS 0x80
#define RAM_DIAG_H_SYS_RAM_4MB 0x01
#define RAM_DIAG_H_SYS_RAM_1MB 0x02
#define RAM_DIAG_H_SYS_RAM_NONE 0x03
#define RAM_DIAG_H_SYS_RAM_MASK 0x03
#define RAM_DIAG_H_MOD_A_RAM_4MB 0x04
#define RAM_DIAG_H_MOD_A_RAM_1MB 0x08
#define RAM_DIAG_H_MOD_A_RAM_NONE 0x0c
#define RAM_DIAG_H_MOD_A_RAM_MASK 0x0c
#define RAM_DIAG_H_MOD_B_RAM_4MB 0x10
#define RAM_DIAG_H_MOD_B_RAM_1MB 0x20
#define RAM_DIAG_H_MOD_B_RAM_NONE 0x30
#define RAM_DIAG_H_MOD_B_RAM_MASK 0x30
#define RAM_DIAG_H_MOD_C_RAM_4MB 0x40
#define RAM_DIAG_H_MOD_C_RAM_1MB 0x80
#define RAM_DIAG_H_MOD_C_RAM_NONE 0xc0
#define RAM_DIAG_H_MOD_C_RAM_MASK 0xc0
#define MEM_STATE_BUS 0x00
#define MEM_STATE_SYS 0x01
#define MEM_STATE_SYS_RELOC 0x02
#define MEM_STATE_MOD_A 0x04
#define MEM_STATE_MOD_B 0x08
#define MEM_STATE_MOD_C 0x10
#define MEM_STATE_MASK (MEM_STATE_SYS | MEM_STATE_MOD_A | MEM_STATE_MOD_B | MEM_STATE_MOD_C)
#define MEM_STATE_WP 0x20
typedef struct cpq_ram_t {
uint8_t wp;
uint32_t phys_base;
uint32_t virt_base;
mem_mapping_t mapping;
} cpq_ram_t;
typedef struct cpq_386_t {
uint8_t regs[8];
uint8_t old_state[256];
uint8_t mem_state[256];
uint32_t ram_bases[4];
uint32_t ram_sizes[4];
uint32_t ram_map_sizes[4];
cpq_ram_t ram[4][64];
cpq_ram_t high_ram[16];
mem_mapping_t regs_mapping;
} cpq_386_t;
static uint8_t
cpq_read_ram(uint32_t addr, void *priv)
{
const cpq_ram_t *dev = (cpq_ram_t *) priv;
uint8_t ret = 0xff;
addr = (addr - dev->virt_base) + dev->phys_base;
if (addr < (mem_size << 10))
ret = mem_read_ram(addr, priv);
return ret;
}
static uint16_t
cpq_read_ramw(uint32_t addr, void *priv)
{
const cpq_ram_t *dev = (cpq_ram_t *) priv;
uint16_t ret = 0xffff;
addr = (addr - dev->virt_base) + dev->phys_base;
if (addr < (mem_size << 10))
ret = mem_read_ramw(addr, priv);
return ret;
}
static uint32_t
cpq_read_raml(uint32_t addr, void *priv)
{
const cpq_ram_t *dev = (cpq_ram_t *) priv;
uint32_t ret = 0xffffffff;
addr = (addr - dev->virt_base) + dev->phys_base;
if (addr < (mem_size << 10))
ret = mem_read_raml(addr, priv);
return ret;
}
static void
cpq_write_ram(uint32_t addr, uint8_t val, void *priv)
{
const cpq_ram_t *dev = (cpq_ram_t *) priv;
addr = (addr - dev->virt_base) + dev->phys_base;
if (!dev->wp && (addr < (mem_size << 10)))
mem_write_ram(addr, val, priv);
}
static void
cpq_write_ramw(uint32_t addr, uint16_t val, void *priv)
{
const cpq_ram_t *dev = (cpq_ram_t *) priv;
addr = (addr - dev->virt_base) + dev->phys_base;
if (!dev->wp && (addr < (mem_size << 10)))
mem_write_ramw(addr, val, priv);
}
static void
cpq_write_raml(uint32_t addr, uint32_t val, void *priv)
{
const cpq_ram_t *dev = (cpq_ram_t *) priv;
addr = (addr - dev->virt_base) + dev->phys_base;
if (!dev->wp && (addr < (mem_size << 10)))
mem_write_raml(addr, val, priv);
}
static uint8_t
cpq_read_regs(uint32_t addr, void *priv)
{
const cpq_386_t *dev = (cpq_386_t *) priv;
uint8_t ret = 0xff;
addr &= 0x00000fff;
switch (addr) {
case 0x00000000:
case 0x00000001:
/* RAM Diagnostics (Read Only) */
case 0x00000002:
case 0x00000003:
/* RAM Setup Port (Read/Write) */
ret = dev->regs[addr];
break;
default:
break;
}
return ret;
}
static uint16_t
cpq_read_regsw(uint32_t addr, void *priv)
{
uint16_t ret = 0xffff;
ret = cpq_read_regs(addr, priv);
ret |= (((uint16_t) cpq_read_regs(addr + 1, priv)) << 8);
return ret;
}
static uint32_t
cpq_read_regsl(uint32_t addr, void *priv)
{
uint32_t ret = 0xffffffff;
ret = cpq_read_regsw(addr, priv);
ret |= (((uint32_t) cpq_read_regsw(addr + 2, priv)) << 16);
return ret;
}
static void
cpq_recalc_state(cpq_386_t *dev, uint8_t i)
{
uint32_t addr;
addr = ((uint32_t) i) << 16;
if (dev->mem_state[i] == 0x00)
mem_set_mem_state(addr, 0x00010000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
else if (dev->mem_state[i] == MEM_STATE_WP)
mem_set_mem_state(addr, 0x00010000, MEM_READ_EXTANY | MEM_WRITE_DISABLED);
else if (dev->mem_state[i] & MEM_STATE_WP)
mem_set_mem_state(addr, 0x00010000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED);
else
mem_set_mem_state(addr, 0x00010000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
dev->old_state[i] = dev->mem_state[i];
}
static void
cpq_recalc_states(cpq_386_t *dev)
{
/* Recalculate the entire 16 MB space. */
for (uint16_t i = 0; i < 256; i++) {
if (dev->mem_state[i] != dev->old_state[i])
cpq_recalc_state(dev, i);
}
flushmmucache_nopc();
}
static void
cpq_recalc_cache(cpq_386_t *dev)
{
cpu_cache_ext_enabled = (dev->regs[0x00000002] & 0x40);
cpu_update_waitstates();
}
static void
cpq_recalc_ram(cpq_386_t *dev)
{
uint8_t sys_ram = (dev->regs[0x00000001] & RAM_DIAG_H_SYS_RAM_MASK) & 0x01;
uint8_t setup_port = dev->regs[0x00000002] & 0x0f;
uint8_t sys_min_high = sys_ram ? 0xfa : 0xf4;
uint8_t ram_states[4] = { MEM_STATE_SYS, MEM_STATE_MOD_A,
MEM_STATE_MOD_B, MEM_STATE_MOD_C };
uint8_t ram_bases[4][2][16] = { { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 } },
{ { 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00 },
{ 0x40, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 } },
{ { 0x00, 0x00, 0x00, 0x20, 0x20, 0x00, 0x20, 0x20,
0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x00, 0x00 },
{ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x50,
0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 } },
{ { 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x60,
0x00, 0x00, 0x90, 0x90, 0x90, 0x90, 0x00, 0x00 },
{ 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
0x00, 0x00, 0x90, 0x00, 0x00, 0xc0, 0xc0, 0xc0 } } };
uint8_t ram_sizes[4][2][16] = { { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x30, 0x00, 0x10, 0x20, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30 } },
{ { 0x00, 0x00, 0x10, 0x10, 0x10, 0x40, 0x10, 0x10,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00 },
{ 0x40, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 } },
{ { 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x40, 0x40,
0x30, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00 },
{ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10,
0x00, 0x10, 0x10, 0x30, 0x40, 0x40, 0x40, 0x40 } },
{ { 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10,
0x00, 0x00, 0x10, 0x20, 0x30, 0x40, 0x00, 0x00 },
{ 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x20, 0x30 } } };
uint8_t size;
uint8_t start;
uint8_t end;
uint8_t k;
uint32_t virt_base;
cpq_ram_t *cram;
for (uint16_t i = 0x10; i < sys_min_high; i++)
dev->mem_state[i] &= ~MEM_STATE_MASK;
for (uint8_t i = 0; i < 4; i++) {
for (uint8_t j = 0; j <= 64; j++) {
if ((i >= 1) || (j >= 0x10))
mem_mapping_disable(&dev->ram[i][j].mapping);
}
}
for (uint8_t i = 0; i < 4; i++) {
size = ram_sizes[i][sys_ram][setup_port];
if (size > 0x00) {
start = ram_bases[i][sys_ram][setup_port];
end = start + (size - 1);
virt_base = ((uint32_t) start) << 16;
for (uint16_t j = start; j <= end; j++) {
k = j - start;
if (i == 0)
k += 0x10;
cram = &(dev->ram[i][k]);
dev->mem_state[j] |= ram_states[i];
cram->virt_base = ((uint32_t) j) << 16;
cram->phys_base = cram->virt_base - virt_base + dev->ram_bases[i];
mem_mapping_set_addr(&cram->mapping, cram->virt_base, 0x00010000);
mem_mapping_set_exec(&cram->mapping, &(ram[cram->phys_base]));
}
}
}
/* Recalculate the entire 16 MB space. */
cpq_recalc_states(dev);
}
static void
cpq_write_regs(uint32_t addr, uint8_t val, void *priv)
{
cpq_386_t *dev = (cpq_386_t *) priv;
addr &= 0x00000fff;
switch (addr) {
case 0x00000000:
case 0x00000001:
/* RAM Relocation (Write Only) */
dev->regs[addr + 4] = val;
if (addr == 0x00000000) {
dev->mem_state[0x0e] &= ~(MEM_STATE_SYS | MEM_STATE_WP);
dev->mem_state[0x0f] &= ~(MEM_STATE_SYS | MEM_STATE_WP);
dev->mem_state[0xfe] &= ~MEM_STATE_WP;
dev->mem_state[0xff] &= ~MEM_STATE_WP;
if (!(val & 0x01)) {
dev->mem_state[0x0e] |= MEM_STATE_SYS;
dev->mem_state[0x0f] |= MEM_STATE_SYS;
}
if (!(val & 0x02)) {
dev->mem_state[0x0e] |= MEM_STATE_WP;
dev->mem_state[0x0f] |= MEM_STATE_WP;
dev->mem_state[0xfe] |= MEM_STATE_WP;
dev->mem_state[0xff] |= MEM_STATE_WP;
}
cpq_recalc_state(dev, 0x0e);
cpq_recalc_state(dev, 0x0f);
cpq_recalc_state(dev, 0xfe);
cpq_recalc_state(dev, 0xff);
flushmmucache_nopc();
}
break;
case 0x00000002:
case 0x00000003:
/* RAM Setup Port (Read/Write) */
dev->regs[addr] = val;
if (addr == 0x00000002) {
cpq_recalc_ram(dev);
cpq_recalc_cache(dev);
}
break;
default:
break;
}
}
static void
cpq_write_regsw(uint32_t addr, uint16_t val, void *priv)
{
cpq_write_regs(addr, val & 0xff, priv);
cpq_write_regs(addr + 1, (val >> 8) & 0xff, priv);
}
static void
cpq_write_regsl(uint32_t addr, uint32_t val, void *priv)
{
cpq_write_regsw(addr, val & 0xff, priv);
cpq_write_regsw(addr + 2, (val >> 16) & 0xff, priv);
}
static void
compaq_ram_init(cpq_ram_t *dev)
{
mem_mapping_add(&dev->mapping,
0x00000000,
0x00010000,
cpq_read_ram,
cpq_read_ramw,
cpq_read_raml,
cpq_write_ram,
cpq_write_ramw,
cpq_write_raml,
NULL,
MEM_MAPPING_INTERNAL,
dev);
mem_mapping_disable(&dev->mapping);
}
static void
compaq_ram_diags_parse(cpq_386_t *dev)
{
uint8_t val = dev->regs[0x00000001];
uint32_t accum = 0x00100000;
for (uint8_t i = 0; i < 4; i++) {
dev->ram_bases[i] = accum;
switch (val & 0x03) {
case RAM_DIAG_H_SYS_RAM_1MB:
dev->ram_sizes[i] = 0x00100000;
break;
case RAM_DIAG_H_SYS_RAM_4MB:
dev->ram_sizes[i] = 0x00400000;
break;
default:
break;
}
if (i == 0)
dev->ram_sizes[i] -= 0x00100000;
dev->ram_map_sizes[i] = dev->ram_sizes[i];
accum += dev->ram_sizes[i];
if (accum >= (mem_size << 10)) {
dev->ram_sizes[i] = (mem_size << 10) - dev->ram_bases[i];
break;
}
val >>= 2;
}
}
static void
compaq_recalc_base_ram(cpq_386_t *dev)
{
uint8_t base_mem = dev->regs[0x00000000] & RAM_DIAG_L_BASE_MEM_MASK;
uint8_t sys_ram = dev->regs[0x00000001] & RAM_DIAG_H_SYS_RAM_MASK;
uint8_t low_start = 0x00;
uint8_t low_end = 0x00;
uint8_t high_start = 0x00;
uint8_t high_end = 0x00;
cpq_ram_t *cram;
switch (base_mem) {
case RAM_DIAG_L_BASE_MEM_256KB:
switch (sys_ram) {
case RAM_DIAG_H_SYS_RAM_1MB:
low_start = 0x00;
low_end = 0x03;
high_start = 0xf4;
high_end = 0xff;
break;
case RAM_DIAG_H_SYS_RAM_4MB:
low_start = 0x00;
low_end = 0x03;
high_start = 0xfa;
high_end = 0xff;
break;
default:
fatal("Compaq 386 - Invalid configuation: %02X %02X\n", base_mem, sys_ram);
return;
}
break;
case RAM_DIAG_L_BASE_MEM_512KB:
switch (sys_ram) {
case RAM_DIAG_H_SYS_RAM_1MB:
low_start = 0x00;
low_end = 0x07;
high_start = 0xf8;
high_end = 0xff;
break;
case RAM_DIAG_H_SYS_RAM_4MB:
low_start = 0x00;
low_end = 0x07;
high_start = 0xfa;
high_end = 0xff;
break;
default:
fatal("Compaq 386 - Invalid configuation: %02X %02X\n", base_mem, sys_ram);
return;
}
break;
case RAM_DIAG_L_BASE_MEM_640KB:
switch (sys_ram) {
case RAM_DIAG_H_SYS_RAM_1MB:
low_start = 0x00;
low_end = 0x09;
high_start = 0xfa;
high_end = 0xff;
break;
case RAM_DIAG_H_SYS_RAM_4MB:
low_start = 0x00;
low_end = 0x09;
high_start = 0xfa;
high_end = 0xff;
break;
default:
fatal("Compaq 386 - Invalid configuation: %02X %02X\n", base_mem, sys_ram);
return;
}
break;
default:
fatal("Compaq 386 - Invalid configuation: %02X %02X\n", base_mem, sys_ram);
return;
}
switch (sys_ram) {
case RAM_DIAG_H_SYS_RAM_1MB:
if (mem_size < 1024)
dev->regs[0x00000002] = 0x01;
else if (mem_size == 8192)
dev->regs[0x00000002] = 0x09;
else if (mem_size >= 11264)
dev->regs[0x00000002] = 0x0d;
else
dev->regs[0x00000002] = (mem_size >> 10);
break;
case RAM_DIAG_H_SYS_RAM_4MB:
if (mem_size < 4096)
dev->regs[0x00000002] = 0x04;
else if (mem_size == 11264)
dev->regs[0x00000002] = 0x0c;
else if (mem_size >= 16384)
dev->regs[0x00000002] = 0x00;
else if (mem_size > 13312)
dev->regs[0x00000002] = 0x0d;
else
dev->regs[0x00000002] = (mem_size >> 10);
break;
default:
fatal("Compaq 386 - Invalid configuation: %02X\n", sys_ram);
return;
}
/* The base 640 kB. */
for (uint8_t i = low_start; i <= low_end; i++) {
cram = &(dev->ram[0][i]);
cram->phys_base = cram->virt_base = ((uint32_t) i) << 16;
dev->mem_state[i] |= MEM_STATE_SYS;
mem_mapping_set_addr(&cram->mapping, cram->virt_base, 0x00010000);
mem_mapping_set_exec(&cram->mapping, &(ram[cram->phys_base]));
cpq_recalc_state(dev, i);
}
/* The relocated 128 kB. */
for (uint8_t i = 0x0e; i <= 0x0f; i++) {
cram = &(dev->ram[0][i]);
cram->phys_base = cram->virt_base = ((uint32_t) i) << 16;
mem_mapping_set_addr(&cram->mapping, cram->virt_base, 0x00010000);
mem_mapping_set_exec(&cram->mapping, &(ram[cram->phys_base]));
}
/* Blocks FA-FF. */
for (uint16_t i = high_start; i <= high_end; i++) {
cram = &(dev->high_ram[i & 0x0f]);
cram->phys_base = ((uint32_t) (i & 0x0f)) << 16;
cram->virt_base = ((uint32_t) i) << 16;
dev->mem_state[i] |= MEM_STATE_SYS;
mem_mapping_set_addr(&cram->mapping, cram->virt_base, 0x00010000);
mem_mapping_set_exec(&cram->mapping, &(ram[cram->phys_base]));
cpq_recalc_state(dev, i);
}
}
static void
compaq_386_close(void *priv)
{
cpq_386_t *dev = (cpq_386_t *) priv;
free(dev);
}
static void *
compaq_386_init(UNUSED(const device_t *info))
{
cpq_386_t *dev = (cpq_386_t *) calloc(1, sizeof(cpq_386_t));
mem_mapping_add(&dev->regs_mapping,
0x80c00000,
0x00001000,
cpq_read_regs,
cpq_read_regsw,
cpq_read_regsl,
cpq_write_regs,
cpq_write_regsw,
cpq_write_regsl,
NULL,
MEM_MAPPING_INTERNAL,
dev);
mem_set_mem_state(0x80c00000, 0x00001000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
dev->regs[0x00000000] = RAM_DIAG_L_PERMA_BITS;
if (mem_size >= 640)
dev->regs[0x00000000] |= RAM_DIAG_L_BASE_MEM_640KB;
else if (mem_size >= 512)
dev->regs[0x00000000] |= RAM_DIAG_L_BASE_MEM_512KB;
else if (mem_size >= 256)
dev->regs[0x00000000] |= RAM_DIAG_L_BASE_MEM_256KB;
else
dev->regs[0x00000000] |= RAM_DIAG_L_BASE_MEM_INV;
/* Indicate no parity error. */
dev->regs[0x00000000] |= 0x0f;
if (mem_size >= 1024) {
switch (mem_size) {
case 1024:
dev->regs[0x00000001] = RAM_DIAG_H_SYS_RAM_4MB | RAM_DIAG_H_MOD_A_RAM_NONE |
RAM_DIAG_H_MOD_B_RAM_NONE | RAM_DIAG_H_MOD_C_RAM_NONE;
break;
case 2048:
dev->regs[0x00000001] = RAM_DIAG_H_SYS_RAM_4MB | RAM_DIAG_H_MOD_A_RAM_NONE |
RAM_DIAG_H_MOD_B_RAM_NONE | RAM_DIAG_H_MOD_C_RAM_NONE;
break;
case 3072:
dev->regs[0x00000001] = RAM_DIAG_H_SYS_RAM_4MB | RAM_DIAG_H_MOD_A_RAM_NONE |
RAM_DIAG_H_MOD_B_RAM_NONE | RAM_DIAG_H_MOD_C_RAM_NONE;
break;
case 4096:
dev->regs[0x00000001] = RAM_DIAG_H_SYS_RAM_4MB | RAM_DIAG_H_MOD_A_RAM_NONE |
RAM_DIAG_H_MOD_B_RAM_NONE | RAM_DIAG_H_MOD_C_RAM_NONE;
break;
case 5120:
dev->regs[0x00000001] = RAM_DIAG_H_SYS_RAM_4MB | RAM_DIAG_H_MOD_A_RAM_1MB |
RAM_DIAG_H_MOD_B_RAM_NONE | RAM_DIAG_H_MOD_C_RAM_NONE;
break;
case 6144:
dev->regs[0x00000001] = RAM_DIAG_H_SYS_RAM_4MB | RAM_DIAG_H_MOD_A_RAM_1MB |
RAM_DIAG_H_MOD_B_RAM_1MB | RAM_DIAG_H_MOD_C_RAM_NONE;
break;
case 7168:
dev->regs[0x00000001] = RAM_DIAG_H_SYS_RAM_4MB | RAM_DIAG_H_MOD_A_RAM_1MB |
RAM_DIAG_H_MOD_B_RAM_1MB | RAM_DIAG_H_MOD_C_RAM_1MB;
break;
case 8192:
dev->regs[0x00000001] = RAM_DIAG_H_SYS_RAM_4MB | RAM_DIAG_H_MOD_A_RAM_4MB |
RAM_DIAG_H_MOD_B_RAM_NONE | RAM_DIAG_H_MOD_C_RAM_NONE;
break;
case 9216:
dev->regs[0x00000001] = RAM_DIAG_H_SYS_RAM_4MB | RAM_DIAG_H_MOD_A_RAM_4MB |
RAM_DIAG_H_MOD_B_RAM_1MB | RAM_DIAG_H_MOD_C_RAM_NONE;
break;
case 10240:
dev->regs[0x00000001] = RAM_DIAG_H_SYS_RAM_4MB | RAM_DIAG_H_MOD_A_RAM_4MB |
RAM_DIAG_H_MOD_B_RAM_1MB | RAM_DIAG_H_MOD_C_RAM_1MB;
break;
case 11264:
case 12288:
dev->regs[0x00000001] = RAM_DIAG_H_SYS_RAM_4MB | RAM_DIAG_H_MOD_A_RAM_4MB |
RAM_DIAG_H_MOD_B_RAM_4MB | RAM_DIAG_H_MOD_C_RAM_NONE;
break;
case 13312:
dev->regs[0x00000001] = RAM_DIAG_H_SYS_RAM_4MB | RAM_DIAG_H_MOD_A_RAM_4MB |
RAM_DIAG_H_MOD_B_RAM_4MB | RAM_DIAG_H_MOD_C_RAM_1MB;
break;
case 14336:
case 15360:
case 16384:
dev->regs[0x00000001] = RAM_DIAG_H_SYS_RAM_4MB | RAM_DIAG_H_MOD_A_RAM_4MB |
RAM_DIAG_H_MOD_B_RAM_4MB | RAM_DIAG_H_MOD_C_RAM_4MB;
break;
default:
break;
}
} else
dev->regs[0x00000001] = RAM_DIAG_H_SYS_RAM_1MB | RAM_DIAG_H_MOD_A_RAM_NONE |
RAM_DIAG_H_MOD_B_RAM_NONE | RAM_DIAG_H_MOD_C_RAM_NONE;
dev->regs[0x00000003] = 0xfc;
dev->regs[0x00000004] = dev->regs[0x00000005] = 0xff;
compaq_ram_diags_parse(dev);
mem_mapping_disable(&ram_low_mapping);
mem_mapping_disable(&ram_mid_mapping);
mem_mapping_disable(&ram_high_mapping);
#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64))
/* Should never be the case, but you never know what a user may set. */
if (mem_size > 1048576)
mem_mapping_disable(&ram_2gb_mapping);
#endif
/* Initialize in reverse order for memory mapping precedence
reasons. */
for (int8_t i = 3; i >= 0; i--) {
for (uint8_t j = 0; j < 64; j++)
compaq_ram_init(&(dev->ram[i][j]));
}
for (uint8_t i = 0; i < 16; i++)
compaq_ram_init(&(dev->high_ram[i]));
/* First, set the entire 256 MB of space to invalid states. */
for (uint16_t i = 0; i < 256; i++)
dev->old_state[i] = 0xff;
/* Then, recalculate the base RAM mappings. */
compaq_recalc_base_ram(dev);
/* Enable the external cache. */
dev->regs[0x00000002] |= 0x40;
cpq_recalc_cache(dev);
/* Recalculate the rest of the RAM mapping. */
cpq_recalc_ram(dev);
return dev;
}
const device_t compaq_386_device = {
.name = "Compaq 386 Memory Control",
.internal_name = "compaq_386",
.flags = 0,
.local = 0,
.init = compaq_386_init,
.close = compaq_386_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -1,18 +1,19 @@
/*
* 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.
*
* Implementation of the Contaq/Cypress 82C596(A) and 597 chipsets.
* Implementation of the Contaq/Cypress 82C596(A) and 597 chipsets.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2021 Miran Grca.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2021 Miran Grca.
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
@@ -29,7 +30,6 @@
#include <86box/smram.h>
#include <86box/chipset.h>
#ifdef ENABLE_CONTAQ_82C59X_LOG
int contaq_82c59x_do_log = ENABLE_CONTAQ_82C59X_LOG;
@@ -38,274 +38,278 @@ contaq_82c59x_log(const char *fmt, ...)
{
va_list ap;
if (contaq_82c59x_do_log)
{
if (contaq_82c59x_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define contaq_82c59x_log(fmt, ...)
# define contaq_82c59x_log(fmt, ...)
#endif
typedef struct
{
uint32_t phys, virt;
typedef struct mem_remapping_t {
uint32_t phys;
uint32_t virt;
} mem_remapping_t;
typedef struct contaq_82c59x_t {
uint8_t index;
uint8_t green;
uint8_t smi_status_set;
uint8_t regs[256];
uint8_t smi_status[2];
typedef struct
{
uint8_t index, green,
smi_status_set,
regs[256], smi_status[2];
smram_t *smram[2];
smram_t *smram[2];
} contaq_82c59x_t;
static void
contaq_82c59x_isa_speed_recalc(contaq_82c59x_t *dev)
{
if (dev->regs[0x1c] & 0x02)
cpu_set_isa_speed(7159091);
cpu_set_isa_speed(7159091);
else {
/* TODO: ISA clock dividers for 386 and alt. 486. */
switch (dev->regs[0x10] & 0x03) {
case 0x00:
cpu_set_isa_speed(cpu_busspeed / 4);
break;
case 0x01:
cpu_set_isa_speed(cpu_busspeed / 6);
break;
case 0x02:
cpu_set_isa_speed(cpu_busspeed / 8);
break;
case 0x03:
cpu_set_isa_speed(cpu_busspeed / 5);
break;
}
/* TODO: ISA clock dividers for 386 and alt. 486. */
switch (dev->regs[0x10] & 0x03) {
case 0x00:
cpu_set_isa_speed(cpu_busspeed / 4);
break;
case 0x01:
cpu_set_isa_speed(cpu_busspeed / 6);
break;
case 0x02:
cpu_set_isa_speed(cpu_busspeed / 8);
break;
case 0x03:
cpu_set_isa_speed(cpu_busspeed / 5);
break;
default:
break;
}
}
}
static void
contaq_82c59x_shadow_recalc(contaq_82c59x_t *dev)
{
uint32_t i, base;
uint8_t bit;
uint32_t i;
uint32_t base;
uint8_t bit;
shadowbios = shadowbios_write = 0;
/* F0000-FFFFF */
if (dev->regs[0x15] & 0x80) {
shadowbios |= 1;
mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_EXTANY);
shadowbios |= 1;
mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_EXTANY);
} else {
shadowbios_write |= 1;
mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
shadowbios_write |= 1;
mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
}
/* C0000-CFFFF */
if (dev->regs[0x15] & 0x01)
mem_set_mem_state_both(0xc0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
mem_set_mem_state_both(0xc0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
else {
for (i = 0; i < 4; i++) {
base = 0xc0000 + (i << 14);
bit = 1 << (i + 2);
if (dev->regs[0x15] & bit) {
if (dev->regs[0x15] & 0x02)
mem_set_mem_state_both(base, 0x04000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL);
else
mem_set_mem_state_both(base, 0x04000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL);
} else
mem_set_mem_state_both(base, 0x04000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
}
for (i = 0; i < 4; i++) {
base = 0xc0000 + (i << 14);
bit = 1 << (i + 2);
if (dev->regs[0x15] & bit) {
if (dev->regs[0x15] & 0x02)
mem_set_mem_state_both(base, 0x04000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL);
else
mem_set_mem_state_both(base, 0x04000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL);
} else
mem_set_mem_state_both(base, 0x04000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
}
}
if (dev->green) {
/* D0000-DFFFF */
if (dev->regs[0x6e] & 0x01)
mem_set_mem_state_both(0xd0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
else {
for (i = 0; i < 4; i++) {
base = 0xd0000 + (i << 14);
bit = 1 << (i + 2);
if (dev->regs[0x6e] & bit) {
if (dev->regs[0x6e] & 0x02)
mem_set_mem_state_both(base, 0x04000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL);
else
mem_set_mem_state_both(base, 0x04000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
} else
mem_set_mem_state_both(base, 0x04000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
}
}
/* D0000-DFFFF */
if (dev->regs[0x6e] & 0x01)
mem_set_mem_state_both(0xd0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
else {
for (i = 0; i < 4; i++) {
base = 0xd0000 + (i << 14);
bit = 1 << (i + 2);
if (dev->regs[0x6e] & bit) {
if (dev->regs[0x6e] & 0x02)
mem_set_mem_state_both(base, 0x04000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL);
else
mem_set_mem_state_both(base, 0x04000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
} else
mem_set_mem_state_both(base, 0x04000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
}
}
/* E0000-EFFFF */
if (dev->regs[0x6f] & 0x01)
mem_set_mem_state_both(0xe0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
else {
for (i = 0; i < 4; i++) {
base = 0xe0000 + (i << 14);
bit = 1 << (i + 2);
if (dev->regs[0x6f] & bit) {
shadowbios |= 1;
if (dev->regs[0x6f] & 0x02)
mem_set_mem_state_both(base, 0x04000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL);
else {
shadowbios_write |= 1;
mem_set_mem_state_both(base, 0x04000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
}
} else
mem_set_mem_state_both(base, 0x04000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
}
}
/* E0000-EFFFF */
if (dev->regs[0x6f] & 0x01)
mem_set_mem_state_both(0xe0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
else {
for (i = 0; i < 4; i++) {
base = 0xe0000 + (i << 14);
bit = 1 << (i + 2);
if (dev->regs[0x6f] & bit) {
shadowbios |= 1;
if (dev->regs[0x6f] & 0x02)
mem_set_mem_state_both(base, 0x04000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL);
else {
shadowbios_write |= 1;
mem_set_mem_state_both(base, 0x04000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
}
} else
mem_set_mem_state_both(base, 0x04000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
}
}
}
}
static void
contaq_82c59x_smram_recalc(contaq_82c59x_t *dev)
{
smram_disable(dev->smram[1]);
if (dev->regs[0x70] & 0x04)
smram_enable(dev->smram[1], 0x00040000, 0x000a0000, 0x00020000, 1, 1);
smram_enable(dev->smram[1], 0x00040000, 0x000a0000, 0x00020000, 1, 1);
}
static void
contaq_82c59x_write(uint16_t addr, uint8_t val, void *priv)
{
contaq_82c59x_t *dev = (contaq_82c59x_t *)priv;
contaq_82c59x_t *dev = (contaq_82c59x_t *) priv;
switch (addr) {
case 0x22:
dev->index = val;
break;
case 0x22:
dev->index = val;
break;
case 0x23:
contaq_82c59x_log("Contaq 82C59x: dev->regs[%02x] = %02x\n", dev->index, val);
case 0x23:
contaq_82c59x_log("Contaq 82C59x: dev->regs[%02x] = %02x\n", dev->index, val);
if ((dev->index >= 0x60) && !dev->green)
return;
if ((dev->index >= 0x60) && !dev->green)
return;
switch (dev->index) {
/* Registers common to 82C596(A) and 82C597. */
case 0x10:
dev->regs[dev->index] = val;
contaq_82c59x_isa_speed_recalc(dev);
break;
switch (dev->index) {
/* Registers common to 82C596(A) and 82C597. */
case 0x10:
dev->regs[dev->index] = val;
contaq_82c59x_isa_speed_recalc(dev);
break;
case 0x11:
dev->regs[dev->index] = val;
cpu_cache_int_enabled = !!(val & 0x01);
cpu_update_waitstates();
break;
case 0x11:
dev->regs[dev->index] = val;
cpu_cache_int_enabled = !!(val & 0x01);
cpu_update_waitstates();
break;
case 0x12: case 0x13:
dev->regs[dev->index] = val;
break;
case 0x12:
case 0x13:
dev->regs[dev->index] = val;
break;
case 0x14:
dev->regs[dev->index] = val;
reset_on_hlt = !!(val & 0x80);
break;
case 0x14:
dev->regs[dev->index] = val;
reset_on_hlt = !!(val & 0x80);
break;
case 0x15:
dev->regs[dev->index] = val;
contaq_82c59x_shadow_recalc(dev);
break;
case 0x15:
dev->regs[dev->index] = val;
contaq_82c59x_shadow_recalc(dev);
break;
case 0x16 ... 0x1b:
dev->regs[dev->index] = val;
break;
case 0x16 ... 0x1b:
dev->regs[dev->index] = val;
break;
case 0x1c:
/* TODO: What's NPRST (generated if bit 3 is set)? */
dev->regs[dev->index] = val;
contaq_82c59x_isa_speed_recalc(dev);
break;
case 0x1c:
/* TODO: What's NPRST (generated if bit 3 is set)? */
dev->regs[dev->index] = val;
contaq_82c59x_isa_speed_recalc(dev);
break;
case 0x1d ... 0x1f:
dev->regs[dev->index] = val;
break;
case 0x1d ... 0x1f:
dev->regs[dev->index] = val;
break;
/* Green (82C597-specific) registers. */
case 0x60 ... 0x63:
dev->regs[dev->index] = val;
break;
/* Green (82C597-specific) registers. */
case 0x60 ... 0x63:
dev->regs[dev->index] = val;
break;
case 0x64:
dev->regs[dev->index] = val;
if (val & 0x80) {
if (dev->regs[0x65] & 0x80)
smi_line = 1;
dev->smi_status[0] |= 0x10;
}
break;
case 0x64:
dev->regs[dev->index] = val;
if (val & 0x80) {
if (dev->regs[0x65] & 0x80)
smi_raise();
dev->smi_status[0] |= 0x10;
}
break;
case 0x65 ... 0x69:
dev->regs[dev->index] = val;
break;
case 0x65 ... 0x69:
dev->regs[dev->index] = val;
break;
case 0x6a:
dev->regs[dev->index] = val;
dev->smi_status_set = !!(val & 0x80);
break;
case 0x6a:
dev->regs[dev->index] = val;
dev->smi_status_set = !!(val & 0x80);
break;
case 0x6b ... 0x6d:
dev->regs[dev->index] = val;
break;
case 0x6b ... 0x6d:
dev->regs[dev->index] = val;
break;
case 0x6e: case 0x6f:
dev->regs[dev->index] = val;
contaq_82c59x_shadow_recalc(dev);
break;
case 0x6e:
case 0x6f:
dev->regs[dev->index] = val;
contaq_82c59x_shadow_recalc(dev);
break;
case 0x70:
dev->regs[dev->index] = val;
contaq_82c59x_smram_recalc(dev);
break;
case 0x70:
dev->regs[dev->index] = val;
contaq_82c59x_smram_recalc(dev);
break;
case 0x71 ... 0x79:
dev->regs[dev->index] = val;
break;
case 0x71 ... 0x79:
dev->regs[dev->index] = val;
break;
case 0x7b: case 0x7c:
dev->regs[dev->index] = val;
break;
}
break;
case 0x7b:
case 0x7c:
dev->regs[dev->index] = val;
break;
default:
break;
}
break;
default:
break;
}
}
static uint8_t
contaq_82c59x_read(uint16_t addr, void *priv)
{
contaq_82c59x_t *dev = (contaq_82c59x_t *)priv;
uint8_t ret = 0xff;
contaq_82c59x_t *dev = (contaq_82c59x_t *) priv;
uint8_t ret = 0xff;
if (addr == 0x23) {
if (dev->index == 0x6a) {
ret = dev->smi_status[dev->smi_status_set];
/* I assume it's cleared on read. */
dev->smi_status[dev->smi_status_set] = 0x00;
} else
ret = dev->regs[dev->index];
if (dev->index == 0x6a) {
ret = dev->smi_status[dev->smi_status_set];
/* I assume it's cleared on read. */
dev->smi_status[dev->smi_status_set] = 0x00;
} else
ret = dev->regs[dev->index];
}
return ret;
}
static void
contaq_82c59x_close(void *priv)
{
contaq_82c59x_t *dev = (contaq_82c59x_t *)priv;
contaq_82c59x_t *dev = (contaq_82c59x_t *) priv;
smram_del(dev->smram[1]);
smram_del(dev->smram[0]);
@@ -313,11 +317,10 @@ contaq_82c59x_close(void *priv)
free(dev);
}
static void *
contaq_82c59x_init(const device_t *info)
{
contaq_82c59x_t *dev = (contaq_82c59x_t *)malloc(sizeof(contaq_82c59x_t));
contaq_82c59x_t *dev = (contaq_82c59x_t *) malloc(sizeof(contaq_82c59x_t));
memset(dev, 0x00, sizeof(contaq_82c59x_t));
dev->green = info->local;
@@ -334,44 +337,42 @@ contaq_82c59x_init(const device_t *info)
contaq_82c59x_shadow_recalc(dev);
if (dev->green) {
/* SMRAM 0: Fixed A0000-BFFFF to A0000-BFFFF DRAM. */
dev->smram[0] = smram_add();
smram_enable(dev->smram[0], 0x000a0000, 0x000a0000, 0x00020000, 0, 1);
/* SMRAM 0: Fixed A0000-BFFFF to A0000-BFFFF DRAM. */
dev->smram[0] = smram_add();
smram_enable(dev->smram[0], 0x000a0000, 0x000a0000, 0x00020000, 0, 1);
/* SMRAM 1: Optional. */
dev->smram[1] = smram_add();
contaq_82c59x_smram_recalc(dev);
/* SMRAM 1: Optional. */
dev->smram[1] = smram_add();
contaq_82c59x_smram_recalc(dev);
}
return dev;
}
const device_t contaq_82c596a_device = {
"Contaq 82C596A",
"contaq_82c596a",
0,
0,
contaq_82c59x_init,
contaq_82c59x_close,
NULL,
{ NULL },
NULL,
NULL,
NULL
.name = "Contaq 82C596A",
.internal_name = "contaq_82c596a",
.flags = 0,
.local = 0,
.init = contaq_82c59x_init,
.close = contaq_82c59x_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t contaq_82c597_device = {
"Contaq 82C597",
"contaq_82c597",
0,
1,
contaq_82c59x_init,
contaq_82c59x_close,
NULL,
{ NULL },
NULL,
NULL,
NULL
.name = "Contaq 82C597",
.internal_name = "contaq_82c597",
.flags = 0,
.local = 1,
.init = contaq_82c59x_init,
.close = contaq_82c59x_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -1,21 +1,19 @@
/*
* 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.
*
* Implementation of the Chips & Technologies CS4031 chipset.
* Implementation of the Chips & Technologies CS4031 chipset.
*
*
*
* Authors: Tiseno100
*
* Copyright 2021 Tiseno100
* Authors: Tiseno100
*
* Copyright 2021 Tiseno100
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
@@ -29,124 +27,128 @@
#include <86box/io.h>
#include <86box/device.h>
#include <86box/mem.h>
#include <86box/plat_unused.h>
#include <86box/port_92.h>
#include <86box/chipset.h>
typedef struct
{
uint8_t index,
regs[256];
typedef struct cs4031_t {
uint8_t index;
uint8_t regs[256];
port_92_t *port_92;
} cs4031_t;
#ifdef ENABLE_CS4031_LOG
int cs4031_do_log = ENABLE_CS4031_LOG;
static void
cs4031_log(const char *fmt, ...)
{
va_list ap;
if (cs4031_do_log)
{
if (cs4031_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define cs4031_log(fmt, ...)
# define cs4031_log(fmt, ...)
#endif
static void cs4031_shadow_recalc(cs4031_t *dev)
static void
cs4031_shadow_recalc(cs4031_t *dev)
{
mem_set_mem_state_both(0xa0000, 0x10000, (dev->regs[0x18] & 0x01) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY));
mem_set_mem_state_both(0xb0000, 0x10000, (dev->regs[0x18] & 0x02) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY));
for (uint32_t i = 0; i < 7; i++)
{
for (uint32_t i = 0; i < 7; i++) {
if (i < 4)
mem_set_mem_state_both(0xc0000 + (i << 14), 0x4000, ((dev->regs[0x19] & (1 << i)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x1a] & (1 << i)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY));
else
mem_set_mem_state_both(0xd0000 + ((i - 4) << 16), 0x10000, ((dev->regs[0x19] & (1 << i)) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x1a] & (1 << i)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY));
}
shadowbios = !!(dev->regs[0x19] & 0x40);
shadowbios = !!(dev->regs[0x19] & 0x40);
shadowbios_write = !!(dev->regs[0x1a] & 0x40);
}
static void
cs4031_write(uint16_t addr, uint8_t val, void *priv)
{
cs4031_t *dev = (cs4031_t *)priv;
cs4031_t *dev = (cs4031_t *) priv;
switch (addr)
{
case 0x22:
dev->index = val;
break;
case 0x23:
cs4031_log("CS4031: dev->regs[%02x] = %02x\n", dev->index, val);
switch (dev->index)
{
case 0x05:
dev->regs[dev->index] = val & 0x3f;
switch (addr) {
case 0x22:
dev->index = val;
break;
case 0x23:
cs4031_log("CS4031: dev->regs[%02x] = %02x\n", dev->index, val);
switch (dev->index) {
case 0x05:
dev->regs[dev->index] = val & 0x3f;
break;
case 0x06:
dev->regs[dev->index] = val & 0xbc;
break;
case 0x07:
dev->regs[dev->index] = val & 0x0f;
break;
case 0x10:
dev->regs[dev->index] = val & 0x3d;
break;
case 0x11:
dev->regs[dev->index] = val & 0x8d;
break;
case 0x12:
case 0x13:
dev->regs[dev->index] = val & 0x8d;
break;
case 0x14:
case 0x15:
case 0x16:
case 0x17:
dev->regs[dev->index] = val & 0x7f;
break;
case 0x18:
dev->regs[dev->index] = val & 0xf3;
cs4031_shadow_recalc(dev);
break;
case 0x19:
case 0x1a:
dev->regs[dev->index] = val & 0x7f;
cs4031_shadow_recalc(dev);
break;
case 0x1b:
dev->regs[dev->index] = val;
break;
case 0x1c:
dev->regs[dev->index] = val & 0xb3;
port_92_set_features(dev->port_92, val & 0x10, val & 0x20);
break;
default:
break;
}
break;
case 0x06:
dev->regs[dev->index] = val & 0xbc;
break;
case 0x07:
dev->regs[dev->index] = val & 0x0f;
break;
case 0x10:
dev->regs[dev->index] = val & 0x3d;
break;
case 0x11:
dev->regs[dev->index] = val & 0x8d;
break;
case 0x12:
case 0x13:
dev->regs[dev->index] = val & 0x8d;
break;
case 0x14:
case 0x15:
case 0x16:
case 0x17:
dev->regs[dev->index] = val & 0x7f;
break;
case 0x18:
dev->regs[dev->index] = val & 0xf3;
cs4031_shadow_recalc(dev);
break;
case 0x19:
case 0x1a:
dev->regs[dev->index] = val & 0x7f;
cs4031_shadow_recalc(dev);
break;
case 0x1b:
dev->regs[dev->index] = val;
break;
case 0x1c:
dev->regs[dev->index] = val & 0xb3;
port_92_set_features(dev->port_92, val & 0x10, val & 0x20);
break;
}
break;
default:
break;
}
}
static uint8_t
cs4031_read(uint16_t addr, void *priv)
{
cs4031_t *dev = (cs4031_t *)priv;
const cs4031_t *dev = (cs4031_t *) priv;
return (addr == 0x23) ? dev->regs[dev->index] : 0xff;
}
@@ -154,15 +156,15 @@ cs4031_read(uint16_t addr, void *priv)
static void
cs4031_close(void *priv)
{
cs4031_t *dev = (cs4031_t *)priv;
cs4031_t *dev = (cs4031_t *) priv;
free(dev);
}
static void *
cs4031_init(const device_t *info)
cs4031_init(UNUSED(const device_t *info))
{
cs4031_t *dev = (cs4031_t *)malloc(sizeof(cs4031_t));
cs4031_t *dev = (cs4031_t *) malloc(sizeof(cs4031_t));
memset(dev, 0, sizeof(cs4031_t));
dev->port_92 = device_add(&port_92_device);
@@ -176,14 +178,15 @@ cs4031_init(const device_t *info)
}
const device_t cs4031_device = {
"Chips & Technogies CS4031",
"cs4031",
0,
0,
cs4031_init,
cs4031_close,
NULL,
{NULL},
NULL,
NULL,
NULL};
.name = "Chips & Technogies CS4031",
.internal_name = "cs4031",
.flags = 0,
.local = 0,
.init = cs4031_init,
.close = cs4031_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -1,18 +1,18 @@
/*
* 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.
*
* Emulation of C&T CS8230 ("386/AT") chipset.
* Emulation of C&T CS8230 ("386/AT") chipset.
*
*
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
*
* Copyright 2020 Sarah Walker.
* Copyright 2020 Sarah Walker.
*/
#include <stdio.h>
#include <stdint.h>
@@ -25,144 +25,161 @@
#include <86box/io.h>
#include <86box/device.h>
#include <86box/mem.h>
#include <86box/plat_unused.h>
#include <86box/fdd.h>
#include <86box/fdc.h>
#include <86box/chipset.h>
typedef struct
{
int idx;
uint8_t regs[256];
typedef struct cs8230_t {
int idx;
uint8_t regs[256];
} cs8230_t;
static void
shadow_control(uint32_t addr, uint32_t size, int state)
{
switch (state) {
case 0x00:
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
break;
case 0x01:
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
break;
case 0x10:
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY);
break;
case 0x11:
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
break;
case 0x00:
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
break;
case 0x01:
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
break;
case 0x10:
mem_set_mem_state(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY);
break;
case 0x11:
mem_set_mem_state(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
break;
default:
break;
}
flushmmucache_nopc();
}
static void
rethink_shadow_mappings(cs8230_t *cs8230)
{
int c;
for (c = 0; c < 32; c++) {
/* Addresses 40000-bffff in 16k blocks */
if (cs8230->regs[0xa + (c >> 3)] & (1 << (c & 7)))
mem_set_mem_state(0x40000 + (c << 14), 0x4000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); /* I/O channel */
else
mem_set_mem_state(0x40000 + (c << 14), 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); /* System board */
for (uint8_t c = 0; c < 32; c++) {
/* Addresses 40000-bffff in 16k blocks */
if (cs8230->regs[0xa + (c >> 3)] & (1 << (c & 7)))
mem_set_mem_state(0x40000 + (c << 14), 0x4000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); /* I/O channel */
else
mem_set_mem_state(0x40000 + (c << 14), 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); /* System board */
}
for (c = 0; c < 16; c++) {
/* Addresses c0000-fffff in 16k blocks. System board ROM can be mapped here */
if (cs8230->regs[0xe + (c >> 3)] & (1 << (c & 7)))
mem_set_mem_state(0xc0000 + (c << 14), 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); /* I/O channel */
else
shadow_control(0xc0000 + (c << 14), 0x4000, (cs8230->regs[9] >> (3 - (c >> 2))) & 0x11);
for (uint8_t c = 0; c < 16; c++) {
/* Addresses c0000-fffff in 16k blocks. System board ROM can be mapped here */
if (cs8230->regs[0xe + (c >> 3)] & (1 << (c & 7)))
mem_set_mem_state(0xc0000 + (c << 14), 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY); /* I/O channel */
else
shadow_control(0xc0000 + (c << 14), 0x4000, (cs8230->regs[9] >> (3 - (c >> 2))) & 0x11);
}
}
static uint8_t
cs8230_read(uint16_t port, void *p)
cs8230_read(uint16_t port, void *priv)
{
cs8230_t *cs8230 = (cs8230_t *) p;
uint8_t ret = 0xff;
const cs8230_t *cs8230 = (cs8230_t *) priv;
uint8_t ret = 0xff;
if (port & 1) {
switch (cs8230->idx) {
case 0x04: /* 82C301 ID/version */
ret = cs8230->regs[cs8230->idx] & ~0xe3;
break;
switch (cs8230->idx) {
case 0x04: /* 82C301 ID/version */
ret = cs8230->regs[cs8230->idx] & ~0xe3;
break;
case 0x08: /* 82C302 ID/Version */
ret = cs8230->regs[cs8230->idx] & ~0xe0;
break;
case 0x08: /* 82C302 ID/Version */
ret = cs8230->regs[cs8230->idx] & ~0xe0;
break;
case 0x05: case 0x06: /* 82C301 registers */
case 0x09: case 0x0a: case 0x0b: case 0x0c: /* 82C302 registers */
case 0x0d: case 0x0e: case 0x0f:
case 0x10: case 0x11: case 0x12: case 0x13:
case 0x28: case 0x29: case 0x2a:
ret = cs8230->regs[cs8230->idx];
break;
}
case 0x05:
case 0x06: /* 82C301 registers */
case 0x09:
case 0x0a:
case 0x0b:
case 0x0c: /* 82C302 registers */
case 0x0d:
case 0x0e:
case 0x0f:
case 0x10:
case 0x11:
case 0x12:
case 0x13:
case 0x28:
case 0x29:
case 0x2a:
ret = cs8230->regs[cs8230->idx];
break;
default:
break;
}
}
return ret;
}
static void
cs8230_write(uint16_t port, uint8_t val, void *p)
cs8230_write(uint16_t port, uint8_t val, void *priv)
{
cs8230_t *cs8230 = (cs8230_t *)p;
cs8230_t *cs8230 = (cs8230_t *) priv;
if (!(port & 1))
cs8230->idx = val;
cs8230->idx = val;
else {
cs8230->regs[cs8230->idx] = val;
switch (cs8230->idx) {
case 0x09: /* RAM/ROM Configuration in boot area */
case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: /* Address maps */
rethink_shadow_mappings(cs8230);
break;
}
cs8230->regs[cs8230->idx] = val;
switch (cs8230->idx) {
case 0x09: /* RAM/ROM Configuration in boot area */
case 0x0a:
case 0x0b:
case 0x0c:
case 0x0d:
case 0x0e:
case 0x0f: /* Address maps */
rethink_shadow_mappings(cs8230);
break;
default:
break;
}
}
}
static void
cs8230_close(void *priv)
{
cs8230_t *cs8230 = (cs8230_t *)priv;
cs8230_t *cs8230 = (cs8230_t *) priv;
free(cs8230);
}
static void
*cs8230_init(const device_t *info)
static void *
cs8230_init(UNUSED(const device_t *info))
{
cs8230_t *cs8230 = (cs8230_t *)malloc(sizeof(cs8230_t));
cs8230_t *cs8230 = (cs8230_t *) malloc(sizeof(cs8230_t));
memset(cs8230, 0, sizeof(cs8230_t));
io_sethandler(0x0022, 0x0002, cs8230_read, NULL, NULL, cs8230_write, NULL, NULL, cs8230);
if (mem_size > 768) {
mem_mapping_set_addr(&ram_mid_mapping, 0xa0000, mem_size > 1024 ? 0x60000 : 0x20000 + (mem_size - 768) * 1024);
mem_mapping_set_exec(&ram_mid_mapping, ram + 0xa0000);
mem_mapping_set_addr(&ram_mid_mapping, 0xa0000, mem_size > 1024 ? 0x60000 : 0x20000 + (mem_size - 768) * 1024);
mem_mapping_set_exec(&ram_mid_mapping, ram + 0xa0000);
}
return cs8230;
}
const device_t cs8230_device = {
"C&T CS8230 (386/AT)",
"cs8230",
0,
0,
cs8230_init, cs8230_close, NULL,
{ NULL }, NULL, NULL,
NULL
.name = "C&T CS8230 (386/AT)",
.internal_name = "cs8230",
.flags = 0,
.local = 0,
.init = cs8230_init,
.close = cs8230_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -1,19 +1,19 @@
/*
* 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.
*
* Implementation of the ETEQ Cheetah ET6000 chipset.
* Implementation of the ETEQ Cheetah ET6000 chipset.
*
* Authors: Tiseno100
*
* Copyright 2021 Tiseno100
*
* Authors: Tiseno100
*
* Copyright 2021 Tiseno100
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
@@ -28,35 +28,37 @@
#include <86box/device.h>
#include <86box/mem.h>
#include <86box/pit.h>
#include <86box/plat_unused.h>
#include <86box/port_92.h>
#include <86box/chipset.h>
#define INDEX (dev->index - 0x10)
typedef struct
{
uint8_t index, regs[6];
typedef struct et6000_t {
uint8_t index;
uint8_t regs[256];
} et6000_t;
#ifdef ENABLE_ET6000_LOG
int et6000_do_log = ENABLE_ET6000_LOG;
static void
et6000_log(const char *fmt, ...)
{
va_list ap;
if (et6000_do_log)
{
if (et6000_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define et6000_log(fmt, ...)
# define et6000_log(fmt, ...)
#endif
static void et6000_shadow_control(int base, int size, int can_read, int can_write)
static void
et6000_shadow_control(int base, int size, int can_read, int can_write)
{
mem_set_mem_state_both(base, size, (can_read ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | (can_write ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY));
flushmmucache_nopc();
@@ -65,57 +67,61 @@ static void et6000_shadow_control(int base, int size, int can_read, int can_writ
static void
et6000_write(uint16_t addr, uint8_t val, void *priv)
{
et6000_t *dev = (et6000_t *)priv;
et6000_t *dev = (et6000_t *) priv;
switch (addr)
{
case 0x22:
dev->index = val;
break;
case 0x23:
switch (INDEX)
{
case 0: /* System Configuration Register */
dev->regs[INDEX] = val & 0xdf;
et6000_shadow_control(0xa0000, 0x20000, val & 1, val & 1);
refresh_at_enable = !(val & 0x10);
switch (addr) {
case 0x22:
dev->index = val;
break;
case 0x23:
switch (INDEX) {
case 0: /* System Configuration Register */
dev->regs[INDEX] = val & 0xdf;
et6000_shadow_control(0xa0000, 0x20000, val & 1, val & 1);
refresh_at_enable = !(val & 0x10);
break;
case 1: /* CACHE Configuration and Non-Cacheable Block Size */
dev->regs[INDEX] = val & 0xf0;
break;
case 2: /* Non-Cacheable Block Address Register */
dev->regs[INDEX] = val & 0xfe;
break;
case 3: /* DRAM Bank and Type Configuration Register */
dev->regs[INDEX] = val;
break;
case 4: /* DRAM Configuration Register */
dev->regs[INDEX] = val;
et6000_shadow_control(0xc0000, 0x10000, (dev->regs[0x15] & 2) && (val & 0x20), (dev->regs[0x15] & 2) && (val & 0x20) && (dev->regs[0x15] & 1));
et6000_shadow_control(0xd0000, 0x10000, (dev->regs[0x15] & 8) && (val & 0x20), (dev->regs[0x15] & 8) && (val & 0x20) && (dev->regs[0x15] & 4));
break;
case 5: /* Shadow RAM Configuration Register */
dev->regs[INDEX] = val;
et6000_shadow_control(0xc0000, 0x10000, (val & 2) && (dev->regs[0x14] & 0x20), (val & 2) && (dev->regs[0x14] & 0x20) && (val & 1));
et6000_shadow_control(0xd0000, 0x10000, (val & 8) && (dev->regs[0x14] & 0x20), (val & 8) && (dev->regs[0x14] & 0x20) && (val & 4));
et6000_shadow_control(0xe0000, 0x10000, val & 0x20, (val & 0x20) && (val & 0x10));
et6000_shadow_control(0xf0000, 0x10000, val & 0x40, !(val & 0x40));
break;
default:
break;
}
et6000_log("ET6000: dev->regs[%02x] = %02x\n", dev->index, dev->regs[dev->index]);
break;
case 1: /* CACHE Configuration and Non-Cacheable Block Size */
dev->regs[INDEX] = val & 0xf0;
default:
break;
case 2: /* Non-Cacheable Block Address Register */
dev->regs[INDEX] = val & 0xfe;
break;
case 3: /* DRAM Bank and Type Configuration Register */
dev->regs[INDEX] = val;
break;
case 4: /* DRAM Configuration Register */
dev->regs[INDEX] = val;
et6000_shadow_control(0xc0000, 0x10000, (dev->regs[0x15] & 2) && (val & 0x20), (dev->regs[0x15] & 2) && (val & 0x20) && (dev->regs[0x15] & 1));
et6000_shadow_control(0xd0000, 0x10000, (dev->regs[0x15] & 8) && (val & 0x20), (dev->regs[0x15] & 8) && (val & 0x20) && (dev->regs[0x15] & 4));
break;
case 5: /* Shadow RAM Configuration Register */
dev->regs[INDEX] = val;
et6000_shadow_control(0xc0000, 0x10000, (val & 2) && (dev->regs[0x14] & 0x20), (val & 2) && (dev->regs[0x14] & 0x20) && (val & 1));
et6000_shadow_control(0xd0000, 0x10000, (val & 8) && (dev->regs[0x14] & 0x20), (val & 8) && (dev->regs[0x14] & 0x20) && (val & 4));
et6000_shadow_control(0xe0000, 0x10000, val & 0x20, (val & 0x20) && (val & 0x10));
et6000_shadow_control(0xf0000, 0x10000, val & 0x40, !(val & 0x40));
break;
}
et6000_log("ET6000: dev->regs[%02x] = %02x\n", dev->index, dev->regs[dev->index]);
break;
}
}
static uint8_t
et6000_read(uint16_t addr, void *priv)
{
et6000_t *dev = (et6000_t *)priv;
const et6000_t *dev = (et6000_t *) priv;
return ((addr == 0x23) && (INDEX >= 0) && (INDEX <= 5)) ? dev->regs[INDEX] : 0xff;
}
@@ -123,15 +129,15 @@ et6000_read(uint16_t addr, void *priv)
static void
et6000_close(void *priv)
{
et6000_t *dev = (et6000_t *)priv;
et6000_t *dev = (et6000_t *) priv;
free(dev);
}
static void *
et6000_init(const device_t *info)
et6000_init(UNUSED(const device_t *info))
{
et6000_t *dev = (et6000_t *)malloc(sizeof(et6000_t));
et6000_t *dev = (et6000_t *) malloc(sizeof(et6000_t));
memset(dev, 0, sizeof(et6000_t));
/* Port 92h */
@@ -149,14 +155,15 @@ et6000_init(const device_t *info)
}
const device_t et6000_device = {
"ETEQ Cheetah ET6000",
"et6000",
0,
0,
et6000_init,
et6000_close,
NULL,
{NULL},
NULL,
NULL,
NULL};
.name = "ETEQ Cheetah ET6000",
.internal_name = "et6000",
.flags = 0,
.local = 0,
.init = et6000_init,
.close = et6000_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -1,19 +1,22 @@
/*
* 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.
*
* Implementation of the G2 GC100/GC100A chipset.
* NOTE: As documentation is currently available only for the
* CG100 chipset, the GC100A chipset has been reverese-engineered.
* Thus, its behavior may not be fully accurate.
* Implementation of the G2 GC100/GC100A chipset.
*
* Authors: EngiNerd, <webmaster.crrc@yahoo.it>
* NOTE: As documentation is currently available only for the
* GC100 chipset, the GC100A chipset has been reverese-engineered.
* Thus, its behavior may not be fully accurate.
*
* Copyright 2020-2021 EngiNerd.
*
*
* Authors: EngiNerd, <webmaster.crrc@yahoo.it>
*
* Copyright 2020-2021 EngiNerd.
*/
#include <stdarg.h>
#include <stdint.h>
@@ -41,13 +44,10 @@
#include <86box/io.h>
#include <86box/video.h>
typedef struct
{
uint8_t reg[0x10];
typedef struct gc100_t {
uint8_t reg[0x10];
} gc100_t;
#ifdef ENABLE_GC100_LOG
int gc100_do_log = ENABLE_GC100_LOG;
@@ -59,143 +59,144 @@ gc100_log(const char *fmt, ...)
if (gc100_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
va_end(ap);
}
}
#else
#define gc100_log(fmt, ...)
# define gc100_log(fmt, ...)
#endif
static uint8_t
get_fdd_switch_settings(void)
{
int i, fdd_count = 0;
for (i = 0; i < FDD_NUM; i++) {
if (fdd_get_flags(i))
fdd_count++;
uint8_t fdd_count = 0;
for (uint8_t i = 0; i < FDD_NUM; i++) {
if (fdd_get_flags(i))
fdd_count++;
}
if (!fdd_count)
return 0x00;
else
return ((fdd_count - 1) << 6) | 0x01;
return ((fdd_count - 1) << 6) | 0x01;
}
static uint8_t
get_videomode_switch_settings(void)
{
if (video_is_mda())
return 0x30;
return 0x30;
else if (video_is_cga())
return 0x20; /* 0x10 would be 40x25 */
return 0x20; /* 0x10 would be 40x25 */
else
return 0x00;
return 0x00;
}
static void
gc100_write(uint16_t port, uint8_t val, void *priv)
{
gc100_t *dev = (gc100_t *) priv;
gc100_t *dev = (gc100_t *) priv;
uint16_t addr = port & 0xf;
dev->reg[addr] = val;
switch (addr) {
/* addr 0x2
* bits 5-7: not used
* bit 4: intenal memory wait states
* bits 2-3: external memory wait states
* bits 0-1: i/o access wait states
*/
case 2:
break;
/* addr 0x2
* bits 5-7: not used
* bit 4: intenal memory wait states
* bits 2-3: external memory wait states
* bits 0-1: i/o access wait states
*/
case 2:
break;
/* addr 0x3
* bits 1-7: not used
* bit 0: turbo 0 xt 1
*/
case 3:
if (val & 1)
cpu_dynamic_switch(0);
else
cpu_dynamic_switch(cpu);
break;
/* addr 0x5
* programmable dip-switches
* bits 6-7: floppy drive number
* bits 4-5: video mode
* bits 2-3: memory size
* bit 1: fpu
* bit 0: not used
*/
/* addr 0x3
* bits 1-7: not used
* bit 0: turbo 0 xt 1
*/
case 3:
if (val & 1)
cpu_dynamic_switch(0);
else
cpu_dynamic_switch(cpu);
break;
/* addr 0x6 */
/* addr 0x5
* programmable dip-switches
* bits 6-7: floppy drive number
* bits 4-5: video mode
* bits 2-3: memory size
* bit 1: fpu
* bit 0: not used
*/
/* addr 0x7 */
/* addr 0x6 */
/* addr 0x7 */
default:
break;
}
gc100_log("GC100: Write %02x at %02x\n", val, port);
}
static uint8_t
gc100_read(uint16_t port, void *priv)
{
gc100_t *dev = (gc100_t *) priv;
uint8_t ret = 0xff;
uint16_t addr = port & 0xf;
const gc100_t *dev = (gc100_t *) priv;
uint8_t ret = 0xff;
uint16_t addr = port & 0xf;
ret = dev->reg[addr];
gc100_log("GC100: Read %02x at %02x\n", ret, port);
switch (addr) {
/* addr 0x2
* bits 5-7: not used
* bit 4: intenal memory wait states
* bits 2-3: external memory wait states
* bits 0-1: i/o access wait states
*/
case 0x2:
break;
/* addr 0x2
* bits 5-7: not used
* bit 4: intenal memory wait states
* bits 2-3: external memory wait states
* bits 0-1: i/o access wait states
*/
case 0x2:
break;
/* addr 0x3
* bits 1-7: not used
* bit 0: turbo 0 xt 1
*/
case 0x3:
break;
/* addr 0x3
* bits 1-7: not used
* bit 0: turbo 0 xt 1
*/
case 0x3:
break;
/* addr 0x5
* programmable dip-switches
* bits 6-7: floppy drive number
* bits 4-5: video mode
* bits 2-3: memory size
* bit 1: fpu
* bit 0: not used
*/
case 0x5:
ret = ret & 0x0c;
ret |= get_fdd_switch_settings();
ret |= get_videomode_switch_settings();
if (hasfpu)
ret |= 0x02;
break;
/* addr 0x5
* programmable dip-switches
* bits 6-7: floppy drive number
* bits 4-5: video mode
* bits 2-3: memory size
* bit 1: fpu
* bit 0: not used
*/
case 0x5:
ret = ret & 0x0c;
ret |= get_fdd_switch_settings();
ret |= get_videomode_switch_settings();
if (hasfpu)
ret |= 0x02;
break;
/* addr 0x6 */
/* addr 0x6 */
/* addr 0x7 */
/* addr 0x7 */
default:
break;
}
return ret;
}
static void
gc100_close(void *priv)
{
@@ -204,7 +205,6 @@ gc100_close(void *priv)
free(dev);
}
static void *
gc100_init(const device_t *info)
{
@@ -216,37 +216,44 @@ gc100_init(const device_t *info)
dev->reg[0x5] = 0x0;
dev->reg[0x6] = 0x0;
dev->reg[0x7] = 0x0;
if (info->local) {
/* GC100A */
/* GC100A */
io_sethandler(0x0c2, 0x02, gc100_read, NULL, NULL, gc100_write, NULL, NULL, dev);
io_sethandler(0x0c5, 0x03, gc100_read, NULL, NULL, gc100_write, NULL, NULL, dev);
} else {
/* GC100 */
/* GC100 */
io_sethandler(0x022, 0x02, gc100_read, NULL, NULL, gc100_write, NULL, NULL, dev);
io_sethandler(0x025, 0x01, gc100_read, NULL, NULL, gc100_write, NULL, NULL, dev);
}
return dev;
}
const device_t gc100_device = {
"G2 GC100",
"gc100",
0,
0,
gc100_init, gc100_close, NULL,
{ NULL }, NULL, NULL,
NULL
.name = "G2 GC100",
.internal_name = "gc100",
.flags = 0,
.local = 0,
.init = gc100_init,
.close = gc100_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t gc100a_device = {
"G2 GC100A",
"gc100a",
0,
1,
gc100_init, gc100_close, NULL,
{ NULL }, NULL, NULL,
NULL
.name = "G2 GC100A",
.internal_name = "gc100a",
.flags = 0,
.local = 1,
.init = gc100_init,
.close = gc100_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

@@ -1,20 +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.
* 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.
*
* Implementation of the IMS 8848/8849 chipset.
* Implementation of the IMS 8848/8849 chipset.
*
*
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Tiseno100,
* Authors: Miran Grca, <mgrca8@gmail.com>
* Tiseno100,
*
* Copyright 2021 Miran Grca.
* Copyright 2021 Tiseno100.
* Copyright 2021 Miran Grca.
* Copyright 2021 Tiseno100.
*/
#include <stdarg.h>
#include <stdint.h>
@@ -30,10 +30,11 @@
#include <86box/mem.h>
#include <86box/smram.h>
#include <86box/pci.h>
#include <86box/pic.h>
#include <86box/plat_unused.h>
#include <86box/port_92.h>
#include <86box/chipset.h>
/*
IMS 884x Configuration Registers
@@ -42,158 +43,156 @@
By: Tiseno100, Miran Grca(OBattler)
Register 00h:
Bit 3: F0000-FFFFF Shadow Enable
Bit 2: E0000-EFFFF Shadow Enable
Bit 0: ????
Bit 3: F0000-FFFFF Shadow Enable
Bit 2: E0000-EFFFF Shadow Enable
Bit 0: ????
Register 04h:
Bit 3: Cache Write Hit Wait State
Bit 2: Cache Read Hit Wait State
Bit 3: Cache Write Hit Wait State
Bit 2: Cache Read Hit Wait State
Register 06h:
Bit 3: System BIOS Cacheable (1: Yes / 0: No)
Bit 1: Power Management Mode (1: IRQ / 0: SMI#)
Bit 3: System BIOS Cacheable (1: Yes / 0: No)
Bit 1: Power Management Mode (1: IRQ / 0: SMI#)
Register 08h:
Bit 2: System BIOS Shadow Write (1: Enable / 0: Disable)
Bit 1: System BIOS Shadow Read?
Bit 2: System BIOS Shadow Write (1: Enable / 0: Disable)
Bit 1: System BIOS Shadow Read?
Register 0Dh:
Bit 0: IO 100H-3FFH Idle Detect (1: Enable / 0: Disable)
Bit 0: IO 100H-3FFH Idle Detect (1: Enable / 0: Disable)
Register 0Eh:
Bit 7: DMA & Local Bus Idle Detect (1: Enable / 0: Disable)
Bit 6: Floppy Disk Idle Detect (1: Enable / 0: Disable)
Bit 5: IDE Idle Detect (1: Enable / 0: Disable)
Bit 4: Serial Port Idle Detect (1: Enable / 0: Disable)
Bit 3: Parallel Port Idle Detect (1: Enable / 0: Disable)
Bit 2: Keyboard Idle Detect (1: Enable / 0: Disable)
Bit 1: Video Idle Detect (1: Enable / 0: Disable)
Bit 7: DMA & Local Bus Idle Detect (1: Enable / 0: Disable)
Bit 6: Floppy Disk Idle Detect (1: Enable / 0: Disable)
Bit 5: IDE Idle Detect (1: Enable / 0: Disable)
Bit 4: Serial Port Idle Detect (1: Enable / 0: Disable)
Bit 3: Parallel Port Idle Detect (1: Enable / 0: Disable)
Bit 2: Keyboard Idle Detect (1: Enable / 0: Disable)
Bit 1: Video Idle Detect (1: Enable / 0: Disable)
Register 12h:
Bits 3-2: Power Saving Timer (00 = 1 MIN, 01 = 3 MIN, 10 = 5 MIN, 11 = 8 MIN)
Bit 1: Base Memory (1: 512KB / 0: 640KB)
Bits 3-2: Power Saving Timer (00 = 1 MIN, 01 = 3 MIN, 10 = 5 MIN, 11 = 8 MIN)
Bit 1: Base Memory (1: 512KB / 0: 640KB)
Register 1Ah:
Bit 3: Cache Write Hit W/S For PCI (1: Enabled / 0: Disable)
Bit 2: Cache Read Hit W/S For PCI (1: Enabled / 0: Disable)
Bit 1: VESA Clock Skew (1: 4ns/6ns, 0: No Delay/2ns)
Bit 3: Cache Write Hit W/S For PCI (1: Enabled / 0: Disable)
Bit 2: Cache Read Hit W/S For PCI (1: Enabled / 0: Disable)
Bit 1: VESA Clock Skew (1: 4ns/6ns, 0: No Delay/2ns)
Register 1Bh:
Bit 6: Enable SMRAM (always at 30000-4FFFF) in SMM
Bit 5: ????
Bit 4: Software SMI#
Bit 3: DC000-DFFFF Shadow Enable
Bit 2: D8000-DBFFF Shadow Enable
Bit 1: D4000-D7FFF Shadow Enable
Bit 0: D0000-D3FFF Shadow Enable
Bit 6: Enable SMRAM (always at 30000-4FFFF) in SMM
Bit 5: ????
Bit 4: Software SMI#
Bit 3: DC000-DFFFF Shadow Enable
Bit 2: D8000-DBFFF Shadow Enable
Bit 1: D4000-D7FFF Shadow Enable
Bit 0: D0000-D3FFF Shadow Enable
Register 1Ch:
Bits 7-4: INTA IRQ routing (0 = disabled, 1 to F = IRQ)
Bit 3: CC000-CFFFF Shadow Enable
Bit 2: C8000-CBFFF Shadow Enable
Bit 1: C4000-C7FFF Shadow Enable
Bit 0: C0000-C3FFF Shadow Enable
Bits 7-4: INTA IRQ routing (0 = disabled, 1 to F = IRQ)
Bit 3: CC000-CFFFF Shadow Enable
Bit 2: C8000-CBFFF Shadow Enable
Bit 1: C4000-C7FFF Shadow Enable
Bit 0: C0000-C3FFF Shadow Enable
Register 1Dh:
Bits 7-4: INTB IRQ routing (0 = disabled, 1 to F = IRQ)
Bits 7-4: INTB IRQ routing (0 = disabled, 1 to F = IRQ)
Register 1Eh:
Bits 7-4: INTC IRQ routing (0 = disabled, 1 to F = IRQ)
Bit 1: C4000-C7FFF Cacheable
Bit 0: C0000-C3FFF Cacheable
Bits 7-4: INTC IRQ routing (0 = disabled, 1 to F = IRQ)
Bit 1: C4000-C7FFF Cacheable
Bit 0: C0000-C3FFF Cacheable
Register 21h:
Bits 7-4: INTD IRQ routing (0 = disabled, 1 to F = IRQ)
Bits 7-4: INTD IRQ routing (0 = disabled, 1 to F = IRQ)
Register 22h:
Bit 5: Local Bus Master #2 select (0 = VESA, 1 = PCI)
Bit 4: Local Bus Master #1 select (0 = VESA, 1 = PCI)
Bits 1-0: Internal HADS# Delay Always (00 = No Delay, 01 = 1 Clk, 10 = 2 Clks)
Bit 5: Local Bus Master #2 select (0 = VESA, 1 = PCI)
Bit 4: Local Bus Master #1 select (0 = VESA, 1 = PCI)
Bits 1-0: Internal HADS# Delay Always (00 = No Delay, 01 = 1 Clk, 10 = 2 Clks)
Register 23h:
Bit 7: Seven Bits Tag (1: Enabled / 0: Disable)
Bit 3: Extend LBRDY#(VL Master) (1: Enabled / 0: Disable)
Bit 2: Sync LRDY#(VL Slave) (1: Enabled / 0: Disable)
Bit 0: HADS# Delay After LB. Cycle (1: Enabled / 0: Disable)
Bit 7: Seven Bits Tag (1: Enabled / 0: Disable)
Bit 3: Extend LBRDY#(VL Master) (1: Enabled / 0: Disable)
Bit 2: Sync LRDY#(VL Slave) (1: Enabled / 0: Disable)
Bit 0: HADS# Delay After LB. Cycle (1: Enabled / 0: Disable)
*/
typedef struct
{
uint8_t idx, access_data,
regs[256], pci_conf[256];
typedef struct ims8848_t {
uint8_t idx;
uint8_t access_data;
uint8_t pci_slot;
uint8_t pad;
smram_t *smram;
uint8_t regs[256];
uint8_t pci_conf[256];
smram_t *smram;
} ims8848_t;
#ifdef ENABLE_IMS8848_LOG
int ims8848_do_log = ENABLE_IMS8848_LOG;
static void
ims8848_log(const char *fmt, ...)
{
va_list ap;
if (ims8848_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define ims8848_log(fmt, ...)
# define ims8848_log(fmt, ...)
#endif
/* Shadow write always enabled, 1B and 1C control C000-DFFF read. */
static void
ims8848_recalc(ims8848_t *dev)
{
int i, state_on;
int state_on;
uint32_t base;
ims8848_log("SHADOW: 00 = %02X, 08 = %02X, 1B = %02X, 1C = %02X\n",
dev->regs[0x00], dev->regs[0x08], dev->regs[0x1b], dev->regs[0x1c]);
dev->regs[0x00], dev->regs[0x08], dev->regs[0x1b], dev->regs[0x1c]);
state_on = MEM_READ_INTERNAL;
state_on |= (dev->regs[0x08] & 0x04) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
for (i = 0; i < 2; i++) {
base = 0xe0000 + (i << 16);
if (dev->regs[0x00] & (1 << (i + 2)))
mem_set_mem_state_both(base, 0x10000, state_on);
else
mem_set_mem_state_both(base, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
for (uint8_t i = 0; i < 2; i++) {
base = 0xe0000 + (i << 16);
if (dev->regs[0x00] & (1 << (i + 2)))
mem_set_mem_state_both(base, 0x10000, state_on);
else
mem_set_mem_state_both(base, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
}
for (i = 0; i < 4; i++) {
base = 0xc0000 + (i << 14);
if (dev->regs[0x1c] & (1 << i))
mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
else
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
for (uint8_t i = 0; i < 4; i++) {
base = 0xc0000 + (i << 14);
if (dev->regs[0x1c] & (1 << i))
mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
else
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
base = 0xd0000 + (i << 14);
if (dev->regs[0x1b] & (1 << i))
mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
else
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
base = 0xd0000 + (i << 14);
if (dev->regs[0x1b] & (1 << i))
mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
else
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
}
flushmmucache_nopc();
}
static void
ims8848_base_memory(ims8848_t *dev)
{
/* We can use the proper mem_set_access to handle that. */
mem_set_mem_state_both(0x80000, 0x20000, (dev->regs[0x12] & 2) ?
(MEM_READ_DISABLED | MEM_WRITE_DISABLED) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL));
mem_set_mem_state_both(0x80000, 0x20000, (dev->regs[0x12] & 2) ? (MEM_READ_DISABLED | MEM_WRITE_DISABLED) : (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL));
}
static void
ims8848_smram(ims8848_t *dev)
{
@@ -202,137 +201,148 @@ ims8848_smram(ims8848_t *dev)
smram_enable(dev->smram, 0x00030000, 0x00030000, 0x20000, dev->regs[0x1b] & 0x40, 1);
}
static void
ims8848_write(uint16_t addr, uint8_t val, void *priv)
{
ims8848_t *dev = (ims8848_t *) priv;
uint8_t old = dev->regs[dev->idx];
uint8_t old = dev->regs[dev->idx];
switch (addr) {
case 0x22:
ims8848_log("[W] IDX = %02X\n", val);
dev->idx = val;
break;
case 0x23:
ims8848_log("[W] IDX IN = %02X\n", val);
if (((val & 0x0f) == ((dev->idx >> 4) & 0x0f)) && ((val & 0xf0) == ((dev->idx << 4) & 0xf0)))
dev->access_data = 1;
break;
case 0x24:
ims8848_log("[W] [%i] REG %02X = %02X\n", dev->access_data, dev->idx, val);
if (dev->access_data) {
dev->regs[dev->idx] = val;
switch (dev->idx) {
case 0x00: case 0x08: case 0x1b: case 0x1c:
/* Shadow RAM */
ims8848_recalc(dev);
if (dev->idx == 0x1b) {
ims8848_smram(dev);
if (!(old & 0x10) && (val & 0x10))
smi_line = 1;
} else if (dev->idx == 0x1c)
pci_set_irq_routing(PCI_INTA, (val >> 4) ? (val >> 4) : PCI_IRQ_DISABLED);
break;
case 0x22:
ims8848_log("[W] IDX = %02X\n", val);
dev->idx = val;
break;
case 0x23:
ims8848_log("[W] IDX IN = %02X\n", val);
if (((val & 0x0f) == ((dev->idx >> 4) & 0x0f)) && ((val & 0xf0) == ((dev->idx << 4) & 0xf0)))
dev->access_data = 1;
break;
case 0x24:
ims8848_log("[W] [%i] REG %02X = %02X\n", dev->access_data, dev->idx, val);
if (dev->access_data) {
dev->regs[dev->idx] = val;
switch (dev->idx) {
case 0x00:
case 0x08:
case 0x1b:
case 0x1c:
/* Shadow RAM */
ims8848_recalc(dev);
if (dev->idx == 0x1b) {
ims8848_smram(dev);
if (!(old & 0x10) && (val & 0x10))
smi_raise();
} else if (dev->idx == 0x1c)
pci_set_irq_routing(PCI_INTA, (val >> 4) ? (val >> 4) : PCI_IRQ_DISABLED);
break;
case 0x1d: case 0x1e:
pci_set_irq_routing(PCI_INTB + (dev->idx - 0x1d), (val >> 4) ? (val >> 4) : PCI_IRQ_DISABLED);
break;
case 0x21:
pci_set_irq_routing(PCI_INTD, (val >> 4) ? (val >> 4) : PCI_IRQ_DISABLED);
break;
case 0x1d:
case 0x1e:
pci_set_irq_routing(PCI_INTB + (dev->idx - 0x1d), (val >> 4) ? (val >> 4) : PCI_IRQ_DISABLED);
break;
case 0x21:
pci_set_irq_routing(PCI_INTD, (val >> 4) ? (val >> 4) : PCI_IRQ_DISABLED);
break;
case 0x12:
/* Base Memory */
ims8848_base_memory(dev);
break;
}
dev->access_data = 0;
}
break;
case 0x12:
/* Base Memory */
ims8848_base_memory(dev);
break;
default:
break;
}
dev->access_data = 0;
}
break;
default:
break;
}
}
static uint8_t
ims8848_read(uint16_t addr, void *priv)
{
uint8_t ret = 0xff;
uint8_t ret = 0xff;
ims8848_t *dev = (ims8848_t *) priv;
#ifdef ENABLE_IMS8848_LOG
uint8_t old_ad = dev->access_data;
#endif
switch (addr) {
case 0x22:
ims8848_log("[R] IDX = %02X\n", ret);
ret = dev->idx;
break;
case 0x23:
ims8848_log("[R] IDX IN = %02X\n", ret);
ret = (dev->idx >> 4) | (dev->idx << 4);
break;
case 0x24:
if (dev->access_data) {
ret = dev->regs[dev->idx];
dev->access_data = 0;
}
ims8848_log("[R] [%i] REG %02X = %02X\n", old_ad, dev->idx, ret);
break;
case 0x22:
ims8848_log("[R] IDX = %02X\n", ret);
ret = dev->idx;
break;
case 0x23:
ims8848_log("[R] IDX IN = %02X\n", ret);
ret = (dev->idx >> 4) | (dev->idx << 4);
break;
case 0x24:
if (dev->access_data) {
ret = dev->regs[dev->idx];
dev->access_data = 0;
}
ims8848_log("[R] [%i] REG %02X = %02X\n", old_ad, dev->idx, ret);
break;
default:
break;
}
return ret;
}
static void
ims8849_pci_write(int func, int addr, uint8_t val, void *priv)
{
ims8848_t *dev = (ims8848_t *)priv;
ims8848_t *dev = (ims8848_t *) priv;
ims8848_log("IMS 884x-PCI: dev->regs[%02x] = %02x POST: %02x\n", addr, val, inb(0x80));
if (func == 0) switch (addr) {
case 0x04:
dev->pci_conf[addr] = val;
break;
if (func == 0)
switch (addr) {
case 0x04:
dev->pci_conf[addr] = val;
break;
case 0x05:
dev->pci_conf[addr] = val & 3;
break;
case 0x05:
dev->pci_conf[addr] = val & 3;
break;
case 0x07:
dev->pci_conf[addr] &= val & 0xf7;
break;
case 0x07:
dev->pci_conf[addr] &= val & 0xf7;
break;
case 0x0c ... 0x0d:
dev->pci_conf[addr] = val;
break;
case 0x0c ... 0x0d:
dev->pci_conf[addr] = val;
break;
case 0x52 ... 0x55:
dev->pci_conf[addr] = val;
break;
}
case 0x52 ... 0x55:
dev->pci_conf[addr] = val;
break;
default:
break;
}
}
static uint8_t
ims8849_pci_read(int func, int addr, void *priv)
{
ims8848_t *dev = (ims8848_t *)priv;
uint8_t ret = 0xff;
const ims8848_t *dev = (ims8848_t *) priv;
uint8_t ret = 0xff;
if (func == 0)
ret = dev->pci_conf[addr];
ret = dev->pci_conf[addr];
return ret;
}
static void
ims8848_reset(void *priv)
{
ims8848_t *dev = (ims8848_t *)priv;
ims8848_t *dev = (ims8848_t *) priv;
memset(dev->regs, 0x00, sizeof(dev->regs));
memset(dev->pci_conf, 0x00, sizeof(dev->pci_conf));
@@ -347,7 +357,7 @@ ims8848_reset(void *priv)
dev->pci_conf[0x0b] = 0x06;
ims8848_recalc(dev); /* Shadow RAM Setup */
ims8848_recalc(dev); /* Shadow RAM Setup */
ims8848_base_memory(dev); /* Base Memory Setup */
pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED);
@@ -358,7 +368,6 @@ ims8848_reset(void *priv)
ims8848_smram(dev);
}
static void
ims8848_close(void *priv)
{
@@ -369,9 +378,8 @@ ims8848_close(void *priv)
free(dev);
}
static void *
ims8848_init(const device_t *info)
ims8848_init(UNUSED(const device_t *info))
{
ims8848_t *dev = (ims8848_t *) malloc(sizeof(ims8848_t));
memset(dev, 0, sizeof(ims8848_t));
@@ -379,15 +387,15 @@ ims8848_init(const device_t *info)
device_add(&port_92_device);
/* IMS 8848:
22h Index
23h Data Unlock
24h Data
22h Index
23h Data Unlock
24h Data
IMS 8849:
PCI Device 0: IMS 8849 Dummy for compatibility reasons
PCI Device 0: IMS 8849 Dummy for compatibility reasons
*/
io_sethandler(0x0022, 0x0003, ims8848_read, NULL, NULL, ims8848_write, NULL, NULL, dev);
pci_add_card(PCI_ADD_NORTHBRIDGE, ims8849_pci_read, ims8849_pci_write, dev);
pci_add_card(PCI_ADD_NORTHBRIDGE, ims8849_pci_read, ims8849_pci_write, dev, &dev->pci_slot);
dev->smram = smram_add();
smram_set_separate_smram(1);
@@ -400,13 +408,16 @@ ims8848_init(const device_t *info)
return dev;
}
const device_t ims8848_device = {
"IMS 8848/8849",
"ims8848",
0,
0,
ims8848_init, ims8848_close, ims8848_reset,
{ NULL }, NULL, NULL,
NULL
.name = "IMS 8848/8849",
.internal_name = "ims8848",
.flags = 0,
.local = 0,
.init = ims8848_init,
.close = ims8848_close,
.reset = ims8848_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -1,24 +1,30 @@
/*
* 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.
*
* Emulation of Intel 82420EX chipset that acts as both the
* northbridge and the southbridge.
* This file is part of the 86Box distribution.
*
* Emulation of Intel 82420EX chipset that acts as both the
* northbridge and the southbridge.
*
*
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2020 Miran Grca.
* Copyright 2020 Miran Grca.
*/
#define USE_DRB_HACK
#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/device.h>
#include <86box/io.h>
#include <86box/apm.h>
@@ -26,81 +32,86 @@
#include <86box/mem.h>
#include <86box/smram.h>
#include <86box/pci.h>
#include <86box/pic.h>
#include <86box/timer.h>
#include <86box/pit.h>
#include <86box/plat_unused.h>
#include <86box/port_92.h>
#include <86box/hdc_ide.h>
#include <86box/hdc.h>
#include <86box/machine.h>
#include <86box/chipset.h>
#include <86box/spd.h>
#ifndef USE_DRB_HACK
#include <86box/row.h>
#endif
#define MEM_STATE_SHADOW_R 0x01
#define MEM_STATE_SHADOW_W 0x02
#define MEM_STATE_SMRAM 0x04
#define MEM_STATE_SHADOW_R 0x01
#define MEM_STATE_SHADOW_W 0x02
#define MEM_STATE_SMRAM 0x04
typedef struct i420ex_t {
uint8_t has_ide;
uint8_t smram_locked;
uint8_t pci_slot;
uint8_t pad;
uint8_t regs[256];
typedef struct
{
uint8_t has_ide, smram_locked,
regs[256];
uint16_t timer_base;
uint16_t timer_latch;
uint16_t timer_base,
timer_latch;
smram_t *smram;
smram_t *smram;
double fast_off_period;
double fast_off_period;
pc_timer_t timer;
pc_timer_t fast_off_timer;
pc_timer_t timer, fast_off_timer;
apm_t * apm;
port_92_t * port_92;
apm_t *apm;
port_92_t *port_92;
} i420ex_t;
#ifdef ENABLE_I420EX_LOG
int i420ex_do_log = ENABLE_I420EX_LOG;
static void
i420ex_log(const char *fmt, ...)
{
va_list ap;
if (i420ex_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define i420ex_log(fmt, ...)
# define i420ex_log(fmt, ...)
#endif
static void
i420ex_map(uint32_t addr, uint32_t size, int state)
{
switch (state & 3) {
case 0:
mem_set_mem_state_both(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
break;
case 1:
mem_set_mem_state_both(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY);
break;
case 2:
mem_set_mem_state_both(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
break;
case 3:
mem_set_mem_state_both(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
break;
case 0:
mem_set_mem_state_both(addr, size, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
break;
case 1:
mem_set_mem_state_both(addr, size, MEM_READ_INTERNAL | MEM_WRITE_EXTANY);
break;
case 2:
mem_set_mem_state_both(addr, size, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
break;
case 3:
mem_set_mem_state_both(addr, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
break;
default:
break;
}
flushmmucache_nopc();
}
static void
i420ex_smram_handler_phase0(void)
{
@@ -108,51 +119,70 @@ i420ex_smram_handler_phase0(void)
smram_disable_all();
}
static void
i420ex_smram_handler_phase1(i420ex_t *dev)
{
uint8_t *regs = (uint8_t *) dev->regs;
const uint8_t *regs = (uint8_t *) dev->regs;
uint32_t host_base = 0x000a0000, ram_base = 0x000a0000;
uint32_t size = 0x00010000;
uint32_t host_base = 0x000a0000;
uint32_t ram_base = 0x000a0000;
uint32_t size = 0x00010000;
switch (regs[0x70] & 0x07) {
case 0: case 1:
default:
host_base = ram_base = 0x00000000;
size = 0x00000000;
break;
case 2:
host_base = 0x000a0000;
ram_base = 0x000a0000;
break;
case 3:
host_base = 0x000b0000;
ram_base = 0x000b0000;
break;
case 4:
host_base = 0x000c0000;
ram_base = 0x000a0000;
break;
case 5:
host_base = 0x000d0000;
ram_base = 0x000a0000;
break;
case 6:
host_base = 0x000e0000;
ram_base = 0x000a0000;
break;
case 7:
host_base = 0x000f0000;
ram_base = 0x000a0000;
break;
default:
case 0:
case 1:
host_base = ram_base = 0x00000000;
size = 0x00000000;
break;
case 2:
host_base = 0x000a0000;
ram_base = 0x000a0000;
break;
case 3:
host_base = 0x000b0000;
ram_base = 0x000b0000;
break;
case 4:
host_base = 0x000c0000;
ram_base = 0x000a0000;
break;
case 5:
host_base = 0x000d0000;
ram_base = 0x000a0000;
break;
case 6:
host_base = 0x000e0000;
ram_base = 0x000a0000;
break;
case 7:
host_base = 0x000f0000;
ram_base = 0x000a0000;
break;
}
smram_enable(dev->smram, host_base, ram_base, size,
(regs[0x70] & 0x70) == 0x40, !(regs[0x70] & 0x20));
(regs[0x70] & 0x70) == 0x40, !(regs[0x70] & 0x20));
}
#ifndef USE_DRB_HACK
static void
i420ex_drb_recalc(i420ex_t *dev)
{
uint32_t boundary;
for (int8_t i = 4; i >= 0; i--)
row_disable(i);
for (uint8_t i = 0; i <= 4; i++) {
boundary = ((uint32_t) dev->regs[0x60 + i]) & 0xff;
row_set_boundary(i, boundary);
}
flushmmucache();
}
#endif
static void
i420ex_write(int func, int addr, uint8_t val, void *priv)
@@ -160,206 +190,219 @@ i420ex_write(int func, int addr, uint8_t val, void *priv)
i420ex_t *dev = (i420ex_t *) priv;
if (func > 0)
return;
return;
if (((addr >= 0x0f) && (addr < 0x4c)) && (addr != 0x40))
return;
return;
switch (addr) {
case 0x05:
dev->regs[addr] = (val & 0x01);
break;
case 0x05:
dev->regs[addr] = (val & 0x01);
break;
case 0x07:
dev->regs[addr] &= ~(val & 0xf0);
break;
case 0x07:
dev->regs[addr] &= ~(val & 0xf0);
break;
case 0x40:
dev->regs[addr] = (val & 0x7f);
break;
case 0x44:
dev->regs[addr] = (val & 0x07);
break;
case 0x48:
dev->regs[addr] = (val & 0x3f);
if (dev->has_ide) {
ide_pri_disable();
switch (val & 0x03) {
case 0x01:
ide_set_base(0, 0x01f0);
ide_set_side(0, 0x03f6);
ide_pri_enable();
break;
case 0x02:
ide_set_base(0, 0x0170);
ide_set_side(0, 0x0376);
ide_pri_enable();
break;
}
}
break;
case 0x49: case 0x53:
dev->regs[addr] = (val & 0x1f);
break;
case 0x4c: case 0x51:
case 0x57:
case 0x68: case 0x69:
dev->regs[addr] = val;
if (addr == 0x4c) {
dma_alias_remove();
if (!(val & 0x80))
dma_alias_set();
}
break;
case 0x4d:
dev->regs[addr] = (dev->regs[addr] & 0xef) | (val & 0x10);
break;
case 0x4e:
dev->regs[addr] = (val & 0xf7);
break;
case 0x50:
dev->regs[addr] = (val & 0x0f);
break;
case 0x52:
dev->regs[addr] = (val & 0x7f);
break;
case 0x56:
dev->regs[addr] = (val & 0x3e);
break;
case 0x59: /* PAM0 */
if ((dev->regs[0x59] ^ val) & 0xf0) {
i420ex_map(0xf0000, 0x10000, val >> 4);
shadowbios = (val & 0x10);
}
dev->regs[0x59] = val & 0xf0;
break;
case 0x5a: /* PAM1 */
if ((dev->regs[0x5a] ^ val) & 0x0f)
i420ex_map(0xc0000, 0x04000, val & 0xf);
if ((dev->regs[0x5a] ^ val) & 0xf0)
i420ex_map(0xc4000, 0x04000, val >> 4);
dev->regs[0x5a] = val;
break;
case 0x5b: /*PAM2 */
if ((dev->regs[0x5b] ^ val) & 0x0f)
i420ex_map(0xc8000, 0x04000, val & 0xf);
if ((dev->regs[0x5b] ^ val) & 0xf0)
i420ex_map(0xcc000, 0x04000, val >> 4);
dev->regs[0x5b] = val;
break;
case 0x5c: /*PAM3 */
if ((dev->regs[0x5c] ^ val) & 0x0f)
i420ex_map(0xd0000, 0x04000, val & 0xf);
if ((dev->regs[0x5c] ^ val) & 0xf0)
i420ex_map(0xd4000, 0x04000, val >> 4);
dev->regs[0x5c] = val;
break;
case 0x5d: /* PAM4 */
if ((dev->regs[0x5d] ^ val) & 0x0f)
i420ex_map(0xd8000, 0x04000, val & 0xf);
if ((dev->regs[0x5d] ^ val) & 0xf0)
i420ex_map(0xdc000, 0x04000, val >> 4);
dev->regs[0x5d] = val;
break;
case 0x5e: /* PAM5 */
if ((dev->regs[0x5e] ^ val) & 0x0f)
i420ex_map(0xe0000, 0x04000, val & 0xf);
if ((dev->regs[0x5e] ^ val) & 0xf0)
i420ex_map(0xe4000, 0x04000, val >> 4);
dev->regs[0x5e] = val;
break;
case 0x5f: /* PAM6 */
if ((dev->regs[0x5f] ^ val) & 0x0f)
i420ex_map(0xe8000, 0x04000, val & 0xf);
if ((dev->regs[0x5f] ^ val) & 0xf0)
i420ex_map(0xec000, 0x04000, val >> 4);
dev->regs[0x5f] = val;
break;
case 0x60: case 0x61: case 0x62: case 0x63: case 0x64:
spd_write_drbs(dev->regs, 0x60, 0x64, 1);
break;
case 0x66: case 0x67:
i420ex_log("Set IRQ routing: INT %c -> %02X\n", 0x41 + (addr & 0x01), val);
dev->regs[addr] = val & 0x8f;
if (val & 0x80)
pci_set_irq_routing(PCI_INTA + (addr & 0x01), PCI_IRQ_DISABLED);
else
pci_set_irq_routing(PCI_INTA + (addr & 0x01), val & 0xf);
break;
case 0x70: /* SMRAM */
i420ex_smram_handler_phase0();
if (dev->smram_locked)
dev->regs[0x70] = (dev->regs[0x70] & 0xdf) | (val & 0x20);
else {
dev->regs[0x70] = (dev->regs[0x70] & 0x88) | (val & 0x77);
dev->smram_locked = (val & 0x10);
if (dev->smram_locked)
dev->regs[0x70] &= 0xbf;
}
i420ex_smram_handler_phase1(dev);
break;
case 0xa0:
dev->regs[addr] = val & 0x1f;
apm_set_do_smi(dev->apm, !!(val & 0x01) && !!(dev->regs[0xa2] & 0x80));
switch ((val & 0x18) >> 3) {
case 0x00:
dev->fast_off_period = PCICLK * 32768.0 * 60000.0;
break;
case 0x01:
default:
dev->fast_off_period = 0.0;
break;
case 0x02:
dev->fast_off_period = PCICLK;
break;
case 0x03:
dev->fast_off_period = PCICLK * 32768.0;
break;
}
cpu_fast_off_count = dev->regs[0xa8] + 1;
timer_disable(&dev->fast_off_timer);
if (dev->fast_off_period != 0.0)
timer_on_auto(&dev->fast_off_timer, dev->fast_off_period);
break;
case 0xa2:
dev->regs[addr] = val & 0xff;
apm_set_do_smi(dev->apm, !!(dev->regs[0xa0] & 0x01) && !!(val & 0x80));
break;
case 0xaa:
dev->regs[addr] &= (val & 0xff);
break;
case 0xac: case 0xae:
dev->regs[addr] = val & 0xff;
break;
case 0xa4:
dev->regs[addr] = val & 0xfb;
cpu_fast_off_flags = (cpu_fast_off_flags & 0xffffff00) | dev->regs[addr];
break;
case 0xa5:
dev->regs[addr] = val;
cpu_fast_off_flags = (cpu_fast_off_flags & 0xffff00ff) | (dev->regs[addr] << 8);
break;
case 0xa7:
dev->regs[addr] = val & 0xe0;
cpu_fast_off_flags = (cpu_fast_off_flags & 0x00ffffff) | (dev->regs[addr] << 24);
break;
case 0xa8:
dev->regs[addr] = val & 0xff;
cpu_fast_off_val = val;
cpu_fast_off_count = val + 1;
timer_disable(&dev->fast_off_timer);
if (dev->fast_off_period != 0.0)
timer_on_auto(&dev->fast_off_timer, dev->fast_off_period);
break;
case 0x40:
dev->regs[addr] = (val & 0x7f);
break;
case 0x44:
dev->regs[addr] = (val & 0x07);
break;
case 0x48:
dev->regs[addr] = (val & 0x3f);
if (dev->has_ide) {
ide_pri_disable();
switch (val & 0x03) {
case 0x01:
ide_set_base(0, 0x01f0);
ide_set_side(0, 0x03f6);
ide_pri_enable();
break;
case 0x02:
ide_set_base(0, 0x0170);
ide_set_side(0, 0x0376);
ide_pri_enable();
break;
default:
break;
}
}
break;
case 0x49:
case 0x53:
dev->regs[addr] = (val & 0x1f);
break;
case 0x4c:
case 0x51:
case 0x57:
case 0x68:
case 0x69:
dev->regs[addr] = val;
if (addr == 0x4c) {
dma_alias_remove();
if (!(val & 0x80))
dma_alias_set();
}
break;
case 0x4d:
dev->regs[addr] = (dev->regs[addr] & 0xef) | (val & 0x10);
break;
case 0x4e:
dev->regs[addr] = (val & 0xf7);
break;
case 0x50:
dev->regs[addr] = (val & 0x0f);
break;
case 0x52:
dev->regs[addr] = (val & 0x7f);
break;
case 0x56:
dev->regs[addr] = (val & 0x3e);
break;
case 0x59: /* PAM0 */
if ((dev->regs[0x59] ^ val) & 0xf0) {
i420ex_map(0xf0000, 0x10000, val >> 4);
shadowbios = (val & 0x10);
}
dev->regs[0x59] = val & 0xf0;
break;
case 0x5a: /* PAM1 */
if ((dev->regs[0x5a] ^ val) & 0x0f)
i420ex_map(0xc0000, 0x04000, val & 0xf);
if ((dev->regs[0x5a] ^ val) & 0xf0)
i420ex_map(0xc4000, 0x04000, val >> 4);
dev->regs[0x5a] = val;
break;
case 0x5b: /*PAM2 */
if ((dev->regs[0x5b] ^ val) & 0x0f)
i420ex_map(0xc8000, 0x04000, val & 0xf);
if ((dev->regs[0x5b] ^ val) & 0xf0)
i420ex_map(0xcc000, 0x04000, val >> 4);
dev->regs[0x5b] = val;
break;
case 0x5c: /*PAM3 */
if ((dev->regs[0x5c] ^ val) & 0x0f)
i420ex_map(0xd0000, 0x04000, val & 0xf);
if ((dev->regs[0x5c] ^ val) & 0xf0)
i420ex_map(0xd4000, 0x04000, val >> 4);
dev->regs[0x5c] = val;
break;
case 0x5d: /* PAM4 */
if ((dev->regs[0x5d] ^ val) & 0x0f)
i420ex_map(0xd8000, 0x04000, val & 0xf);
if ((dev->regs[0x5d] ^ val) & 0xf0)
i420ex_map(0xdc000, 0x04000, val >> 4);
dev->regs[0x5d] = val;
break;
case 0x5e: /* PAM5 */
if ((dev->regs[0x5e] ^ val) & 0x0f)
i420ex_map(0xe0000, 0x04000, val & 0xf);
if ((dev->regs[0x5e] ^ val) & 0xf0)
i420ex_map(0xe4000, 0x04000, val >> 4);
dev->regs[0x5e] = val;
break;
case 0x5f: /* PAM6 */
if ((dev->regs[0x5f] ^ val) & 0x0f)
i420ex_map(0xe8000, 0x04000, val & 0xf);
if ((dev->regs[0x5f] ^ val) & 0xf0)
i420ex_map(0xec000, 0x04000, val >> 4);
dev->regs[0x5f] = val;
break;
case 0x60:
case 0x61:
case 0x62:
case 0x63:
case 0x64:
#ifdef USE_DRB_HACK
spd_write_drbs(dev->regs, 0x60, 0x64, 1);
#else
dev->regs[addr] = val;
i420ex_drb_recalc(dev);
#endif
break;
case 0x66:
case 0x67:
i420ex_log("Set IRQ routing: INT %c -> %02X\n", 0x41 + (addr & 0x01), val);
dev->regs[addr] = val & 0x8f;
if (val & 0x80)
pci_set_irq_routing(PCI_INTA + (addr & 0x01), PCI_IRQ_DISABLED);
else
pci_set_irq_routing(PCI_INTA + (addr & 0x01), val & 0xf);
break;
case 0x70: /* SMRAM */
i420ex_smram_handler_phase0();
if (dev->smram_locked)
dev->regs[0x70] = (dev->regs[0x70] & 0xdf) | (val & 0x20);
else {
dev->regs[0x70] = (dev->regs[0x70] & 0x88) | (val & 0x77);
dev->smram_locked = (val & 0x10);
if (dev->smram_locked)
dev->regs[0x70] &= 0xbf;
}
i420ex_smram_handler_phase1(dev);
break;
case 0xa0:
dev->regs[addr] = val & 0x1f;
apm_set_do_smi(dev->apm, !!(val & 0x01) && !!(dev->regs[0xa2] & 0x80));
switch ((val & 0x18) >> 3) {
case 0x00:
dev->fast_off_period = PCICLK * 32768.0 * 60000.0;
break;
case 0x01:
default:
dev->fast_off_period = 0.0;
break;
case 0x02:
dev->fast_off_period = PCICLK;
break;
case 0x03:
dev->fast_off_period = PCICLK * 32768.0;
break;
}
cpu_fast_off_count = cpu_fast_off_val + 1;
cpu_fast_off_period_set(cpu_fast_off_val, dev->fast_off_period);
break;
case 0xa2:
dev->regs[addr] = val & 0xff;
apm_set_do_smi(dev->apm, !!(dev->regs[0xa0] & 0x01) && !!(val & 0x80));
break;
case 0xaa:
dev->regs[addr] &= (val & 0xff);
break;
case 0xac:
case 0xae:
dev->regs[addr] = val & 0xff;
break;
case 0xa4:
dev->regs[addr] = val & 0xfb;
cpu_fast_off_flags = (cpu_fast_off_flags & 0xffffff00) | dev->regs[addr];
break;
case 0xa5:
dev->regs[addr] = val;
cpu_fast_off_flags = (cpu_fast_off_flags & 0xffff00ff) | (dev->regs[addr] << 8);
break;
case 0xa7:
dev->regs[addr] = val & 0xe0;
cpu_fast_off_flags = (cpu_fast_off_flags & 0x00ffffff) | (dev->regs[addr] << 24);
break;
case 0xa8:
dev->regs[addr] = val & 0xff;
cpu_fast_off_val = val;
cpu_fast_off_count = val + 1;
cpu_fast_off_period_set(cpu_fast_off_val, dev->fast_off_period);
break;
default:
break;
}
}
static uint8_t
i420ex_read(int func, int addr, void *priv)
{
i420ex_t *dev = (i420ex_t *) priv;
uint8_t ret;
const i420ex_t *dev = (i420ex_t *) priv;
uint8_t ret;
ret = 0xff;
@@ -369,7 +412,6 @@ i420ex_read(int func, int addr, void *priv)
return ret;
}
static void
i420ex_reset_hard(void *priv)
{
@@ -377,22 +419,25 @@ i420ex_reset_hard(void *priv)
memset(dev->regs, 0, 256);
dev->regs[0x00] = 0x86; dev->regs[0x01] = 0x80; /*Intel*/
dev->regs[0x02] = 0x86; dev->regs[0x03] = 0x04; /*82378IB (I420EX)*/
dev->regs[0x00] = 0x86;
dev->regs[0x01] = 0x80; /*Intel*/
dev->regs[0x02] = 0x86;
dev->regs[0x03] = 0x04; /*82378IB (I420EX)*/
dev->regs[0x04] = 0x07;
dev->regs[0x07] = 0x02;
dev->regs[0x4c] = 0x4d;
dev->regs[0x4e] = 0x03;
/* Bits 2:1 of register 50h are 00 is 25 MHz, and 01 if 33 MHz, 10 and 11 are reserved. */
/* Bits 2:1 of register 50h are 00 is 25 MHz, and 01 if 33 MHz, 10 and 11 are reserved. */
if (cpu_busspeed >= 33333333)
dev->regs[0x50] |= 0x02;
dev->regs[0x50] |= 0x02;
dev->regs[0x51] = 0x80;
dev->regs[0x60] = dev->regs[0x61] = dev->regs[0x62] = dev->regs[0x63] = dev->regs[0x64] = 0x01;
dev->regs[0x66] = 0x80; dev->regs[0x67] = 0x80;
dev->regs[0x69] = 0x02;
dev->regs[0xa0] = 0x08;
dev->regs[0xa8] = 0x0f;
dev->regs[0x66] = 0x80;
dev->regs[0x67] = 0x80;
dev->regs[0x69] = 0x02;
dev->regs[0xa0] = 0x08;
dev->regs[0xa8] = 0x0f;
mem_set_mem_state(0x000a0000, 0x00060000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
mem_set_mem_state_smm(0x000a0000, 0x00060000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
@@ -401,20 +446,18 @@ i420ex_reset_hard(void *priv)
pci_set_irq_routing(PCI_INTB, PCI_IRQ_DISABLED);
if (dev->has_ide)
ide_pri_disable();
ide_pri_disable();
}
static void
i420ex_apm_out(uint16_t port, uint8_t val, void *p)
i420ex_apm_out(UNUSED(uint16_t port), UNUSED(uint8_t val), void *priv)
{
i420ex_t *dev = (i420ex_t *) p;
i420ex_t *dev = (i420ex_t *) priv;
if (dev->apm->do_smi)
dev->regs[0xaa] |= 0x80;
dev->regs[0xaa] |= 0x80;
}
static void
i420ex_fast_off_count(void *priv)
{
@@ -422,78 +465,71 @@ i420ex_fast_off_count(void *priv)
cpu_fast_off_count--;
if (cpu_fast_off_count == 0) {
smi_line = 1;
dev->regs[0xaa] |= 0x20;
cpu_fast_off_count = dev->regs[0xa8] + 1;
}
timer_on_auto(&dev->fast_off_timer, dev->fast_off_period);
smi_raise();
dev->regs[0xaa] |= 0x20;
}
static void
i420ex_reset(void *p)
i420ex_reset(void *priv)
{
i420ex_t *dev = (i420ex_t *) p;
int i;
i420ex_t *dev = (i420ex_t *) priv;
i420ex_write(0, 0x48, 0x00, p);
i420ex_write(0, 0x48, 0x00, priv);
for (i = 0; i < 7; i++)
i420ex_write(0, 0x59 + i, 0x00, p);
/* Disable the PIC mouse latch. */
i420ex_write(0, 0x4e, 0x03, priv);
for (i = 0; i <= 4; i++)
i420ex_write(0, 0x60 + i, 0x01, p);
for (uint8_t i = 0; i < 7; i++)
i420ex_write(0, 0x59 + i, 0x00, priv);
dev->regs[0x70] &= 0xef; /* Forcibly unlock the SMRAM register. */
for (uint8_t i = 0; i <= 4; i++)
dev->regs[0x60 + i] = 0x01;
dev->regs[0x70] &= 0xef; /* Forcibly unlock the SMRAM register. */
dev->smram_locked = 0;
i420ex_write(0, 0x70, 0x00, p);
i420ex_write(0, 0x70, 0x00, priv);
mem_set_mem_state(0x000a0000, 0x00060000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
mem_set_mem_state_smm(0x000a0000, 0x00060000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
i420ex_write(0, 0xa0, 0x08, p);
i420ex_write(0, 0xa2, 0x00, p);
i420ex_write(0, 0xa4, 0x00, p);
i420ex_write(0, 0xa5, 0x00, p);
i420ex_write(0, 0xa6, 0x00, p);
i420ex_write(0, 0xa7, 0x00, p);
i420ex_write(0, 0xa8, 0x0f, p);
i420ex_write(0, 0xa0, 0x08, priv);
i420ex_write(0, 0xa2, 0x00, priv);
i420ex_write(0, 0xa4, 0x00, priv);
i420ex_write(0, 0xa5, 0x00, priv);
i420ex_write(0, 0xa6, 0x00, priv);
i420ex_write(0, 0xa7, 0x00, priv);
i420ex_write(0, 0xa8, 0x0f, priv);
}
static void
i420ex_close(void *p)
i420ex_close(void *priv)
{
i420ex_t *dev = (i420ex_t *)p;
i420ex_t *dev = (i420ex_t *) priv;
smram_del(dev->smram);
free(dev);
}
static void
i420ex_speed_changed(void *priv)
{
i420ex_t *dev = (i420ex_t *) priv;
int te;
int te;
te = timer_is_enabled(&dev->timer);
timer_disable(&dev->timer);
if (te)
timer_set_delay_u64(&dev->timer, ((uint64_t) dev->timer_latch) * TIMER_USEC);
timer_set_delay_u64(&dev->timer, ((uint64_t) dev->timer_latch) * TIMER_USEC);
te = timer_is_enabled(&dev->fast_off_timer);
te = timer_is_on(&dev->fast_off_timer);
timer_stop(&dev->fast_off_timer);
if (te)
timer_on_auto(&dev->fast_off_timer, dev->fast_off_period);
timer_on_auto(&dev->fast_off_timer, dev->fast_off_period);
}
static void *
i420ex_init(const device_t *info)
{
@@ -502,7 +538,7 @@ i420ex_init(const device_t *info)
dev->smram = smram_add();
pci_add_card(PCI_ADD_NORTHBRIDGE, i420ex_read, i420ex_write, dev);
pci_add_card(PCI_ADD_NORTHBRIDGE, i420ex_read, i420ex_write, dev, &dev->pci_slot);
dev->has_ide = info->local;
@@ -510,9 +546,11 @@ i420ex_init(const device_t *info)
cpu_fast_off_flags = 0x00000000;
cpu_fast_off_val = dev->regs[0xa8];
cpu_fast_off_val = dev->regs[0xa8];
cpu_fast_off_count = cpu_fast_off_val + 1;
cpu_register_fast_off_handler(&dev->fast_off_timer);
dev->apm = device_add(&apm_pci_device);
/* APM intercept handler to update 82420EX SMI status on APM SMI. */
io_sethandler(0x00b2, 0x0001, NULL, NULL, NULL, i420ex_apm_out, NULL, NULL, dev);
@@ -523,39 +561,40 @@ i420ex_init(const device_t *info)
device_add(&ide_pci_2ch_device);
#ifndef USE_DRB_HACK
row_device.local = 4 | (1 << 8) | (0x01 << 16) | (8 << 24);
device_add((const device_t *) &row_device);
#endif
i420ex_reset_hard(dev);
return dev;
}
const device_t i420ex_device =
{
"Intel 82420EX",
"i420ex",
DEVICE_PCI,
0x00,
i420ex_init,
i420ex_close,
i420ex_reset,
{ NULL },
i420ex_speed_changed,
NULL,
NULL
const device_t i420ex_device = {
.name = "Intel 82420EX",
.internal_name = "i420ex",
.flags = DEVICE_PCI,
.local = 0x00,
.init = i420ex_init,
.close = i420ex_close,
.reset = i420ex_reset,
{ .available = NULL },
.speed_changed = i420ex_speed_changed,
.force_redraw = NULL,
.config = NULL
};
const device_t i420ex_ide_device =
{
"Intel 82420EX (With IDE)",
"i420ex_ide",
DEVICE_PCI,
0x01,
i420ex_init,
i420ex_close,
i420ex_reset,
{ NULL },
i420ex_speed_changed,
NULL,
NULL
const device_t i420ex_ide_device = {
.name = "Intel 82420EX (With IDE)",
.internal_name = "i420ex_ide",
.flags = DEVICE_PCI,
.local = 0x01,
.init = i420ex_init,
.close = i420ex_close,
.reset = i420ex_reset,
{ .available = NULL },
.speed_changed = i420ex_speed_changed,
.force_redraw = NULL,
.config = NULL
};

File diff suppressed because it is too large Load Diff

View File

@@ -1,17 +1,19 @@
/*
* 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.
*
* Implementation of the Intel 82335(KU82335) chipset.
* Implementation of the Intel 82335(KU82335) chipset.
*
* Copyright 2021 Tiseno100
*
*
* Authors: Tiseno100
*
* Copyright 2021 Tiseno100.
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
@@ -26,22 +28,23 @@
#include <86box/device.h>
#include <86box/mem.h>
#include <86box/chipset.h>
#include <86box/plat_unused.h>
/* Shadow capabilities */
#define DISABLED_SHADOW (MEM_READ_EXTANY | MEM_WRITE_EXTANY)
#define ENABLED_SHADOW ((LOCK_STATUS) ? RO_SHADOW : RW_SHADOW)
#define RW_SHADOW (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL)
#define RO_SHADOW (MEM_READ_INTERNAL | MEM_WRITE_DISABLED)
#define ENABLED_SHADOW ((LOCK_STATUS) ? RO_SHADOW : RW_SHADOW)
#define RW_SHADOW (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL)
#define RO_SHADOW (MEM_READ_INTERNAL | MEM_WRITE_DISABLED)
/* Granularity Register Enable & Recalc */
#define EXTENDED_GRANULARITY_ENABLED (dev->regs[0x2c] & 0x01)
#define GRANULARITY_RECALC ((dev->regs[0x2e] & (1 << (i + 8))) ? ((dev->regs[0x2e] & (1 << i)) ? RO_SHADOW : RW_SHADOW) : DISABLED_SHADOW)
#define GRANULARITY_RECALC ((dev->regs[0x2e] & (1 << (i + 8))) ? ((dev->regs[0x2e] & (1 << i)) ? RO_SHADOW : RW_SHADOW) : DISABLED_SHADOW)
/* R/W operator for the Video RAM region */
#define DETERMINE_VIDEO_RAM_WRITE_ACCESS ((dev->regs[0x22] & (0x08 << 8)) ? RW_SHADOW : RO_SHADOW)
/* Base System 512/640KB switch */
#define ENABLE_TOP_128KB (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL)
#define ENABLE_TOP_128KB (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL)
#define DISABLE_TOP_128KB (MEM_READ_EXTANY | MEM_WRITE_EXTANY)
/* ROM size determination */
@@ -54,91 +57,92 @@
#define DEFINE_RC1_REMAP_SIZE ((dev->regs[0x24] & 0x02) ? 128 : 256)
#define DEFINE_RC2_REMAP_SIZE ((dev->regs[0x26] & 0x02) ? 128 : 256)
typedef struct
{
typedef struct intel_82335_t {
uint16_t regs[256];
uint16_t regs[256],
cfg_locked;
uint16_t cfg_locked;
} intel_82335_t;
#ifdef ENABLE_INTEL_82335_LOG
int intel_82335_do_log = ENABLE_INTEL_82335_LOG;
static void
intel_82335_log(const char *fmt, ...)
{
va_list ap;
if (intel_82335_do_log)
{
if (intel_82335_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define intel_82335_log(fmt, ...)
# define intel_82335_log(fmt, ...)
#endif
static void
intel_82335_write(uint16_t addr, uint16_t val, void *priv)
{
intel_82335_t *dev = (intel_82335_t *)priv;
uint32_t romsize = 0, base = 0, i = 0, rc1_remap = 0, rc2_remap = 0;
intel_82335_t *dev = (intel_82335_t *) priv;
uint32_t romsize = 0;
uint32_t base = 0;
uint32_t rc1_remap = 0;
uint32_t rc2_remap = 0;
dev->regs[addr] = val;
if (!dev->cfg_locked)
{
if (!dev->cfg_locked) {
intel_82335_log("Register %02x: Write %04x\n", addr, val);
switch (addr)
{
case 0x22: /* Memory Controller */
switch (addr) {
case 0x22: /* Memory Controller */
/* Check if the ROM chips are 256 or 512Kbit (Just for Shadowing sanity) */
romsize = ROM_SIZE;
/* Check if the ROM chips are 256 or 512Kbit (Just for Shadowing sanity) */
romsize = ROM_SIZE;
if (!EXTENDED_GRANULARITY_ENABLED)
{
shadowbios = !!(dev->regs[0x22] & 0x01);
shadowbios_write = !!(dev->regs[0x22] & 0x01);
if (!EXTENDED_GRANULARITY_ENABLED) {
shadowbios = !!(dev->regs[0x22] & 0x01);
shadowbios_write = !!(dev->regs[0x22] & 0x01);
/* Base System 512/640KB set */
mem_set_mem_state_both(0x80000, 0x20000, (dev->regs[0x22] & 0x08) ? ENABLE_TOP_128KB : DISABLE_TOP_128KB);
/* Base System 512/640KB set */
#if 0
mem_set_mem_state_both(0x80000, 0x20000, (dev->regs[0x22] & 0x08) ? ENABLE_TOP_128KB : DISABLE_TOP_128KB);
#endif
/* Video RAM shadow*/
mem_set_mem_state_both(0xa0000, 0x20000, (dev->regs[0x22] & (0x04 << 8)) ? DETERMINE_VIDEO_RAM_WRITE_ACCESS : DISABLED_SHADOW);
/* Video RAM shadow*/
mem_set_mem_state_both(0xa0000, 0x20000, (dev->regs[0x22] & (0x04 << 8)) ? DETERMINE_VIDEO_RAM_WRITE_ACCESS : DISABLED_SHADOW);
/* Option ROM shadow */
mem_set_mem_state_both(0xc0000, 0x20000, (dev->regs[0x22] & (0x02 << 8)) ? ENABLED_SHADOW : DISABLED_SHADOW);
/* Option ROM shadow */
mem_set_mem_state_both(0xc0000, 0x20000, (dev->regs[0x22] & (0x02 << 8)) ? ENABLED_SHADOW : DISABLED_SHADOW);
/* System ROM shadow */
mem_set_mem_state_both(0xe0000, 0x20000, (dev->regs[0x22] & 0x01) ? ENABLED_SHADOW : DISABLED_SHADOW);
}
break;
case 0x24: /* Roll Compare (Just top remapping. Not followed according to datasheet!) */
case 0x26:
rc1_remap = (dev->regs[0x24] & 0x01) ? DEFINE_RC1_REMAP_SIZE : 0;
rc2_remap = (dev->regs[0x26] & 0x01) ? DEFINE_RC2_REMAP_SIZE : 0;
mem_remap_top(rc1_remap + rc2_remap);
break;
case 0x2e: /* Extended Granularity (Enabled if Bit 0 in Register 2Ch is set) */
if (EXTENDED_GRANULARITY_ENABLED)
{
for (i = 0; i < 8; i++)
{
base = 0xc0000 + (i << 15);
shadowbios = (dev->regs[0x2e] & (1 << (i + 8))) && (base == romsize);
shadowbios_write = (dev->regs[0x2e] & (1 << i)) && (base == romsize);
mem_set_mem_state_both(base, 0x8000, GRANULARITY_RECALC);
/* System ROM shadow */
mem_set_mem_state_both(0xe0000, 0x20000, (dev->regs[0x22] & 0x01) ? ENABLED_SHADOW : DISABLED_SHADOW);
}
break;
}
case 0x24: /* Roll Compare (Just top remapping. Not followed according to datasheet!) */
case 0x26:
rc1_remap = (dev->regs[0x24] & 0x01) ? DEFINE_RC1_REMAP_SIZE : 0;
rc2_remap = (dev->regs[0x26] & 0x01) ? DEFINE_RC2_REMAP_SIZE : 0;
mem_remap_top(rc1_remap + rc2_remap);
break;
case 0x2e: /* Extended Granularity (Enabled if Bit 0 in Register 2Ch is set) */
if (EXTENDED_GRANULARITY_ENABLED) {
for (uint8_t i = 0; i < 8; i++) {
base = 0xc0000 + (i << 15);
shadowbios = (dev->regs[0x2e] & (1 << (i + 8))) && (base == romsize);
shadowbios_write = (dev->regs[0x2e] & (1 << i)) && (base == romsize);
mem_set_mem_state_both(base, 0x8000, GRANULARITY_RECALC);
}
}
break;
default:
break;
}
}
@@ -149,7 +153,7 @@ intel_82335_write(uint16_t addr, uint16_t val, void *priv)
static uint16_t
intel_82335_read(uint16_t addr, void *priv)
{
intel_82335_t *dev = (intel_82335_t *)priv;
const intel_82335_t *dev = (intel_82335_t *) priv;
intel_82335_log("Register %02x: Read %04x\n", addr, dev->regs[addr]);
@@ -159,19 +163,20 @@ intel_82335_read(uint16_t addr, void *priv)
static void
intel_82335_close(void *priv)
{
intel_82335_t *dev = (intel_82335_t *)priv;
intel_82335_t *dev = (intel_82335_t *) priv;
free(dev);
}
static void *
intel_82335_init(const device_t *info)
intel_82335_init(UNUSED(const device_t *info))
{
intel_82335_t *dev = (intel_82335_t *)malloc(sizeof(intel_82335_t));
intel_82335_t *dev = (intel_82335_t *) malloc(sizeof(intel_82335_t));
memset(dev, 0, sizeof(intel_82335_t));
memset(dev->regs, 0, sizeof(dev->regs));
dev->regs[0x22] = 0x08;
dev->regs[0x28] = 0xf9;
dev->cfg_locked = 0;
@@ -197,14 +202,15 @@ intel_82335_init(const device_t *info)
}
const device_t intel_82335_device = {
"Intel 82335",
"intel_82335",
0,
0,
intel_82335_init,
intel_82335_close,
NULL,
{NULL},
NULL,
NULL,
NULL};
.name = "Intel 82335",
.internal_name = "intel_82335",
.flags = 0,
.local = 0,
.init = intel_82335_init,
.close = intel_82335_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,324 +1,335 @@
/*
* 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.
*
* Emulation of Intel System I/O PCI chip.
* Emulation of Intel System I/O PCI chip.
*
*
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2016-2018 Miran Grca.
* Copyright 2016-2018 Miran Grca.
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include "cpu.h"
#include <86box/device.h>
#include <86box/io.h>
#include <86box/apm.h>
#include <86box/dma.h>
#include <86box/mem.h>
#include <86box/pci.h>
#include <86box/pic.h>
#include <86box/timer.h>
#include <86box/pit.h>
#include <86box/port_92.h>
#include <86box/machine.h>
#include <86box/chipset.h>
#include <86box/plat_unused.h>
typedef struct sio_t {
uint8_t id;
uint8_t pci_slot;
uint8_t pad;
uint8_t pad0;
typedef struct
{
uint8_t id,
regs[256];
uint8_t regs[256];
uint16_t timer_base,
timer_latch;
uint16_t timer_base;
uint16_t timer_latch;
double fast_off_period;
double fast_off_period;
pc_timer_t timer, fast_off_timer;
pc_timer_t timer;
pc_timer_t fast_off_timer;
apm_t * apm;
port_92_t * port_92;
apm_t *apm;
port_92_t *port_92;
} sio_t;
#ifdef ENABLE_SIO_LOG
int sio_do_log = ENABLE_SIO_LOG;
static void
sio_log(const char *fmt, ...)
{
va_list ap;
if (sio_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define sio_log(fmt, ...)
# define sio_log(fmt, ...)
#endif
static void
sio_timer_write(uint16_t addr, uint8_t val, void *priv)
{
sio_t *dev = (sio_t *) priv;
if (!(addr & 0x0002)) {
if (addr & 0x0001)
dev->timer_latch = (dev->timer_latch & 0xff) | (val << 8);
else
dev->timer_latch = (dev->timer_latch & 0xff00) | val;
if (addr & 0x0001)
dev->timer_latch = (dev->timer_latch & 0xff) | (val << 8);
else
dev->timer_latch = (dev->timer_latch & 0xff00) | val;
timer_set_delay_u64(&dev->timer, ((uint64_t) dev->timer_latch) * TIMER_USEC);
timer_set_delay_u64(&dev->timer, ((uint64_t) dev->timer_latch) * TIMER_USEC);
}
}
static void
sio_timer_writew(uint16_t addr, uint16_t val, void *priv)
{
sio_t *dev = (sio_t *) priv;
if (!(addr & 0x0002)) {
dev->timer_latch = val;
dev->timer_latch = val;
timer_set_delay_u64(&dev->timer, ((uint64_t) dev->timer_latch) * TIMER_USEC);
timer_set_delay_u64(&dev->timer, ((uint64_t) dev->timer_latch) * TIMER_USEC);
}
}
static uint8_t
sio_timer_read(uint16_t addr, void *priv)
{
sio_t *dev = (sio_t *) priv;
sio_t *dev = (sio_t *) priv;
uint16_t sio_timer_latch;
uint8_t ret = 0xff;
uint8_t ret = 0xff;
if (!(addr & 0x0002)) {
cycles -= ((int) (PITCONST >> 32));
cycles -= ((int) (PITCONST >> 32));
sio_timer_latch = timer_get_remaining_us(&dev->timer);
sio_timer_latch = timer_get_remaining_us(&dev->timer);
if (addr & 0x0001)
ret = sio_timer_latch >> 8;
else
ret = sio_timer_latch & 0xff;
if (addr & 0x0001)
ret = sio_timer_latch >> 8;
else
ret = sio_timer_latch & 0xff;
}
return ret;
}
static uint16_t
sio_timer_readw(uint16_t addr, void *priv)
{
sio_t *dev = (sio_t *) priv;
sio_t *dev = (sio_t *) priv;
uint16_t ret = 0xffff;
if (!(addr & 0x0002)) {
cycles -= ((int) (PITCONST >> 32));
cycles -= ((int) (PITCONST >> 32));
ret = timer_get_remaining_us(&dev->timer);
ret = timer_get_remaining_us(&dev->timer);
}
return ret;
}
static void
sio_write(int func, int addr, uint8_t val, void *priv)
{
sio_t *dev = (sio_t *) priv;
sio_t *dev = (sio_t *) priv;
uint8_t old;
if (func > 0)
return;
return;
if (((addr >= 0x0f) && (addr < 0x4c)) && (addr != 0x40))
return;
return;
/* The IB (original) variant of the SIO has no PCI IRQ steering. */
if ((addr >= 0x60) && (addr <= 0x63) && (dev->id < 0x03))
return;
return;
old = dev->regs[addr];
switch (addr) {
case 0x04: /*Command register*/
if (dev->id == 0x03)
dev->regs[addr] = (dev->regs[addr] & 0xf7) | (val & 0x08);
break;
case 0x04: /*Command register*/
if (dev->id == 0x03)
dev->regs[addr] = (dev->regs[addr] & 0xf7) | (val & 0x08);
break;
case 0x07:
dev->regs[addr] &= ~(val & 0x38);
break;
case 0x07:
dev->regs[addr] &= ~(val & 0x38);
break;
case 0x40:
if (dev->id == 0x03) {
dev->regs[addr] = (val & 0x7f);
case 0x40:
if (dev->id == 0x03) {
dev->regs[addr] = (val & 0x7f);
if (!((val ^ old) & 0x40))
return;
if (!((val ^ old) & 0x40))
return;
dma_alias_remove();
if (!(val & 0x40))
dma_alias_set();
} else
dev->regs[addr] = (val & 0x3f);
break;
case 0x41: case 0x44:
dev->regs[addr] = (val & 0x1f);
break;
case 0x42:
if (dev->id == 0x03)
dev->regs[addr] = val;
else
dev->regs[addr] = (val & 0x77);
break;
case 0x43:
if (dev->id == 0x03)
dev->regs[addr] = (val & 0x01);
break;
case 0x45: case 0x46:
case 0x47: case 0x48:
case 0x49: case 0x4a:
case 0x4b: case 0x4e:
case 0x54: case 0x55:
case 0x56:
dev->regs[addr] = val;
break;
case 0x4c: case 0x4d:
dev->regs[addr] = (val & 0x7f);
break;
case 0x4f:
dev->regs[addr] = val;
dma_alias_remove();
if (!(val & 0x40))
dma_alias_set();
} else
dev->regs[addr] = (val & 0x3f);
break;
case 0x41:
case 0x44:
dev->regs[addr] = (val & 0x1f);
break;
case 0x42:
if (dev->id == 0x03)
dev->regs[addr] = val;
else
dev->regs[addr] = (val & 0x77);
break;
case 0x43:
if (dev->id == 0x03)
dev->regs[addr] = (val & 0x01);
break;
case 0x45:
case 0x46:
case 0x47:
case 0x48:
case 0x49:
case 0x4a:
case 0x4b:
case 0x4e:
case 0x54:
case 0x55:
case 0x56:
dev->regs[addr] = val;
break;
case 0x4c:
dev->regs[addr] = (val & 0x7f);
break;
case 0x4d:
dev->regs[addr] = (val & 0x7f);
break;
case 0x4f:
dev->regs[addr] = val;
if (!((val ^ old) & 0x40))
return;
if (!((val ^ old) & 0x40))
return;
port_92_remove(dev->port_92);
if (val & 0x40)
port_92_add(dev->port_92);
break;
case 0x57:
dev->regs[addr] = val;
port_92_remove(dev->port_92);
if (val & 0x40)
port_92_add(dev->port_92);
break;
case 0x57:
dev->regs[addr] = val;
dma_remove_sg();
dma_set_sg_base(val);
break;
case 0x60: case 0x61: case 0x62: case 0x63:
if (dev->id == 0x03) {
sio_log("Set IRQ routing: INT %c -> %02X\n", 0x41 + (addr & 0x03), val);
dev->regs[addr] = val & 0x8f;
if (val & 0x80)
pci_set_irq_routing(PCI_INTA + (addr & 0x03), PCI_IRQ_DISABLED);
else
pci_set_irq_routing(PCI_INTA + (addr & 0x03), val & 0xf);
}
break;
case 0x80:
case 0x81:
if (addr == 0x80)
dev->regs[addr] = val & 0xfd;
else
dev->regs[addr] = val;
dma_remove_sg();
dma_set_sg_base(val);
break;
case 0x60:
case 0x61:
case 0x62:
case 0x63:
if (dev->id == 0x03) {
sio_log("Set IRQ routing: INT %c -> %02X\n", 0x41 + (addr & 0x03), val);
dev->regs[addr] = val & 0x8f;
if (val & 0x80)
pci_set_irq_routing(PCI_INTA + (addr & 0x03), PCI_IRQ_DISABLED);
else
pci_set_irq_routing(PCI_INTA + (addr & 0x03), val & 0xf);
}
break;
case 0x80:
case 0x81:
if (addr == 0x80)
dev->regs[addr] = val & 0xfd;
else
dev->regs[addr] = val;
if (dev->timer_base & 0x01) {
io_removehandler(dev->timer_base & 0xfffc, 0x0004,
sio_timer_read, sio_timer_readw, NULL,
sio_timer_write, sio_timer_writew, NULL, dev);
}
dev->timer_base = (dev->regs[0x81] << 8) | (dev->regs[0x80] & 0xfd);
if (dev->timer_base & 0x01) {
io_sethandler(dev->timer_base & 0xfffc, 0x0004,
sio_timer_read, sio_timer_readw, NULL,
sio_timer_write, sio_timer_writew, NULL, dev);
}
break;
case 0xa0:
if (dev->id == 0x03) {
dev->regs[addr] = val & 0x1f;
apm_set_do_smi(dev->apm, !!(val & 0x01) && !!(dev->regs[0xa2] & 0x80));
switch ((val & 0x18) >> 3) {
case 0x00:
dev->fast_off_period = PCICLK * 32768.0 * 60000.0;
break;
case 0x01:
default:
dev->fast_off_period = 0.0;
break;
case 0x02:
dev->fast_off_period = PCICLK;
break;
case 0x03:
dev->fast_off_period = PCICLK * 32768.0;
break;
}
cpu_fast_off_count = dev->regs[0xa8] + 1;
timer_disable(&dev->fast_off_timer);
if (dev->fast_off_period != 0.0)
timer_on_auto(&dev->fast_off_timer, dev->fast_off_period);
}
break;
case 0xa2:
if (dev->id == 0x03) {
dev->regs[addr] = val & 0xff;
apm_set_do_smi(dev->apm, !!(dev->regs[0xa0] & 0x01) && !!(val & 0x80));
}
break;
case 0xaa:
if (dev->id == 0x03)
dev->regs[addr] &= (val & 0xff);
break;
case 0xac: case 0xae:
if (dev->id == 0x03)
dev->regs[addr] = val & 0xff;
break;
case 0xa4:
if (dev->id == 0x03) {
dev->regs[addr] = val & 0xfb;
cpu_fast_off_flags = (cpu_fast_off_flags & 0xffffff00) | dev->regs[addr];
}
break;
case 0xa5:
if (dev->id == 0x03) {
dev->regs[addr] = val & 0xff;
cpu_fast_off_flags = (cpu_fast_off_flags & 0xffff00ff) | (dev->regs[addr] << 8);
}
break;
case 0xa7:
if (dev->id == 0x03) {
dev->regs[addr] = val & 0xa0;
cpu_fast_off_flags = (cpu_fast_off_flags & 0x00ffffff) | (dev->regs[addr] << 24);
}
break;
case 0xa8:
dev->regs[addr] = val & 0xff;
cpu_fast_off_val = val;
cpu_fast_off_count = val + 1;
timer_disable(&dev->fast_off_timer);
if (dev->fast_off_period != 0.0)
timer_on_auto(&dev->fast_off_timer, dev->fast_off_period);
break;
if (dev->timer_base & 0x01) {
io_removehandler(dev->timer_base & 0xfffc, 0x0004,
sio_timer_read, sio_timer_readw, NULL,
sio_timer_write, sio_timer_writew, NULL, dev);
}
dev->timer_base = (dev->regs[0x81] << 8) | (dev->regs[0x80] & 0xfd);
if (dev->timer_base & 0x01) {
io_sethandler(dev->timer_base & 0xfffc, 0x0004,
sio_timer_read, sio_timer_readw, NULL,
sio_timer_write, sio_timer_writew, NULL, dev);
}
break;
case 0xa0:
if (dev->id == 0x03) {
dev->regs[addr] = val & 0x1f;
apm_set_do_smi(dev->apm, !!(val & 0x01) && !!(dev->regs[0xa2] & 0x80));
switch ((val & 0x18) >> 3) {
case 0x00:
dev->fast_off_period = PCICLK * 32768.0 * 60000.0;
break;
case 0x01:
default:
dev->fast_off_period = 0.0;
break;
case 0x02:
dev->fast_off_period = PCICLK;
break;
case 0x03:
dev->fast_off_period = PCICLK * 32768.0;
break;
}
cpu_fast_off_count = cpu_fast_off_val + 1;
cpu_fast_off_period_set(cpu_fast_off_val, dev->fast_off_period);
}
break;
case 0xa2:
if (dev->id == 0x03) {
dev->regs[addr] = val & 0xff;
apm_set_do_smi(dev->apm, !!(dev->regs[0xa0] & 0x01) && !!(val & 0x80));
}
break;
case 0xaa:
if (dev->id == 0x03)
dev->regs[addr] &= (val & 0xff);
break;
case 0xac:
case 0xae:
if (dev->id == 0x03)
dev->regs[addr] = val & 0xff;
break;
case 0xa4:
if (dev->id == 0x03) {
dev->regs[addr] = val & 0xfb;
cpu_fast_off_flags = (cpu_fast_off_flags & 0xffffff00) | dev->regs[addr];
}
break;
case 0xa5:
if (dev->id == 0x03) {
dev->regs[addr] = val & 0xff;
cpu_fast_off_flags = (cpu_fast_off_flags & 0xffff00ff) | (dev->regs[addr] << 8);
}
break;
case 0xa7:
if (dev->id == 0x03) {
dev->regs[addr] = val & 0xa0;
cpu_fast_off_flags = (cpu_fast_off_flags & 0x00ffffff) | (dev->regs[addr] << 24);
}
break;
case 0xa8:
dev->regs[addr] = val & 0xff;
cpu_fast_off_val = val;
cpu_fast_off_count = val + 1;
cpu_fast_off_period_set(cpu_fast_off_val, dev->fast_off_period);
break;
default:
break;
}
}
static uint8_t
sio_read(int func, int addr, void *priv)
{
sio_t *dev = (sio_t *) priv;
uint8_t ret;
const sio_t *dev = (sio_t *) priv;
uint8_t ret;
ret = 0xff;
@@ -328,47 +339,48 @@ sio_read(int func, int addr, void *priv)
return ret;
}
static void
sio_config_write(uint16_t addr, uint8_t val, void *priv)
sio_config_write(UNUSED(uint16_t addr), UNUSED(uint8_t val), UNUSED(void *priv))
{
//
}
static uint8_t
sio_config_read(uint16_t port, void *priv)
sio_config_read(uint16_t port, UNUSED(void *priv))
{
uint8_t ret = 0x00;
switch (port & 0x000f) {
case 3:
ret = 0xff;
break;
case 5:
ret = 0xd3;
case 3:
ret = 0xff;
break;
case 5:
ret = 0xd3;
switch (cpu_pci_speed) {
case 20000000:
ret |= 0x0c;
break;
case 25000000:
default:
ret |= 0x00;
break;
case 30000000:
ret |= 0x08;
break;
case 33333333:
ret |= 0x04;
break;
}
break;
switch (cpu_pci_speed) {
case 20000000:
ret |= 0x0c;
break;
case 25000000:
default:
ret |= 0x00;
break;
case 30000000:
ret |= 0x08;
break;
case 33333333:
ret |= 0x04;
break;
}
break;
default:
break;
}
return ret;
}
static void
sio_reset_hard(void *priv)
{
@@ -376,27 +388,37 @@ sio_reset_hard(void *priv)
memset(dev->regs, 0, 256);
dev->regs[0x00] = 0x86; dev->regs[0x01] = 0x80; /*Intel*/
dev->regs[0x02] = 0x84; dev->regs[0x03] = 0x04; /*82378IB (SIO)*/
dev->regs[0x00] = 0x86;
dev->regs[0x01] = 0x80; /*Intel*/
dev->regs[0x02] = 0x84;
dev->regs[0x03] = 0x04; /*82378IB (SIO)*/
dev->regs[0x04] = 0x07;
dev->regs[0x07] = 0x02;
dev->regs[0x08] = dev->id;
dev->regs[0x40] = 0x20; dev->regs[0x41] = 0x00;
dev->regs[0x40] = 0x20;
dev->regs[0x41] = 0x00;
dev->regs[0x42] = 0x04;
dev->regs[0x45] = 0x10; dev->regs[0x46] = 0x0f;
dev->regs[0x45] = 0x10;
dev->regs[0x46] = 0x0f;
dev->regs[0x48] = 0x01;
dev->regs[0x4a] = 0x10; dev->regs[0x4b] = 0x0f;
dev->regs[0x4c] = 0x56; dev->regs[0x4d] = 0x40;
dev->regs[0x4e] = 0x07; dev->regs[0x4f] = 0x4f;
dev->regs[0x4a] = 0x10;
dev->regs[0x4b] = 0x0f;
dev->regs[0x4c] = 0x56;
dev->regs[0x4d] = 0x40;
dev->regs[0x4e] = 0x07;
dev->regs[0x4f] = 0x4f;
dev->regs[0x57] = 0x04;
if (dev->id == 0x03) {
dev->regs[0x60] = 0x80; dev->regs[0x61] = 0x80; dev->regs[0x62] = 0x80; dev->regs[0x63] = 0x80;
dev->regs[0x60] = 0x80;
dev->regs[0x61] = 0x80;
dev->regs[0x62] = 0x80;
dev->regs[0x63] = 0x80;
}
dev->regs[0x80] = 0x78;
if (dev->id == 0x03) {
dev->regs[0xa0] = 0x08;
dev->regs[0xa8] = 0x0f;
dev->regs[0xa0] = 0x08;
dev->regs[0xa8] = 0x0f;
}
pci_set_irq_routing(PCI_INTA, PCI_IRQ_DISABLED);
@@ -405,121 +427,113 @@ sio_reset_hard(void *priv)
pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED);
if (dev->timer_base & 0x0001) {
io_removehandler(dev->timer_base & 0xfffc, 0x0004,
sio_timer_read, sio_timer_readw, NULL,
sio_timer_write, sio_timer_writew, NULL, dev);
io_removehandler(dev->timer_base & 0xfffc, 0x0004,
sio_timer_read, sio_timer_readw, NULL,
sio_timer_write, sio_timer_writew, NULL, dev);
}
dev->timer_base = 0x0078;
}
static void
sio_apm_out(uint16_t port, uint8_t val, void *p)
sio_apm_out(UNUSED(uint16_t port), UNUSED(uint8_t val), void *priv)
{
sio_t *dev = (sio_t *) p;
sio_t *dev = (sio_t *) priv;
if (dev->apm->do_smi)
dev->regs[0xaa] |= 0x80;
dev->regs[0xaa] |= 0x80;
}
static void
sio_fast_off_count(void *priv)
{
sio_t *dev = (sio_t *) priv;
cpu_fast_off_count--;
if (cpu_fast_off_count == 0) {
smi_line = 1;
dev->regs[0xaa] |= 0x20;
cpu_fast_off_count = dev->regs[0xa8] + 1;
}
timer_on_auto(&dev->fast_off_timer, dev->fast_off_period);
smi_raise();
dev->regs[0xaa] |= 0x20;
}
static void
sio_reset(void *p)
sio_reset(void *priv)
{
sio_t *dev = (sio_t *) p;
const sio_t *dev = (sio_t *) priv;
sio_write(0, 0x57, 0x04, p);
/* Disable the PIC mouse latch. */
sio_write(0, 0x4d, 0x40, priv);
sio_write(0, 0x57, 0x04, priv);
dma_set_params(1, 0xffffffff);
if (dev->id == 0x03) {
sio_write(0, 0xa0, 0x08, p);
sio_write(0, 0xa2, 0x00, p);
sio_write(0, 0xa4, 0x00, p);
sio_write(0, 0xa5, 0x00, p);
sio_write(0, 0xa6, 0x00, p);
sio_write(0, 0xa7, 0x00, p);
sio_write(0, 0xa8, 0x0f, p);
sio_write(0, 0xa0, 0x08, priv);
sio_write(0, 0xa2, 0x00, priv);
sio_write(0, 0xa4, 0x00, priv);
sio_write(0, 0xa5, 0x00, priv);
sio_write(0, 0xa6, 0x00, priv);
sio_write(0, 0xa7, 0x00, priv);
sio_write(0, 0xa8, 0x0f, priv);
}
}
static void
sio_close(void *p)
sio_close(void *priv)
{
sio_t *dev = (sio_t *)p;
sio_t *dev = (sio_t *) priv;
free(dev);
}
static void
sio_speed_changed(void *priv)
{
sio_t *dev = (sio_t *) priv;
int te;
int te;
te = timer_is_enabled(&dev->timer);
timer_disable(&dev->timer);
if (te)
timer_set_delay_u64(&dev->timer, ((uint64_t) dev->timer_latch) * TIMER_USEC);
timer_set_delay_u64(&dev->timer, ((uint64_t) dev->timer_latch) * TIMER_USEC);
if (dev->id == 0x03) {
te = timer_is_enabled(&dev->fast_off_timer);
te = timer_is_on(&dev->fast_off_timer);
timer_stop(&dev->fast_off_timer);
if (te)
timer_on_auto(&dev->fast_off_timer, dev->fast_off_period);
timer_stop(&dev->fast_off_timer);
if (te)
timer_on_auto(&dev->fast_off_timer, dev->fast_off_period);
}
}
static void *
sio_init(const device_t *info)
{
sio_t *dev = (sio_t *) malloc(sizeof(sio_t));
memset(dev, 0, sizeof(sio_t));
pci_add_card(PCI_ADD_SOUTHBRIDGE, sio_read, sio_write, dev);
pci_add_card(PCI_ADD_SOUTHBRIDGE, sio_read, sio_write, dev, &dev->pci_slot);
dev->id = info->local;
if (dev->id == 0x03)
timer_add(&dev->fast_off_timer, sio_fast_off_count, dev, 0);
timer_add(&dev->fast_off_timer, sio_fast_off_count, dev, 0);
sio_reset_hard(dev);
cpu_fast_off_flags = 0x00000000;
if (dev->id == 0x03) {
cpu_fast_off_val = dev->regs[0xa8];
cpu_fast_off_count = cpu_fast_off_val + 1;
cpu_fast_off_val = dev->regs[0xa8];
cpu_fast_off_count = cpu_fast_off_val + 1;
cpu_register_fast_off_handler(&dev->fast_off_timer);
} else
cpu_fast_off_val = cpu_fast_off_count = 0;
cpu_fast_off_val = cpu_fast_off_count = 0;
if (dev->id == 0x03) {
dev->apm = device_add(&apm_pci_device);
/* APM intercept handler to update 82378ZB SMI status on APM SMI. */
io_sethandler(0x00b2, 0x0001, NULL, NULL, NULL, sio_apm_out, NULL, NULL, dev);
dev->apm = device_add(&apm_pci_device);
/* APM intercept handler to update 82378ZB SMI status on APM SMI. */
io_sethandler(0x00b2, 0x0001, NULL, NULL, NULL, sio_apm_out, NULL, NULL, dev);
}
dev->port_92 = device_add(&port_92_pci_device);
@@ -530,48 +544,46 @@ sio_init(const device_t *info)
dma_high_page_init();
if (dev->id == 0x03)
dma_alias_set();
dma_alias_set();
io_sethandler(0x0073, 0x0001,
sio_config_read, NULL, NULL, sio_config_write, NULL, NULL, dev);
sio_config_read, NULL, NULL, sio_config_write, NULL, NULL, dev);
io_sethandler(0x0075, 0x0001,
sio_config_read, NULL, NULL, sio_config_write, NULL, NULL, dev);
sio_config_read, NULL, NULL, sio_config_write, NULL, NULL, dev);
timer_add(&dev->timer, NULL, NULL, 0);
// device_add(&i8254_sec_device);
#if 0
device_add(&i8254_sec_device);
#endif
return dev;
}
const device_t sio_device =
{
"Intel 82378IB (SIO)",
"sio",
DEVICE_PCI,
0x00,
sio_init,
sio_close,
sio_reset,
{ NULL },
sio_speed_changed,
NULL,
NULL
const device_t sio_device = {
.name = "Intel 82378IB (SIO)",
.internal_name = "sio",
.flags = DEVICE_PCI,
.local = 0x00,
.init = sio_init,
.close = sio_close,
.reset = sio_reset,
{ .available = NULL },
.speed_changed = sio_speed_changed,
.force_redraw = NULL,
.config = NULL
};
const device_t sio_zb_device =
{
"Intel 82378ZB (SIO)",
"sio_zb",
DEVICE_PCI,
0x03,
sio_init,
sio_close,
sio_reset,
{ NULL },
sio_speed_changed,
NULL,
NULL
const device_t sio_zb_device = {
.name = "Intel 82378ZB (SIO)",
.internal_name = "sio_zb",
.flags = DEVICE_PCI,
.local = 0x03,
.init = sio_init,
.close = sio_close,
.reset = sio_reset,
{ .available = NULL },
.speed_changed = sio_speed_changed,
.force_redraw = NULL,
.config = NULL
};

File diff suppressed because it is too large Load Diff

View File

@@ -1,22 +1,22 @@
/*
* 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.
*
* Implementation of the Olivetti EVA (98/86) Gate Array.
*
* Note: This chipset has no datasheet, everything were done via
* reverse engineering the BIOS of various machines using it.
*
* Implementation of the Olivetti EVA (98/86) Gate Array.
*
* Note: This chipset has no datasheet, everything were done via
* reverse engineering the BIOS of various machines using it.
*
* Authors: EngiNerd <webmaster.crrc@yahoo.it>
*
* Copyright 2020-2021 EngiNerd
* Copyright 2020-2021 EngiNerd
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
@@ -32,16 +32,17 @@
#include <86box/chipset.h>
#include <86box/video.h>
#include <86box/mem.h>
#include <86box/plat_unused.h>
typedef struct
{
uint8_t reg_065;
uint8_t reg_067;
typedef struct olivetti_eva_t {
uint8_t reg_065;
uint8_t reg_067;
uint8_t reg_069;
} olivetti_eva_t;
#ifdef ENABLE_OLIVETTI_EVA_LOG
int olivetti_eva_do_log = ENABLE_OLIVETTI_EVA_LOG;
static void
olivetti_eva_log(const char *fmt, ...)
{
@@ -50,11 +51,11 @@ olivetti_eva_log(const char *fmt, ...)
if (olivetti_eva_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
va_end(ap);
}
}
#else
#define olivetti_eva_log(fmt, ...)
# define olivetti_eva_log(fmt, ...)
#endif
static void
@@ -73,23 +74,27 @@ olivetti_eva_write(uint16_t addr, uint8_t val, void *priv)
case 0x069:
dev->reg_069 = val;
/*
* Unfortunately, if triggered, the BIOS remapping function fails causing
* Unfortunately, if triggered, the BIOS remapping function fails causing
* a fatal error. Therefore, this code section is currently commented.
*/
// if (val & 1){
// /*
// * Set the register to 7 or above for the BIOS to trigger the
// * memory remapping function if shadowing is active.
// */
// dev->reg_069 = 0x7;
// }
// if (val & 8) {
// /*
// * Activate shadowing for region e0000-fffff
// */
// mem_remap_top(256);
// mem_set_mem_state_both(0xa0000, 0x60000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
// }
#if 0
if (val & 1) {
/*
* Set the register to 7 or above for the BIOS to trigger the
* memory remapping function if shadowing is active.
*/
dev->reg_069 = 0x7;
}
if (val & 8) {
/*
* Activate shadowing for region e0000-fffff
*/
mem_remap_top(256);
mem_set_mem_state_both(0xa0000, 0x60000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
}
#endif
break;
default:
break;
}
}
@@ -97,8 +102,9 @@ olivetti_eva_write(uint16_t addr, uint8_t val, void *priv)
static uint8_t
olivetti_eva_read(uint16_t addr, void *priv)
{
olivetti_eva_t *dev = (olivetti_eva_t *) priv;
uint8_t ret = 0xff;
const olivetti_eva_t *dev = (olivetti_eva_t *) priv;
uint8_t ret = 0xff;
switch (addr) {
case 0x065:
ret = dev->reg_065;
@@ -110,12 +116,13 @@ olivetti_eva_read(uint16_t addr, void *priv)
case 0x069:
ret = dev->reg_069;
break;
default:
break;
}
olivetti_eva_log("Olivetti EVA Gate Array: Read %02x at %02x\n", ret, addr);
return ret;
}
static void
olivetti_eva_close(void *priv)
{
@@ -125,28 +132,28 @@ olivetti_eva_close(void *priv)
}
static void *
olivetti_eva_init(const device_t *info)
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));
/* GA98 registers */
dev->reg_065 = 0x00;
/* RAM page registers: never read, only set */
dev->reg_067 = 0x00;
/* RAM enable registers */
dev->reg_069 = 0x0;
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);
io_sethandler(0x0069, 0x0001, olivetti_eva_read, NULL, NULL, olivetti_eva_write, NULL, NULL, dev);
/* 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.
@@ -157,11 +164,15 @@ olivetti_eva_init(const device_t *info)
}
const device_t olivetti_eva_device = {
"Olivetti EVA Gate Array",
"olivetta_eva",
0,
0,
olivetti_eva_init, olivetti_eva_close, NULL,
{ NULL }, NULL, NULL,
NULL
.name = "Olivetti EVA Gate Array",
.internal_name = "olivetta_eva",
.flags = 0,
.local = 0,
.init = olivetti_eva_init,
.close = olivetti_eva_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -1,20 +1,21 @@
/*
* 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.
*
* Implementation of the OPTi 82C283 chipset.
* Implementation of the OPTi 82C283 chipset.
*
* Authors: Tiseno100,
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2021 Tiseno100.
* Copyright 2021 Miran Grca.
*
* Authors: Tiseno100,
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2021 Tiseno100.
* Copyright 2021 Miran Grca.
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
@@ -28,9 +29,10 @@
#include <86box/io.h>
#include <86box/device.h>
#include <86box/mem.h>
#include <86box/plat_fallthrough.h>
#include <86box/plat_unused.h>
#include <86box/chipset.h>
#ifdef ENABLE_OPTI283_LOG
int opti283_do_log = ENABLE_OPTI283_LOG;
@@ -39,241 +41,236 @@ opti283_log(const char *fmt, ...)
{
va_list ap;
if (opti283_do_log)
{
if (opti283_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define opti283_log(fmt, ...)
# define opti283_log(fmt, ...)
#endif
typedef struct
{
uint32_t phys, virt;
typedef struct mem_remapping_t {
uint32_t phys;
uint32_t virt;
} mem_remapping_t;
typedef struct
{
uint8_t index, shadow_high,
regs[256];
mem_remapping_t mem_remappings[2];
mem_mapping_t mem_mappings[2];
typedef struct opti283_t {
uint8_t index;
uint8_t shadow_high;
uint8_t regs[256];
mem_remapping_t mem_remappings[2];
mem_mapping_t mem_mappings[2];
} opti283_t;
static uint8_t
opti283_read_remapped_ram(uint32_t addr, void *priv)
{
mem_remapping_t *dev = (mem_remapping_t *) priv;
const mem_remapping_t *dev = (mem_remapping_t *) priv;
return mem_read_ram((addr - dev->virt) + dev->phys, priv);
}
static uint16_t
opti283_read_remapped_ramw(uint32_t addr, void *priv)
{
mem_remapping_t *dev = (mem_remapping_t *) priv;
const mem_remapping_t *dev = (mem_remapping_t *) priv;
return mem_read_ramw((addr - dev->virt) + dev->phys, priv);
}
static uint32_t
opti283_read_remapped_raml(uint32_t addr, void *priv)
{
mem_remapping_t *dev = (mem_remapping_t *) priv;
const mem_remapping_t *dev = (mem_remapping_t *) priv;
return mem_read_raml((addr - dev->virt) + dev->phys, priv);
}
static void
opti283_write_remapped_ram(uint32_t addr, uint8_t val, void *priv)
{
mem_remapping_t *dev = (mem_remapping_t *) priv;
const mem_remapping_t *dev = (mem_remapping_t *) priv;
mem_write_ram((addr - dev->virt) + dev->phys, val, priv);
}
static void
opti283_write_remapped_ramw(uint32_t addr, uint16_t val, void *priv)
{
mem_remapping_t *dev = (mem_remapping_t *) priv;
const mem_remapping_t *dev = (mem_remapping_t *) priv;
mem_write_ramw((addr - dev->virt) + dev->phys, val, priv);
}
static void
opti283_write_remapped_raml(uint32_t addr, uint32_t val, void *priv)
{
mem_remapping_t *dev = (mem_remapping_t *) priv;
const mem_remapping_t *dev = (mem_remapping_t *) priv;
mem_write_raml((addr - dev->virt) + dev->phys, val, priv);
}
static void
opti283_shadow_recalc(opti283_t *dev)
{
uint32_t i, base;
uint32_t base;
uint32_t rbase;
uint8_t sh_enable, sh_mode;
uint8_t rom, sh_copy;
uint8_t sh_enable;
uint8_t sh_mode;
uint8_t rom;
uint8_t sh_copy;
shadowbios = shadowbios_write = 0;
dev->shadow_high = 0;
dev->shadow_high = 0;
opti283_log("OPTI 283: %02X %02X %02X %02X\n", dev->regs[0x11], dev->regs[0x12], dev->regs[0x13], dev->regs[0x14]);
if (dev->regs[0x11] & 0x80) {
mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
opti283_log("OPTI 283: F0000-FFFFF READ_EXTANY, WRITE_INTERNAL\n");
shadowbios_write = 1;
mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
opti283_log("OPTI 283: F0000-FFFFF READ_EXTANY, WRITE_INTERNAL\n");
shadowbios_write = 1;
} else {
shadowbios = 1;
if (dev->regs[0x14] & 0x80) {
mem_set_mem_state_both(0xf0000, 0x01000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
opti283_log("OPTI 283: F0000-F0FFF READ_INTERNAL, WRITE_INTERNAL\n");
shadowbios_write = 1;
} else {
mem_set_mem_state_both(0xf0000, 0x01000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED);
opti283_log("OPTI 283: F0000-F0FFF READ_INTERNAL, WRITE_DISABLED\n");
}
shadowbios = 1;
if (dev->regs[0x14] & 0x80) {
mem_set_mem_state_both(0xf0000, 0x01000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
opti283_log("OPTI 283: F0000-F0FFF READ_INTERNAL, WRITE_INTERNAL\n");
shadowbios_write = 1;
} else {
mem_set_mem_state_both(0xf0000, 0x01000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED);
opti283_log("OPTI 283: F0000-F0FFF READ_INTERNAL, WRITE_DISABLED\n");
}
mem_set_mem_state_both(0xf1000, 0x0f000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED);
opti283_log("OPTI 283: F1000-FFFFF READ_INTERNAL, WRITE_DISABLED\n");
mem_set_mem_state_both(0xf1000, 0x0f000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED);
opti283_log("OPTI 283: F1000-FFFFF READ_INTERNAL, WRITE_DISABLED\n");
}
sh_copy = dev->regs[0x11] & 0x08;
for (i = 0; i < 12; i++) {
base = 0xc0000 + (i << 14);
if (i >= 4)
sh_enable = dev->regs[0x12] & (1 << (i - 4));
else
sh_enable = dev->regs[0x13] & (1 << (i + 4));
sh_mode = dev->regs[0x11] & (1 << (i >> 2));
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)));
for (uint8_t i = 0; i < 12; i++) {
base = 0xc0000 + (i << 14);
if (i >= 4)
sh_enable = dev->regs[0x12] & (1 << (i - 4));
else
sh_enable = dev->regs[0x13] & (1 << (i + 4));
sh_mode = dev->regs[0x11] & (1 << (i >> 2));
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 (base >= 0x000e0000)
shadowbios |= 1;
if (base >= 0x000d0000)
dev->shadow_high |= 1;
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);
opti283_log("OPTI 283: %08X-%08X READ_INTERNAL, WRITE_DISABLED\n", base, base + 0x3fff);
} else {
if (base >= 0x000e0000)
shadowbios_write |= 1;
if (sh_mode) {
mem_set_mem_state_both(base, 0x4000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED);
opti283_log("OPTI 283: %08X-%08X READ_INTERNAL, WRITE_DISABLED\n", base, base + 0x3fff);
} else {
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);
}
}
} else {
if (base >= 0xe0000) {
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_DISABLED);
opti283_log("OPTI 283: %08X-%08X READ_EXTANY, WRITE_DISABLED\n", base, base + 0x3fff);
} else {
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTERNAL | MEM_WRITE_DISABLED);
opti283_log("OPTI 283: %08X-%08X READ_EXTERNAL, WRITE_DISABLED\n", base, base + 0x3fff);
}
}
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);
}
}
} else {
if (base >= 0xe0000) {
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_DISABLED);
opti283_log("OPTI 283: %08X-%08X READ_EXTANY, WRITE_DISABLED\n", base, base + 0x3fff);
} else {
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTERNAL | MEM_WRITE_DISABLED);
opti283_log("OPTI 283: %08X-%08X READ_EXTERNAL, WRITE_DISABLED\n", base, base + 0x3fff);
}
}
}
rbase = ((uint32_t) (dev->regs[0x13] & 0x0f)) << 20;
if (rbase > 0) {
dev->mem_remappings[0].virt = rbase;
mem_mapping_set_addr(&dev->mem_mappings[0], rbase, 0x00020000);
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]);
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]);
mem_mapping_disable(&dev->mem_mappings[0]);
mem_mapping_disable(&dev->mem_mappings[1]);
}
flushmmucache_nopc();
}
static void
opti283_write(uint16_t addr, uint8_t val, void *priv)
{
opti283_t *dev = (opti283_t *)priv;
opti283_t *dev = (opti283_t *) priv;
switch (addr) {
case 0x22:
dev->index = val;
break;
case 0x22:
dev->index = val;
break;
case 0x24:
opti283_log("OPTi 283: dev->regs[%02x] = %02x\n", dev->index, val);
case 0x24:
opti283_log("OPTi 283: dev->regs[%02x] = %02x\n", dev->index, val);
switch (dev->index) {
case 0x10:
dev->regs[dev->index] = val;
break;
switch (dev->index) {
case 0x10:
dev->regs[dev->index] = val;
break;
case 0x14:
reset_on_hlt = !!(val & 0x40);
/* FALLTHROUGH */
case 0x11: case 0x12:
case 0x13:
dev->regs[dev->index] = val;
opti283_shadow_recalc(dev);
break;
}
break;
case 0x14:
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:
break;
}
}
static uint8_t
opti283_read(uint16_t addr, void *priv)
{
opti283_t *dev = (opti283_t *)priv;
uint8_t ret = 0xff;
const opti283_t *dev = (opti283_t *) priv;
uint8_t ret = 0xff;
if (addr == 0x24)
ret = dev->regs[dev->index];
ret = dev->regs[dev->index];
return ret;
}
static void
opti283_close(void *priv)
{
opti283_t *dev = (opti283_t *)priv;
opti283_t *dev = (opti283_t *) priv;
free(dev);
}
static void *
opti283_init(const device_t *info)
opti283_init(UNUSED(const device_t *info))
{
opti283_t *dev = (opti283_t *)malloc(sizeof(opti283_t));
opti283_t *dev = (opti283_t *) malloc(sizeof(opti283_t));
memset(dev, 0x00, sizeof(opti283_t));
io_sethandler(0x0022, 0x0001, opti283_read, NULL, NULL, opti283_write, NULL, NULL, dev);
@@ -286,14 +283,14 @@ opti283_init(const device_t *info)
dev->mem_remappings[1].phys = 0x000d0000;
mem_mapping_add(&dev->mem_mappings[0], 0, 0x00020000,
opti283_read_remapped_ram, opti283_read_remapped_ramw, opti283_read_remapped_raml,
opti283_write_remapped_ram, opti283_write_remapped_ramw, opti283_write_remapped_raml,
opti283_read_remapped_ram, opti283_read_remapped_ramw, opti283_read_remapped_raml,
opti283_write_remapped_ram, opti283_write_remapped_ramw, opti283_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,
opti283_read_remapped_ram, opti283_read_remapped_ramw, opti283_read_remapped_raml,
opti283_write_remapped_ram, opti283_write_remapped_ramw, opti283_write_remapped_raml,
opti283_read_remapped_ram, opti283_read_remapped_ramw, opti283_read_remapped_raml,
opti283_write_remapped_ram, opti283_write_remapped_ramw, opti283_write_remapped_raml,
&ram[dev->mem_remappings[1].phys], MEM_MAPPING_INTERNAL, &dev->mem_remappings[1]);
mem_mapping_disable(&dev->mem_mappings[1]);
@@ -302,17 +299,16 @@ opti283_init(const device_t *info)
return dev;
}
const device_t opti283_device = {
"OPTi 82C283",
"opti283",
0,
0,
opti283_init,
opti283_close,
NULL,
{ NULL },
NULL,
NULL,
NULL
.name = "OPTi 82C283",
.internal_name = "opti283",
.flags = 0,
.local = 0,
.init = opti283_init,
.close = opti283_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -1,17 +1,19 @@
/*
* 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.
*
* Implementation of the OPTi 82C291 chipset.
* Authors: plant/nerd73, Tiseno100
* Implementation of the OPTi 82C291 chipset.
*
* Copyright 2020 plant/nerd73.
* Copyright 2021 Tiseno100.
*
*
* Authors: plant/nerd73, Tiseno100
*
* Copyright 2020 plant/nerd73.
* Copyright 2021 Tiseno100.
*/
#include <stdarg.h>
#include <stdint.h>
@@ -26,135 +28,141 @@
#include <86box/io.h>
#include <86box/device.h>
#include <86box/mem.h>
#include <86box/plat_unused.h>
#include <86box/port_92.h>
#include <86box/chipset.h>
#ifdef ENABLE_OPTI291_LOG
int opti291_do_log = ENABLE_OPTI291_LOG;
static void
opti291_log(const char *fmt, ...)
{
va_list ap;
va_list ap;
if (opti291_do_log)
{
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
if (opti291_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define opti291_log(fmt, ...)
# define opti291_log(fmt, ...)
#endif
typedef struct
{
uint8_t index, regs[256];
port_92_t *port_92;
typedef struct opti291_t {
uint8_t index;
uint8_t regs[256];
port_92_t *port_92;
} opti291_t;
static void opti291_recalc(opti291_t *dev)
static void
opti291_recalc(opti291_t *dev)
{
mem_set_mem_state_both(0xf0000, 0x10000, (!(dev->regs[0x23] & 0x40) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x27] & 0x80) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL));
mem_set_mem_state_both(0xf0000, 0x10000, (!(dev->regs[0x23] & 0x40) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x27] & 0x80) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL));
for (uint32_t i = 0; i < 4; i++)
{
mem_set_mem_state_both(0xc0000 + (i << 14), 0x4000, ((dev->regs[0x26] & (1 << (i + 4))) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x27] & 0x10) ? MEM_WRITE_DISABLED : ((dev->regs[0x26] & (1 << i)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)));
mem_set_mem_state_both(0xd0000 + (i << 14), 0x4000, ((dev->regs[0x25] & (1 << (i + 4))) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x27] & 0x20) ? MEM_WRITE_DISABLED : ((dev->regs[0x25] & (1 << i)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)));
mem_set_mem_state_both(0xe0000 + (i << 14), 0x4000, ((dev->regs[0x24] & (1 << (i + 4))) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x27] & 0x40) ? MEM_WRITE_DISABLED : ((dev->regs[0x24] & (1 << i)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)));
}
flushmmucache();
for (uint32_t i = 0; i < 4; i++) {
mem_set_mem_state_both(0xc0000 + (i << 14), 0x4000, ((dev->regs[0x26] & (1 << (i + 4))) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x27] & 0x10) ? MEM_WRITE_DISABLED : ((dev->regs[0x26] & (1 << i)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)));
mem_set_mem_state_both(0xd0000 + (i << 14), 0x4000, ((dev->regs[0x25] & (1 << (i + 4))) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x27] & 0x20) ? MEM_WRITE_DISABLED : ((dev->regs[0x25] & (1 << i)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)));
mem_set_mem_state_both(0xe0000 + (i << 14), 0x4000, ((dev->regs[0x24] & (1 << (i + 4))) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[0x27] & 0x40) ? MEM_WRITE_DISABLED : ((dev->regs[0x24] & (1 << i)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)));
}
flushmmucache();
}
static void
opti291_write(uint16_t addr, uint8_t val, void *priv)
{
opti291_t *dev = (opti291_t *)priv;
opti291_t *dev = (opti291_t *) priv;
switch (addr)
{
case 0x22:
dev->index = val;
break;
case 0x24:
opti291_log("OPTi 291: dev->regs[%02x] = %02x\n", dev->index, val);
switch (dev->index)
{
case 0x20:
dev->regs[dev->index] = val & 0x3f;
break;
case 0x21:
dev->regs[dev->index] = val & 0xf3;
break;
case 0x22:
dev->regs[dev->index] = val;
break;
case 0x23:
case 0x24:
case 0x25:
case 0x26:
dev->regs[dev->index] = val;
opti291_recalc(dev);
break;
case 0x27:
case 0x28:
dev->regs[dev->index] = val;
break;
case 0x29:
dev->regs[dev->index] = val & 0x0f;
break;
case 0x2a:
case 0x2b:
case 0x2c:
dev->regs[dev->index] = val;
break;
}
break;
}
switch (addr) {
case 0x22:
dev->index = val;
break;
case 0x24:
opti291_log("OPTi 291: dev->regs[%02x] = %02x\n", dev->index, val);
switch (dev->index) {
case 0x20:
dev->regs[dev->index] = val & 0x3f;
break;
case 0x21:
dev->regs[dev->index] = val & 0xf3;
break;
case 0x22:
dev->regs[dev->index] = val;
break;
case 0x23:
case 0x24:
case 0x25:
case 0x26:
dev->regs[dev->index] = val;
opti291_recalc(dev);
break;
case 0x27:
case 0x28:
dev->regs[dev->index] = val;
break;
case 0x29:
dev->regs[dev->index] = val & 0x0f;
break;
case 0x2a:
case 0x2b:
case 0x2c:
dev->regs[dev->index] = val;
break;
default:
break;
}
break;
default:
break;
}
}
static uint8_t
opti291_read(uint16_t addr, void *priv)
{
opti291_t *dev = (opti291_t *)priv;
const opti291_t *dev = (opti291_t *) priv;
return (addr == 0x24) ? dev->regs[dev->index] : 0xff;
return (addr == 0x24) ? dev->regs[dev->index] : 0xff;
}
static void
opti291_close(void *priv)
{
opti291_t *dev = (opti291_t *)priv;
opti291_t *dev = (opti291_t *) priv;
free(dev);
free(dev);
}
static void *
opti291_init(const device_t *info)
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 *) malloc(sizeof(opti291_t));
memset(dev, 0, 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);
dev->regs[0x22] = 0xf0;
dev->regs[0x23] = 0x40;
dev->regs[0x28] = 0x08;
dev->regs[0x29] = 0xa0;
device_add(&port_92_device);
opti291_recalc(dev);
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);
dev->regs[0x22] = 0xf0;
dev->regs[0x23] = 0x40;
dev->regs[0x28] = 0x08;
dev->regs[0x29] = 0xa0;
device_add(&port_92_device);
opti291_recalc(dev);
return dev;
return dev;
}
const device_t opti291_device = {
"OPTi 82C291",
"opti291",
0,
0,
opti291_init,
opti291_close,
NULL,
{NULL},
NULL,
NULL,
NULL};
.name = "OPTi 82C291",
.internal_name = "opti291",
.flags = 0,
.local = 0,
.init = opti291_init,
.close = opti291_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -1,18 +1,19 @@
/*
* 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.
*
* Implementation of the OPTi 82C391/392 chipset.
* Implementation of the OPTi 82C391/392 chipset.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2021 Miran Grca.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2021 Miran Grca.
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
@@ -26,9 +27,9 @@
#include <86box/io.h>
#include <86box/device.h>
#include <86box/mem.h>
#include <86box/plat_unused.h>
#include <86box/chipset.h>
#ifdef ENABLE_OPTI391_LOG
int opti391_do_log = ENABLE_OPTI391_LOG;
@@ -37,160 +38,167 @@ opti391_log(const char *fmt, ...)
{
va_list ap;
if (opti391_do_log)
{
if (opti391_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define opti391_log(fmt, ...)
# define opti391_log(fmt, ...)
#endif
typedef struct
{
uint32_t phys, virt;
typedef struct mem_remapping_t {
uint32_t phys;
uint32_t virt;
} mem_remapping_t;
typedef struct
{
uint8_t index, regs[256];
typedef struct opti391_t {
uint8_t index;
uint8_t regs[256];
} opti391_t;
static void
opti391_shadow_recalc(opti391_t *dev)
{
uint32_t i, base;
uint8_t sh_enable, sh_master;
uint8_t sh_wp, sh_write_internal;
uint32_t base;
uint8_t sh_enable;
uint8_t sh_master;
uint8_t sh_wp;
uint8_t sh_write_internal;
shadowbios = shadowbios_write = 0;
/* F0000-FFFFF */
sh_enable = !(dev->regs[0x22] & 0x80);
if (sh_enable)
mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
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);
mem_set_mem_state_both(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED);
sh_write_internal = (dev->regs[0x26] & 0x40);
/* D0000-EFFFF */
for (i = 0; i < 8; i++) {
base = 0xd0000 + (i << 14);
if (base >= 0xe0000) {
sh_master = (dev->regs[0x22] & 0x40);
sh_wp = (dev->regs[0x22] & 0x10);
} else {
sh_master = (dev->regs[0x22] & 0x20);
sh_wp = (dev->regs[0x22] & 0x08);
}
sh_enable = dev->regs[0x23] & (1 << i);
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);
} else {
sh_master = (dev->regs[0x22] & 0x20);
sh_wp = (dev->regs[0x22] & 0x08);
}
sh_enable = dev->regs[0x23] & (1 << i);
if (sh_master) {
if (sh_enable) {
if (sh_wp)
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)
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
else
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
} else if (sh_write_internal)
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
else
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
if (sh_master) {
if (sh_enable) {
if (sh_wp)
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)
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
else
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
} else if (sh_write_internal)
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
else
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
}
/* C0000-CFFFF */
sh_master = !(dev->regs[0x26] & 0x10);
sh_wp = (dev->regs[0x26] & 0x20);
for (i = 0; i < 4; i++) {
base = 0xc0000 + (i << 14);
sh_enable = dev->regs[0x26] & (1 << i);
sh_wp = (dev->regs[0x26] & 0x20);
for (uint8_t i = 0; i < 4; i++) {
base = 0xc0000 + (i << 14);
sh_enable = dev->regs[0x26] & (1 << i);
if (sh_master) {
if (sh_enable) {
if (sh_wp)
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)
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
else
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
} else if (sh_write_internal)
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
else
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
if (sh_master) {
if (sh_enable) {
if (sh_wp)
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)
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
else
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
} else if (sh_write_internal)
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
else
mem_set_mem_state_both(base, 0x4000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
}
}
static void
opti391_write(uint16_t addr, uint8_t val, void *priv)
{
opti391_t *dev = (opti391_t *)priv;
opti391_t *dev = (opti391_t *) priv;
switch (addr) {
case 0x22:
dev->index = val;
break;
case 0x22:
dev->index = val;
break;
case 0x24:
opti391_log("OPTi 391: dev->regs[%02x] = %02x\n", dev->index, val);
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);
break;
switch (dev->index) {
case 0x20:
dev->regs[dev->index] = (dev->regs[dev->index] & 0xc0) | (val & 0x3f);
break;
case 0x21: case 0x24: case 0x25: case 0x27:
case 0x28: case 0x29: case 0x2a: case 0x2b:
dev->regs[dev->index] = val;
break;
case 0x21:
case 0x24:
case 0x25:
case 0x27:
case 0x28:
case 0x29:
case 0x2a:
case 0x2b:
dev->regs[dev->index] = val;
break;
case 0x22: case 0x23:
case 0x26:
dev->regs[dev->index] = val;
opti391_shadow_recalc(dev);
break;
}
break;
case 0x22:
case 0x23:
case 0x26:
dev->regs[dev->index] = val;
opti391_shadow_recalc(dev);
break;
default:
break;
}
break;
default:
break;
}
}
static uint8_t
opti391_read(uint16_t addr, void *priv)
{
opti391_t *dev = (opti391_t *)priv;
uint8_t ret = 0xff;
const opti391_t *dev = (opti391_t *) priv;
uint8_t ret = 0xff;
if (addr == 0x24)
ret = dev->regs[dev->index];
ret = dev->regs[dev->index];
return ret;
}
static void
opti391_close(void *priv)
{
opti391_t *dev = (opti391_t *)priv;
opti391_t *dev = (opti391_t *) priv;
free(dev);
}
static void *
opti391_init(const device_t *info)
opti391_init(UNUSED(const device_t *info))
{
opti391_t *dev = (opti391_t *)malloc(sizeof(opti391_t));
opti391_t *dev = (opti391_t *) malloc(sizeof(opti391_t));
memset(dev, 0x00, sizeof(opti391_t));
io_sethandler(0x0022, 0x0001, opti391_read, NULL, NULL, opti391_write, NULL, NULL, dev);
@@ -211,17 +219,16 @@ opti391_init(const device_t *info)
return dev;
}
const device_t opti391_device = {
"OPTi 82C391",
"opti391",
0,
0,
opti391_init,
opti391_close,
NULL,
{ NULL },
NULL,
NULL,
NULL
.name = "OPTi 82C391",
.internal_name = "opti391",
.flags = 0,
.local = 0,
.init = opti391_init,
.close = opti391_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -1,20 +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.
* 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.
*
* Implementation of the OPTi 82C493/82C495 chipset.
* Implementation of the OPTi 82C493/82C495 chipset.
*
*
*
* Authors: Tiseno100,
* Miran Grca, <mgrca8@gmail.com>
* Authors: Tiseno100,
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2020 Tiseno100.
* Copyright 2016-2020 Miran Grca.
* Copyright 2008-2020 Tiseno100.
* Copyright 2016-2020 Miran Grca.
*/
#include <stdarg.h>
#include <stdint.h>
@@ -31,159 +31,156 @@
#include <86box/port_92.h>
#include <86box/chipset.h>
typedef struct
{
uint8_t idx,
regs[256],
scratch[2];
typedef struct opti495_t {
uint8_t idx;
uint8_t regs[256];
uint8_t scratch[2];
} opti495_t;
#ifdef ENABLE_OPTI495_LOG
int opti495_do_log = ENABLE_OPTI495_LOG;
static void
opti495_log(const char *fmt, ...)
{
va_list ap;
if (opti495_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define opti495_log(fmt, ...)
# define opti495_log(fmt, ...)
#endif
static void
opti495_recalc(opti495_t *dev)
{
uint32_t base;
uint32_t i, shflags = 0;
uint32_t shflags = 0;
shadowbios = 0;
shadowbios = 0;
shadowbios_write = 0;
if (dev->regs[0x22] & 0x80) {
shadowbios = 1;
shadowbios_write = 0;
shflags = MEM_READ_EXTANY | MEM_WRITE_INTERNAL;
shadowbios = 1;
shadowbios_write = 0;
shflags = MEM_READ_EXTANY | MEM_WRITE_INTERNAL;
} else {
shadowbios = 0;
shadowbios_write = 1;
shflags = MEM_READ_INTERNAL | MEM_WRITE_DISABLED;
shadowbios = 0;
shadowbios_write = 1;
shflags = MEM_READ_INTERNAL | MEM_WRITE_DISABLED;
}
mem_set_mem_state_both(0xf0000, 0x10000, shflags);
for (i = 0; i < 8; i++) {
base = 0xd0000 + (i << 14);
for (uint8_t i = 0; i < 8; i++) {
base = 0xd0000 + (i << 14);
if ((dev->regs[0x22] & ((base >= 0xe0000) ? 0x20 : 0x40)) &&
(dev->regs[0x23] & (1 << i))) {
shflags = MEM_READ_INTERNAL;
shflags |= (dev->regs[0x22] & ((base >= 0xe0000) ? 0x08 : 0x10)) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
} else {
if (dev->regs[0x26] & 0x40) {
shflags = MEM_READ_EXTANY;
shflags |= (dev->regs[0x22] & ((base >= 0xe0000) ? 0x08 : 0x10)) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
} else
shflags = MEM_READ_EXTANY | MEM_WRITE_EXTANY;
}
if ((dev->regs[0x22] & ((base >= 0xe0000) ? 0x20 : 0x40)) && (dev->regs[0x23] & (1 << i))) {
shflags = MEM_READ_INTERNAL;
shflags |= (dev->regs[0x22] & ((base >= 0xe0000) ? 0x08 : 0x10)) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
} else {
if (dev->regs[0x26] & 0x40) {
shflags = MEM_READ_EXTANY;
shflags |= (dev->regs[0x22] & ((base >= 0xe0000) ? 0x08 : 0x10)) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
} else
shflags = MEM_READ_EXTANY | MEM_WRITE_EXTANY;
}
mem_set_mem_state_both(base, 0x4000, shflags);
mem_set_mem_state_both(base, 0x4000, shflags);
}
for (i = 0; i < 4; i++) {
base = 0xc0000 + (i << 14);
for (uint8_t i = 0; i < 4; i++) {
base = 0xc0000 + (i << 14);
if ((dev->regs[0x26] & 0x10) && (dev->regs[0x26] & (1 << i))) {
shflags = MEM_READ_INTERNAL;
shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
} else {
if (dev->regs[0x26] & 0x40) {
shflags = MEM_READ_EXTANY;
shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
} else
shflags = MEM_READ_EXTANY | MEM_WRITE_EXTANY;
}
if ((dev->regs[0x26] & 0x10) && (dev->regs[0x26] & (1 << i))) {
shflags = MEM_READ_INTERNAL;
shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
} else {
if (dev->regs[0x26] & 0x40) {
shflags = MEM_READ_EXTANY;
shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
} else
shflags = MEM_READ_EXTANY | MEM_WRITE_EXTANY;
}
mem_set_mem_state_both(base, 0x4000, shflags);
mem_set_mem_state_both(base, 0x4000, shflags);
}
flushmmucache();
}
static void
opti495_write(uint16_t addr, uint8_t val, void *priv)
{
opti495_t *dev = (opti495_t *) priv;
switch (addr) {
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;
opti495_log("[%04X:%08X] [W] dev->regs[%04X] = %02X\n", CS, cpu_state.pc, dev->idx, val);
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;
opti495_log("[%04X:%08X] [W] dev->regs[%04X] = %02X\n", CS, cpu_state.pc, dev->idx, val);
switch(dev->idx) {
case 0x21:
cpu_cache_ext_enabled = !!(dev->regs[0x21] & 0x10);
cpu_update_waitstates();
break;
switch (dev->idx) {
case 0x21:
cpu_cache_ext_enabled = !!(dev->regs[0x21] & 0x10);
cpu_update_waitstates();
break;
case 0x22:
case 0x23:
case 0x26:
opti495_recalc(dev);
break;
}
}
break;
case 0x22:
case 0x23:
case 0x26:
opti495_recalc(dev);
break;
default:
break;
}
}
break;
case 0xe1:
case 0xe2:
dev->scratch[~addr & 0x01] = val;
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;
opti495_t *dev = (opti495_t *) priv;
uint8_t ret = 0xff;
const 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)) {
ret = dev->regs[dev->idx];
opti495_log("[%04X:%08X] [R] dev->regs[%04X] = %02X\n", CS, cpu_state.pc, dev->idx, ret);
}
break;
case 0xe1:
case 0xe2:
ret = dev->scratch[~addr & 0x01];
break;
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)) {
ret = dev->regs[dev->idx];
opti495_log("[%04X:%08X] [R] dev->regs[%04X] = %02X\n", CS, cpu_state.pc, dev->idx, ret);
}
break;
case 0xe1:
case 0xe2:
ret = dev->scratch[~addr & 0x01];
break;
default:
break;
}
return ret;
}
static void
opti495_close(void *priv)
{
@@ -192,7 +189,6 @@ opti495_close(void *priv)
free(dev);
}
static void *
opti495_init(const device_t *info)
{
@@ -207,26 +203,26 @@ opti495_init(const device_t *info)
dev->scratch[0] = dev->scratch[1] = 0xff;
if (info->local == 1) {
/* 85C495 */
dev->regs[0x20] = 0x02;
dev->regs[0x21] = 0x20;
dev->regs[0x22] = 0xe4;
dev->regs[0x25] = 0xf0;
dev->regs[0x26] = 0x80;
dev->regs[0x27] = 0xb1;
dev->regs[0x28] = 0x80;
dev->regs[0x29] = 0x10;
/* 85C495 */
dev->regs[0x20] = 0x02;
dev->regs[0x21] = 0x20;
dev->regs[0x22] = 0xe4;
dev->regs[0x25] = 0xf0;
dev->regs[0x26] = 0x80;
dev->regs[0x27] = 0xb1;
dev->regs[0x28] = 0x80;
dev->regs[0x29] = 0x10;
} else {
/* 85C493 */
dev->regs[0x20] = 0x40;
dev->regs[0x22] = 0x84;
dev->regs[0x24] = 0x87;
dev->regs[0x25] = 0xf1; /* Note: 0xf0 is also valid default. */
dev->regs[0x27] = 0x91;
dev->regs[0x28] = 0x80;
dev->regs[0x29] = 0x10;
dev->regs[0x2a] = 0x80;
dev->regs[0x2b] = 0x10;
/* 85C493 */
dev->regs[0x20] = 0x40;
dev->regs[0x22] = 0x84;
dev->regs[0x24] = 0x87;
dev->regs[0x25] = 0xf1; /* Note: 0xf0 is also valid default. */
dev->regs[0x27] = 0x91;
dev->regs[0x28] = 0x80;
dev->regs[0x29] = 0x10;
dev->regs[0x2a] = 0x80;
dev->regs[0x2b] = 0x10;
}
opti495_recalc(dev);
@@ -236,24 +232,30 @@ opti495_init(const device_t *info)
return dev;
}
const device_t opti493_device = {
"OPTi 82C493",
"opti493",
0,
0,
opti495_init, opti495_close, NULL,
{ NULL }, NULL, NULL,
NULL
.name = "OPTi 82C493",
.internal_name = "opti493",
.flags = 0,
.local = 0,
.init = opti495_init,
.close = opti495_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t opti495_device = {
"OPTi 82C495",
"opti495",
0,
1,
opti495_init, opti495_close, NULL,
{ NULL }, NULL, NULL,
NULL
.name = "OPTi 82C495",
.internal_name = "opti495",
.flags = 0,
.local = 1,
.init = opti495_init,
.close = opti495_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -1,20 +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.
* 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.
*
* Implementation of the OPTi 82C493/82C499 chipset.
* Implementation of the OPTi 82C493/82C499 chipset.
*
*
*
* Authors: Tiseno100,
* Miran Grca, <mgrca8@gmail.com>
* Authors: Tiseno100,
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2020 Tiseno100.
* Copyright 2016-2020 Miran Grca.
* Copyright 2008-2020 Tiseno100.
* Copyright 2016-2020 Miran Grca.
*/
#include <stdarg.h>
#include <stdint.h>
@@ -29,174 +29,179 @@
#include <86box/device.h>
#include <86box/mem.h>
#include <86box/port_92.h>
#include <86box/plat_unused.h>
#include <86box/chipset.h>
typedef struct
{
uint8_t idx,
regs[256], scratch[2];
typedef struct opti499_t {
uint8_t idx;
uint8_t regs[256];
uint8_t scratch[2];
} opti499_t;
#ifdef ENABLE_OPTI499_LOG
int opti499_do_log = ENABLE_OPTI499_LOG;
static void
opti499_log(const char *fmt, ...)
{
va_list ap;
if (opti499_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define opti499_log(fmt, ...)
# define opti499_log(fmt, ...)
#endif
static void
opti499_recalc(opti499_t *dev)
{
uint32_t base;
uint32_t i, shflags = 0;
uint32_t shflags = 0;
shadowbios = 0;
shadowbios = 0;
shadowbios_write = 0;
if (dev->regs[0x22] & 0x80) {
shadowbios = 1;
shadowbios_write = 0;
shflags = MEM_READ_EXTANY | MEM_WRITE_INTERNAL;
shadowbios = 1;
shadowbios_write = 0;
shflags = MEM_READ_EXTANY | MEM_WRITE_INTERNAL;
} else {
shadowbios = 0;
shadowbios_write = 1;
shflags = MEM_READ_INTERNAL | MEM_WRITE_DISABLED;
shadowbios = 0;
shadowbios_write = 1;
shflags = MEM_READ_INTERNAL | MEM_WRITE_DISABLED;
}
mem_set_mem_state_both(0xf0000, 0x10000, shflags);
for (i = 0; i < 8; i++) {
base = 0xd0000 + (i << 14);
for (uint8_t i = 0; i < 8; i++) {
base = 0xd0000 + (i << 14);
if ((dev->regs[0x22] & ((base >= 0xe0000) ? 0x20 : 0x40)) &&
(dev->regs[0x23] & (1 << i))) {
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)))
shflags = MEM_READ_EXTANY | MEM_WRITE_EXTANY;
else
shflags = MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL;
}
if ((dev->regs[0x22] & ((base >= 0xe0000) ? 0x20 : 0x40)) && (dev->regs[0x23] & (1 << i))) {
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)))
shflags = MEM_READ_EXTANY | MEM_WRITE_EXTANY;
else
shflags = MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL;
}
mem_set_mem_state_both(base, 0x4000, shflags);
mem_set_mem_state_both(base, 0x4000, shflags);
}
for (i = 0; i < 4; i++) {
base = 0xc0000 + (i << 14);
for (uint8_t i = 0; i < 4; i++) {
base = 0xc0000 + (i << 14);
if ((dev->regs[0x26] & 0x10) && (dev->regs[0x26] & (1 << i))) {
shflags = MEM_READ_INTERNAL;
shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
} else {
if (dev->regs[0x26] & 0x40) {
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)))
shflags = MEM_READ_EXTANY | MEM_WRITE_EXTANY;
else
shflags = MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL;
}
}
if ((dev->regs[0x26] & 0x10) && (dev->regs[0x26] & (1 << i))) {
shflags = MEM_READ_INTERNAL;
shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
} else {
if (dev->regs[0x26] & 0x40) {
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)))
shflags = MEM_READ_EXTANY | MEM_WRITE_EXTANY;
else
shflags = MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL;
}
}
mem_set_mem_state_both(base, 0x4000, shflags);
mem_set_mem_state_both(base, 0x4000, shflags);
}
flushmmucache_nopc();
}
static void
opti499_write(uint16_t addr, uint8_t val, void *priv)
{
opti499_t *dev = (opti499_t *) priv;
switch (addr) {
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;
opti499_log("[%04X:%08X] [W] dev->regs[%04X] = %02X\n", CS, cpu_state.pc, dev->idx, val);
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;
opti499_log("[%04X:%08X] [W] dev->regs[%04X] = %02X\n", CS, cpu_state.pc, dev->idx, val);
switch(dev->idx) {
case 0x20:
reset_on_hlt = !(val & 0x02);
break;
switch (dev->idx) {
case 0x20:
reset_on_hlt = !(val & 0x02);
break;
case 0x21:
cpu_cache_ext_enabled = !!(dev->regs[0x21] & 0x10);
cpu_update_waitstates();
break;
case 0x21:
cpu_cache_ext_enabled = !!(dev->regs[0x21] & 0x10);
cpu_update_waitstates();
break;
case 0x22: case 0x23:
case 0x26: case 0x2d:
opti499_recalc(dev);
break;
}
}
break;
case 0x22:
case 0x23:
case 0x26:
case 0x2d:
opti499_recalc(dev);
break;
case 0xe1: case 0xe2:
dev->scratch[~addr & 0x01] = val;
break;
default:
break;
}
}
break;
case 0xe1:
case 0xe2:
dev->scratch[~addr & 0x01] = val;
break;
default:
break;
}
}
static uint8_t
opti499_read(uint16_t addr, void *priv)
{
uint8_t ret = 0xff;
uint8_t ret = 0xff;
opti499_t *dev = (opti499_t *) priv;
switch (addr) {
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];
opti499_log("[%04X:%08X] [R] dev->regs[%04X] = %02X\n", CS, cpu_state.pc, dev->idx, ret);
}
break;
case 0xe1:
case 0xe2:
ret = dev->scratch[~addr & 0x01];
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];
opti499_log("[%04X:%08X] [R] dev->regs[%04X] = %02X\n", CS, cpu_state.pc, dev->idx, ret);
}
break;
case 0xe1:
case 0xe2:
ret = dev->scratch[~addr & 0x01];
break;
default:
break;
}
return ret;
}
static void
opti499_reset(void *priv)
{
@@ -213,7 +218,7 @@ opti499_reset(void *priv)
dev->regs[0x27] = 0xd1;
dev->regs[0x28] = dev->regs[0x2a] = 0x80;
dev->regs[0x29] = dev->regs[0x2b] = 0x10;
dev->regs[0x2d] = 0x40;
dev->regs[0x2d] = 0x40;
reset_on_hlt = 1;
@@ -225,7 +230,6 @@ opti499_reset(void *priv)
free(dev);
}
static void
opti499_close(void *priv)
{
@@ -234,9 +238,8 @@ opti499_close(void *priv)
free(dev);
}
static void *
opti499_init(const device_t *info)
opti499_init(UNUSED(const device_t *info))
{
opti499_t *dev = (opti499_t *) malloc(sizeof(opti499_t));
memset(dev, 0, sizeof(opti499_t));
@@ -253,13 +256,16 @@ opti499_init(const device_t *info)
return dev;
}
const device_t opti499_device = {
"OPTi 82C499",
"opti499",
0,
1,
opti499_init, opti499_close, opti499_reset,
{ NULL }, NULL, NULL,
NULL
.name = "OPTi 82C499",
.internal_name = "opti499",
.flags = 0,
.local = 1,
.init = opti499_init,
.close = opti499_close,
.reset = opti499_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -1,20 +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.
* 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.
*
* Implementation of the OPTi 82C546/82C547(Python) & 82C596/82C597(Cobra) chipsets.
* Authors: plant/nerd73,
* Implementation of the OPTi 82C546/82C547(Python) & 82C596/82C597(Cobra) chipsets.
* Authors: plant/nerd73,
* Miran Grca, <mgrca8@gmail.com>
* Tiseno100
*
* Copyright 2020 plant/nerd73.
* Copyright 2020 Miran Grca.
* Copyright 2021 Tiseno100.
* Copyright 2020 plant/nerd73.
* Copyright 2020 Miran Grca.
* Copyright 2021 Tiseno100.
*/
#include <stdarg.h>
#include <stdint.h>
@@ -32,9 +32,10 @@
#include <86box/port_92.h>
#include <86box/chipset.h>
typedef struct
{
uint8_t idx, regs[16];
typedef struct opti5x7_t {
uint8_t idx;
uint8_t is_pci;
uint8_t regs[16];
} opti5x7_t;
#ifdef ENABLE_OPTI5X7_LOG
@@ -45,45 +46,50 @@ opti5x7_log(const char *fmt, ...)
{
va_list ap;
if (opti5x7_do_log)
{
if (opti5x7_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define opti5x7_log(fmt, ...)
# define opti5x7_log(fmt, ...)
#endif
static void
opti5x7_shadow_map(int cur_reg, opti5x7_t *dev)
{
/*
Register 4h: Cxxxx Segment
Register 5h: Dxxxx Segment
/*
Register 4h: Cxxxx Segment
Register 5h: Dxxxx Segment
Bits 7-6: xC000-xFFFF
Bits 5-4: x8000-xBFFF
Bits 3-2: x4000-x7FFF
Bits 0-1: x0000-x3FFF
Bits 7-6: xC000-xFFFF
Bits 5-4: x8000-xBFFF
Bits 3-2: x4000-x7FFF
Bits 0-1: x0000-x3FFF
x-y
0 0 Read/Write AT bus
1 0 Read from AT - Write to DRAM
1 1 Read from DRAM - Write to DRAM
0 1 Read from DRAM (write protected)
*/
if (cur_reg == 0x06)
{
mem_set_mem_state_both(0xe0000, 0x10000, ((dev->regs[6] & 1) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[6] & 2) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY));
mem_set_mem_state_both(0xf0000, 0x10000, ((dev->regs[6] & 4) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[6] & 8) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY));
}
else
{
for (int i = 0; i < 4; i++)
mem_set_mem_state_both(0xc0000 + ((cur_reg & 1) << 16) + (i << 14), 0x4000, ((dev->regs[cur_reg] & (1 << (2 * i))) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[cur_reg] & (2 << (2 * i))) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY));
x-y
0 0 Read/Write AT bus
1 0 Read from AT - Write to DRAM
1 1 Read from DRAM - Write to DRAM
0 1 Read from DRAM (write protected)
*/
if (cur_reg == 0x06) {
if (dev->is_pci) {
mem_set_mem_state_cpu_both(0xe0000, 0x10000, ((dev->regs[6] & 1) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[6] & 2) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY));
mem_set_mem_state_cpu_both(0xf0000, 0x10000, ((dev->regs[6] & 4) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[6] & 8) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY));
} else {
mem_set_mem_state_both(0xe0000, 0x10000, ((dev->regs[6] & 1) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[6] & 2) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY));
mem_set_mem_state_both(0xf0000, 0x10000, ((dev->regs[6] & 4) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[6] & 8) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY));
}
} else {
for (uint8_t i = 0; i < 4; i++) {
if (dev->is_pci)
mem_set_mem_state_cpu_both(0xc0000 + ((cur_reg & 1) << 16) + (i << 14), 0x4000, ((dev->regs[cur_reg] & (1 << (2 * i))) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[cur_reg] & (2 << (2 * i))) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY));
else
mem_set_mem_state_both(0xc0000 + ((cur_reg & 1) << 16) + (i << 14), 0x4000, ((dev->regs[cur_reg] & (1 << (2 * i))) ? MEM_READ_INTERNAL : MEM_READ_EXTANY) | ((dev->regs[cur_reg] & (2 << (2 * i))) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY));
}
}
flushmmucache_nopc();
@@ -92,63 +98,65 @@ Bits 0-1: x0000-x3FFF
static void
opti5x7_write(uint16_t addr, uint8_t val, void *priv)
{
opti5x7_t *dev = (opti5x7_t *)priv;
opti5x7_t *dev = (opti5x7_t *) priv;
switch (addr)
{
case 0x22:
dev->idx = val;
break;
case 0x24:
switch (dev->idx)
{
case 0x00: /* DRAM Configuration Register #1 */
dev->regs[dev->idx] = val & 0x7f;
switch (addr) {
case 0x22:
dev->idx = val;
break;
case 0x01: /* DRAM Control Register #1 */
dev->regs[dev->idx] = val;
case 0x24:
switch (dev->idx) {
case 0x00: /* DRAM Configuration Register #1 */
dev->regs[dev->idx] = val & 0x7f;
break;
case 0x01: /* DRAM Control Register #1 */
dev->regs[dev->idx] = val;
break;
case 0x02: /* Cache Control Register #1 */
dev->regs[dev->idx] = val;
cpu_cache_ext_enabled = !!(dev->regs[0x02] & 0x0c);
cpu_update_waitstates();
break;
case 0x03: /* Cache Control Register #2 */
dev->regs[dev->idx] = val;
break;
case 0x04: /* Shadow RAM Control Register #1 */
case 0x05: /* Shadow RAM Control Register #2 */
case 0x06: /* Shadow RAM Control Register #3 */
dev->regs[dev->idx] = val;
opti5x7_shadow_map(dev->idx, dev);
break;
case 0x07: /* Tag Test Register */
case 0x08: /* CPU Cache Control Register #1 */
case 0x09: /* System Memory Function Register #1 */
case 0x0a: /* System Memory Address Decode Register #1 */
case 0x0b: /* System Memory Address Decode Register #2 */
dev->regs[dev->idx] = val;
break;
case 0x0c: /* Extended DMA Register */
dev->regs[dev->idx] = val & 0xcf;
break;
case 0x0d: /* ROMCS# Register */
case 0x0e: /* Local Master Preemption Register */
case 0x0f: /* Deturbo Control Register #1 */
case 0x10: /* Cache Write-Hit Control Register */
case 0x11: /* Master Cycle Control Register */
dev->regs[dev->idx] = val;
break;
default:
break;
}
opti5x7_log("OPTi 5x7: dev->regs[%02x] = %02x\n", dev->idx, dev->regs[dev->idx]);
break;
case 0x02: /* Cache Control Register #1 */
dev->regs[dev->idx] = val;
cpu_cache_ext_enabled = !!(dev->regs[0x02] & 0x0c);
cpu_update_waitstates();
default:
break;
case 0x03: /* Cache Control Register #2 */
dev->regs[dev->idx] = val;
break;
case 0x04: /* Shadow RAM Control Register #1 */
case 0x05: /* Shadow RAM Control Register #2 */
case 0x06: /* Shadow RAM Control Register #3 */
dev->regs[dev->idx] = val;
opti5x7_shadow_map(dev->idx, dev);
break;
case 0x07: /* Tag Test Register */
case 0x08: /* CPU Cache Control Register #1 */
case 0x09: /* System Memory Function Register #1 */
case 0x0a: /* System Memory Address Decode Register #1 */
case 0x0b: /* System Memory Address Decode Register #2 */
dev->regs[dev->idx] = val;
break;
case 0x0c: /* Extended DMA Register */
dev->regs[dev->idx] = val & 0xcf;
break;
case 0x0d: /* ROMCS# Register */
case 0x0e: /* Local Master Preemption Register */
case 0x0f: /* Deturbo Control Register #1 */
case 0x10: /* Cache Write-Hit Control Register */
case 0x11: /* Master Cycle Control Register */
dev->regs[dev->idx] = val;
break;
}
opti5x7_log("OPTi 5x7: dev->regs[%02x] = %02x\n", dev->idx, dev->regs[dev->idx]);
break;
}
}
static uint8_t
opti5x7_read(uint16_t addr, void *priv)
{
opti5x7_t *dev = (opti5x7_t *)priv;
const opti5x7_t *dev = (opti5x7_t *) priv;
return (addr == 0x24) ? dev->regs[dev->idx] : 0xff;
}
@@ -156,7 +164,7 @@ opti5x7_read(uint16_t addr, void *priv)
static void
opti5x7_close(void *priv)
{
opti5x7_t *dev = (opti5x7_t *)priv;
opti5x7_t *dev = (opti5x7_t *) priv;
free(dev);
}
@@ -164,9 +172,11 @@ opti5x7_close(void *priv)
static void *
opti5x7_init(const device_t *info)
{
opti5x7_t *dev = (opti5x7_t *)malloc(sizeof(opti5x7_t));
opti5x7_t *dev = (opti5x7_t *) malloc(sizeof(opti5x7_t));
memset(dev, 0, sizeof(opti5x7_t));
dev->is_pci = info->local;
io_sethandler(0x0022, 0x0001, opti5x7_read, NULL, NULL, opti5x7_write, NULL, NULL, dev);
io_sethandler(0x0024, 0x0001, opti5x7_read, NULL, NULL, opti5x7_write, NULL, NULL, dev);
@@ -176,14 +186,29 @@ opti5x7_init(const device_t *info)
}
const device_t opti5x7_device = {
"OPTi 82C5x6/82C5x7",
"opti5x7",
0,
0,
opti5x7_init,
opti5x7_close,
NULL,
{NULL},
NULL,
NULL,
NULL};
.name = "OPTi 82C5x6/82C5x7",
.internal_name = "opti5x7",
.flags = 0,
.local = 0,
.init = opti5x7_init,
.close = opti5x7_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t opti5x7_pci_device = {
.name = "OPTi 82C5x6/82C5x7 (PCI)",
.internal_name = "opti5x7_pci",
.flags = 0,
.local = 1,
.init = opti5x7_init,
.close = opti5x7_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

239
src/chipset/opti602.c Normal file
View File

@@ -0,0 +1,239 @@
/*
* 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 82C601/82C602 Buffer Devices.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2023 Miran Grca.
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include "cpu.h"
#include <86box/io.h>
#include <86box/device.h>
#include <86box/mem.h>
#include <86box/timer.h>
#include <86box/nvr.h>
#include <86box/smram.h>
#include <86box/port_92.h>
#include <86box/chipset.h>
#include <86box/plat_unused.h>
typedef struct opti602_t {
uint8_t idx;
uint8_t regs[256];
uint8_t gpio[32];
uint16_t gpio_base;
uint16_t gpio_mask;
uint16_t gpio_size;
nvr_t *nvr;
} opti602_t;
#ifdef ENABLE_OPTI602_LOG
int opti602_do_log = ENABLE_OPTI602_LOG;
static void
opti602_log(const char *fmt, ...)
{
va_list ap;
if (opti602_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
# define opti602_log(fmt, ...)
#endif
static void
opti602_gpio_write(uint16_t addr, uint8_t val, void *priv)
{
opti602_t *dev = (opti602_t *) priv;
dev->gpio[addr - dev->gpio_base] = val;
}
static uint8_t
opti602_gpio_read(uint16_t addr, void *priv)
{
const opti602_t *dev = (opti602_t *) priv;
uint8_t ret = 0xff;
ret = dev->gpio[addr - dev->gpio_base];
return ret;
}
static void
opti602_gpio_recalc(opti602_t *dev)
{
if (dev->gpio_base != 0x0000)
io_removehandler(dev->gpio_base, dev->gpio_size, opti602_gpio_read, NULL, NULL, opti602_gpio_write, NULL, NULL, dev);
dev->gpio_base = dev->regs[0xf8];
dev->gpio_base |= (((uint16_t) dev->regs[0xf7]) << 8);
dev->gpio_size = 1 << ((dev->regs[0xf9] >> 2) & 0x07);
dev->gpio_mask = ~(dev->gpio_size - 1);
dev->gpio_base &= dev->gpio_mask;
dev->gpio_mask = ~dev->gpio_mask;
if (dev->gpio_base != 0x0000)
io_sethandler(dev->gpio_base, dev->gpio_size, opti602_gpio_read, NULL, NULL, opti602_gpio_write, NULL, NULL, dev);
}
static void
opti602_write(uint16_t addr, uint8_t val, void *priv)
{
opti602_t *dev = (opti602_t *) priv;
switch (addr) {
case 0x22:
dev->idx = val;
break;
case 0x24:
if ((dev->idx == 0xea) || ((dev->idx >= 0xf7) && (dev->idx <= 0xfa))) {
dev->regs[dev->idx] = val;
opti602_log("dev->regs[%04x] = %08x\n", dev->idx, val);
/* TODO: Registers 0x30-0x3F for OPTi 802GP and 898. */
switch (dev->idx) {
case 0xea:
/* GREEN Power Port */
break;
case 0xf7:
case 0xf8:
/* General Purpose Chip Select Registers */
opti602_gpio_recalc(dev);
break;
case 0xf9:
/* General Purpose Chip Select Register */
nvr_bank_set(0, !!(val & 0x20), dev->nvr);
opti602_gpio_recalc(dev);
break;
case 0xfa:
/* GPM Port */
break;
default:
break;
}
}
break;
default:
break;
}
}
static uint8_t
opti602_read(uint16_t addr, void *priv)
{
uint8_t ret = 0xff;
const opti602_t *dev = (opti602_t *) priv;
switch (addr) {
case 0x24:
if ((dev->idx == 0xea) || ((dev->idx >= 0xf7) && (dev->idx <= 0xfa))) {
ret = dev->regs[dev->idx];
if ((dev->idx == 0xfa) && (dev->regs[0xf9] & 0x40))
ret |= dev->regs[0xea];
}
break;
default:
break;
}
return ret;
}
static void
opti602_reset(void *priv)
{
opti602_t *dev = (opti602_t *) priv;
memset(dev->regs, 0x00, 256 * sizeof(uint8_t));
memset(dev->gpio, 0x00, 32 * sizeof(uint8_t));
dev->regs[0xfa] = 0x07;
dev->gpio[0x01] |= 0xfe;
nvr_bank_set(0, 0, dev->nvr);
opti602_gpio_recalc(dev);
}
static void
opti602_close(void *priv)
{
opti602_t *dev = (opti602_t *) priv;
free(dev);
}
static void *
opti602_init(UNUSED(const device_t *info))
{
opti602_t *dev = (opti602_t *) calloc(1, sizeof(opti602_t));
io_sethandler(0x0022, 0x0001, opti602_read, NULL, NULL, opti602_write, NULL, NULL, dev);
io_sethandler(0x0024, 0x0001, opti602_read, NULL, NULL, opti602_write, NULL, NULL, dev);
dev->nvr = device_add(&at_mb_nvr_device);
opti602_reset(dev);
return dev;
}
const device_t opti601_device = {
.name = "OPTi 82C601",
.internal_name = "opti601",
.flags = 0,
.local = 0,
.init = opti602_init,
.close = opti602_close,
.reset = opti602_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t opti602_device = {
.name = "OPTi 82C602",
.internal_name = "opti602",
.flags = 0,
.local = 0,
.init = opti602_init,
.close = opti602_close,
.reset = opti602_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -1,19 +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.
* 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.
*
* Implementation of the OPTi 82C822 VESA Local Bus to PCI Bridge Interface.
* Implementation of the OPTi 82C822 VESA Local Bus to PCI
* Bridge Interface.
*
*
* Authors: Tiseno100,
*
* Copyright 2021 Tiseno100.
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2022 Miran Grca.
*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
@@ -22,287 +23,381 @@
#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/io.h>
#include <86box/apm.h>
#include <86box/dma.h>
#include <86box/mem.h>
#include <86box/smram.h>
#include <86box/pci.h>
#include <86box/timer.h>
#include <86box/pic.h>
#include <86box/pit.h>
#include <86box/plat_unused.h>
#include <86box/port_92.h>
#include <86box/hdc_ide.h>
#include <86box/hdc.h>
#include <86box/machine.h>
#include <86box/chipset.h>
#include <86box/spd.h>
/* Shadow RAM */
#define SYSTEM_READ ((dev->pci_conf[0x44] & 2) ? MEM_READ_INTERNAL : MEM_READ_EXTANY)
#define SYSTEM_WRITE ((dev->pci_conf[0x44] & 1) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)
#define SHADOW_READ ((dev->pci_conf[cur_reg] & (1 << (4 + i))) ? MEM_READ_INTERNAL : MEM_READ_EXTANY)
#define SHADOW_WRITE ((dev->pci_conf[cur_reg] & (1 << i)) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY)
typedef struct opti822_t {
uint8_t irq_convert;
uint8_t pci_slot;
uint8_t pad;
uint8_t pad0;
uint8_t pci_regs[256];
} opti822_t;
// #define ENABLE_OPTI822_LOG 1
#ifdef ENABLE_OPTI822_LOG
int opti822_do_log = ENABLE_OPTI822_LOG;
static void
opti822_log(const char *fmt, ...)
{
va_list ap;
if (opti822_do_log)
{
if (opti822_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define opti822_log(fmt, ...)
# define opti822_log(fmt, ...)
#endif
typedef struct opti822_t
/* NOTE: We currently cheat and pass all PCI shadow RAM accesses to ISA as well.
This is because we currently do not have separate access mappings for
PCI and ISA at all. */
static void
opti822_recalc(opti822_t *dev)
{
uint8_t pci_conf[256];
} opti822_t;
int reg;
int bit_r;
int bit_w;
int state;
uint32_t base;
int opti822_irq_routing[7] = {5, 9, 0x0a, 0x0b, 0x0c, 0x0e, 0x0f};
for (uint8_t i = 0; i < 12; i++) {
base = 0x000c0000 + (i << 14);
reg = 0x44 + ((i >> 2) ^ 3);
bit_w = (i & 3);
bit_r = bit_w + 4;
bit_w = 1 << bit_w;
bit_r = 1 << bit_r;
state = (dev->pci_regs[reg] & bit_w) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
state |= (dev->pci_regs[reg] & bit_r) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
mem_set_mem_state_bus_both(base, 0x00004000, state);
}
void opti822_shadow(int cur_reg, opti822_t *dev)
state = (dev->pci_regs[0x44] & 0x01) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
state |= (dev->pci_regs[0x44] & 0x02) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
mem_set_mem_state_bus_both(0x000f0000, 0x00010000, state);
}
/* NOTE: We cheat here. The real ALi M1435 uses a level to edge triggered IRQ converter
when the most siginificant bit is set. We work around that by manipulating the
emulated PIC's ELCR register. */
static void
opti822_update_irqs(opti822_t *dev, int set)
{
if (cur_reg == 0x44)
mem_set_mem_state_both(0xf0000, 0x10000, SYSTEM_READ | SYSTEM_WRITE);
else
for (int i = 0; i < 4; i++)
mem_set_mem_state_both(0xe0000 - (((cur_reg & 3) - 1) << 16) + (i << 14), 0x4000, SHADOW_READ | SHADOW_WRITE);
uint8_t val;
int reg;
int shift;
int irq;
int irq_map[8] = { -1, 5, 9, 10, 11, 12, 14, 15 };
pic_t *temp_pic;
flushmmucache_nopc();
#if 0
dev->irq_convert = (dev->pci_regs[0x53] & 0x08);
#endif
dev->irq_convert = 1;
for (uint8_t i = 0; i < 16; i++) {
reg = 0x88 + (i >> 1);
shift = (i & 1) << 2;
val = (dev->pci_regs[reg] >> shift) & 0x0f;
irq = irq_map[val & 0x07];
if (irq == -1)
continue;
temp_pic = (irq >= 8) ? &pic2 : &pic;
irq &= 7;
if (dev->irq_convert && set && (val & 0x08))
temp_pic->elcr |= (1 << irq);
else
temp_pic->elcr &= ~(1 << irq);
}
}
static void
opti822_write(int func, int addr, uint8_t val, void *priv)
opti822_pci_write(int func, int addr, uint8_t val, void *priv)
{
opti822_t *dev = (opti822_t *) priv;
int irq;
int irq_map[8] = { -1, 5, 9, 10, 11, 12, 14, 15 };
int pin;
int slot;
opti822_t *dev = (opti822_t *)priv;
opti822_log("opti822_write(%02X, %02X, %02X)\n", func, addr, val);
switch (func)
{
case 0x04: /* Command Register */
dev->pci_conf[addr] = val & 0x40;
break;
if (func > 0)
return;
case 0x05: /* Command Register */
dev->pci_conf[addr] = val & 1;
break;
switch (addr) {
/* Command Register */
case 0x04:
dev->pci_regs[addr] = (val & 0x40) | 0x07;
break;
case 0x06: /* Status Register */
dev->pci_conf[addr] |= val & 0xc0;
break;
/* Status Register */
case 0x06:
if (!(dev->pci_regs[0x52] & 0x04))
dev->pci_regs[addr] = (val & 0x80);
break;
case 0x07:
dev->pci_regs[addr] &= ~(val & 0xf9);
break;
case 0x07: /* Status Register */
dev->pci_conf[addr] = val & 0xa9;
break;
/* Master Latency Timer Register */
case 0x0d:
dev->pci_regs[addr] = val;
break;
case 0x40:
dev->pci_conf[addr] = val & 0xc0;
break;
case 0x40:
dev->pci_regs[addr] = (val & 0xc0) | 0x01;
break;
case 0x41:
/* TODO: Bit 15th enable the PCI Bridge when 1. */
dev->pci_regs[addr] = val & 0xcf;
break;
case 0x41:
dev->pci_conf[addr] = val & 0xcf;
break;
case 0x42:
dev->pci_regs[addr] = val & 0xf8;
break;
case 0x43:
dev->pci_regs[addr] = val;
break;
case 0x42:
dev->pci_conf[addr] = val & 0xf8;
break;
case 0x44:
dev->pci_regs[addr] = val & 0xcb;
opti822_recalc(dev);
break;
case 0x45 ... 0x47:
dev->pci_regs[addr] = val;
opti822_recalc(dev);
break;
case 0x43:
dev->pci_conf[addr] = val;
break;
/* Memory hole stuff. */
case 0x48 ... 0x51:
dev->pci_regs[addr] = val;
break;
case 0x44: /* Shadow RAM */
case 0x45:
case 0x46:
case 0x47:
dev->pci_conf[addr] = (addr == 0x44) ? (val & 0xcb) : val;
opti822_shadow(addr, dev);
break;
case 0x52:
dev->pci_regs[addr] = val;
break;
case 0x48:
case 0x49:
case 0x4a:
case 0x4b:
case 0x4c:
case 0x4d:
case 0x4e:
case 0x4f:
case 0x50:
case 0x51:
case 0x52:
case 0x53:
case 0x54:
case 0x55:
case 0x56:
case 0x57:
dev->pci_conf[addr] = val;
break;
case 0x53:
dev->pci_regs[addr] = val;
opti822_update_irqs(dev, 0);
opti822_update_irqs(dev, 1);
break;
case 0x58:
dev->pci_conf[addr] = val & 0xfc;
break;
case 0x54 ... 0x57:
dev->pci_regs[addr] = val;
break;
case 0x59:
case 0x5a:
case 0x5b:
case 0x5c:
case 0x5d:
case 0x5e:
case 0x5f:
dev->pci_conf[addr] = val;
break;
case 0x58:
dev->pci_regs[addr] = val & 0xfc;
break;
case 0x59 ... 0x5b:
dev->pci_regs[addr] = val;
break;
case 0x60:
dev->pci_conf[addr] = val & 0xfc;
break;
case 0x5c ... 0x5f:
dev->pci_regs[addr] = val;
break;
case 0x61:
case 0x62:
case 0x63:
case 0x64:
case 0x65:
case 0x66:
case 0x67:
dev->pci_conf[addr] = val;
break;
case 0x60:
dev->pci_regs[addr] = val & 0xfc;
break;
case 0x61 ... 0x63:
dev->pci_regs[addr] = val;
break;
case 0x68:
dev->pci_conf[addr] = val & 0xfc;
break;
case 0x64 ... 0x67:
dev->pci_regs[addr] = val;
break;
case 0x69:
case 0x6a:
case 0x6b:
case 0x6c:
case 0x6d:
case 0x6e:
case 0x6f:
dev->pci_conf[addr] = val;
break;
case 0x68:
dev->pci_regs[addr] = val & 0xfc;
break;
case 0x69 ... 0x6b:
dev->pci_regs[addr] = val;
break;
case 0x70:
dev->pci_conf[addr] = val & 0xfc;
break;
case 0x6c ... 0x6f:
dev->pci_regs[addr] = val;
break;
case 0x71:
case 0x72:
case 0x73:
dev->pci_conf[addr] = val;
break;
case 0x70:
dev->pci_regs[addr] = val & 0xfc;
break;
case 0x71 ... 0x73:
dev->pci_regs[addr] = val;
break;
case 0x74:
dev->pci_conf[addr] = val & 0xfc;
break;
case 0x74:
dev->pci_regs[addr] = val & 0xf8;
break;
case 0x75:
case 0x76:
dev->pci_conf[addr] = val;
break;
/* ROMCS# and NVMCS# stuff. */
case 0x75:
dev->pci_regs[addr] = val;
break;
case 0x77:
dev->pci_conf[addr] = val & 0xe7;
break;
case 0x76:
dev->pci_regs[addr] = val;
break;
case 0x78:
dev->pci_conf[addr] = val;
break;
case 0x77:
dev->pci_regs[addr] = val;
break;
case 0x79:
dev->pci_conf[addr] = val & 0xfc;
break;
/* Enabling of memory blocks at ISA bus. */
case 0x78:
dev->pci_regs[addr] = val;
break;
case 0x79:
dev->pci_regs[addr] = val & 0xfc;
break;
case 0x7a:
case 0x7b:
case 0x7c:
case 0x7d:
case 0x7e:
dev->pci_conf[addr] = val;
break;
case 0x7a:
dev->pci_regs[addr] = val;
break;
case 0x7f:
dev->pci_conf[addr] = val & 3;
break;
case 0x7b ... 0x7c:
dev->pci_regs[addr] = val;
break;
case 0x80:
case 0x81:
case 0x82:
case 0x84:
case 0x85:
case 0x86:
dev->pci_conf[addr] = val;
break;
case 0x7d ... 0x7e:
dev->pci_regs[addr] = val;
break;
case 0x88: /* PCI IRQ Routing */
case 0x89: /* Very hacky implementation. Needs surely a rewrite after */
case 0x8a: /* a PCI rework happens. */
case 0x8b:
case 0x8c:
case 0x8d:
case 0x8e:
case 0x8f:
dev->pci_conf[addr] = val;
if (addr % 2)
{
pci_set_irq_routing(PCI_INTB, ((val & 0x0f) != 0) ? opti822_irq_routing[(val & 7) - 1] : PCI_IRQ_DISABLED);
pci_set_irq_routing(PCI_INTA, (((val >> 4) & 0x0f) != 0) ? opti822_irq_routing[((val >> 4) & 7) - 1] : PCI_IRQ_DISABLED);
}
else
{
pci_set_irq_routing(PCI_INTD, ((val & 0x0f) != 0) ? opti822_irq_routing[(val & 7) - 1] : PCI_IRQ_DISABLED);
pci_set_irq_routing(PCI_INTC, (((val >> 4) & 0x0f) != 0) ? opti822_irq_routing[((val >> 4) & 7) - 1] : PCI_IRQ_DISABLED);
}
break;
case 0x7f:
dev->pci_regs[addr] = val & 0x03;
break;
case 0x80 ... 0x81:
dev->pci_regs[addr] = val;
break;
case 0x82:
dev->pci_regs[addr] = val;
break;
case 0x84 ... 0x85:
dev->pci_regs[addr] = val;
break;
case 0x86:
dev->pci_regs[addr] = val;
break;
case 0x88 ... 0x8f:
dev->pci_regs[addr] = val;
opti822_update_irqs(dev, 0);
irq = irq_map[val & 0x07];
pin = 4 - ((addr & 0x01) << 1);
slot = ((addr & 0x06) >> 1);
if (irq >= 0) {
opti822_log("Set IRQ routing: INT %c%c -> %02X\n", pin + 0x40, slot + 0x31, irq);
pci_set_irq_routing(pin + (slot << 2), irq);
pci_set_irq_level(pin + (slot << 2), !!(val & 0x07));
} else {
opti822_log("Set IRQ routing: INT %c%c -> FF\n", pin + 0x40, slot + 0x31);
pci_set_irq_routing(pin + (slot << 2), PCI_IRQ_DISABLED);
}
irq = irq_map[(val >> 4) & 0x07];
pin = 3 - ((addr & 0x01) << 1);
slot = ((addr & 0x06) >> 1);
if (irq >= 0) {
opti822_log("Set IRQ routing: INT %c%c -> %02X\n", pin + 0x40, slot + 0x31, irq);
pci_set_irq_routing(pin + (slot << 2), irq);
pci_set_irq_level(pin + (slot << 2), !!((val >> 4) & 0x07));
} else {
opti822_log("Set IRQ routing: INT %c%c -> FF\n", pin + 0x40, slot + 0x31);
pci_set_irq_routing(pin + (slot << 2), PCI_IRQ_DISABLED);
}
opti822_update_irqs(dev, 1);
break;
default:
break;
}
opti822_log("OPTI822: dev->pci_conf[%02x] = %02x\n", addr, dev->pci_conf[addr]);
}
static uint8_t
opti822_read(int func, int addr, void *priv)
opti822_pci_read(int func, int addr, void *priv)
{
opti822_t *dev = (opti822_t *)priv;
return dev->pci_conf[addr];
const opti822_t *dev = (opti822_t *) priv;
uint8_t ret;
ret = 0xff;
if (func == 0)
ret = dev->pci_regs[addr];
opti822_log("opti822_read(%02X, %02X) = %02X\n", func, addr, ret);
return ret;
}
static void
opti822_reset(void *priv)
{
opti822_t *dev = (opti822_t *)priv;
opti822_t *dev = (opti822_t *) priv;
dev->pci_conf[0x00] = 0x45;
dev->pci_conf[0x01] = 0x10;
dev->pci_conf[0x02] = 0x22;
dev->pci_conf[0x03] = 0xc8;
dev->pci_conf[0x04] = 7;
dev->pci_conf[0x06] = 0x40;
dev->pci_conf[0x07] = 1;
dev->pci_conf[0x08] = 1;
dev->pci_conf[0x0b] = 6;
dev->pci_conf[0x0d] = 0x20;
dev->pci_conf[0x40] = 1;
dev->pci_conf[0x43] = 0x20;
dev->pci_conf[0x52] = 6;
dev->pci_conf[0x53] = 0x90;
memset(dev->pci_regs, 0, 256);
dev->pci_regs[0x00] = 0x45;
dev->pci_regs[0x01] = 0x10; /*OPTi*/
dev->pci_regs[0x02] = 0x22;
dev->pci_regs[0x03] = 0xc8; /*82C822 PCIB*/
dev->pci_regs[0x04] = 0x07;
dev->pci_regs[0x06] = 0x80;
dev->pci_regs[0x07] = 0x02;
dev->pci_regs[0x08] = 0x01;
dev->pci_regs[0x0b] = 0x06;
dev->pci_regs[0x0d] = 0x20;
dev->pci_regs[0x40] = 0x01;
dev->pci_regs[0x41] = 0x0c;
dev->pci_regs[0x43] = 0x02;
dev->pci_regs[0x52] = 0x06;
dev->pci_regs[0x53] = 0x90;
dev->irq_convert = 1 /*0*/;
for (uint8_t i = 0; i < 16; i++)
pci_set_irq_routing(PCI_INTA + i, PCI_IRQ_DISABLED);
}
static void
opti822_close(void *priv)
{
opti822_t *dev = (opti822_t *)priv;
opti822_t *dev = (opti822_t *) priv;
free(dev);
}
static void *
opti822_init(const device_t *info)
opti822_init(UNUSED(const device_t *info))
{
opti822_t *dev = (opti822_t *)malloc(sizeof(opti822_t));
opti822_t *dev = (opti822_t *) malloc(sizeof(opti822_t));
memset(dev, 0, sizeof(opti822_t));
pci_add_card(PCI_ADD_NORTHBRIDGE, opti822_read, opti822_write, dev);
pci_add_card(PCI_ADD_NORTHBRIDGE, opti822_pci_read, opti822_pci_write, dev, &dev->pci_slot);
opti822_reset(dev);
@@ -310,14 +405,15 @@ opti822_init(const device_t *info)
}
const device_t opti822_device = {
"OPTi 82C822 PCIB",
"opti822",
DEVICE_PCI,
0,
opti822_init,
opti822_close,
opti822_reset,
{NULL},
NULL,
NULL,
NULL};
.name = "OPTi 82C822 PCIB",
.internal_name = "opti822",
.flags = DEVICE_PCI,
.local = 0,
.init = opti822_init,
.close = opti822_close,
.reset = opti822_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -1,20 +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.
* 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.
*
* Implementation of the OPTi 82C802G/82C895 chipset.
* Implementation of the OPTi 82C802G/82C895 chipset.
*
*
*
* Authors: Tiseno100,
* Miran Grca, <mgrca8@gmail.com>
* Authors: Tiseno100,
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2020 Tiseno100.
* Copyright 2016-2020 Miran Grca.
* Copyright 2008-2020 Tiseno100.
* Copyright 2016-2020 Miran Grca.
*/
#include <stdarg.h>
#include <stdint.h>
@@ -32,196 +32,212 @@
#include <86box/port_92.h>
#include <86box/chipset.h>
typedef struct opti895_t {
uint8_t idx;
uint8_t forced_green;
uint8_t is_pci;
uint8_t regs[256];
uint8_t scratch[2];
typedef struct
{
uint8_t idx, forced_green,
regs[256],
scratch[2];
smram_t *smram;
smram_t *smram;
} opti895_t;
#define ENABLE_OPTI895_LOG 1
#ifdef ENABLE_OPTI895_LOG
int opti895_do_log = ENABLE_OPTI895_LOG;
static void
opti895_log(const char *fmt, ...)
{
va_list ap;
if (opti895_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define opti895_log(fmt, ...)
# define opti895_log(fmt, ...)
#endif
static void
opti895_recalc(opti895_t *dev)
{
uint32_t base;
uint32_t i, shflags = 0;
uint32_t shflags = 0;
shadowbios = 0;
shadowbios = 0;
shadowbios_write = 0;
if (dev->regs[0x22] & 0x80) {
shadowbios = 1;
shadowbios_write = 0;
shflags = MEM_READ_EXTANY | MEM_WRITE_INTERNAL;
shadowbios = 1;
shadowbios_write = 0;
shflags = MEM_READ_EXTANY | MEM_WRITE_INTERNAL;
} else {
shadowbios = 0;
shadowbios_write = 1;
shflags = MEM_READ_INTERNAL | MEM_WRITE_DISABLED;
shadowbios = 0;
shadowbios_write = 1;
shflags = MEM_READ_INTERNAL | MEM_WRITE_DISABLED;
}
mem_set_mem_state_both(0xf0000, 0x10000, shflags);
if (dev->is_pci)
mem_set_mem_state_cpu_both(0xf0000, 0x10000, shflags);
else
mem_set_mem_state_both(0xf0000, 0x10000, shflags);
for (i = 0; i < 8; i++) {
base = 0xd0000 + (i << 14);
for (uint8_t i = 0; i < 8; i++) {
base = 0xd0000 + (i << 14);
if (dev->regs[0x23] & (1 << i)) {
shflags = MEM_READ_INTERNAL;
shflags |= (dev->regs[0x22] & ((base >= 0xe0000) ? 0x08 : 0x10)) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
} else {
shflags = (dev->regs[0x2d] & (1 << ((i >> 1) + 2))) ? MEM_READ_EXTANY : MEM_READ_EXTERNAL;
if (dev->regs[0x26] & 0x40)
shflags |= (dev->regs[0x22] & ((base >= 0xe0000) ? 0x08 : 0x10)) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
else {
if (dev->regs[0x26] & 0x80)
shflags |= (dev->regs[0x2d] & (1 << ((i >> 1) + 2))) ? MEM_WRITE_EXTANY : MEM_WRITE_EXTERNAL;
else
shflags |= MEM_WRITE_EXTERNAL;
}
}
if (dev->regs[0x23] & (1 << i)) {
shflags = MEM_READ_INTERNAL;
shflags |= (dev->regs[0x22] & ((base >= 0xe0000) ? 0x08 : 0x10)) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
} else {
shflags = (dev->regs[0x2d] & (1 << ((i >> 1) + 2))) ? MEM_READ_EXTANY : MEM_READ_EXTERNAL;
if (dev->regs[0x26] & 0x40)
shflags |= (dev->regs[0x22] & ((base >= 0xe0000) ? 0x08 : 0x10)) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
else {
if (dev->regs[0x26] & 0x80)
shflags |= (dev->regs[0x2d] & (1 << ((i >> 1) + 2))) ? MEM_WRITE_EXTANY : MEM_WRITE_EXTERNAL;
else
shflags |= MEM_WRITE_EXTERNAL;
}
}
mem_set_mem_state_both(base, 0x4000, shflags);
if (dev->is_pci)
mem_set_mem_state_cpu_both(base, 0x4000, shflags);
else
mem_set_mem_state_both(base, 0x4000, shflags);
}
for (i = 0; i < 4; i++) {
base = 0xc0000 + (i << 14);
for (uint8_t i = 0; i < 4; i++) {
base = 0xc0000 + (i << 14);
if (dev->regs[0x26] & (1 << i)) {
shflags = MEM_READ_INTERNAL;
shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
} else {
shflags = (dev->regs[0x2d] & (1 << (i >> 1))) ? MEM_READ_EXTANY : MEM_READ_EXTERNAL;
if (dev->regs[0x26] & 0x40)
shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
else {
if (dev->regs[0x26] & 0x80)
shflags |= (dev->regs[0x2d] & (1 << (i >> 1))) ? MEM_WRITE_EXTANY : MEM_WRITE_EXTERNAL;
else
shflags |= MEM_WRITE_EXTERNAL;
}
}
if (dev->regs[0x26] & (1 << i)) {
shflags = MEM_READ_INTERNAL;
shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
} else {
shflags = (dev->regs[0x2d] & (1 << (i >> 1))) ? MEM_READ_EXTANY : MEM_READ_EXTERNAL;
if (dev->regs[0x26] & 0x40)
shflags |= (dev->regs[0x26] & 0x20) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
else {
if (dev->regs[0x26] & 0x80)
shflags |= (dev->regs[0x2d] & (1 << (i >> 1))) ? MEM_WRITE_EXTANY : MEM_WRITE_EXTERNAL;
else
shflags |= MEM_WRITE_EXTERNAL;
}
}
mem_set_mem_state_both(base, 0x4000, shflags);
if (dev->is_pci)
mem_set_mem_state_cpu_both(base, 0x4000, shflags);
else
mem_set_mem_state_both(base, 0x4000, shflags);
}
flushmmucache_nopc();
}
static void
opti895_write(uint16_t addr, uint8_t val, void *priv)
{
opti895_t *dev = (opti895_t *) priv;
opti895_log("opti895_write(%04X, %08X)\n", addr, val);
switch (addr) {
case 0x22:
dev->idx = val;
break;
case 0x23:
if (dev->idx == 0x01) {
dev->regs[dev->idx] = val;
opti895_log("dev->regs[%04x] = %08x\n", dev->idx, val);
}
break;
case 0x24:
if (((dev->idx >= 0x20) && (dev->idx <= 0x2f)) ||
((dev->idx >= 0xe0) && (dev->idx <= 0xef))) {
dev->regs[dev->idx] = val;
opti895_log("dev->regs[%04x] = %08x\n", dev->idx, val);
case 0x22:
dev->idx = val;
break;
case 0x23:
if (dev->idx == 0x01) {
dev->regs[dev->idx] = val;
opti895_log("dev->regs[%04x] = %08x\n", dev->idx, val);
}
break;
case 0x24:
if (((dev->idx >= 0x20) && (dev->idx <= 0x2f)) || ((dev->idx >= 0xe0) && (dev->idx <= 0xef))) {
dev->regs[dev->idx] = val;
opti895_log("dev->regs[%04x] = %08x\n", dev->idx, val);
switch(dev->idx) {
case 0x21:
cpu_cache_ext_enabled = !!(dev->regs[0x21] & 0x10);
cpu_update_waitstates();
break;
/* TODO: Registers 0x30-0x3F for OPTi 802GP and 898. */
switch (dev->idx) {
case 0x21:
cpu_cache_ext_enabled = !!(dev->regs[0x21] & 0x10);
cpu_update_waitstates();
break;
case 0x22:
case 0x23:
case 0x26:
case 0x2d:
opti895_recalc(dev);
break;
case 0x22:
case 0x23:
case 0x26:
case 0x2d:
opti895_recalc(dev);
break;
case 0x24:
smram_state_change(dev->smram, 0, !!(val & 0x80));
break;
case 0x24:
smram_state_change(dev->smram, 0, !!(val & 0x80));
break;
case 0xe0:
if (!(val & 0x01))
dev->forced_green = 0;
break;
case 0xe0:
if (!(val & 0x01))
dev->forced_green = 0;
break;
case 0xe1:
if ((val & 0x08) && (dev->regs[0xe0] & 0x01)) {
smi_line = 1;
dev->forced_green = 1;
break;
}
break;
}
}
break;
case 0xe1:
if ((val & 0x08) && (dev->regs[0xe0] & 0x01)) {
smi_raise();
dev->forced_green = 1;
break;
}
break;
case 0xe1:
case 0xe2:
dev->scratch[addr - 0xe1] = val;
break;
default:
break;
}
}
break;
case 0xe1:
case 0xe2:
dev->scratch[addr - 0xe1] = val;
break;
default:
break;
}
}
static uint8_t
opti895_read(uint16_t addr, void *priv)
{
uint8_t ret = 0xff;
opti895_t *dev = (opti895_t *) priv;
uint8_t ret = 0xff;
const opti895_t *dev = (opti895_t *) priv;
switch (addr) {
case 0x23:
if (dev->idx == 0x01)
ret = dev->regs[dev->idx];
break;
case 0x24:
if (((dev->idx >= 0x20) && (dev->idx <= 0x2f)) ||
((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;
}
break;
case 0xe1:
case 0xe2:
ret = dev->scratch[addr - 0xe1];
break;
case 0x23:
if (dev->idx == 0x01)
ret = dev->regs[dev->idx];
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))) {
ret = dev->regs[dev->idx];
if (dev->idx == 0xe0)
ret = (ret & 0xf6) | (in_smm ? 0x00 : 0x08) | !!dev->forced_green;
}
break;
case 0xe1:
case 0xe2:
ret = dev->scratch[addr - 0xe1];
break;
default:
break;
}
opti895_log("opti895_read(%04X) = %02X\n", addr, ret);
return ret;
}
static void
opti895_close(void *priv)
{
@@ -232,7 +248,6 @@ opti895_close(void *priv)
free(dev);
}
static void *
opti895_init(const device_t *info)
{
@@ -243,6 +258,8 @@ opti895_init(const device_t *info)
io_sethandler(0x0022, 0x0003, opti895_read, NULL, NULL, opti895_write, NULL, NULL, dev);
dev->is_pci = info->local;
dev->scratch[0] = dev->scratch[1] = 0xff;
dev->regs[0x01] = 0xc0;
@@ -273,24 +290,44 @@ opti895_init(const device_t *info)
return dev;
}
const device_t opti802g_device = {
"OPTi 82C802G",
"opti802g",
0,
0,
opti895_init, opti895_close, NULL,
{ NULL }, NULL, NULL,
NULL
.name = "OPTi 82C802G",
.internal_name = "opti802g",
.flags = 0,
.local = 0,
.init = opti895_init,
.close = opti895_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t opti802g_pci_device = {
.name = "OPTi 82C802G (PCI)",
.internal_name = "opti802g_pci",
.flags = 0,
.local = 1,
.init = opti895_init,
.close = opti895_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t opti895_device = {
"OPTi 82C895",
"opti895",
0,
0,
opti895_init, opti895_close, NULL,
{ NULL }, NULL, NULL,
NULL
.name = "OPTi 82C895",
.internal_name = "opti895",
.flags = 0,
.local = 0,
.init = opti895_init,
.close = opti895_close,
.reset = NULL,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

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

File diff suppressed because it is too large Load Diff

View File

@@ -10,29 +10,29 @@
#include <86box/io.h>
#include <86box/device.h>
#include <86box/mem.h>
#include <86box/plat_unused.h>
#include <86box/chipset.h>
typedef struct
{
uint8_t cur_reg, tries,
regs[258];
typedef struct rabbit_t {
uint8_t cur_reg;
uint8_t tries;
uint8_t regs[258];
} rabbit_t;
static void
rabbit_recalcmapping(rabbit_t *dev)
{
uint32_t shread, shwrite;
uint32_t shread;
uint32_t shwrite;
uint32_t shflags = 0;
shread = !!(dev->regs[0x101] & 0x40);
shread = !!(dev->regs[0x101] & 0x40);
shwrite = !!(dev->regs[0x100] & 0x02);
shflags = shread ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
shflags |= shwrite ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
shadowbios = !!shread;
shadowbios = !!shread;
shadowbios_write = !!shwrite;
#ifdef USE_SHADOW_C0000
@@ -42,79 +42,83 @@ rabbit_recalcmapping(rabbit_t *dev)
#endif
switch (dev->regs[0x100] & 0x09) {
case 0x01:
case 0x01:
/* The one BIOS we use seems to use something else to control C0000-DFFFF shadow,
no idea what. */
#ifdef USE_SHADOW_C0000
/* 64K at 0C0000-0CFFFF */
mem_set_mem_state(0x000c0000, 0x00010000, shflags);
/* FALLTHROUGH */
/* 64K at 0C0000-0CFFFF */
mem_set_mem_state(0x000c0000, 0x00010000, shflags);
/* FALLTHROUGH */
#endif
case 0x00:
/* 64K at 0F0000-0FFFFF */
mem_set_mem_state(0x000f0000, 0x00010000, shflags);
break;
case 0x00:
/* 64K at 0F0000-0FFFFF */
mem_set_mem_state(0x000f0000, 0x00010000, shflags);
break;
case 0x09:
case 0x09:
#ifdef USE_SHADOW_C0000
/* 128K at 0C0000-0DFFFF */
mem_set_mem_state(0x000c0000, 0x00020000, shflags);
/* FALLTHROUGH */
/* 128K at 0C0000-0DFFFF */
mem_set_mem_state(0x000c0000, 0x00020000, shflags);
/* FALLTHROUGH */
#endif
case 0x08:
/* 128K at 0E0000-0FFFFF */
mem_set_mem_state(0x000e0000, 0x00020000, shflags);
break;
case 0x08:
/* 128K at 0E0000-0FFFFF */
mem_set_mem_state(0x000e0000, 0x00020000, shflags);
break;
default:
break;
}
flushmmucache();
}
static void
rabbit_write(uint16_t addr, uint8_t val, void *priv)
{
rabbit_t *dev = (rabbit_t *) priv;
switch (addr) {
case 0x22:
dev->cur_reg = val;
dev->tries = 0;
break;
case 0x23:
if (dev->cur_reg == 0x83) {
if (dev->tries < 0x02) {
dev->regs[dev->tries++ | 0x100] = val;
if (dev->tries == 0x02)
rabbit_recalcmapping(dev);
}
} else
dev->regs[dev->cur_reg] = val;
break;
case 0x22:
dev->cur_reg = val;
dev->tries = 0;
break;
case 0x23:
if (dev->cur_reg == 0x83) {
if (dev->tries < 0x02) {
dev->regs[dev->tries++ | 0x100] = val;
if (dev->tries == 0x02)
rabbit_recalcmapping(dev);
}
} else
dev->regs[dev->cur_reg] = val;
break;
default:
break;
}
}
static uint8_t
rabbit_read(uint16_t addr, void *priv)
{
uint8_t ret = 0xff;
uint8_t ret = 0xff;
rabbit_t *dev = (rabbit_t *) priv;
switch (addr) {
case 0x23:
if (dev->cur_reg == 0x83) {
if (dev->tries < 0x02)
ret = dev->regs[dev->tries++ | 0x100];
} else
ret = dev->regs[dev->cur_reg];
break;
case 0x23:
if (dev->cur_reg == 0x83) {
if (dev->tries < 0x02)
ret = dev->regs[dev->tries++ | 0x100];
} else
ret = dev->regs[dev->cur_reg];
break;
default:
break;
}
return ret;
}
static void
rabbit_close(void *priv)
{
@@ -123,9 +127,8 @@ rabbit_close(void *priv)
free(dev);
}
static void *
rabbit_init(const device_t *info)
rabbit_init(UNUSED(const device_t *info))
{
rabbit_t *dev = (rabbit_t *) malloc(sizeof(rabbit_t));
memset(dev, 0, sizeof(rabbit_t));
@@ -135,13 +138,16 @@ rabbit_init(const device_t *info)
return dev;
}
const device_t rabbit_device = {
"SiS Rabbit",
"rabbit",
0,
0,
rabbit_init, rabbit_close, NULL,
{ NULL }, NULL, NULL,
NULL
};
.name = "SiS Rabbit",
.internal_name = "rabbit",
.flags = 0,
.local = 0,
.init = rabbit_init,
.close = rabbit_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

@@ -1,17 +1,19 @@
/*
* 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.
*
* Emulation of the SiS 85c401/85c402, 85c460, 85c461, and
* 85c407/85c471 chipsets.
* Emulation of the SiS 85c401/85c402, 85c460, 85c461, and
* 85c407/85c471 chipsets.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2019,2020 Miran Grca.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2019-2020 Miran Grca.
*/
#include <stdarg.h>
#include <stdint.h>
@@ -26,6 +28,7 @@
#include <86box/timer.h>
#include <86box/io.h>
#include <86box/device.h>
#include <86box/plat_unused.h>
#include <86box/port_92.h>
#include <86box/mem.h>
#include <86box/smram.h>
@@ -33,278 +36,315 @@
#include <86box/machine.h>
#include <86box/chipset.h>
typedef struct
{
uint8_t cur_reg, tries,
reg_base, reg_last,
reg_00, is_471,
regs[39], scratch[2];
uint32_t mem_state[8];
smram_t *smram;
port_92_t *port_92;
typedef struct sis_85c4xx_t {
uint8_t cur_reg;
uint8_t tries;
uint8_t reg_base;
uint8_t reg_last;
uint8_t reg_00;
uint8_t is_471;
uint8_t force_flush;
uint8_t shadowed;
uint8_t smram_enabled;
uint8_t pad;
uint8_t regs[39];
uint8_t scratch[2];
uint32_t mem_state[8];
smram_t *smram;
port_92_t *port_92;
} sis_85c4xx_t;
static void
sis_85c4xx_recalcremap(sis_85c4xx_t *dev)
{
if (dev->is_471) {
if ((mem_size > 8192) || (dev->shadowed & 0x3c) || (dev->regs[0x0b] & 0x02))
mem_remap_top(0);
else
mem_remap_top(-256);
}
}
static void
sis_85c4xx_recalcmapping(sis_85c4xx_t *dev)
{
uint32_t base, n = 0;
uint32_t i, shflags = 0;
uint32_t readext, writeext;
uint8_t romcs = 0xc0, cur_romcs;
uint32_t base;
uint32_t n = 0;
uint32_t shflags = 0;
uint32_t readext;
uint32_t writeext;
uint8_t romcs = 0xc0;
uint8_t cur_romcs;
shadowbios = 0;
dev->shadowed = 0x00;
shadowbios = 0;
shadowbios_write = 0;
if (dev->regs[0x03] & 0x40)
romcs |= 0x01;
romcs |= 0x01;
if (dev->regs[0x03] & 0x80)
romcs |= 0x30;
romcs |= 0x30;
if (dev->regs[0x08] & 0x04)
romcs |= 0x02;
romcs |= 0x02;
for (i = 0; i < 8; i++) {
base = 0xc0000 + (i << 15);
cur_romcs = romcs & (1 << i);
readext = cur_romcs ? MEM_READ_EXTANY : MEM_READ_EXTERNAL;
writeext = cur_romcs ? MEM_WRITE_EXTANY : MEM_WRITE_EXTERNAL;
for (uint8_t i = 0; i < 8; i++) {
base = 0xc0000 + (i << 15);
cur_romcs = romcs & (1 << i);
readext = cur_romcs ? MEM_READ_EXTANY : MEM_READ_EXTERNAL;
writeext = cur_romcs ? MEM_WRITE_EXTANY : MEM_WRITE_EXTERNAL;
if ((i > 5) || (dev->regs[0x02] & (1 << i))) {
shadowbios |= (base >= 0xe0000) && (dev->regs[0x02] & 0x80);
shadowbios_write |= (base >= 0xe0000) && !(dev->regs[0x02] & 0x40);
shflags = (dev->regs[0x02] & 0x80) ? MEM_READ_INTERNAL : readext;
shflags |= (dev->regs[0x02] & 0x40) ? writeext : MEM_WRITE_INTERNAL;
if (dev->mem_state[i] != shflags) {
n++;
mem_set_mem_state(base, 0x8000, shflags);
if ((base >= 0xf0000) && (dev->mem_state[i] & MEM_READ_INTERNAL) && !(shflags & MEM_READ_INTERNAL))
mem_invalidate_range(base, base + 0x7fff);
dev->mem_state[i] = shflags;
}
} else {
shflags = readext | writeext;
if (dev->mem_state[i] != shflags) {
n++;
mem_set_mem_state(base, 0x8000, shflags);
dev->mem_state[i] = shflags;
}
}
if ((i > 5) || (dev->regs[0x02] & (1 << i))) {
shadowbios |= (base >= 0xe0000) && (dev->regs[0x02] & 0x80);
shadowbios_write |= (base >= 0xe0000) && !(dev->regs[0x02] & 0x40);
shflags = (dev->regs[0x02] & 0x80) ? MEM_READ_INTERNAL : readext;
shflags |= (dev->regs[0x02] & 0x40) ? writeext : MEM_WRITE_INTERNAL;
if (dev->regs[0x02] & 0x80)
dev->shadowed |= (1 << i);
if (!(dev->regs[0x02] & 0x40))
dev->shadowed |= (1 << i);
if (dev->force_flush || (dev->mem_state[i] != shflags)) {
n++;
mem_set_mem_state_both(base, 0x8000, shflags);
if ((base >= 0xf0000) && (dev->mem_state[i] & MEM_READ_INTERNAL) && !(shflags & MEM_READ_INTERNAL))
mem_invalidate_range(base, base + 0x7fff);
dev->mem_state[i] = shflags;
}
} else {
shflags = readext | writeext;
if (dev->force_flush || (dev->mem_state[i] != shflags)) {
n++;
mem_set_mem_state_both(base, 0x8000, shflags);
dev->mem_state[i] = shflags;
}
}
}
if (n > 0)
flushmmucache_nopc();
if (dev->force_flush) {
flushmmucache();
dev->force_flush = 0;
} else if (n > 0)
flushmmucache_nopc();
sis_85c4xx_recalcremap(dev);
}
static void
sis_85c4xx_sw_smi_out(uint16_t port, uint8_t val, void *priv)
sis_85c4xx_sw_smi_out(UNUSED(uint16_t port), UNUSED(uint8_t val), void *priv)
{
sis_85c4xx_t *dev = (sis_85c4xx_t *) priv;
if (dev->regs[0x18] & 0x02) {
if (dev->regs[0x0b] & 0x10)
smi_line = 1;
else
picint(1 << ((dev->regs[0x0b] & 0x08) ? 15 : 12));
soft_reset_mask = 1;
dev->regs[0x19] |= 0x02;
if (dev->regs[0x0b] & 0x10)
smi_raise();
else
picint(1 << ((dev->regs[0x0b] & 0x08) ? 15 : 12));
soft_reset_mask = 1;
dev->regs[0x19] |= 0x02;
}
}
static void
sis_85c4xx_sw_smi_handler(sis_85c4xx_t *dev)
{
uint16_t addr;
if (!dev->is_471)
return;
return;
addr = dev->regs[0x14] | (dev->regs[0x15] << 8);
io_handler((dev->regs[0x0b] & 0x80) && (dev->regs[0x18] & 0x02), addr, 0x0001,
NULL, NULL, NULL, sis_85c4xx_sw_smi_out, NULL, NULL, dev);
NULL, NULL, NULL, sis_85c4xx_sw_smi_out, NULL, NULL, dev);
}
static void
sis_85c4xx_out(uint16_t port, uint8_t val, void *priv)
{
sis_85c4xx_t *dev = (sis_85c4xx_t *) priv;
uint8_t rel_reg = dev->cur_reg - dev->reg_base;
uint8_t valxor = 0x00;
uint32_t host_base = 0x000e0000, ram_base = 0x000a0000;
sis_85c4xx_t *dev = (sis_85c4xx_t *) priv;
uint8_t rel_reg = dev->cur_reg - dev->reg_base;
uint8_t valxor = 0x00;
uint32_t host_base = 0x000e0000;
uint32_t ram_base = 0x000a0000;
switch (port) {
case 0x22:
dev->cur_reg = val;
break;
case 0x23:
if ((dev->cur_reg >= dev->reg_base) && (dev->cur_reg <= dev->reg_last)) {
valxor = val ^ dev->regs[rel_reg];
if (rel_reg == 0x19)
dev->regs[rel_reg] &= ~val;
else
dev->regs[rel_reg] = val;
case 0x22:
dev->cur_reg = val;
break;
case 0x23:
if ((dev->cur_reg >= dev->reg_base) && (dev->cur_reg <= dev->reg_last)) {
valxor = val ^ dev->regs[rel_reg];
if (rel_reg == 0x19)
dev->regs[rel_reg] &= ~val;
else if (rel_reg == 0x00)
dev->regs[rel_reg] = (dev->regs[rel_reg] & 0x1f) | (val & 0xe0);
else
dev->regs[rel_reg] = val;
switch (rel_reg) {
case 0x01:
cpu_cache_ext_enabled = ((val & 0x84) == 0x84);
cpu_update_waitstates();
break;
switch (rel_reg) {
case 0x01:
cpu_cache_ext_enabled = ((val & 0x84) == 0x84);
cpu_update_waitstates();
break;
case 0x02: case 0x03:
case 0x08:
if (valxor)
sis_85c4xx_recalcmapping(dev);
break;
case 0x02:
case 0x03:
case 0x08:
if (valxor)
sis_85c4xx_recalcmapping(dev);
break;
case 0x0b:
sis_85c4xx_sw_smi_handler(dev);
if (dev->is_471 && (valxor & 0x02)) {
if (val & 0x02)
mem_remap_top(0);
else
mem_remap_top(256);
}
break;
case 0x0b:
sis_85c4xx_sw_smi_handler(dev);
if (valxor & 0x02)
sis_85c4xx_recalcremap(dev);
break;
case 0x13:
if (dev->is_471 && (valxor & 0xf0)) {
smram_disable(dev->smram);
host_base = (val & 0x80) ? 0x00060000 : 0x000e0000;
switch ((val >> 5) & 0x03) {
case 0x00:
ram_base = 0x000a0000;
break;
case 0x01:
ram_base = 0x000b0000;
break;
case 0x02:
ram_base = (val & 0x80) ? 0x00000000 : 0x000e0000;
break;
default:
ram_base = 0x00000000;
break;
}
if (ram_base != 0x00000000)
smram_enable(dev->smram, host_base, ram_base, 0x00010000, (val & 0x10), 1);
}
break;
case 0x13:
if (dev->is_471 && (valxor & 0xf0)) {
smram_disable(dev->smram);
host_base = (val & 0x80) ? 0x00060000 : 0x000e0000;
switch ((val >> 5) & 0x03) {
case 0x00:
ram_base = 0x000a0000;
break;
case 0x01:
ram_base = 0x000b0000;
break;
case 0x02:
ram_base = (val & 0x80) ? 0x00000000 : 0x000e0000;
break;
default:
ram_base = 0x00000000;
break;
}
dev->smram_enabled = (ram_base != 0x00000000);
if (ram_base != 0x00000000)
smram_enable(dev->smram, host_base, ram_base, 0x00010000, (val & 0x10), 1);
sis_85c4xx_recalcremap(dev);
}
break;
case 0x14: case 0x15:
case 0x18:
sis_85c4xx_sw_smi_handler(dev);
break;
case 0x14:
case 0x15:
case 0x18:
sis_85c4xx_sw_smi_handler(dev);
break;
case 0x1c:
if (dev->is_471)
soft_reset_mask = 0;
break;
case 0x1c:
if (dev->is_471)
soft_reset_mask = 0;
break;
case 0x22:
if (dev->is_471 && (valxor & 0x01)) {
port_92_remove(dev->port_92);
if (val & 0x01)
port_92_add(dev->port_92);
}
break;
}
} else if ((dev->reg_base == 0x60) && (dev->cur_reg == 0x00))
dev->reg_00 = val;
dev->cur_reg = 0x00;
break;
case 0x22:
if (dev->is_471 && (valxor & 0x01)) {
port_92_remove(dev->port_92);
if (val & 0x01)
port_92_add(dev->port_92);
}
break;
default:
break;
}
} else if ((dev->reg_base == 0x60) && (dev->cur_reg == 0x00))
dev->reg_00 = val;
dev->cur_reg = 0x00;
break;
case 0xe1: case 0xe2:
dev->scratch[port - 0xe1] = val;
return;
case 0xe1:
case 0xe2:
dev->scratch[port - 0xe1] = val;
return;
default:
break;
}
}
static uint8_t
sis_85c4xx_in(uint16_t port, void *priv)
{
sis_85c4xx_t *dev = (sis_85c4xx_t *) priv;
uint8_t rel_reg = dev->cur_reg - dev->reg_base;
uint8_t ret = 0xff;
sis_85c4xx_t *dev = (sis_85c4xx_t *) priv;
uint8_t rel_reg = dev->cur_reg - dev->reg_base;
uint8_t ret = 0xff;
switch (port) {
case 0x23:
if (dev->is_471 && (dev->cur_reg == 0x1c))
ret = inb(0x70);
/* On the SiS 40x, the shadow RAM read and write enable bits are write-only! */
if ((dev->reg_base == 0x60) && (dev->cur_reg == 0x62))
ret = dev->regs[rel_reg] & 0x3f;
else if ((dev->cur_reg >= dev->reg_base) && (dev->cur_reg <= dev->reg_last))
ret = dev->regs[rel_reg];
else if ((dev->reg_base == 0x60) && (dev->cur_reg == 0x00))
ret = dev->reg_00;
if (dev->reg_base != 0x60)
dev->cur_reg = 0x00;
break;
case 0x23:
if (dev->is_471 && (dev->cur_reg == 0x1c))
ret = inb(0x70);
/* On the SiS 40x, the shadow RAM read and write enable bits are write-only! */
if ((dev->reg_base == 0x60) && (dev->cur_reg == 0x62))
ret = dev->regs[rel_reg] & 0x3f;
else if ((dev->cur_reg >= dev->reg_base) && (dev->cur_reg <= dev->reg_last))
ret = dev->regs[rel_reg];
else if ((dev->reg_base == 0x60) && (dev->cur_reg == 0x00))
ret = dev->reg_00;
if (dev->reg_base != 0x60)
dev->cur_reg = 0x00;
break;
case 0xe1: case 0xe2:
ret = dev->scratch[port - 0xe1];
case 0xe1:
case 0xe2:
ret = dev->scratch[port - 0xe1];
break;
default:
break;
}
return ret;
}
static void
sis_85c4xx_reset(void *priv)
{
sis_85c4xx_t *dev = (sis_85c4xx_t *) priv;
int mem_size_mb = mem_size >> 10;
sis_85c4xx_t *dev = (sis_85c4xx_t *) priv;
int mem_size_mb = mem_size >> 10;
static uint8_t ram_4xx[64] = { 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x0b, 0x00, 0x00, 0x00,
0x19, 0x00, 0x06, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
0x19, 0x00, 0x06, 0x00, 0x14, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1b, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static uint8_t ram_471[64] = { 0x00, 0x00, 0x01, 0x01, 0x02, 0x20, 0x09, 0x09, 0x04, 0x04, 0x05, 0x05, 0x0b, 0x0b, 0x0b, 0x0b,
0x13, 0x21, 0x06, 0x06, 0x0d, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
0x1b, 0x1b, 0x1b, 0x1b, 0x0f, 0x0f, 0x0f, 0x0f, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e };
0x13, 0x21, 0x06, 0x06, 0x0d, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
0x1b, 0x1b, 0x1b, 0x1b, 0x0f, 0x0f, 0x0f, 0x0f, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e };
memset(dev->regs, 0x00, sizeof(dev->regs));
if (cpu_s->rspeed < 25000000)
dev->regs[0x08] = 0x80;
dev->regs[0x08] = 0x80;
if (dev->is_471) {
dev->regs[0x09] = 0x40;
if (mem_size_mb >= 64) {
if ((mem_size_mb >= 65) && (mem_size_mb < 68))
dev->regs[0x09] |= 0x22;
else
dev->regs[0x09] |= 0x24;
} else
dev->regs[0x09] |= ram_471[mem_size_mb];
dev->regs[0x09] = 0x40;
if (mem_size_mb >= 64) {
if ((mem_size_mb >= 65) && (mem_size_mb < 68))
dev->regs[0x09] |= 0x22;
else
dev->regs[0x09] |= 0x24;
} else
dev->regs[0x09] |= ram_471[mem_size_mb];
dev->regs[0x11] = 0x09;
dev->regs[0x12] = 0xff;
dev->regs[0x1f] = 0x20; /* Video access enabled. */
dev->regs[0x23] = 0xf0;
dev->regs[0x26] = 0x01;
dev->regs[0x11] = 0x09;
dev->regs[0x12] = 0xff;
dev->regs[0x1f] = 0x20; /* Video access enabled. */
dev->regs[0x23] = 0xf0;
dev->regs[0x26] = 0x01;
smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x00010000, 0, 1);
smram_enable(dev->smram, 0x000e0000, 0x000a0000, 0x00010000, 0, 1);
port_92_remove(dev->port_92);
port_92_remove(dev->port_92);
mem_remap_top(256);
soft_reset_mask = 0;
soft_reset_mask = 0;
} else {
/* Bits 6 and 7 must be clear on the SiS 40x. */
if (dev->reg_base == 0x60)
dev->reg_00 = 0x24;
/* Bits 6 and 7 must be clear on the SiS 40x. */
if (dev->reg_base == 0x60)
dev->reg_00 = 0x24;
if (mem_size_mb == 64)
dev->regs[0x00] = 0x1f;
else if (mem_size_mb < 64)
dev->regs[0x00] = ram_4xx[mem_size_mb];
if (mem_size_mb == 64)
dev->regs[0x00] = 0x1f;
else if (mem_size_mb < 64)
dev->regs[0x00] = ram_4xx[mem_size_mb];
dev->regs[0x11] = 0x01;
dev->regs[0x11] = 0x01;
}
dev->scratch[0] = dev->scratch[1] = 0xff;
@@ -312,22 +352,21 @@ sis_85c4xx_reset(void *priv)
cpu_cache_ext_enabled = 0;
cpu_update_waitstates();
dev->force_flush = 1;
sis_85c4xx_recalcmapping(dev);
}
static void
sis_85c4xx_close(void *priv)
{
sis_85c4xx_t *dev = (sis_85c4xx_t *) priv;
if (dev->is_471)
smram_del(dev->smram);
smram_del(dev->smram);
free(dev);
}
static void *
sis_85c4xx_init(const device_t *info)
{
@@ -339,63 +378,78 @@ sis_85c4xx_init(const device_t *info)
dev->reg_base = info->local & 0xff;
if (dev->is_471) {
dev->reg_last = dev->reg_base + 0x76;
dev->reg_last = dev->reg_base + 0x76;
dev->smram = smram_add();
dev->smram = smram_add();
dev->port_92 = device_add(&port_92_device);
dev->port_92 = device_add(&port_92_device);
} else
dev->reg_last = dev->reg_base + 0x11;
dev->reg_last = dev->reg_base + 0x11;
io_sethandler(0x0022, 0x0002,
sis_85c4xx_in, NULL, NULL, sis_85c4xx_out, NULL, NULL, dev);
sis_85c4xx_in, NULL, NULL, sis_85c4xx_out, NULL, NULL, dev);
io_sethandler(0x00e1, 0x0002,
sis_85c4xx_in, NULL, NULL, sis_85c4xx_out, NULL, NULL, dev);
sis_85c4xx_in, NULL, NULL, sis_85c4xx_out, NULL, NULL, dev);
sis_85c4xx_reset(dev);
return dev;
}
const device_t sis_85c401_device = {
"SiS 85c401/85c402",
"sis_85c401",
0,
0x060,
sis_85c4xx_init, sis_85c4xx_close, sis_85c4xx_reset,
{ NULL }, NULL, NULL,
NULL
.name = "SiS 85c401/85c402",
.internal_name = "sis_85c401",
.flags = 0,
.local = 0x060,
.init = sis_85c4xx_init,
.close = sis_85c4xx_close,
.reset = sis_85c4xx_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t sis_85c460_device = {
"SiS 85c460",
"sis_85c460",
0,
0x050,
sis_85c4xx_init, sis_85c4xx_close, sis_85c4xx_reset,
{ NULL }, NULL, NULL,
NULL
.name = "SiS 85c460",
.internal_name = "sis_85c460",
.flags = 0,
.local = 0x050,
.init = sis_85c4xx_init,
.close = sis_85c4xx_close,
.reset = sis_85c4xx_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
/* TODO: Log to make sure the registers are correct. */
const device_t sis_85c461_device = {
"SiS 85c461",
"sis_85c461",
0,
0x050,
sis_85c4xx_init, sis_85c4xx_close, sis_85c4xx_reset,
{ NULL }, NULL, NULL,
NULL
.name = "SiS 85c461",
.internal_name = "sis_85c461",
.flags = 0,
.local = 0x050,
.init = sis_85c4xx_init,
.close = sis_85c4xx_close,
.reset = sis_85c4xx_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};
const device_t sis_85c471_device = {
"SiS 85c407/85c471",
"sis_85c471",
0,
0x150,
sis_85c4xx_init, sis_85c4xx_close, sis_85c4xx_reset,
{ NULL }, NULL, NULL,
NULL
.name = "SiS 85c407/85c471",
.internal_name = "sis_85c471",
.flags = 0,
.local = 0x150,
.init = sis_85c4xx_init,
.close = sis_85c4xx_close,
.reset = sis_85c4xx_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -1,20 +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.
* 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.
*
* Implementation of the SiS 85C50x Chipset.
* Implementation of the SiS 85C50x Chipset.
*
*
*
* Authors: Tiseno100,
* Miran Grca, <mgrca8@gmail.com>
* Authors: Tiseno100,
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2020,2021 Tiseno100.
* Copyright 2020,2021 Miran Grca.
* Copyright 2020-2021 Tiseno100.
* Copyright 2020-2021 Miran Grca.
*/
#include <stdarg.h>
#include <stdio.h>
@@ -29,6 +29,9 @@
#include <86box/timer.h>
#include <86box/apm.h>
#include <86box/machine.h>
#include <86box/pic.h>
#include <86box/plat_unused.h>
#include <86box/mem.h>
#include <86box/smram.h>
#include <86box/pci.h>
@@ -36,285 +39,337 @@
#include <86box/chipset.h>
#ifdef ENABLE_SIS_85C50X_LOG
int sis_85c50x_do_log = ENABLE_SIS_85C50X_LOG;
static void
sis_85c50x_log(const char *fmt, ...)
{
va_list ap;
if (sis_85c50x_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define sis_85c50x_log(fmt, ...)
# define sis_85c50x_log(fmt, ...)
#endif
typedef struct sis_85c50x_t {
uint8_t index;
uint8_t nb_slot;
uint8_t sb_slot;
uint8_t pad;
typedef struct sis_85c50x_t
{
uint8_t index,
pci_conf[256], pci_conf_sb[256],
regs[256];
uint8_t pci_conf[256];
uint8_t pci_conf_sb[256];
uint8_t regs[256];
smram_t * smram;
port_92_t * port_92;
smram_t *smram[2];
port_92_t *port_92;
} sis_85c50x_t;
static void
sis_85c50x_shadow_recalc(sis_85c50x_t *dev)
{
uint32_t base, i, can_read, can_write;
uint32_t base;
uint32_t can_read;
uint32_t can_write;
can_read = (dev->pci_conf[0x53] & 0x40) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
can_read = (dev->pci_conf[0x53] & 0x40) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
can_write = (dev->pci_conf[0x53] & 0x20) ? MEM_WRITE_EXTANY : MEM_WRITE_INTERNAL;
if (!can_read)
can_write = MEM_WRITE_EXTANY;
can_write = MEM_WRITE_EXTANY;
mem_set_mem_state_both(0xf0000, 0x10000, can_read | can_write);
shadowbios = 1;
shadowbios = 1;
shadowbios_write = 1;
for (i = 0; i < 4; i++) {
base = 0xe0000 + (i << 14);
mem_set_mem_state_both(base, 0x4000, (dev->pci_conf[0x54] & (1 << (7 - i))) ? (can_read | can_write) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY));
base = 0xd0000 + (i << 14);
mem_set_mem_state_both(base, 0x4000, (dev->pci_conf[0x55] & (1 << (7 - i))) ? (can_read | can_write) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY));
base = 0xc0000 + (i << 14);
mem_set_mem_state_both(base, 0x4000, (dev->pci_conf[0x56] & (1 << (7 - i))) ? (can_read | can_write) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY));
for (uint8_t i = 0; i < 4; i++) {
base = 0xe0000 + (i << 14);
mem_set_mem_state_both(base, 0x4000, (dev->pci_conf[0x54] & (1 << (7 - i))) ? (can_read | can_write) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY));
base = 0xd0000 + (i << 14);
mem_set_mem_state_both(base, 0x4000, (dev->pci_conf[0x55] & (1 << (7 - i))) ? (can_read | can_write) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY));
base = 0xc0000 + (i << 14);
mem_set_mem_state_both(base, 0x4000, (dev->pci_conf[0x56] & (1 << (7 - i))) ? (can_read | can_write) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY));
}
flushmmucache_nopc();
}
static void
sis_85c50x_smm_recalc(sis_85c50x_t *dev)
{
/* NOTE: Naming mismatch - what the datasheet calls "host address" is what we call ram_base. */
uint32_t ram_base = (dev->pci_conf[0x64] << 20) |
((dev->pci_conf[0x65] & 0x07) << 28);
uint32_t host_base = (dev->pci_conf[0x64] << 20) | ((dev->pci_conf[0x65] & 0x07) << 28);
smram_disable(dev->smram);
smram_disable_all();
if ((((dev->pci_conf[0x65] & 0xe0) >> 5) != 0x00) && (ram_base == 0x00000000))
return;
if ((((dev->pci_conf[0x65] & 0xe0) >> 5) != 0x00) && (host_base == 0x00000000))
return;
switch ((dev->pci_conf[0x65] & 0xe0) >> 5) {
case 0x00:
smram_enable(dev->smram, 0xe0000, 0xe0000, 0x8000, (dev->pci_conf[0x65] & 0x10), 1);
break;
case 0x01:
smram_enable(dev->smram, 0xb0000, ram_base, 0x10000, (dev->pci_conf[0x65] & 0x10), 1);
break;
case 0x02:
smram_enable(dev->smram, 0xa0000, ram_base, 0x10000, (dev->pci_conf[0x65] & 0x10), 1);
break;
case 0x04:
smram_enable(dev->smram, 0xa0000, ram_base, 0x8000, (dev->pci_conf[0x65] & 0x10), 1);
break;
case 0x06:
smram_enable(dev->smram, 0xb0000, ram_base, 0x8000, (dev->pci_conf[0x65] & 0x10), 1);
break;
case 0x00:
sis_85c50x_log("SiS 50x SMRAM: 000E0000-000E7FFF -> 000E0000-000E7FFF\n");
smram_enable(dev->smram[0], 0xe0000, 0xe0000, 0x8000, (dev->pci_conf[0x65] & 0x10), 1);
break;
case 0x01:
host_base |= 0x000b0000;
sis_85c50x_log("SiS 50x SMRAM: %08X-%08X -> 000B0000-000BFFFF\n", host_base, host_base + 0x10000 - 1);
smram_enable(dev->smram[0], host_base, 0xb0000, 0x10000, (dev->pci_conf[0x65] & 0x10), 1);
smram_enable(dev->smram[1], host_base ^ 0x00100000, 0xb0000, 0x10000, (dev->pci_conf[0x65] & 0x10), 1);
break;
case 0x02:
host_base |= 0x000a0000;
sis_85c50x_log("SiS 50x SMRAM: %08X-%08X -> 000A0000-000AFFFF\n", host_base, host_base + 0x10000 - 1);
smram_enable(dev->smram[0], host_base, 0xa0000, 0x10000, (dev->pci_conf[0x65] & 0x10), 1);
smram_enable(dev->smram[1], host_base ^ 0x00100000, 0xa0000, 0x10000, (dev->pci_conf[0x65] & 0x10), 1);
break;
case 0x04:
host_base |= 0x000a0000;
sis_85c50x_log("SiS 50x SMRAM: %08X-%08X -> 000A0000-000AFFFF\n", host_base, host_base + 0x8000 - 1);
smram_enable(dev->smram[0], host_base, 0xa0000, 0x8000, (dev->pci_conf[0x65] & 0x10), 1);
smram_enable(dev->smram[1], host_base ^ 0x00100000, 0xa0000, 0x8000, (dev->pci_conf[0x65] & 0x10), 1);
break;
case 0x06:
host_base |= 0x000b0000;
sis_85c50x_log("SiS 50x SMRAM: %08X-%08X -> 000B0000-000BFFFF\n", host_base, host_base + 0x8000 - 1);
smram_enable(dev->smram[0], host_base, 0xb0000, 0x8000, (dev->pci_conf[0x65] & 0x10), 1);
smram_enable(dev->smram[1], host_base ^ 0x00100000, 0xa0000, 0x8000, (dev->pci_conf[0x65] & 0x10), 1);
break;
default:
break;
}
}
static void
sis_85c50x_write(int func, int addr, uint8_t val, void *priv)
{
sis_85c50x_t *dev = (sis_85c50x_t *)priv;
uint8_t valxor = (val ^ dev->pci_conf[addr]);
sis_85c50x_t *dev = (sis_85c50x_t *) priv;
switch (addr) {
case 0x04: /* Command - low byte */
dev->pci_conf[addr] = (dev->pci_conf[addr] & 0xb4) | (val & 0x4b);
break;
case 0x07: /* Status - high byte */
dev->pci_conf[addr] = ((dev->pci_conf[addr] & 0xf9) & ~(val & 0xf8)) | (val & 0x06);
break;
case 0x50:
dev->pci_conf[addr] = val;
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;
break;
case 0x53: /* Shadow RAM */
case 0x54:
case 0x55:
case 0x56:
dev->pci_conf[addr] = val;
sis_85c50x_shadow_recalc(dev);
if (addr == 0x54)
sis_85c50x_smm_recalc(dev);
break;
case 0x57: case 0x58: case 0x59: case 0x5a:
case 0x5c: case 0x5d: case 0x5e: case 0x61:
case 0x62: case 0x63: case 0x67: case 0x68:
case 0x6a: case 0x6b: case 0x6c: case 0x6d:
case 0x6e: case 0x6f:
dev->pci_conf[addr] = val;
break;
case 0x5f:
dev->pci_conf[addr] = val & 0xfe;
break;
case 0x5b:
dev->pci_conf[addr] = val;
if (valxor & 0xc0)
port_92_set_features(dev->port_92, !!(val & 0x40), !!(val & 0x80));
break;
case 0x60: /* SMI */
if ((dev->pci_conf[0x68] & 0x01) && !(dev->pci_conf[addr] & 0x02) && (val & 0x02)) {
dev->pci_conf[0x69] |= 0x01;
smi_line = 1;
}
dev->pci_conf[addr] = val & 0x3e;
break;
case 0x64: /* SMRAM */
case 0x65:
dev->pci_conf[addr] = val;
sis_85c50x_smm_recalc(dev);
break;
case 0x66:
dev->pci_conf[addr] = (val & 0x7f);
break;
case 0x69:
dev->pci_conf[addr] &= ~(val);
break;
}
sis_85c50x_log("85C501: [W] (%02X, %02X) = %02X\n", func, addr, val);
sis_85c50x_log("85C501: dev->pci_conf[%02x] = %02x\n", addr, val);
if (func == 0x00)
switch (addr) {
case 0x04: /* Command - low byte */
dev->pci_conf[addr] = (dev->pci_conf[addr] & 0xb4) | (val & 0x4b);
break;
case 0x07: /* Status - high byte */
dev->pci_conf[addr] = ((dev->pci_conf[addr] & 0xf9) & ~(val & 0xf8)) | (val & 0x06);
break;
case 0x50:
dev->pci_conf[addr] = val;
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;
break;
case 0x53: /* Shadow RAM */
case 0x54:
case 0x55:
case 0x56:
dev->pci_conf[addr] = val;
sis_85c50x_shadow_recalc(dev);
if (addr == 0x54)
sis_85c50x_smm_recalc(dev);
break;
case 0x57:
case 0x58:
case 0x59:
case 0x5a:
case 0x5c:
case 0x5d:
case 0x5e:
case 0x61:
case 0x62:
case 0x63:
case 0x67:
case 0x68:
case 0x6a:
case 0x6b:
case 0x6c:
case 0x6d:
case 0x6e:
case 0x6f:
dev->pci_conf[addr] = val;
break;
case 0x5f:
dev->pci_conf[addr] = val & 0xfe;
break;
case 0x5b:
dev->pci_conf[addr] = val;
break;
case 0x60: /* SMI */
if ((dev->pci_conf[0x68] & 0x01) && !(dev->pci_conf[addr] & 0x02) && (val & 0x02)) {
dev->pci_conf[0x69] |= 0x01;
smi_raise();
}
dev->pci_conf[addr] = val & 0x3e;
break;
case 0x64: /* SMRAM */
case 0x65:
dev->pci_conf[addr] = val;
sis_85c50x_smm_recalc(dev);
break;
case 0x66:
dev->pci_conf[addr] = (val & 0x7f);
break;
case 0x69:
dev->pci_conf[addr] &= ~val;
break;
default:
break;
}
}
static uint8_t
sis_85c50x_read(int func, int addr, void *priv)
{
sis_85c50x_t *dev = (sis_85c50x_t *)priv;
const sis_85c50x_t *dev = (sis_85c50x_t *) priv;
uint8_t ret = 0xff;
sis_85c50x_log("85C501: dev->pci_conf[%02x] (%02x)\n", addr, dev->pci_conf[addr]);
if (func == 0x00)
ret = dev->pci_conf[addr];
return dev->pci_conf[addr];
}
static void
sis_85c50x_sb_write(int func, int addr, uint8_t val, void *priv)
{
sis_85c50x_t *dev = (sis_85c50x_t *)priv;
switch (addr) {
case 0x04: /* Command */
dev->pci_conf_sb[addr] = val & 0x0f;
break;
case 0x07: /* Status */
dev->pci_conf_sb[addr] &= ~(val & 0x30);
break;
case 0x40: /* BIOS Control Register */
dev->pci_conf_sb[addr] = val & 0x3f;
break;
case 0x41: case 0x42: case 0x43: case 0x44:
/* INTA/B/C/D# Remapping Control Register */
dev->pci_conf_sb[addr] = val & 0x8f;
if (val & 0x80)
pci_set_irq_routing(PCI_INTA + (addr - 0x41), PCI_IRQ_DISABLED);
else
pci_set_irq_routing(PCI_INTA + (addr - 0x41), val & 0xf);
break;
case 0x48: /* ISA Master/DMA Memory Cycle Control Register 1 */
case 0x49: /* ISA Master/DMA Memory Cycle Control Register 2 */
case 0x4a: /* ISA Master/DMA Memory Cycle Control Register 3 */
case 0x4b: /* ISA Master/DMA Memory Cycle Control Register 4 */
dev->pci_conf_sb[addr] = val;
break;
}
sis_85c50x_log("85C503: dev->pci_conf_sb[%02x] = %02x\n", addr, val);
}
static uint8_t
sis_85c50x_sb_read(int func, int addr, void *priv)
{
sis_85c50x_t *dev = (sis_85c50x_t *)priv;
sis_85c50x_log("85C503: dev->pci_conf_sb[%02x] (%02x)\n", addr, dev->pci_conf_sb[addr]);
return dev->pci_conf_sb[addr];
}
static void
sis_85c50x_isa_write(uint16_t addr, uint8_t val, void *priv)
{
sis_85c50x_t *dev = (sis_85c50x_t *)priv;
switch (addr) {
case 0x22:
dev->index = val;
break;
case 0x23:
switch (dev->index) {
case 0x80:
dev->regs[dev->index] = val & 0xe7;
break;
case 0x81:
dev->regs[dev->index] = val & 0xf4;
break;
case 0x84: case 0x88: case 0x9: case 0x8a:
case 0x8b:
dev->regs[dev->index] = val;
break;
case 0x85:
outb(0x70, val);
break;
}
break;
}
sis_85c50x_log("85C501-ISA: dev->regs[%02x] = %02x\n", addr, val);
}
static uint8_t
sis_85c50x_isa_read(uint16_t addr, void *priv)
{
sis_85c50x_t *dev = (sis_85c50x_t *)priv;
uint8_t ret = 0xff;
switch (addr) {
case 0x22:
ret = dev->index;
break;
case 0x23:
if (dev->index == 0x85)
ret = inb(0x70);
else
ret = dev->regs[dev->index];
break;
}
sis_85c50x_log("85C501-ISA: dev->regs[%02x] (%02x)\n", dev->index, ret);
sis_85c50x_log("85C501: [R] (%02X, %02X) = %02X\n", func, addr, ret);
return ret;
}
static void
sis_85c50x_sb_write(int func, int addr, uint8_t val, void *priv)
{
sis_85c50x_t *dev = (sis_85c50x_t *) priv;
sis_85c50x_log("85C503: [W] (%02X, %02X) = %02X\n", func, addr, val);
if (func == 0x00)
switch (addr) {
case 0x04: /* Command */
dev->pci_conf_sb[addr] = val & 0x0f;
break;
case 0x07: /* Status */
dev->pci_conf_sb[addr] &= ~(val & 0x30);
break;
case 0x40: /* BIOS Control Register */
dev->pci_conf_sb[addr] = val & 0x3f;
break;
case 0x41:
case 0x42:
case 0x43:
case 0x44:
/* INTA/B/C/D# Remapping Control Register */
dev->pci_conf_sb[addr] = val & 0x8f;
if (val & 0x80)
pci_set_irq_routing(PCI_INTA + (addr - 0x41), PCI_IRQ_DISABLED);
else
pci_set_irq_routing(PCI_INTA + (addr - 0x41), val & 0xf);
break;
case 0x48: /* ISA Master/DMA Memory Cycle Control Register 1 */
case 0x49: /* ISA Master/DMA Memory Cycle Control Register 2 */
case 0x4a: /* ISA Master/DMA Memory Cycle Control Register 3 */
case 0x4b: /* ISA Master/DMA Memory Cycle Control Register 4 */
dev->pci_conf_sb[addr] = val;
break;
default:
break;
}
}
static uint8_t
sis_85c50x_sb_read(int func, int addr, void *priv)
{
const sis_85c50x_t *dev = (sis_85c50x_t *) priv;
uint8_t ret = 0xff;
if (func == 0x00)
ret = dev->pci_conf_sb[addr];
sis_85c50x_log("85C503: [W] (%02X, %02X) = %02X\n", func, addr, ret);
return ret;
}
static void
sis_85c50x_isa_write(uint16_t addr, uint8_t val, void *priv)
{
sis_85c50x_t *dev = (sis_85c50x_t *) priv;
sis_85c50x_log("85C503 ISA: [W] (%04X) = %02X\n", addr, val);
switch (addr) {
case 0x22:
dev->index = val;
break;
case 0x23:
switch (dev->index) {
case 0x80:
dev->regs[dev->index] = val & 0xe7;
break;
case 0x81:
dev->regs[dev->index] = val & 0xf4;
break;
case 0x84:
case 0x88:
case 0x89:
case 0x8a:
case 0x8b:
dev->regs[dev->index] = val;
break;
case 0x85:
outb(0x70, val);
break;
default:
break;
}
break;
default:
break;
}
}
static uint8_t
sis_85c50x_isa_read(uint16_t addr, void *priv)
{
const sis_85c50x_t *dev = (sis_85c50x_t *) priv;
uint8_t ret = 0xff;
switch (addr) {
case 0x22:
ret = dev->index;
break;
case 0x23:
if (dev->index == 0x85)
ret = inb(0x70);
else
ret = dev->regs[dev->index];
break;
default:
break;
}
sis_85c50x_log("85C503 ISA: [R] (%04X) = %02X\n", addr, ret);
return ret;
}
static void
sis_85c50x_reset(void *priv)
{
sis_85c50x_t *dev = (sis_85c50x_t *)priv;
sis_85c50x_t *dev = (sis_85c50x_t *) priv;
/* North Bridge (SiS 85C501/502) */
dev->pci_conf[0x00] = 0x39;
@@ -352,37 +407,38 @@ sis_85c50x_reset(void *priv)
dev->pci_conf_sb[0x09] = 0x00;
dev->pci_conf_sb[0x0a] = 0x01;
dev->pci_conf_sb[0x0b] = 0x06;
sis_85c50x_write(0, 0x41, 0x80, dev);
sis_85c50x_write(0, 0x42, 0x80, dev);
sis_85c50x_write(0, 0x43, 0x80, dev);
sis_85c50x_write(0, 0x44, 0x80, dev);
sis_85c50x_sb_write(0, 0x41, 0x80, dev);
sis_85c50x_sb_write(0, 0x42, 0x80, dev);
sis_85c50x_sb_write(0, 0x43, 0x80, dev);
sis_85c50x_sb_write(0, 0x44, 0x80, dev);
}
static void
sis_85c50x_close(void *priv)
{
sis_85c50x_t *dev = (sis_85c50x_t *)priv;
sis_85c50x_t *dev = (sis_85c50x_t *) priv;
smram_del(dev->smram);
smram_del(dev->smram[1]);
smram_del(dev->smram[0]);
free(dev);
}
static void *
sis_85c50x_init(const device_t *info)
sis_85c50x_init(UNUSED(const device_t *info))
{
sis_85c50x_t *dev = (sis_85c50x_t *)malloc(sizeof(sis_85c50x_t));
sis_85c50x_t *dev = (sis_85c50x_t *) malloc(sizeof(sis_85c50x_t));
memset(dev, 0x00, sizeof(sis_85c50x_t));
/* 501/502 (Northbridge) */
pci_add_card(PCI_ADD_NORTHBRIDGE, sis_85c50x_read, sis_85c50x_write, dev);
pci_add_card(PCI_ADD_NORTHBRIDGE, sis_85c50x_read, sis_85c50x_write, dev, &dev->nb_slot);
/* 503 (Southbridge) */
pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_85c50x_sb_read, sis_85c50x_sb_write, dev);
pci_add_card(PCI_ADD_SOUTHBRIDGE, sis_85c50x_sb_read, sis_85c50x_sb_write, dev, &dev->sb_slot);
io_sethandler(0x0022, 0x0002, sis_85c50x_isa_read, NULL, NULL, sis_85c50x_isa_write, NULL, NULL, dev);
dev->smram = smram_add();
dev->smram[0] = smram_add();
dev->smram[1] = smram_add();
dev->port_92 = device_add(&port_92_device);
sis_85c50x_reset(dev);
@@ -390,14 +446,16 @@ sis_85c50x_init(const device_t *info)
return dev;
}
const device_t sis_85c50x_device = {
"SiS 85C50x",
"sis_85c50x",
DEVICE_PCI,
0,
sis_85c50x_init, sis_85c50x_close,
sis_85c50x_reset, { NULL },
NULL, NULL,
NULL
.name = "SiS 85C50x",
.internal_name = "sis_85c50x",
.flags = DEVICE_PCI,
.local = 0,
.init = sis_85c50x_init,
.close = sis_85c50x_close,
.reset = sis_85c50x_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

File diff suppressed because it is too large Load Diff

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