mirror of
https://github.com/86Box/86Box.git
synced 2026-02-22 17:45:31 -07:00
Merge branch 'master' into fullscreenstaticonqt
This commit is contained in:
@@ -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
286
.ci/Jenkinsfile
vendored
@@ -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
966
.ci/build.sh
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
17
.ci/dependencies_macports.txt
Normal file
17
.ci/dependencies_macports.txt
Normal 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
14
.ci/dependencies_msys.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
ninja
|
||||
cmake
|
||||
gcc
|
||||
pkgconf
|
||||
openal
|
||||
freetype
|
||||
SDL2
|
||||
zlib
|
||||
libpng
|
||||
rtmidi
|
||||
libslirp
|
||||
fluidsynth
|
||||
qt5-static
|
||||
qt5-translations
|
||||
@@ -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
19
.clang-format
Normal 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
|
||||
@@ -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
21
.gitattributes
vendored
Normal 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
|
||||
32
.github/ISSUE_TEMPLATE/bug_report.md
vendored
32
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -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
80
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal 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?
|
||||
7
.github/ISSUE_TEMPLATE/config.yml
vendored
7
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -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.
|
||||
|
||||
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -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
5
.github/codeql/codeql-config.yml
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
name: "86Box CodeQL config"
|
||||
|
||||
queries:
|
||||
- uses: security-extended
|
||||
# - uses: security-and-quality
|
||||
9
.github/dependabot.yml
vendored
Normal file
9
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
version: 2
|
||||
|
||||
updates:
|
||||
|
||||
# Maintain dependencies for GitHub Actions
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
105
.github/workflows/c-cpp.yml
vendored
105
.github/workflows/c-cpp.yml
vendored
@@ -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
|
||||
|
||||
655
.github/workflows/cmake.yml
vendored
655
.github/workflows/cmake.yml
vendored
@@ -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
309
.github/workflows/codeql.yml
vendored
Normal 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
26
.gitignore
vendored
@@ -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
10
AUTHORS
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
13
CONTRIBUTING.md
Normal 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).
|
||||
47
README.md
47
README.md
@@ -1,55 +1,72 @@
|
||||
86Box [](http://ci.86box.net/job/86Box)
|
||||
86Box
|
||||
=====
|
||||
|
||||
[](https://ci.86box.net/job/86Box/)
|
||||
[](COPYING) [](https://github.com/86Box/86Box/releases) [](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!
|
||||
|
||||
[](https://kiwiirc.com/client/irc.ringoflightning.net/?nick=86box|?#86Box)
|
||||
|
||||
[](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
77
bumpversion.sh
Normal 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"'\)/'
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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?
|
||||
|
||||
30
cmake/llvm-win32-arm.cmake
Normal file
30
cmake/llvm-win32-arm.cmake
Normal 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?
|
||||
@@ -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?
|
||||
|
||||
@@ -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
5
debian/changelog
vendored
Normal 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
29
debian/control
vendored
Normal 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
38
debian/copyright
vendored
Normal 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
41
debian/postinst
vendored
Normal 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
42
debian/rules
vendored
Normal 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
1
debian/source/format
vendored
Normal file
@@ -0,0 +1 @@
|
||||
3.0 (quilt)
|
||||
15
debian/watch
vendored
Normal file
15
debian/watch
vendored
Normal 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
12
sonar-project.properties
Normal 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
|
||||
1965
src/86box.c
1965
src/86box.c
File diff suppressed because it is too large
Load Diff
@@ -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)
|
||||
|
||||
@@ -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
2445
src/acpi.c
File diff suppressed because it is too large
Load Diff
146
src/apm.c
146
src/apm.c
@@ -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
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
2090
src/cdrom/cdrom.c
2090
src/cdrom/cdrom.c
File diff suppressed because it is too large
Load Diff
@@ -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
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
478
src/cdrom/cdrom_mitsumi.c
Normal 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
|
||||
};
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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
315
src/chipset/ali1435.c
Normal 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
|
||||
};
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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
@@ -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
761
src/chipset/compaq_386.c
Normal 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
|
||||
};
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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
@@ -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
|
||||
};
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
};
|
||||
|
||||
1080
src/chipset/neat.c
1080
src/chipset/neat.c
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
};
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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
239
src/chipset/opti602.c
Normal 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
|
||||
};
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
1342
src/chipset/scamp.c
1342
src/chipset/scamp.c
File diff suppressed because it is too large
Load Diff
2336
src/chipset/scat.c
2336
src/chipset/scat.c
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
@@ -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
@@ -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
|
||||
};
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
1117
src/chipset/stpc.c
1117
src/chipset/stpc.c
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
Reference in New Issue
Block a user