3 Commits

Author SHA1 Message Date
geos_one
b3fc3e05d5 Bump
Some checks failed
Build / build (push) Has been cancelled
2025-08-14 09:29:28 +02:00
geos_one
ef0334b333 Update upstream source from tag 'upstream/2.0-0.9'
Update to upstream version '2.0-0.9'
with Debian dir ab16acf7c6
2025-08-14 09:28:54 +02:00
geos_one
17bb5d7efa New upstream version 2.0-0.9
Some checks failed
Build / build (push) Has been cancelled
2025-08-14 09:28:49 +02:00
632 changed files with 19091 additions and 52291 deletions

3
.github/FUNDING.yml vendored
View File

@@ -1,3 +0,0 @@
# These are supported funding model platforms
patreon: stsp

View File

@@ -19,9 +19,7 @@ or provide the download URL.
**Attach the log**
It is located in ~/.dosemu/boot.log
Unless you get the plain crash of dosemu2,
you may need to enable some logging flags
to make your report more useful.
To make the log more useful, you may need to enable some logging flags.
See description of -D option in `man dosemu.bin`.
**A regression?**
@@ -29,15 +27,6 @@ If you happened to know this problem didn't
exist on dosemu1 or some earlier versions of
dosemu2, please write.
**dosemu2 origins**
Please describe where do you get dosemu2
from (PPA, COPR, git sources). In case of a
source build, please describe any configure-time
customizations. In case of binary packages,
please specify your distribution and make sure
to install the debuginfo packages before creating
the log file.
**Additional info**
Please write here if you did any dosemu2 setup
customizations, like installing any custom DOS

View File

@@ -1,37 +1,31 @@
name: Build
on:
workflow_call:
inputs:
jobtype:
required: true
type: string
subtype:
required: true
type: string
runtype:
required: true
type: string
pull_request:
types:
- opened
- edited
- ready_for_review
- reopened
- synchronize
push:
jobs:
build:
if: contains(github.event.head_commit.message, '[skip ci]') == false
runs-on: ubuntu-22.04
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v2
- name: package install
run: ./ci_prereq.sh
- name: build
env:
JOBTYPE: ${{ inputs.jobtype }}
SUBTYPE: ${{ inputs.subtype }}
RUNTYPE: ${{ inputs.runtype }}
run: ./ci_build.sh
- name: cache binaries
uses: actions/cache@v4
uses: actions/cache@v2
env:
cache-name: test-binaries
with:
@@ -40,23 +34,13 @@ jobs:
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
- name: Enable KVM group perms
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
- name: test
id: test
env:
JOBTYPE: ${{ inputs.jobtype }}
SUBTYPE: ${{ inputs.subtype }}
RUNTYPE: ${{ inputs.runtype }}
run: ./ci_test.sh
- name: upload failure logs
if: ${{ always() && (steps.test.outcome == 'failure') }}
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v2
with:
name: failure-logs
path: test_*

View File

@@ -1,12 +0,0 @@
name: Manual ASAN
on:
workflow_dispatch:
jobs:
manual_asan:
name: Manual (ASAN)
uses: ./.github/workflows/ci-build.yml
with:
jobtype: 'manual'
subtype: 'asan'
runtype: 'simple'

View File

@@ -1,12 +0,0 @@
name: Manual FULL
on:
workflow_dispatch:
jobs:
manual_full:
name: Manual (FULL)
uses: ./.github/workflows/ci-build.yml
with:
jobtype: 'manual'
subtype: ''
runtype: 'full'

View File

@@ -1,12 +0,0 @@
name: Manual Normal
on:
workflow_dispatch:
jobs:
manual_normal:
name: Manual (Normal)
uses: ./.github/workflows/ci-build.yml
with:
jobtype: 'manual'
subtype: ''
runtype: 'normal'

View File

@@ -1,73 +0,0 @@
name: Master
on:
schedule:
- cron: '23 23 * * 0' # 23:23 Every Sunday
pull_request:
types:
- opened
- reopened
- synchronize
push:
jobs:
# scheduled_asan:
# name: Scheduled (ASAN)
# if: (github.event_name == 'schedule' &&
# github.repository_owner == 'dosemu2')
# uses: ./.github/workflows/ci-build.yml
# with:
# jobtype: 'schedule'
# subtype: 'asan'
# runtype: 'simple'
scheduled_full:
name: Scheduled (FULL)
if: (github.event_name == 'schedule' &&
github.repository_owner == 'dosemu2')
uses: ./.github/workflows/ci-build.yml
with:
jobtype: 'schedule'
subtype: ''
runtype: 'full'
triggered:
name: Triggered
if: (github.event_name != 'schedule' &&
contains(github.event.head_commit.message, '[skip ci]') == false &&
contains(github.event.head_commit.message, '[full ci]') == false &&
contains(github.event.head_commit.message, '[asan ci]') == false)
uses: ./.github/workflows/ci-build.yml
with:
jobtype: 'triggered'
subtype: ''
runtype: 'normal'
triggered_asan:
name: Triggered (ASAN)
if: (github.event_name != 'schedule' &&
contains(github.event.head_commit.message, '[skip ci]') == false &&
contains(github.event.head_commit.message, '[full ci]') == false &&
contains(github.event.head_commit.message, '[asan ci]') == true)
uses: ./.github/workflows/ci-build.yml
with:
jobtype: 'triggered'
subtype: 'asan'
runtype: 'simple'
triggered_full:
name: Triggered (FULL)
if: (github.event_name != 'schedule' &&
contains(github.event.head_commit.message, '[skip ci]') == false &&
contains(github.event.head_commit.message, '[full ci]') == true &&
contains(github.event.head_commit.message, '[asan ci]') == false)
uses: ./.github/workflows/ci-build.yml
with:
jobtype: 'triggered'
subtype: ''
runtype: 'full'

39
.gitignore vendored
View File

@@ -1,39 +0,0 @@
/install-sh
/config.status
/config.sub
*.d
!dosrc.d
*.o
configure
config.log
aclocal.m4
autom4te.cache
Makefile.conf
plugin_enable
*.map
*.xxd
_*.h.in
_*.h
*.hh
config.hh.in
*.yy.c
*.zz.c
parser.c
parser.h
parser.output
*.1
dosemu_c.c
global_c.c
etc/Xfonts
/etc/ttf/.uuid
.tstamp
/2.*
/bin
/commands
/lib
dosemu.desktop
dosdebug
hdinfo
bios_symbols.c
keysym_attributes.c
make_attributes

View File

@@ -1,3 +0,0 @@
the .tito/packages directory contains metadata files
named after their packages. Each file has the latest tagged
version and the project's relative directory.

View File

@@ -1 +0,0 @@
2.0pre9-2 ./

View File

@@ -1,6 +0,0 @@
[buildconfig]
builder = tito.builder.Builder
tagger = tito.tagger.VersionTagger
changelog_do_not_remove_cherrypick = 0
changelog_format = %s (%ae)

View File

@@ -1,6 +1,6 @@
language: c
os: linux
sudo: true
dist: focal
if: type = cron

View File

@@ -17,10 +17,8 @@
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
2. All dosemu2 C sources (*.c) that have no explicit copyright statement,
are copyrighted under GPLv2. Headers (*.h) without explicit
copyrights are copyrighted similar to their respective .c
counterparts, or, if no .c file with that name - under GPLv2+.
2. All dosemu2 sources that have no explicit copyright statement,
are copyrighted under GPLv2.
3. Parts of the code not covered by the GPL are marked explicitly
within the code, and/or their copyrights are at the end of this
@@ -46,35 +44,7 @@
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
--- The QEMU emulator, before July 2013
(src/base/dev/pic/*, src/base/dev/ne2k/ne2000.c)
The following points clarify the QEMU license:
1) QEMU as a whole is released under the GNU General Public License
2) Parts of QEMU have specific licenses which are compatible with the
GNU General Public License. Hence each source file contains its own
licensing information.
Many hardware device emulation sources are released under the BSD license.
3) The Tiny Code Generator (TCG) is released under the BSD license
(see license headers in files).
4) QEMU is a trademark of Fabrice Bellard.
Fabrice Bellard.
dosemu2 note: in July 2013 QEMU license was updated to state GPLv2-only:
-1) QEMU as a whole is released under the GNU General Public License
+1) QEMU as a whole is released under the GNU General Public License,
+version 2.
Therefore we take care to remove all changes done since that date,
while porting QEMU sources to dosemu2.
--- The Mach DOS Emulator (mfs.c, emm.c, emufs.s)
--- The Mach DOS Emulator
Copyright (c) 1991 Carnegie Mellon University
All Rights Reserved.
@@ -99,7 +69,7 @@ Carnegie Mellon requests users of this software to return to
any improvements or extensions that they make and grant Carnegie Mellon
the rights to redistribute these changes.
--- XFree86 (src/base/mouse/mouseint.c)
--- XFree86 (mouse code)
Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
Copyright 1993 by David Dawes <dawes@physics.su.oz.au>
@@ -123,14 +93,14 @@ RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
--- Doug Lea's malloc in src/base/lib/misc/dlmalloc.c
--- Doug Lea's malloc in src/base/misc/dlmalloc.c
This is a version (aka dlmalloc) of malloc/free/realloc written by
Doug Lea and released to the public domain, as explained at
http://creativecommons.org/licenses/publicdomain. Send questions,
comments, complaints, performance data, etc to dl@cs.oswego.edu
--- The VGA fonts in src/base/dev/vga/vgafonts.c (copyleft_vgafonts.txt)
--- The VGA fonts in src/env/video/vgafonts.c (copyleft_vgafonts.txt)
This *compilation* is (c) Copyright 1991,1992 Joseph (Yossi) Gil.
Permission is granted to use and redistribute the files comprising

View File

@@ -6,7 +6,7 @@ building and installing dosemu2 from sources
https://code.launchpad.net/~dosemu2/+archive/ubuntu/ppa
of from COPR:
https://copr.fedorainfracloud.org/coprs/stsp/dosemu2/
- gcc >= 8.1 or clang >= 3.7.0
- gcc >= 3.3 or clang >= 3.7.0
- glibc >= 2.20
- linux >= 3.16 for x86-64, >= 4.7 recommended.
With older version than 3.16 there may be some problems
@@ -14,8 +14,11 @@ building and installing dosemu2 from sources
linux >= 4.3 for i386.
linux >= 4.11 if you want to run 32bit dosemu under x86_64 kernel
with multilib environment (you likely don't want to do this).
- x86 (i386/x86-64) target CPU
- bison and flex
- SDL >= 2.0.6, >= 2.26.0 is required for copy/paste support.
- SDL >= 2.0.6, >= 2.0.15 is recommended (older versions may not have
scaling filters and KMS rendering working).
- udev >= 240 recommended for KVM (execution acceleration)
- libslirp >= 4.1.0 recommended for networking
- json-c >= 0.13 recommended
- development libraries: Xext, slang, gpm, alsa, fluidsynth,

View File

@@ -12,7 +12,7 @@ endif
REALTOPDIR ?= $(abspath $(srcdir))
$(REALTOPDIR)/configure: $(REALTOPDIR)/configure.ac
cd $(@D) && autoreconf --install -v -I m4
cd $(@D) && autoreconf -v -I m4
Makefile.conf config.status src/include/config.hh etc/dosemu.desktop: \
$(REALTOPDIR)/configure
@@ -62,7 +62,7 @@ rpm: dosemu2.spec.rpkg
rpkg local
deb:
debuild -e CC=clang -i -us -uc -b
debuild -i -us -uc -b
changelog:
if [ -d $(top_srcdir)/.git -o -f $(top_srcdir)/.git ]; then \

View File

@@ -24,7 +24,7 @@ abs_top_srcdir:=@abs_top_srcdir@
abs_top_builddir:=@abs_top_builddir@
INCDIR=-I${top_builddir}/src/include -I${top_builddir}/src/plugin/include \
-I${top_srcdir}/src/base/bios/x86 -I${top_srcdir}/src/include \
-I${top_builddir}/src/base/bios/x86 -I${top_srcdir}/src/include \
-I${top_srcdir}/src/base/lib
top_srcdir:=$(abs_top_srcdir)
srcdir = $(patsubst %/,%,$(abs_top_srcdir)/src/$(SUBDIR))
@@ -46,16 +46,12 @@ LD:=@CC@
AS:=@AS@
XAS:=@XAS@
AS_LD:=@AS_LD@
XOBJCOPY:=@XOBJCOPY@
CC_FOR_BUILD:=@CC_FOR_BUILD@
CFLAGS_FOR_BUILD:=@CFLAGS_FOR_BUILD@
OBJCOPY:=@OBJCOPY@
YACC:=@YACC@
# NOTE: we really need bison, yacc won't work any more
#YACC=bison -y
LEX:=@LEX@
LN_S := @LN_S@
LN_SFT := @LN_SFT@
# This gets defined even if we chose via ./include/config.h NOT to
# use the debugger
@@ -72,17 +68,8 @@ RANLIB:=@RANLIB@
PACKAGE_NAME:=@PACKAGE_TARNAME@
USE_DL_PLUGINS := @USE_DL_PLUGINS@
X86_EMULATOR := @X86_EMULATOR@
X86_JIT := @X86_JIT@
DNATIVE := @DNATIVE@
KVM := @KVM@
MCONTEXT := @MCONTEXT@
USE_OFD_LOCKS := @USE_OFD_LOCKS@
USE_XATTRS := @USE_XATTRS@
USE_EVTIMER_FD := @USE_EVTIMER_FD@
USE_OSS := @USE_OSS@
USE_SOFTFLOAT := @USE_SOFTFLOAT@
@USE_DL_PLUGINS@
@X86_EMULATOR@
INSTALL:=@INSTALL@
REALTOPDIR:=$(top_srcdir)
@@ -107,7 +94,7 @@ BINPATH:=$(top_builddir)/$(THISVERSION)
RELEASE_DATE="@RELEASE_DATE@"
REVISION:=$(shell cd $(top_srcdir) && ./getversion -r)
ifeq ($(USE_DL_PLUGINS),1)
ifdef USE_DL_PLUGINS
DL_CFLAGS:=-fPIC
else
-include $(top_builddir)/src/plugin/*/Makefile.conf

View File

@@ -17,40 +17,10 @@ https://github.com/dosemu2/dosemu2/issues
## Running
Just type
```
dosemu
```
to run an emulator.
Use
```
dosemu -E <dos_cmd>
```
to run `<dos_cmd>` and exit (add `-T` to not exit).
Use
```
dosemu -K <unix_dir> -E <dos_cmd>
```
or
```
dosemu <unix_full_path> -- <dos_prog_args>
```
to run DOS programs from unix directory.
If you want to run the DOS program from a DOS directory, use this syntax:
```
dosemu -K :C:\\games\\carma -E carma.exe
```
This will run `carma.exe` from `c:\games\carma`. Note the leading colon
after `-K`: it means that the DOS path, rather than unix path, is specified.
You can actually specify both paths:
```
dosemu -K ~/dosgames:carma -E carma.exe
```
This creates the DOS drive for `~/dosgames`, then chdirs to `carma` and
runs `carma.exe`.
Just type `dosemu` to run an emulator.
Use `dosemu -E <dos_cmd>` to run `<dos_cmd>` and exit (add `-T` to not exit).
Use `dosemu -K <unix_dir> -E <dos_cmd>` or `dosemu -K <unix_full_path>`
to run DOS programs from unix directories.
## Configuring

11
THANKS
View File

@@ -4,22 +4,15 @@ Main contributors (with their github names):
Stas Sergeev @stsp
Bart Oldeman @bartoldeman
Andrew Bird @andrewbird
C. Masloch @ecm-pushbx
Ryan C. Underwood @runderwo
Stuart Axon @stuaxo
Special thanks for making dosemu2 feasible
by sponsoring the initial development:
Special thanks for making dosemu2 feasible:
Caylan Van Larson <i@caylan.net>
Hans-Christian Koch <hc.koch@scheerkoch.de>
Many thanks to our Patreon patrons:
Jeffrey H. Ingber <jharrison02@earthlink.net> (@jharrison022)
C. Masloch <pushbx@ulukai.org> (@ecm-pushbx)
doctorwhoguy@gmail.com (@PaddyMac)
Thanks for the good testing and bugreporting:
Julius Schwartzenberg (@jschwartzenberg)
Julius Schwartzenberg @jschwartzenberg
A big thanks goes to Linus Torvalds and Andy Lutomirski,
who helped in solving many dosemu2-specific problems in

View File

@@ -2,18 +2,10 @@
DIR=$(dirname $0 | xargs realpath)
echo "Generating toplevel configure script in $DIR..."
check_scr() {
[ -f $DIR/$1 ] || cp $DIR/scripts/$1 $DIR/$1
}
rm -f aclocal.m4
if ! autoreconf -v -I m4 --install --force $DIR; then
if ! autoreconf -I m4 --install --force $DIR; then
echo "Failure!"
exit 1
fi
check_scr config.sub
check_scr config.guess
check_scr install-sh
echo
echo "Done, now run $DIR/default-configure"

View File

@@ -8,13 +8,6 @@ FDPPBRANCH=""
test -d ${LOCALFDPP} && exit 1
if [ "${TRAVIS}" = "true" ] ; then
echo "Travis seems to have some old version of clang in its local directory"
PATH=$(echo ${PATH} | sed 's,:/usr/local/clang-7.0.0/bin,,g')
export PATH
echo PATH is ${PATH}
fi
git clone --depth 1 --no-single-branch https://github.com/dosemu2/fdpp.git ${LOCALFDPP}
(
cd ${LOCALFDPP} || exit 2
@@ -27,37 +20,14 @@ git clone --depth 1 --no-single-branch https://github.com/dosemu2/fdpp.git ${LOC
echo "EXTRA_DEBUG = 1" >> local.mak
echo "USE_UBSAN = 1" >> local.mak
# Install the build dependancies based FDPP's debian/control file
sudo add-apt-repository ppa:stsp-0/nasm-segelf
sudo add-apt-repository ppa:stsp-0/thunk-gen
sudo apt update -q
mk-build-deps --install --root-cmd sudo
# Seems to miss this, perhaps the optional dependency confuses things
if [ "${TRAVIS}" = "true" ] ; then
sudo apt install binutils
fi
make
sudo make install
make clean all install PREFIX=${LOCALFDPPINST}
)
# Install the build dependancies based Dosemu's debian/control file
sudo add-apt-repository -y ppa:dosemu2/ppa
mk-build-deps --install --root-cmd sudo
if [ "${SUBTYPE}" = "asan" ] ; then
sed -i 's/asan off/asan on/g' compiletime-settings.devel
fi
CC=clang ./default-configure -d
export PKG_CONFIG_PATH=${LOCALFDPPINST}/lib/pkgconfig
./default-configure -d
make
# Install the FAT mount helper
sudo cp test/dosemu_fat_mount.sh /bin/.
sudo chown root.root /bin/dosemu_fat_mount.sh
sudo chmod 755 /bin/dosemu_fat_mount.sh
# Install the TAP helper
sudo cp test/dosemu_tap_interface.sh /bin/.
sudo chown root.root /bin/dosemu_tap_interface.sh
sudo chmod 755 /bin/dosemu_tap_interface.sh

View File

@@ -1,8 +1,55 @@
#!/bin/sh
sudo apt-get update
sudo add-apt-repository -y ppa:dosemu2/ppa
sudo add-apt-repository -y ppa:jwt27/djgpp-toolchain
sudo add-apt-repository -y ppa:tkchia/build-ia16
sudo apt update -q
sudo apt install -y \
devscripts \
equivs \
acl \
comcom32 \
git \
bash
bash \
autoconf \
autotools-dev \
automake \
coreutils \
linuxdoc-tools \
bison \
flex \
gawk \
sed \
libbsd-dev \
libx11-dev \
libxext-dev \
libslang2-dev \
xfonts-utils \
libgpm-dev \
libasound2-dev \
libsdl2-dev \
libsdl2-ttf-dev \
libfontconfig1-dev \
libsdl1.2-dev \
ladspa-sdk \
libfluidsynth-dev \
libao-dev \
libieee1284-3-dev \
libreadline-dev \
libjson-c-dev \
libslirp-dev \
binutils-dev \
libelf-dev \
pkg-config \
clang \
nasm \
python3-cpuinfo \
python3-pexpect \
gcc-djgpp \
qemu-system-common \
gdb \
valgrind \
gcc-ia16-elf \
libi86-ia16-elf \
gcc-multilib \
dos2unix

View File

@@ -1,36 +1,42 @@
#!/bin/bash
#!/bin/sh
. ./ci_test_prereq.sh
set -e
# Get any test binaries we need
TBINS="test-binaries"
THOST="http://www.spheresystems.co.uk/test-binaries"
if [ "${TRAVIS}" = "true" ] ; then
export CI="true"
export CI_BRANCH="${TRAVIS_BRANCH}"
if [ "${TRAVIS_EVENT_TYPE}" = "cron" ] ; then
export RUNTYPE="full"
else
export RUNTYPE="simple"
export CI_EVENT="cron"
fi
export CI_BRANCH="${TRAVIS_BRANCH}"
elif [ "${GITHUB_ACTIONS}" = "true" ] ; then
# CI is already set
export CI_BRANCH="$(echo ${GITHUB_REF} | cut -d/ -f3)"
if [ "${GITHUB_EVENT_NAME}" = "push" ] && [ "${GITHUB_REPOSITORY_OWNER}" = "dosemu2" ] && [ "${CI_BRANCH}" = "devel" ] ; then
export RUNTYPE="simple"
if [ "${GITHUB_EVENT_NAME}" = "scheduled" ] ; then
export CI_EVENT="cron"
fi
export CI_BRANCH="$(echo ${GITHUB_REF} | cut -d/ -f3)"
fi
TBINS="test-binaries"
if [ "${CI}" = "true" ] ; then
[ -d "${HOME}"/cache ] || mkdir "${HOME}"/cache
[ -h "${TBINS}" ] || ln -s "${HOME}"/cache "${TBINS}"
else
[ -d "${TBINS}"] || mkdir "${TBINS}"
fi
python3 test/test_dos.py --get-test-binaries
if [ -f /dev/kvm ] ; then
sudo setfacl -m u:${USER}:rw /dev/kvm
fi
(
cd "${TBINS}" || exit 1
[ -f DR-DOS-7.01.tar ] || wget ${THOST}/DR-DOS-7.01.tar
[ -f FR-DOS-1.20.tar ] || wget ${THOST}/FR-DOS-1.20.tar
[ -f MS-DOS-6.22.tar ] || wget ${THOST}/MS-DOS-6.22.tar
[ -f VARIOUS.tar ] || wget ${THOST}/VARIOUS.tar
[ -f TEST_EMM286.tar ] || wget ${THOST}/TEST_EMM286.tar
)
echo
echo "====================================================="
@@ -43,35 +49,20 @@ echo "====================================================="
# single test example
# python3 test/test_dos.py FRDOS120TestCase.test_mfs_fcb_rename_wild_1
if [ "${TRAVIS}" = "true" ] ; then
ARGS="--require-attr=cputest"
if [ "${CI_EVENT}" = "cron" ] ; then
if [ "${TRAVIS}" = "true" ] ; then
python3 test/test_dos.py --require-attr=cputest PPDOSGITTestCase MSDOS622TestCase FRDOS120TestCase
else
python3 test/test_dos.py
fi
else
ARGS=""
if [ "${CI_BRANCH}" = "devel" ] ; then
python3 test/test_dos.py PPDOSGITTestCase MSDOS622TestCase
else
python3 test/test_dos.py PPDOSGITTestCase
fi
fi
case "${RUNTYPE}" in
"full")
ARGS="${ARGS} PPDOSGITTestCase MSDOS622TestCase FRDOS130TestCase DRDOS701TestCase"
;;
"normal")
ARGS="${ARGS} PPDOSGITTestCase MSDOS622TestCase"
export SKIP_UNCERTAIN=1
;;
"simple")
ARGS="${ARGS} PPDOSGITTestCase"
export SKIP_EXPENSIVE=1
export SKIP_UNCERTAIN=1
;;
esac
# CC is set on Travis and can confuse compilation during tests
unset CC
# Make cpu tests here so that we see any failures
make -C test/cpu clean all
python3 test/test_dos.py ${ARGS}
for i in test_*.*.*.log ; do
test -f $i || exit 0
done

View File

@@ -1,27 +0,0 @@
#!/bin/sh
sudo add-apt-repository -y ppa:jwt27/djgpp-toolchain
sudo add-apt-repository -y ppa:tkchia/build-ia16
sudo apt update -q
sudo apt install -y \
acl \
comcom64 \
nasm \
python3-cpuinfo \
python3-pexpect \
mtools \
gcc-djgpp \
djgpp-dev \
qemu-system-common \
gdb \
valgrind \
gcc-ia16-elf \
libi86-ia16-elf \
libi86-testsuite-ia16-elf \
gcc-multilib \
dos2unix \
bridge-utils \
libvirt-daemon \
libvirt-daemon-system

View File

@@ -1,9 +1,7 @@
config {
experimental on
debug on
asan off
lsan off
tsan off
asan on
ubsan on
optimize off
system-wa off

View File

@@ -16,11 +16,10 @@ AC_PROG_CC
#AC_PROG_CC_C11([AC_DEFINE(HAVE_STD_C11)])
AC_DEFINE(HAVE_STD_C11)
AC_PROG_CPP
AX_PROG_CC_FOR_BUILD
AC_USE_SYSTEM_EXTENSIONS
AC_MSG_CHECKING([for $CC actually being clang])
if $CC -v 2>&1|grep 'clang' >/dev/null; then
if "$CC" -v 2>&1|grep 'clang' >/dev/null; then
AC_MSG_RESULT([yes])
AC_MSG_CHECKING([for clang >= 3.7])
clang_ver=`$CC -v 2>&1 | grep version | sed 's/.*version //' | cut -d " " -f 1`
@@ -36,93 +35,46 @@ if $CC -v 2>&1|grep 'clang' >/dev/null; then
-Wno-address-of-packed-member"
LDFLAGS="$LDFLAGS -Wno-unused-command-line-argument"
use_clang="yes"
AS="$CC"
clang_as_as=1
ASFLAGS="-xassembler -c -"
else
CCAS="$CC"
AC_MSG_RESULT([no])
use_clang="no"
AC_MSG_CHECKING([for $CC actually being c++])
if $CC -v 2>&1 | grep "g++" | grep "COLLECT_GCC" >/dev/null; then
if "$CC" -v 2>&1 | grep "g++" | grep "COLLECT_GCC" >/dev/null; then
AC_MSG_RESULT([yes, using -fpermissive])
DOSEMU_CFLAGS="$DOSEMU_CFLAGS -fpermissive -Wno-narrowing"
DOSEMU_CFLAGS="$DOSEMU_CFLAGS -fpermissive"
else
AC_MSG_RESULT([no])
DOSEMU_CFLAGS="$DOSEMU_CFLAGS -fplan9-extensions"
fi
fi
CONFIG_HOST=`uname -s`
AC_SUBST(CONFIG_HOST)
machine=`$CC -dumpmachine | cut -d- -f1 | sed 's/i.86/i386/'`
AC_PATH_PROG([AS], [as])
if test -z "$AS"; then
AC_PATH_PROG([AS], [as])
if test -z "$AS"; then
AC_PATH_PROG([AS], [clang])
if test -z "$AS"; then
AC_MSG_ERROR(as not found)
fi
AC_MSG_NOTICE(Using clang as as...)
clang_as_as=1
ASFLAGS="-xassembler -c -"
fi
AC_MSG_ERROR(as not found)
fi
AC_PATH_PROGS([XAS], [i686-linux-gnu-as i386-elf-as])
AC_PATH_PROG([XAS], [i386-elf-as])
if test -z "$XAS"; then
if test "$CONFIG_HOST" = "Darwin"; then
AC_MSG_ERROR([Please install i386-elf-binutils from https://github.com/nativeos/homebrew-i386-elf-toolchain])
fi
AC_PATH_PROG([XAS], [x86_64-linux-gnu-as])
if test -z "$XAS"; then
if test "$machine" = "i386" -o "$machine" = "x86_64"; then
XAS="$AS"
if test "$clang_as_as" = "1"; then
XASFLAGS="$ASFLAGS -m32"
else
XASFLAGS="$ASFLAGS --32"
fi
else
AC_MSG_ERROR([cross-assembler not found, please install binutils-i686-linux-gnu])
fi
else
XASFLAGS="$ASFLAGS --32"
fi
XAS="$AS"
XASFLAGS=--32
fi
AC_PATH_PROGS([LD], [ld ld.lld])
AC_PATH_PROG([LD], [ld])
if test -z "$LD"; then
AC_MSG_ERROR(ld not found)
fi
AC_PATH_PROGS([AS_LD], [i686-linux-gnu-ld i386-elf-ld x86_64-linux-gnu-ld ld.lld ld])
AC_PATH_PROG([AS_LD], [i386-elf-ld])
if test -z "$AS_LD"; then
AS_LD="$LD"
fi
AC_PATH_PROG([OBJCOPY], [objcopy])
O_VER=`$OBJCOPY -V | head -n 1 | grep "GNU objcopy"`
if test -z "$O_VER"; then
AC_MSG_WARN([rejecting BSD objcopy])
OBJCOPY=""
fi
AC_PATH_PROGS([OBJCOPY], [i386-elf-objcopy objcopy])
if test -z "$OBJCOPY"; then
AC_PATH_PROG([LOBJCOPY], [llvm-objcopy], [], [$PATH${PATH_SEPARATOR}/usr/local/opt/llvm/bin])
if test -z "$LOBJCOPY"; then
AC_MSG_ERROR(objcopy not found)
fi
OBJCOPY="$LOBJCOPY"
fi
AC_PATH_PROGS([XOBJCOPY], [i686-linux-gnu-objcopy x86_64-linux-gnu-objcopy objcopy])
if test -z "$XOBJCOPY"; then
XOBJCOPY="$OBJCOPY"
AC_MSG_ERROR(objcopy not found)
fi
AC_SUBST(AS)
AC_SUBST(XAS)
AC_SUBST(AS_LD)
AC_SUBST(XOBJCOPY)
AC_SUBST(OBJCOPY)
AC_ARG_WITH(target-bits-32, [AS_HELP_STRING([--with-target-bits-32],
[build for 32bit target (multilib in case of x86_64 host)])],
@@ -133,30 +85,20 @@ AC_ARG_WITH(target-bits-32, [AS_HELP_STRING([--with-target-bits-32],
)
AC_PROG_INSTALL
AC_PROG_LEX([noyywrap])
if test -z "$LEX"; then
if test -z "`echo $LEX | grep flex`" ; then
AC_CHECK_PROG(lex_ok, $LEX, "yes", "no")
fi
if test "$lex_ok" = "no"; then
AC_MSG_WARN(Your system doesn't seem to have lex or flex available.)
AC_MSG_ERROR(Install lex or flex and retry.)
fi
AC_PROG_LN_S
AC_MSG_CHECKING([if $LN_S is a GNU ln])
if $LN_S --help >/dev/null 2>&1; then
AC_MSG_RESULT([yes, using -T])
LN_SFT="$LN_S -f -T"
else
AC_MSG_RESULT([no, using -F])
LN_SFT="$LN_S -f -F"
fi
AC_SUBST(LN_SFT)
AC_CHECK_PROGS([MAKE], [gmake make])
if test -z "$MAKE"; then
AC_CHECK_PROG([MAKE], [make], ["yes"])
if test "$MAKE" != "yes"; then
AC_MSG_ERROR(You don't have make installed)
fi
# export MAKE to run from scripts
export MAKE="$MAKE"
AC_CHECK_PROGS([REALPATH], [realpath])
if test -z "$REALPATH"; then
AC_CHECK_PROG([REALPATH], [realpath], ["yes"])
if test "$REALPATH" != "yes"; then
AC_MSG_ERROR(You don't have realpath installed)
fi
AC_PROG_RANLIB
@@ -174,7 +116,7 @@ AC_PROG_AWK
if test "$ac_cv_prog_AWK" != "gawk" ; then
AC_MSG_ERROR(Install gawk and retry.)
fi
AC_CHECK_PROGS([PKG_CONFIG], [pkg-config])
AC_CHECK_PROG(PKG_CONFIG, pkg-config, yes)
if test -z "$PKG_CONFIG"; then
AC_MSG_ERROR(Install pkg-config and retry.)
fi
@@ -207,6 +149,7 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE([
])],
[
AC_MSG_RESULT([yes])
AC_MSG_NOTICE(Compiling with x86 emulator)
AC_DEFINE(HAVE_ASSIGNABLE_STDERR)
],
[
@@ -214,70 +157,32 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE([
]
)
AC_MSG_CHECKING([for optreset])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
#include <unistd.h>
int main(void)
{
optreset = 1;
return 0;
}
])],
[
AC_MSG_RESULT([yes])
AC_DEFINE(HAVE_OPTRESET)
],
[
AC_MSG_RESULT([no])
]
)
AC_CHECK_LIB(rt, shm_open)
dnl below defines HAVE_xxx so needed even if AC_CHECK_LIB() succeeded
AC_CHECK_FUNCS([shm_open memfd_create fopencookie sigtimedwait closefrom])
AC_CHECK_FUNCS([setxattr], [
USE_XATTRS=1
AC_SUBST(USE_XATTRS)
])
AC_CHECK_FUNCS([timerfd_create], [
USE_EVTIMER_FD=1
AC_SUBST(USE_EVTIMER_FD)
], [AC_CHECK_FUNCS([kqueue], [
USE_EVTIMER_FD=1
AC_SUBST(USE_EVTIMER_FD)
])])
AC_CHECK_FUNCS([mremap])
AC_CHECK_FUNCS([fls])
AC_CHECK_FUNCS([shm_open memfd_create renameat2])
AC_CHECK_DECLS([F_OFD_SETLK], [
USE_OFD_LOCKS=1
AC_SUBST(USE_OFD_LOCKS)
],, [[#include <fcntl.h>]]
)
AC_CHECK_DECLS([MREMAP_MAYMOVE],,, [[#include <sys/mman.h>]])
AC_CHECK_DECLS([MADV_POPULATE_WRITE, MADV_COLD],,,
[[#include <sys/mman.h>]])
AC_CHECK_TYPES([__float80],, [
if test "$machine" != "i386" -a "$machine" != "x86_64"; then
USE_SOFTFLOAT=1
AC_SUBST(USE_SOFTFLOAT)
fi
]
AC_CHECK_DECLS([F_OFD_SETLK],, [
AC_MSG_ERROR([F_OFD_SETLK not available, your glibc is too old])
], [[#include <fcntl.h>]]
)
AC_CHECK_FUNC(strlcpy,, [
PKG_CHECK_MODULES([LIBBSD], [libbsd], [
PKG_CHECK_MODULES([LIBBSD], [libbsd], [
dnl re-check for proper arch (multilib)
AC_CHECK_LIB(bsd, strlcpy,, [AC_MSG_ERROR(libbsd not found)])
], [
dnl extra check because on bsd these functions are available w/o lib
AC_CHECK_FUNC(strlcpy,, [AC_MSG_ERROR(libbsd not found)])
]
)])
)
dnl Here is where we do our stuff
AC_ARG_WITH(confdir, [AS_HELP_STRING([--with-confdir=dir],
[directory suffix under sysconfdir. default: dosemu])],
confdir="$withval", confdir="dosemu")
AC_ARG_WITH(plugindir, [AS_HELP_STRING([--with-plugindir=dir],
[directory for dosemu plugins. default: ${libdir}/dosemu])],
plugindir="$withval", plugindir="${libdir}/dosemu")
AC_ARG_WITH(x11fontdir, [AS_HELP_STRING([--with-x11fontdir=dir],
[directory to install the VGA X11 font. default: ${datadir}/dosemu/Xfonts])],
x11fontdir="$withval", x11fontdir="${datadir}/dosemu/Xfonts")
@@ -288,10 +193,6 @@ AC_ARG_WITH(fdtarball, [AS_HELP_STRING([--with-fdtarball=file],
[path to FreeDOS tarball])],
fdtarball="$withval")
# Hard-code this. It is evaluated at run-time as <binary_dir>../lib/dosemu,
# so we do not use libdir here (which can be lib64 or something unrelated)
plugindir="\${prefix}/lib/dosemu"
AC_SUBST(confdir)
AC_SUBST(plugindir)
AC_SUBST(x11fontdir)
@@ -301,14 +202,20 @@ AC_SUBST(fdtarball)
AC_DEFINE_DIR([SYSCONFDIR], [sysconfdir], [ System config dir ])
AC_DEFINE_DIR([CONFSUBDIR], [confdir], [ dosemu-specific config subdir ])
AC_DEFINE_DIR([PREFIX], [prefix], [ prefix ])
AC_DEFINE_DIR([DOSEMUPLUGINDIR], [plugindir], [ Directory for dosemu plugins ])
AC_DEFINE_DIR([DATADIR], [datadir], [ Where data are placed to ])
AC_DEFINE_DIR([LIBEXECDIR], [libexecdir], [ Where extra executables are placed to ])
AC_DEFINE_DIR([SYSTEM_XFONTS_PATH], [x11fontdir], [ Directory for x11 fonts ])
CONFIG_HOST='linux'
AC_SUBST(CONFIG_HOST)
machine=`"$CC" -dumpmachine | cut -d- -f1`
DOSEMU_CPPFLAGS="$DOSEMU_CPPFLAGS -imacros config.hh"
DOSEMU_CFLAGS="$DOSEMU_CFLAGS -Wall -Wstrict-prototypes -Wmissing-declarations \
-Wnested-externs -fms-extensions -pthread \
-Wno-unused-result -Wcast-qual -Wwrite-strings -Wstrict-aliasing=2 -Wundef"
-Wno-unused-result -Wcast-qual -Wwrite-strings"
AX_CHECK_COMPILE_FLAG([-Waddress-of-packed-member],
[DOSEMU_CFLAGS="$DOSEMU_CFLAGS -Wno-address-of-packed-member"],, [-Werror])
AX_CHECK_COMPILE_FLAG([-Wstring-plus-int],
@@ -322,7 +229,7 @@ AC_ARG_ENABLE(dlplugins,
if test "$enable_dlplugins" != "no"; then
AC_MSG_NOTICE(Using dynamically loaded plugins...)
AC_DEFINE(USE_DL_PLUGINS)
USE_DL_PLUGINS=1
USE_DL_PLUGINS="USE_DL_PLUGINS=1"
AC_SUBST(USE_DL_PLUGINS)
DOSBIN_LDFLAGS="-rdynamic"
AC_SUBST(DOSBIN_LDFLAGS)
@@ -355,45 +262,14 @@ AX_RESTORE_FLAGS([attr_check])
AC_DEFINE_UNQUOTED(SIG_PROTO_PFX, $SIG_PROTO_PFX)
dnl Check whether we have pthreads and whether to use it
AC_CHECK_LIB(pthread, pthread_create,, [
dnl see if the func is provided nevertheless (not needing -lpthread)
AC_CHECK_FUNC(pthread_create,, [
AC_CHECK_LIB(pthread, pthread_create,,[
AC_MSG_ERROR([No libpthread found, please install glibc-devel package])
]
)])
AC_CHECK_FUNC(pthread_cancel,, [
AC_CHECK_HEADERS([bthread.h],, [
AC_MSG_ERROR([pthread_cancel() missing, install libbthread])
])
])
AC_CHECK_LIB(bthread, pthread_cancel)
)
AC_CHECK_FUNCS([pthread_getname_np pthread_setname_np])
AC_CHECK_FUNCS([pthread_attr_setsigmask_np pthread_setattr_default_np])
AC_CHECK_HEADER([wordexp.h],, [
AC_MSG_ERROR([wordexp.h missing, install libwordexp])
])
AC_CHECK_LIB(wordexp, wordexp)
AC_CHECK_HEADERS([scsi/sg.h linux/cdrom.h sys/io.h])
AC_CHECK_HEADERS([sys/kd.h scsi/sg.h linux/cdrom.h])
AC_CHECK_HEADERS([netipx/ipx.h linux/ipx.h netpacket/packet.h])
AC_CHECK_HEADERS([asm/ucontext.h],,, [
#include <ucontext.h>
#include <signal.h>
])
AC_CHECK_HEADERS([ucontext.h],, [
AS_UNSET([ac_cv_header_ucontext_h])
AC_CHECK_HEADER([ucontext.h],
AC_DEFINE([_XOPEN_SOURCE], [500], [Use X/Open 5 with POSIX 1995]),
AC_MSG_ERROR([Can't use ucontext.h]), [
#define _XOPEN_SOURCE 500
])])
AC_CHECK_HEADERS([linux/signal.h],,, [#include <signal.h>])
AC_CHECK_HEADERS([sys/soundcard.h], [
USE_OSS=1
AC_SUBST(USE_OSS)
])
DATE_FMT="%F %T %z"
test -n "$SOURCE_DATE_EPOCH" || SOURCE_DATE_EPOCH=`date +%s`
CONFIG_TIME=`date -u -d "@$SOURCE_DATE_EPOCH" "+$DATE_FMT" 2>/dev/null || date -u -r "$SOURCE_DATE_EPOCH" "+$DATE_FMT" 2>/dev/null || date -u "+$DATE_FMT"`
@@ -477,9 +353,9 @@ AC_ARG_ENABLE(system_wa,
AS_HELP_STRING([--disable-system-wa], [compile without system-specific
work-arounds (mostly for linux kernel) that are not needed on this system]))
AS_IF([test "x$enable_system_wa" = "xno"], [
AC_MSG_NOTICE(Disabling system-specific work-arounds)
AC_MSG_NOTICE(Disasbling system-specific work-arounds)
AC_DEFINE(DISABLE_SYSTEM_WA)
AS_IF([test -z "$WARN_OUTDATED_WA" -a -n "$WARN_UNDISABLED_WA"], [
AS_IF([test -z "$WARN_OUTDATED_WA" -a -z "$NOWARN_UNDISABLED_WA"], [
AC_DEFINE(WARN_UNDISABLED_WA)])
])
AS_IF([test -n "$WARN_OUTDATED_WA"], [
@@ -491,7 +367,7 @@ dnl Do compilation for GDB
HAVE_LIBBFD=0
AC_ARG_ENABLE(debug,
AS_HELP_STRING([--enable-debug], [compile with debug info]))
if test "$enable_debug" != "no"; then
if test "$enable_debug" = "yes"; then
AC_MSG_NOTICE(Compiling with debug info...)
DOSEMU_CFLAGS="$DOSEMU_CFLAGS -ggdb3"
if test "$use_clang" = "yes" ; then
@@ -508,6 +384,7 @@ if test "$enable_debug" != "no"; then
if test "$ac_cv_lib_bfd_bfd_init" = "yes"; then
HAVE_LIBBFD=1
AC_DEFINE(HAVE_LIBBFD)
AC_DEFINE(HAVE_BACKTRACE)
fi
])
if test "$HAVE_LIBBFD" = "1"; then
@@ -521,7 +398,7 @@ if test "$enable_debug" != "no"; then
if test "$HAVE_LIBBFD" != "1"; then
DOSEMU_LDFLAGS="$DOSEMU_LDFLAGS -rdynamic"
fi
AC_CHECK_FUNCS([backtrace backtrace_symbols])
AC_DEFINE(HAVE_BACKTRACE)
])
else
AC_MSG_NOTICE(Compiling without debug info...)
@@ -531,8 +408,6 @@ AC_ARG_ENABLE(profile,
AS_HELP_STRING([--enable-profile], [compile with profile info]))
AC_ARG_ENABLE(asan, [AS_HELP_STRING(--enable-asan, [enable address sanitizer])])
AC_ARG_ENABLE(lsan, [AS_HELP_STRING(--enable-lsan, [enable leak sanitizer])])
AC_ARG_ENABLE(tsan, [AS_HELP_STRING(--enable-tsan, [enable thread sanitizer])])
AC_ARG_ENABLE(ubsan, [AS_HELP_STRING(--enable-ubsan, [enable UB sanitizer])])
AC_SUBST(OPTIONALSUBDIRS)
@@ -546,21 +421,29 @@ dnl CPU emulator
AC_ARG_ENABLE(cpuemu, [AS_HELP_STRING([--disable-cpuemu],
[do NOT compile with optional x86 emulation code])])
if test "$enable_cpuemu" != "no"; then
AC_MSG_NOTICE(Compiling with x86 emulator)
AC_DEFINE(X86_EMULATOR)
X86_EMULATOR=1
AC_SUBST(X86_EMULATOR)
if test "$machine" = "i386" -o "$machine" = "x86_64"; then
AC_ARG_ENABLE(cpuemu_jit, [AS_HELP_STRING([--disable-cpuemu-jit],
[do NOT compile with optional x86 JIT])])
if test "$enable_cpuemu_jit" != "no"; then
AC_MSG_NOTICE(Compiling with x86 JIT)
AC_DEFINE(X86_JIT)
X86_JIT=1
AC_SUBST(X86_JIT)
fi
fi
AC_MSG_CHECKING([for __attribute__((force_align_arg_pointer))])
AX_SAVE_FLAGS([attr_check2])
CFLAGS="-Wall -Werror"
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
void foo(void);
__attribute__((force_align_arg_pointer))
void foo(void)
{
}
])],
[
AC_MSG_RESULT([supported])
AC_MSG_NOTICE(Compiling with x86 emulator)
AC_DEFINE_UNQUOTED(X86_EMULATOR)
X86_EMULATOR="X86_EMULATOR=1"
AC_SUBST(X86_EMULATOR)
],
[
AC_MSG_RESULT([unsupported])
AC_MSG_WARN(Compiling without x86 emulator)
]
)
AX_RESTORE_FLAGS([attr_check2])
fi
AC_ARG_WITH(target_cpu, [AS_HELP_STRING([--with-target-cpu=CPU],
@@ -573,72 +456,25 @@ else
target_cpu=$with_target_cpu
fi
if test "$machine" = "i386" -o "$with_target_bits" = "32" -o \
"$enable_profile" = "yes"; then
if test "$machine" = "x86_64" -a "$with_target_bits" != "32" -a \
"$enable_profile" != "yes"; then
AC_MSG_NOTICE(Compiling as PIE for $machine...)
DOSEMU_CFLAGS="$DOSEMU_CFLAGS -fpie"
DOSEMU_LDFLAGS="$DOSEMU_LDFLAGS -pie"
else
AC_MSG_NOTICE(Compiling as non-PIE...)
DOSEMU_CFLAGS="$DOSEMU_CFLAGS -fno-pie"
AX_CHECK_COMPILE_FLAG([-no-pie],
[DOSEMU_LDFLAGS="$DOSEMU_LDFLAGS -no-pie"])
else
AC_MSG_NOTICE(Compiling as PIE for $machine...)
DOSEMU_CFLAGS="$DOSEMU_CFLAGS -fpie"
DOSEMU_LDFLAGS="$DOSEMU_LDFLAGS -pie"
fi
if test "$CONFIG_HOST" = "Linux"; then
if test "$machine" = "i386" -o "$machine" = "x86_64"; then
AC_ARG_ENABLE(dnative, [AS_HELP_STRING([--disable-dnative],
[do NOT compile with native DPMI support])])
if test "$enable_dnative" != "no"; then
AC_MSG_NOTICE([Enabling native DPMI support...])
AC_DEFINE(DNATIVE)
DNATIVE=1
AC_SUBST(DNATIVE)
fi
AC_DEFINE(USE_KVM)
KVM=1
AC_SUBST(KVM)
fi
fi
if test "$CONFIG_HOST" = "Darwin"; then
DOSEMU_LDFLAGS="$DOSEMU_LDFLAGS -Wl,-undefined,dynamic_lookup"
fi
AC_ARG_ENABLE(mcontext,
AS_HELP_STRING([--disable-mcontext], [disable fast context switch]))
if test "$enable_mcontext" != "no"; then
AC_MSG_NOTICE([Enabling fast context switching...])
AC_DEFINE(MCONTEXT)
MCONTEXT=1
AC_SUBST(MCONTEXT)
fi
if test "$enable_asan" = "yes"; then
AX_CHECK_LINK_FLAG([-fsanitize=address], [
DOSEMU_CFLAGS="$DOSEMU_CFLAGS -fsanitize=address"
# working around this bug:
# https://github.com/google/sanitizers/issues/934
# Linking to libstdc++ seems to be the cure.
LDFLAGS="$LDFLAGS -fsanitize=address -lstdc++"
LDFLAGS="$LDFLAGS -fsanitize=address"
AC_MSG_NOTICE(enabling address sanitizer)
])
fi
if test "$enable_lsan" = "yes"; then
AX_CHECK_LINK_FLAG([-fsanitize=leak], [
DOSEMU_CFLAGS="$DOSEMU_CFLAGS -fsanitize=leak"
LDFLAGS="$LDFLAGS -fsanitize=leak"
AC_MSG_NOTICE(enabling leak sanitizer)
])
fi
if test "$enable_tsan" = "yes"; then
AX_CHECK_LINK_FLAG([-fsanitize=thread], [
DOSEMU_CFLAGS="$DOSEMU_CFLAGS -fsanitize=thread"
LDFLAGS="$LDFLAGS -fsanitize=thread"
AC_MSG_NOTICE(enabling thread sanitizer)
])
fi
if test "$enable_ubsan" = "yes"; then
AX_CHECK_LINK_FLAG([-fsanitize=undefined], [
DOSEMU_CFLAGS="$DOSEMU_CFLAGS -fsanitize=undefined -fno-sanitize=alignment"
@@ -728,9 +564,6 @@ fi
AH_TEMPLATE([HAVE_ASSIGNABLE_STDERR],
[ Define if stderr is not const ])
AH_TEMPLATE([HAVE_OPTRESET],
[ Define if optreset is available ])
AH_TEMPLATE([CONFIG_HOST],
[ Define the host for which Dosemu is configured ])
@@ -758,21 +591,12 @@ AH_TEMPLATE(HAVE_EXECINFO,
AH_TEMPLATE([USE_DL_PLUGINS],
[ DEFINE this, if you want dynamically loaded plugins ])
AH_TEMPLATE([HAVE_BACKTRACE],
[ Define this for backtrace() functionality ])
AH_TEMPLATE([X86_EMULATOR],
[ Define this to use the X86 CPU emulator ])
AH_TEMPLATE([X86_JIT],
[ Define this to use the X86 JIT ])
AH_TEMPLATE([DNATIVE],
[ Define this to enable native DPMI back-end ])
AH_TEMPLATE([USE_KVM],
[ Define this to enable kvm support ])
AH_TEMPLATE([MCONTEXT],
[ Define this to enable libmcontext use ])
AH_TEMPLATE([DISABLE_SYSTEM_WA],
[ Define this to disable system-specific work-arounds that are
unneeded on your system ])

2
debian/changelog vendored
View File

@@ -1,4 +1,4 @@
dosemu2 (2.0pre9-2) focal; urgency=low
dosemu2 (2.0-0.9) focal; urgency=low
* pre9-2

View File

@@ -23,7 +23,7 @@ if [ ! -f $CONF_FILE ]; then
fi
CONF=`cat $CONF_FILE`
CONF=`printf "$CONF"| sed '/^config {/d' | sed '/^}/d' | tr '\n' ' ' `
CONF=`echo -n "$CONF"| sed '/^config {/d' | sed '/^}/d' | tr '\n' ' ' `
SUFFIX=""
while [ "$#" != "0" ]; do
@@ -60,12 +60,6 @@ while [ "$1" != "" ]; do
asan)
if [ "$2" = "on" ]; then STRING="$STRING --enable-asan"; fi
;;
lsan)
if [ "$2" = "on" ]; then STRING="$STRING --enable-lsan"; fi
;;
tsan)
if [ "$2" = "on" ]; then STRING="$STRING --enable-tsan"; fi
;;
ubsan)
if [ "$2" = "on" ]; then STRING="$STRING --enable-ubsan"; fi
;;
@@ -135,29 +129,13 @@ while [ "$1" != "" ]; do
shift; shift;
done
[ -f "$srcdir"/install-sh ] || "$srcdir"/autogen.sh || exit $?
if [ -z "$MAKE" ]; then
if [ `uname -s` = "FreeBSD" ]; then
MAKE=gmake
else
MAKE=make
fi
fi
if [ `uname -s` = "FreeBSD" ]; then
export CPPFLAGS="${CPPFLAGS} -I/usr/local/include"
export LDFLAGS="${LDFLAGS} -L/usr/local/lib"
fi
${MAKE} "$srcdir"/configure
[ -f "$srcdir"/configure ] || "$srcdir"/autogen.sh || exit $?
make "$srcdir"/configure
STRING="$STRING --enable-plugins=$PLUGIN,$EXTRA_PLUGINS"
if [ -n "$FDPP_STR" ]; then
FDPP_STR=`echo $FDPP_STR | sed 's/^ *//'`
STRING="$STRING --with-plugin-options=fdpp,\"$FDPP_STR\""
fi
if [ -z "$CC" ] && which ccache; then
echo "Enabling ccache use"
export CC="ccache cc"
fi
echo exec "$srcdir"/configure $STRING $SUFFIX
eval exec "$srcdir"/configure $STRING $SUFFIX

View File

@@ -4343,14 +4343,15 @@ NAME="AEN650"
><P
>In Windows, the mouse cursor is not always in sync with the native X
mouse cursor. This problem can be easily avoided by enabling mouse grab.
There also exist an
There also exist an alternative mouse driver specially written to
work in ungrabbed mode:
<A
HREF="https://depot.javispedro.com/vbox/vbados/vbados.zip"
HREF="https://github.com/stsp/win31-mouse-driver/tree/master/out"
TARGET="_top"
>alternative mouse driver</A
>
specially written to work in ungrabbed mode under many emulators or
on a real machine.</P
>https://github.com/stsp/win31-mouse-driver/tree/master/out</A
>.
This driver is not limited to use with dosemu2: it can be used with
any other emulator and under bare-metal machine.</P
></DIV
><DIV
CLASS="SECT2"

View File

@@ -115,177 +115,130 @@ HREF="#AEN37"
HREF="#AEN39"
>Game freezes or crashes shortly after start.</A
></DT
><DT
>4.2. <A
HREF="#AEN43"
>Sound is crackling.</A
></DT
></DL
></DD
><DT
>5. <A
HREF="#AEN47"
HREF="#AEN43"
>Carmageddon</A
></DT
><DD
><DL
><DT
>5.1. <A
HREF="#AEN49"
HREF="#AEN45"
>Timer is too fast during race</A
></DT
></DL
></DD
><DT
>6. <A
HREF="#AEN59"
HREF="#AEN55"
>Simon 2</A
></DT
><DD
><DL
><DT
>6.1. <A
HREF="#AEN61"
HREF="#AEN57"
>Game freezes at start.</A
></DT
></DL
></DD
><DT
>7. <A
HREF="#AEN65"
HREF="#AEN61"
>Prince of Persia 2</A
></DT
><DD
><DL
><DT
>7.1. <A
HREF="#AEN67"
HREF="#AEN63"
>Game slows down unbearably after some playing.</A
></DT
></DL
></DD
><DT
>8. <A
HREF="#AEN71"
HREF="#AEN67"
>Cosmo game by Apogee Software</A
></DT
><DD
><DL
><DT
>8.1. <A
HREF="#AEN73"
HREF="#AEN69"
>Cosmo's Cosmic Adventure doesn't start</A
></DT
></DL
></DD
><DT
>9. <A
HREF="#AEN77"
HREF="#AEN73"
>Pinball Fantasies</A
></DT
><DD
><DL
><DT
>9.1. <A
HREF="#AEN79"
HREF="#AEN75"
>Long start-up delay (like half a minute)</A
></DT
><DT
>9.2. <A
HREF="#AEN82"
HREF="#AEN78"
>Black screen and hang after choosing the table.</A
></DT
><DT
>9.3. <A
HREF="#AEN93"
HREF="#AEN89"
>Game doesn't see the Fx keys that should start the game.</A
></DT
></DL
></DD
><DT
>10. <A
HREF="#AEN96"
HREF="#AEN92"
>WordPerfect 6.2</A
></DT
><DD
><DL
><DT
>10.1. <A
HREF="#AEN98"
HREF="#AEN94"
>Hang trying to play the MIDI file embedded in document.</A
></DT
></DL
></DD
><DT
>11. <A
HREF="#AEN103"
HREF="#AEN99"
>LEXICON 1.2 (mod 8.98)</A
></DT
><DD
><DL
><DT
>11.1. <A
HREF="#AEN105"
HREF="#AEN101"
>dosemu crashes after a few minutes of work.</A
></DT
></DL
></DD
><DT
>12. <A
HREF="#AEN109"
HREF="#AEN105"
>Test Drive 2</A
></DT
><DD
><DL
><DT
>12.1. <A
HREF="#AEN111"
HREF="#AEN107"
>Game doesn't start, just returns to command prompt.</A
></DT
></DL
></DD
><DT
>13. <A
HREF="#AEN114"
>Tetris Classic, Super Tetris</A
></DT
><DD
><DL
><DT
>13.1. <A
HREF="#AEN116"
>Game is too slow.</A
></DT
></DL
></DD
><DT
>14. <A
HREF="#AEN120"
>Street Fighter 2</A
></DT
><DD
><DL
><DT
>14.1. <A
HREF="#AEN122"
>Game crashes on intro screen.</A
></DT
></DL
></DD
><DT
>15. <A
HREF="#AEN126"
>Game Wizard (GW)</A
></DT
><DD
><DL
><DT
>15.1. <A
HREF="#AEN128"
>Hangs on start.</A
></DT
></DL
></DD
></DL
></DIV
><DIV
@@ -492,41 +445,13 @@ CLASS="SCREEN"
>
in your dosemu.conf or .dosemurc.</P
></DIV
><DIV
CLASS="SECT2"
><HR><H3
CLASS="SECT2"
><A
NAME="AEN43"
>4.2. Sound is crackling.</A
></H3
><P
>Solution: set
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> $_dos_up = (off)</PRE
></TD
></TR
></TABLE
>
in your dosemu.conf or .dosemurc.
The only "explanation" we can provide, is a conspiracy theory that
prehistoric is trying to slander third-party DOSes that put LoL/SDA
to UMB.</P
></DIV
></DIV
><DIV
CLASS="SECT1"
><HR><H2
CLASS="SECT1"
><A
NAME="AEN47"
NAME="AEN43"
>5. Carmageddon</A
></H2
><DIV
@@ -534,7 +459,7 @@ CLASS="SECT2"
><H3
CLASS="SECT2"
><A
NAME="AEN49"
NAME="AEN45"
>5.1. Timer is too fast during race</A
></H3
><P
@@ -612,7 +537,7 @@ CLASS="SECT1"
><HR><H2
CLASS="SECT1"
><A
NAME="AEN59"
NAME="AEN55"
>6. Simon 2</A
></H2
><DIV
@@ -620,7 +545,7 @@ CLASS="SECT2"
><H3
CLASS="SECT2"
><A
NAME="AEN61"
NAME="AEN57"
>6.1. Game freezes at start.</A
></H3
><P
@@ -650,7 +575,7 @@ CLASS="SECT1"
><HR><H2
CLASS="SECT1"
><A
NAME="AEN65"
NAME="AEN61"
>7. Prince of Persia 2</A
></H2
><DIV
@@ -658,7 +583,7 @@ CLASS="SECT2"
><H3
CLASS="SECT2"
><A
NAME="AEN67"
NAME="AEN63"
>7.1. Game slows down unbearably after some playing.</A
></H3
><P
@@ -684,7 +609,7 @@ CLASS="SECT1"
><HR><H2
CLASS="SECT1"
><A
NAME="AEN71"
NAME="AEN67"
>8. Cosmo game by Apogee Software</A
></H2
><DIV
@@ -692,7 +617,7 @@ CLASS="SECT2"
><H3
CLASS="SECT2"
><A
NAME="AEN73"
NAME="AEN69"
>8.1. Cosmo's Cosmic Adventure doesn't start</A
></H3
><P
@@ -719,7 +644,7 @@ CLASS="SECT1"
><HR><H2
CLASS="SECT1"
><A
NAME="AEN77"
NAME="AEN73"
>9. Pinball Fantasies</A
></H2
><DIV
@@ -727,7 +652,7 @@ CLASS="SECT2"
><H3
CLASS="SECT2"
><A
NAME="AEN79"
NAME="AEN75"
>9.1. Long start-up delay (like half a minute)</A
></H3
><P
@@ -738,7 +663,7 @@ CLASS="SECT2"
><HR><H3
CLASS="SECT2"
><A
NAME="AEN82"
NAME="AEN78"
>9.2. Black screen and hang after choosing the table.</A
></H3
><P
@@ -814,7 +739,7 @@ CLASS="SECT2"
><HR><H3
CLASS="SECT2"
><A
NAME="AEN93"
NAME="AEN89"
>9.3. Game doesn't see the Fx keys that should start the game.</A
></H3
><P
@@ -826,7 +751,7 @@ CLASS="SECT1"
><HR><H2
CLASS="SECT1"
><A
NAME="AEN96"
NAME="AEN92"
>10. WordPerfect 6.2</A
></H2
><DIV
@@ -834,7 +759,7 @@ CLASS="SECT2"
><H3
CLASS="SECT2"
><A
NAME="AEN98"
NAME="AEN94"
>10.1. Hang trying to play the MIDI file embedded in document.</A
></H3
><P
@@ -866,7 +791,7 @@ CLASS="SECT1"
><HR><H2
CLASS="SECT1"
><A
NAME="AEN103"
NAME="AEN99"
>11. LEXICON 1.2 (mod 8.98)</A
></H2
><DIV
@@ -874,7 +799,7 @@ CLASS="SECT2"
><H3
CLASS="SECT2"
><A
NAME="AEN105"
NAME="AEN101"
>11.1. dosemu crashes after a few minutes of work.</A
></H3
><P
@@ -902,7 +827,7 @@ CLASS="SECT1"
><HR><H2
CLASS="SECT1"
><A
NAME="AEN109"
NAME="AEN105"
>12. Test Drive 2</A
></H2
><DIV
@@ -910,7 +835,7 @@ CLASS="SECT2"
><H3
CLASS="SECT2"
><A
NAME="AEN111"
NAME="AEN107"
>12.1. Game doesn't start, just returns to command prompt.</A
></H3
><P
@@ -918,105 +843,6 @@ NAME="AEN111"
these drive letters are occupied. Solution is to copy the game to C:.</P
></DIV
></DIV
><DIV
CLASS="SECT1"
><HR><H2
CLASS="SECT1"
><A
NAME="AEN114"
>13. Tetris Classic, Super Tetris</A
></H2
><DIV
CLASS="SECT2"
><H3
CLASS="SECT2"
><A
NAME="AEN116"
>13.1. Game is too slow.</A
></H3
><P
>Solution: set
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> $_timer_tweaks = (on)</PRE
></TD
></TR
></TABLE
></P
></DIV
></DIV
><DIV
CLASS="SECT1"
><HR><H2
CLASS="SECT1"
><A
NAME="AEN120"
>14. Street Fighter 2</A
></H2
><DIV
CLASS="SECT2"
><H3
CLASS="SECT2"
><A
NAME="AEN122"
>14.1. Game crashes on intro screen.</A
></H3
><P
>Solution: set
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> $_timer_tweaks = (on)</PRE
></TD
></TR
></TABLE
></P
></DIV
></DIV
><DIV
CLASS="SECT1"
><HR><H2
CLASS="SECT1"
><A
NAME="AEN126"
>15. Game Wizard (GW)</A
></H2
><DIV
CLASS="SECT2"
><H3
CLASS="SECT2"
><A
NAME="AEN128"
>15.1. Hangs on start.</A
></H3
><P
>Solution: set
<TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> $_dos_up = (off)</PRE
></TD
></TR
></TABLE
></P
></DIV
></DIV
></DIV
></BODY
></HTML

View File

@@ -1,119 +0,0 @@
#
# spec file template for dosemu2
#
# Written by Mateusz Viste, stsp
#
Name: dosemu2
Version: 2.0pre9
Release: 2
Summary: fast and secure DOS emulator
Group: System/Emulator
License: GPLv2+
URL: https://github.com/dosemu2/dosemu2
VCS: https://github.com/dosemu2/dosemu2.git
Source0: dosemu2.tar.gz
BuildRequires: SDL2-devel
BuildRequires: SDL2_ttf-devel
BuildRequires: fontconfig-devel
BuildRequires: libXext-devel
BuildRequires: alsa-lib-devel
BuildRequires: fluidsynth-devel
BuildRequires: gpm-devel
BuildRequires: libao-devel
BuildRequires: ladspa-devel
BuildRequires: slang-devel
BuildRequires: libslirp-devel
BuildRequires: libieee1284-devel
BuildRequires: mt32emu-devel
BuildRequires: libbsd-devel
BuildRequires: gcc
BuildRequires: bison
BuildRequires: flex
BuildRequires: gawk
BuildRequires: autoconf
BuildRequires: automake
BuildRequires: make
BuildRequires: sed
BuildRequires: bash
BuildRequires: findutils
BuildRequires: git >= 2.0
BuildRequires: bdftopcf
BuildRequires: mkfontscale
BuildRequires: linuxdoc-tools
BuildRequires: readline-devel
BuildRequires: json-c-devel
BuildRequires: libb64-devel
BuildRequires: binutils
BuildRequires: binutils-x86_64-linux-gnu
BuildRequires: pkgconf-pkg-config
BuildRequires: fdpp-devel
BuildRequires: dj64-devel
# our startup script is bash-specific
Requires: bash
Requires: comcom64
Recommends: fluid-soundfont-gm
Suggests: timidity++ >= 2.14.0
Recommends: ladspa
# ncurses-base is for terminfo
Recommends: ncurses-base
Recommends: gdb
Recommends: kbd
Suggests: valgrind
Recommends: install-freedos
Suggests: install-otherdos
# cannot coexist with dosemu1
Conflicts: dosemu
%description
dosemu2 is an emulator for running DOS programs under linux.
It can also serve as a VM to boot various DOSes.
%prep
%setup -T -b 0 -q -n dosemu2
%build
./autogen.sh
%configure
make %{?_smp_mflags}
%check
%install
mkdir -p %{buildroot}%{_sysconfdir}/X11/fontpath.d
make DESTDIR=%{buildroot} install
%files
%defattr(-,root,root)
%{_bindir}/*
%{_mandir}/man1/*
%lang(ru) %dir %{_mandir}/ru
%lang(ru) %dir %{_mandir}/ru/man1
%lang(ru) %{_mandir}/ru/man1/*
# Not using libdir here as we only install plugins, and their path hard-coded
%{_prefix}/lib/dosemu
%{_datadir}/dosemu
%{_datadir}/applications/dosemu.desktop
%{_datadir}/fonts/oldschool
%{_sysconfdir}/X11/fontpath.d/dosemu2*
%doc %{_docdir}/dosemu2
%dir %{_sysconfdir}/dosemu
%config(noreplace) %{_sysconfdir}/dosemu/dosemu.conf
%changelog
* Tue Apr 09 2024 Stas Sergeev <stsp@users.sourceforge.net> 2.0pre9-2
-
* Tue Apr 09 2024 Stas Sergeev <stsp@users.sourceforge.net>
-
* Tue Apr 09 2024 Stas Sergeev <stsp@users.sourceforge.net> 2.0pre9-1
- new package built with tito
* Sat Aug 20 2016 Stas Sergeev <stsp@users.sourceforge.net> 2.0pre6-dev
(none)

View File

@@ -18,6 +18,7 @@ Source0: {{{ git_dir_archive }}}
BuildRequires: SDL2-devel
BuildRequires: SDL2_ttf-devel
BuildRequires: SDL2_image-devel
BuildRequires: fontconfig-devel
BuildRequires: libXext-devel
BuildRequires: alsa-lib-devel
@@ -28,7 +29,6 @@ BuildRequires: ladspa-devel
BuildRequires: slang-devel
BuildRequires: libslirp-devel
BuildRequires: libieee1284-devel
BuildRequires: mt32emu-devel
BuildRequires: libbsd-devel
BuildRequires: gcc
BuildRequires: bison
@@ -44,18 +44,19 @@ BuildRequires: git >= 2.0
BuildRequires: bdftopcf
BuildRequires: mkfontscale
BuildRequires: linuxdoc-tools
BuildRequires: coreutils
BuildRequires: readline-devel
BuildRequires: json-c-devel
BuildRequires: libb64-devel
BuildRequires: binutils
BuildRequires: binutils-x86_64-linux-gnu
BuildRequires: binutils-devel
BuildRequires: pkgconf-pkg-config
BuildRequires: fdpp-devel
BuildRequires: dj64-devel
# require udev with kvm support
Requires: systemd-udev >= 234
# our startup script is bash-specific
Requires: bash
Requires: comcom64
Requires: coreutils
Requires: comcom32
Recommends: fluid-soundfont-gm
Suggests: timidity++ >= 2.14.0
Recommends: ladspa
@@ -79,7 +80,14 @@ It can also serve as a VM to boot various DOSes.
%build
./autogen.sh
%configure
./configure --prefix=%{_prefix} --libdir=%{_libdir} \
--sysconfdir=%{_sysconfdir} --docdir=%{_docdir}/%{name} \
--enable-debug --disable-xbacktrace
# can't use %%configure because of this:
# https://bugzilla.redhat.com/show_bug.cgi?id=1343892
# additionally have to use double-percent for comments:
# https://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/Packagers_Guide/chap-Packagers_Guide-Spec_File_Reference-Comments.html
#%%configure
make %{?_smp_mflags}
%check
@@ -95,8 +103,7 @@ make DESTDIR=%{buildroot} install
%lang(ru) %dir %{_mandir}/ru
%lang(ru) %dir %{_mandir}/ru/man1
%lang(ru) %{_mandir}/ru/man1/*
# Not using libdir here as we only install plugins, and their path hard-coded
%{_prefix}/lib/dosemu
%{_libdir}/dosemu
%{_datadir}/dosemu
%{_datadir}/applications/dosemu.desktop
%{_datadir}/fonts/oldschool

View File

@@ -14,6 +14,8 @@
#
##############################################################################
# Notes for editing this file:
#
# In $_xxx = (n) n is a numerical or boolean value
@@ -23,17 +25,6 @@
# Please note that all options are commented out by default!
# Remove the # in front of the $ to change an option.
# Path to the local directory.
# Note: this option is only valid in global config file.
# Default: "~/.dosemu"
# $_local_dir = "~/.dosemu"
# Name of the local config file under local directory.
# Note: this option is only valid in global config file.
# Default: "dosemurc"
# $_dosemurc = "dosemurc"
##############################################################################
## CPU settings: define the CPU features to DOSEMU.
@@ -68,6 +59,10 @@
# $_cpuemu = (0)
# if possible use Pentium cycle counter for timing. Default: off
# $_rdtsc = (off)
# CPU speed, used in conjunction with the TSC
# Default 0 = calibrated by dosemu, else given (e.g.166.666)
@@ -244,42 +239,27 @@
# $_dosmem = (640)
# Extended Memory size. This memory is accessible via int15h and can be
# used by himem.sys.
# Default: 8192 (8Mb)
# used by himem.sys and the internal XMS driver.
# Default: 8192
# $_ext_mem = (8192)
# $_xms = (8192)
# XMS (internal driver) is only needed if you do not load
# himem.sys or another external XMS driver. Size in Kbytes.
# Default: 16384 (16Mb)
# $_xms = (16384)
# Enable 64K UMB at 0xa0000.
# Enable 64K UMB at 0a0000.
# This is where the VGA graphics memory resides, so enabling this UMB
# will leave you with text mode only.
# Default: auto (enabled only if dosemu runs in text mode)
# $_umb_a0 = (auto)
# Enable 32K UMB at 0xb0000.
# Enable 32K UMB at 0b0000.
# This is where the MDA text memory used to reside, so some programs
# write to that area without hesitation. Therefore it is rather risky
# to enable that UMB: beware even of ansi.sys!
# Default: auto (means: enable only for dumb video mode)
# $_umb_b0 = (auto)
# Enable 32K UMB at 0xb8000.
# This is the text-mode video memory.
# It can be used as UMB only in dumb video mode.
# Use "auto" to get it enabled in that mode.
# And even in that case only few well-behaved programs will work.
# Default: off
# $_umb_b8 = (off)
# $_umb_b0 = (off)
# Enable 16K UMB at 0xf0000.
# Enable 48K UMB at 0f0000.
# This is where normally a read-only BIOS resides but the DOSEMU BIOS does
# not need it. Some (very few) programs rely on this memory being read-only
# (Prehistorik 2); to run such programs, disable this option.
@@ -287,22 +267,6 @@
# $_umb_f0 = (on)
# Enable HMA usage and a20 gating.
# HMA is the ~64K area above 1Mb of RAM.
# Default: on
# $_hma = (on)
# Load DOS kernel to upper memory (UMB or HMA).
# 0 or off means load low, 1 means UMB, 2 means UMB+HMA.
# This gives more free conventional memory but may lead to incompatibilities.
# You can freely disable that option and most of the DOS memory will remain
# in UMB nevertheless (given the proper config.sys).
# Note: only relevant for fdpp.
# Default: 1 (use only UMB, minor incompatibilities)
# $_dos_up = (1)
# EMS (expanded memory) size in Kbytes;
# Warning: disabling EMS (off) is not recommended. Doing so will
# give you the additional 64K of UMB space, but as a side-effect
@@ -329,15 +293,23 @@
# $_ems_conv_pages = (24)
# DPMI memory size in Kbytes
# Default: 0x20000 (128Mb)
# DPMI memory size in Kbytes; default: 0x20000
# $_dpmi = (0x20000)
# DPMI base address
# Default: 0x20000000 (at 512Mb)
# Reserve linear address space for DPMI.
# This is mostly needed for HX extender to be able to load
# non-relocatable win32 binaries.
# Specify the DOS-relative address here or auto for reserve
# adjacent to DOS memory.
# Default: auto
# $_dpmi_base = (0x20000000)
# $_dpmi_lin_rsv_base = (auto)
# Size of reserved linear address space for DPMI.
# Default: 0x8000 (reserve 32Mb)
# $_dpmi_lin_rsv_size = (0x8000)
# Some DJGPP-compiled programs have the NULL pointer dereference bugs.
# They may work under Windows or QDPMI as these unfortunately do not
@@ -383,11 +355,6 @@
# $_cli_timeout = (10)
# apply some tweaks on emulated timers to make some old games more reliable.
# See tweaks.html for more info.
# $_timer_tweaks = (off)
##############################################################################
## Terminal related settings
@@ -423,7 +390,7 @@
# xterm, putty and compatibles window title. Default: %s - DOSEMU
# where %s is the DOS program's name. Use "" to not change the title
# $_xterm_title = "%s - dosemu2"
# $_xterm_title = "%s - DOSEMU"
##############################################################################
## Keyboard related settings
@@ -482,21 +449,14 @@
# $_mouse_baud = (0)
# alternative behaviour in ungrabbed mode
# May fix some problems with cursor positioning, but enabling mouse
# grab is always more reliable.
# Default: off
# $_mouse_ungrab_tweak = (off)
##############################################################################
## Joystick config
# 1st and 2nd joystick device
# e.g. "/dev/input/js0" or default: "/dev/input/js0 /dev/input/js1"
# e.g. "/dev/js0" or default: "/dev/js0 /dev/js1"
# (or "" if you don't want joystick support)
# $_joy_device = "/dev/input/js0 /dev/input/js1"
# $_joy_device = "/dev/js0 /dev/js1"
# range for joystick axis readings, must be > 0, default: 1
@@ -524,9 +484,6 @@
# All "/dev/ttyXX" may be suffixed by the IRQ
# used (instead of the default one), such as "/dev/ttyS2 irq 5"
# or "/dev/ttyS3 irq 9".
# Note: you can use any file here, eg fifo or even a regular file.
# In case of reading a regular file, don't forget to put ^Z (0x1a)
# at the end or there will be no EOF.
#
# "pseudo" keyword may be used to force the pseudo-TTY mode.
# A wrong but quick way to bypass the hardware flow control.
@@ -537,14 +494,6 @@
# "virtual" keyword may be used to redirect the COM port to the terminal.
# A wrong but quick way for the sysop to play his BBS door games locally.
#
# "exec <command>" execute command <command> and pipe it to the serial port.
# For example "exec rxvt -pty-fd 0" launches rxvt that can communicate
# with that serial port. Can also be used to play door games locally.
#
# "pts <name>" create pts <name> and attach its pty to serial port.
# For example "pts /tmp/com1" creates /tmp/com1 for communicating
# with the serial port.
#
# "mouse" keyword enables the serial mouse emulation on the specified port.
# You can then use native mouse driver, like mouse.com.
# Note: if you configured this as a second mouse ($_mouse_internal = (on)),
@@ -557,15 +506,6 @@
# You can then dial to the IP addresses, which will establish the telnet
# connection.
#
# "nullmodem <port_num>" - connect this port to port <port_num> with a
# null-modem cable. You need to also set up port <port_num> and connect
# it to this port the same way.
#
# "ro" - read-only. Write to the port is ignored unless the option below
# is set.
#
# "wrfile <file_name>" - use file <file_name> for com port output.
#
# Default: ""
# $_com1 = ""
@@ -646,17 +586,13 @@
# MPU-401 base i/o port
# $_mpu_base = (0x300)
# $_mpu_base = (0x330)
# MT32 MPU-401 base i/o port
# $_mpu_base_mt32 = (0x330)
# MIDI synth mode for MPU-401 at $_mpu_base_mt32
# MIDI synth mode
# Supported values: "gm", "mt32"
# Default: "mt32"
# Default: "gm"
# $_midi_synth = "mt32"
# $_midi_synth = "gm"
# MPU-401 irq for GM synth mode
# Default: auto (which is equal to $_sb_irq)
@@ -664,9 +600,9 @@
# $_mpu_irq = (auto)
# MPU-401 irq for mt32 synth mode
# Default: 9
# Default: 2
# $_mpu_irq_mt32 = (9)
# $_mpu_irq_mt32 = (2)
# Sound output driver.
# Supported drivers: ao, sdl (if compiled in)
@@ -676,12 +612,8 @@
# MIDI output drivers.
# Comma-separated list of midi drivers to enable.
# Supported GM drivers:
# fluid, timidity, alsa_midi, oss_midi, pipe_midi
# Supported MT-32 drivers:
# munt, alsa_virmidi
# It is better to specify 2 drivers at once, one for GM and one for MT-32.
# Example: "alsa_midi,alsa_virmidi"
# Supported drivers:
# fluid, timidity, munt, alsa_midi, oss_midi, pipe_midi
# Default: "" (which means auto)
# Note: if you use $_wav_file option to record the sound and want
# the rendered midi to also be recorded there, you need to select
@@ -690,16 +622,6 @@
# $_midi_driver = ""
# fluidsynth soundfont path
# $_fluid_sfont = ""
# fluidsynth volume
# Values: 0 to 10 (larger than 10 is possible but results in distortion)
# Default: 6
# $_fluid_volume = (6)
# munt ROMs path.
# Path to munt ROM files.
# Default: "roms" (which means ~/.dosemu/roms)
@@ -719,16 +641,12 @@
# $_opl2lpt_type = "opl2"
# Sound and MIDI plugin parameters.
# Syntax: plugin1:param1=val1 plugin2:param2=val2..."
# Syntax: plugin1:param1=val1,plugin2:param2=val2..."
# Description: dosemu implements many sound and midi plugins.
# Some of them may be selected with the $_sound_driver and $_midi_driver
# options above; some are managed by dosemu automatically.
# This option allows to pass the parameters to any of them.
# Example: "alsa_virmidi:dev_name=munt"
# If your /etc/asound.conf doesn't define the rawmidi device index,
# you can set it like in this example:
# Example: "alsa_midi:dev_name=hw:3,0 alsa_virmidi:dev_name=hw:3,1"
# You can disable some plugins this way: "alsa_virmidi:enabled=0"
# Default: ""
# $_snd_plugin_params = ""
@@ -764,9 +682,9 @@
# $_pktdriver = (on)
# NE2000 emulation (experimental). Default: on
# NE2000 emulation (experimental). Default: off
# $_ne2k = (on)
# $_ne2k = (off)
# Virtual networking type. "eth" for exclusive NIC access, "tap" for
# using the TAP virtual device, "vde" for vde2 and "slirp" for slirp.
@@ -789,12 +707,6 @@
# $_tapdev = "tap0"
# Network daemon socket name (for passt mainly).
# Set to "/tmp/passt_1.socket" to use with passt.
# Default: ""
# $_netsock = ""
# vdeswitch socket name for packet driver in "vde" mode.
# If empty string is specified, dosemu will try to set up the VDE switch
# automatically.
@@ -830,7 +742,7 @@
# Title in the top bar of the window. Default = "DOSEMU2"
# $_X_title = "dosemu2"
# $_X_title = "DOSEMU2"
# Show name of running app in the top bar of the window. Default: on
@@ -918,14 +830,6 @@
# $_X_background_pause = (off)
# Hide the Close button and disable the Close menu item
# $_X_noclose = (off)
# Disable resize by dragging window borders
# $_X_noresize = (off)
##############################################################################
## Settings specific to SDL video driver (dosemu -S)
@@ -939,19 +843,6 @@
# $_SDL_fonts = "Flexi IBM VGA False, Flexi IBM VGA True"
# Show window controls.
# It is not a common need to disable them, and can be done at run-time
# by pressing Ctrl-Alt-b.
# Default: on
# $_SDL_wcontrols = (on)
# Enable native clipboard access.
# Can be toggled at run-time by pressing Ctrl-Alt-c.
# Default: off
# $_SDL_clip_native = (off)
##############################################################################
## Common video driver settings
@@ -972,6 +863,12 @@
# [priv] list of portnumbers such as "0x1ce 0x1cf 0x238" or
# "0x1ce range 0x280,0x29f 310" or "range 0x1a0,(0x1a0+15)". Default: ""
# $_ports = "device /dev/null fast 0x200"
# $_ports = $_ports, " device /dev/lp0 range 0x378 0x37a"
# The blank is important
# "device" means: if the ports are registered, open this device to block
# access. The open must be successful or access to the ports will be denied.
# If you know what you are doing, use /dev/null to fake a device to block
# $_ports = ""

View File

@@ -108,6 +108,7 @@ else
if (strlen($_trace_mmio)) trace_mmio { $$_trace_mmio } endif
cpuspeed $_cpuspeed
rdtsc $_rdtsc
timer 0
mathco $_mathco
@@ -130,17 +131,18 @@ else
endif
umb_a0 $_umb_a0
umb_b0 $_umb_b0
umb_b8 $_umb_b8
umb_f0 $_umb_f0
hma $_hma
dos_up $_dos_up
dpmi $_dpmi
dpmi_base $_dpmi_base
dpmi_lin_rsv_base $_dpmi_lin_rsv_base
dpmi_lin_rsv_size $_dpmi_lin_rsv_size
pm_dos_api 1
ignore_djgpp_null_derefs $_ignore_djgpp_null_derefs
dosmem $_dosmem
ext_mem $_ext_mem
xms $_xms
if ($_ext_mem)
ext_mem $_ext_mem
else
ext_mem $_xms
endif
if ($_emusys ne "") emusys $_emusys endif
@@ -187,13 +189,11 @@ else
fixed_aspect $_X_fixed_aspect vgaemu_memsize $_X_vgaemu_memsize
lfb $_X_lfb pm_interface $_X_pm_interface mitshm $_X_mitshm
background_pause $_X_background_pause fullscreen $_X_fullscreen
noclose $_X_noclose
noresize $_X_noresize
$$xxx
}
## SDL settings
SDL { sdl_hwrend $_SDL_hwrend sdl_fonts $_SDL_fonts sdl_wcontrols $_SDL_wcontrols sdl_clip_native $_SDL_clip_native }
SDL { sdl_hwrend $_SDL_hwrend sdl_fonts $_SDL_fonts }
# video settings
vga_fonts $$_force_vga_fonts
@@ -224,19 +224,17 @@ else
## sound settings
sound $_sound
sound_emu { sb_base $_sb_base
if ($_sound)
sound_emu { sb_base $_sb_base
sb_irq $_sb_irq
sb_dma $_sb_dma
sb_hdma $_sb_hdma
mpu_base $_mpu_base
mpu_base_mt32 $_mpu_base_mt32
midi_synth $_midi_synth
mpu_irq $_mpu_irq
mpu_irq_mt32 $_mpu_irq_mt32
sound_driver $_sound_driver
midi_driver $_midi_driver
fluid_sfont $_fluid_sfont
fluid_volume $_fluid_volume
munt_roms $_munt_roms
opl2lpt_dev $_opl2lpt_dev
opl2lpt_type $_opl2lpt_type
@@ -244,7 +242,8 @@ else
pcm_hpf $_pcm_hpf
midi_file $_midi_file
wav_file $_wav_file
}
}
endif
## joystick settings
joystick_emu { joy_device $_joy_device joy_dos_min $_joy_dos_min
@@ -254,7 +253,6 @@ else
## hacks
cli_timeout $_cli_timeout
timemode $_timemode
timer_tweaks $_timer_tweaks
file_lock_limit $$_file_lock_limit
lfn_support $_lfn_support
@@ -268,33 +266,19 @@ else
ttylocks { directory $$xxx namestub LCK.. }
if (1) # no idea why but we need this...
foreach $xxx (" ", "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16")
$yyy = "com", $xxx
$zzz = "$_com", $xxx
$zzz = $$zzz
if (strlen($zzz))
$jjj = ""
if (strchr($zzz, " ") > 0)
$yyy = strsplit($zzz, strchr($zzz, " ") + 1, 999)
$zzz = strdel($zzz, strchr($zzz, " "), 999)
else
$yyy = ""
endif
if (strchr($zzz, "/") == 0)
if (strchr($yyy, " ") > 0)
$jjj = strsplit($yyy, strchr($yyy, " ") + 1, 999)
$yyy = strdel($yyy, strchr($yyy, " "), 999)
endif
if (strlen($jjj) > 0)
serial { com $xxx device $zzz $$yyy $jjj }
if ($zzz eq "virtual")
serial { com $xxx virtual }
else if ($zzz eq "mouse")
serial { com $xxx mouse }
else if ($zzz eq "vmodem")
serial { com $xxx vmodem }
else
serial { com $xxx device $zzz $$yyy }
endif
else
if (strlen($yyy) > 0)
serial { com $xxx $$zzz $yyy }
else
serial { com $xxx $$zzz }
endif
endif
serial { com $xxx device $$zzz }
endif endif
endif
done
endif
@@ -306,7 +290,7 @@ else
$xxx = "baudrate ", $_mouse_baud
endif
$xxx = $xxx, " device '", $_mouse_dev, "'"
mouse { $$_mouse $$_mouse_flags $$xxx internaldriver mouse_ungrab_tweak $_mouse_ungrab_tweak }
mouse { $$_mouse $$_mouse_flags $$xxx internaldriver }
else
$xxx = "'", $_mouse_dev, "'"
mouse { $$_mouse device $$xxx }
@@ -428,9 +412,9 @@ else
$xxx_pref = strdel($xxxx, strchr($xxxx, "*"), 999);
$xxx_suff = strsplit($xxxx, strchr($xxxx, "*") + 1, 999);
if (strchr($xxx_pref, "/") == 0)
$xxxx = shell("cd '", $xxx_pref, "' 2>/dev/null && printf *")
$xxxx = shell("cd '", $xxx_pref, "' 2>/dev/null && echo -n *")
else
$xxxx = shell("cd '", $DOSEMU_IMAGE_DIR, "/", $xxx_pref, "' 2>/dev/null && printf *")
$xxxx = shell("cd '", $DOSEMU_IMAGE_DIR, "/", $xxx_pref, "' 2>/dev/null && echo -n *")
endif
if ($DOSEMU_SHELL_RETURN)
abort "**** directory ", $xxx_pref, " not accessible";
@@ -444,27 +428,58 @@ else
foreach $xxx ($LIST_DELIM, $xxxx)
$xxx = $xxx_pref, $xxx, $xxx_suff
if (!strncmp($xxx, "/dev/", 4))
$yyy = strdel($xxx, strstr($xxx, ":"), 999);
$zzz = strsplit($xxx, strstr($xxx, ":"), 999);
$yyy = strdel($xxx, strstr($xxx, ":ro"), 999);
$zzz = strsplit($xxx, strstr($xxx, ":ro"), 999);
if (strtol(strdel($xxx,0,8)) > 0)
disk { partition $yyy $$zzz };
$yyy = "disk { partition ", $yyy;
else
disk { wholedisk $yyy $$zzz };
$yyy = "disk { wholedisk ", $yyy;
endif
if (strlen($zzz))
$yyy = $yyy, " readonly"
endif
$yyy = $yyy, " }";
$$yyy;
else
$yyy = strdel($xxx, strstr($xxx, ":"), 999);
$zzz = strsplit($xxx, strstr($xxx, ":"), 999);
$yyy3 = strdel($xxx, strstr($xxx, ":ro"), 999);
$yyy2 = strdel($yyy3, strstr($xxx, ":hdtype1"), 999);
$yyy1 = strdel($yyy2, strstr($xxx, ":hdtype2"), 999);
$yyy = strdel($yyy1, strstr($xxx, ":hdtype9"), 999);
$zzz = strsplit($xxx, strstr($xxx, ":ro"), 999);
$uuu = strsplit($xxx, strstr($xxx, ":hdtype1"), 999);
$vvv = strsplit($xxx, strstr($xxx, ":hdtype2"), 999);
$www = strsplit($xxx, strstr($xxx, ":hdtype9"), 999);
if (strchr($yyy, "/") != 0)
$yyyy = $DOSEMU_IMAGE_DIR, "/", $yyy
$yyy = $yyyy
endif
shell("test -d '", $yyy, "'")
if (!$DOSEMU_SHELL_RETURN)
disk { directory $yyy $$zzz };
if (strlen($zzz))
disk { directory $yyy readonly };
else if (strlen($uuu))
disk { directory $yyy hdtype1 };
else if (strlen($vvv))
disk { directory $yyy hdtype2 };
else if (strlen($www))
disk { directory $yyy hdtype9 };
else
disk { directory $yyy };
endif endif endif endif
else
shell("test -f '", $yyy, "'")
if (!$DOSEMU_SHELL_RETURN)
disk { image $yyy $$zzz };
if (strlen($zzz))
disk { image $yyy readonly };
else if (strlen($uuu))
disk { image $yyy hdtype1 };
else if (strlen($vvv))
disk { image $yyy hdtype2 };
else if (strlen($www))
disk { image $yyy hdtype9 };
else
disk { image $yyy };
endif endif endif endif
else
abort "hdimage ", $yyy, " not found"
endif
@@ -557,7 +572,6 @@ else
tapdev $_tapdev
vdeswitch $_vdeswitch
slirpargs $_slirpargs
netsock $_netsock
vnet $_vnet
pktdriver $_pktdriver
ne2k $_ne2k

View File

@@ -1,7 +1,6 @@
{
/* add your mappings below and send a patch */
"locales": [
{ "lang": "C", "codepage": "cp437", "country": 001 },
{ "lang": "en_US", "codepage": "cp437", "country": 001 },
{ "lang": "cs_CZ", "codepage": "cp852", "country": 042 },
{ "lang": "af_ZA", "codepage": "cp858", "country": 785 },
@@ -61,7 +60,6 @@
{ "lang": "nl_NL", "codepage": "cp858", "country": 031 },
{ "lang": "nn_NO", "codepage": "cp858", "country": 047 },
{ "lang": "no_NO", "codepage": "cp858", "country": 047 },
{ "lang": "pl_PL", "codepage": "cp852", "country": 048 },
{ "lang": "pt_BR", "codepage": "cp858", "country": 055 },
{ "lang": "pt_PT", "codepage": "cp858", "country": 351 },
{ "lang": "sv_FI", "codepage": "cp858", "country": 358 },

View File

@@ -4,14 +4,14 @@ if [ $# != 2 ]; then
echo "Usage: $0 <src_dir> <build_dir>" >&2
exit 1
fi
DATE=`git -C $1 log -1 --format=%cd --date=format-local:'%m%d%H%M.%S'`
DATE=`git -C $1 log -1 --format=%cd --date=rfc`
if [ $? != 0 ]; then
echo "Non-git builds deprecated" >&2
exit 1
fi
TSTAMP=$2/.tstamp
if ! touch -t "$DATE" $TSTAMP 2>/dev/null; then
echo "touch doesnt support -t, build may be incomplete" >&2
if ! touch --date="$DATE" $TSTAMP 2>/dev/null; then
echo "touch doesnt support --date, build may be incomplete" >&2
if [ ! -f "$TSTAMP" ]; then
touch $TSTAMP
fi

323
install-sh Executable file
View File

@@ -0,0 +1,323 @@
#!/bin/sh
# install - install a program, script, or datafile
scriptversion=2005-05-14.22
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
# following copyright and license.
#
# Copyright (C) 1994 X Consortium
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of the X Consortium shall not
# be used in advertising or otherwise to promote the sale, use or other deal-
# ings in this Software without prior written authorization from the X Consor-
# tium.
#
#
# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch. It can only install one file at a time, a restriction
# shared with many OS's install programs.
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"
# put in absolute paths if you don't have them in your path; or use env. vars.
mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
chmodprog="${CHMODPROG-chmod}"
chownprog="${CHOWNPROG-chown}"
chgrpprog="${CHGRPPROG-chgrp}"
stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
mkdirprog="${MKDIRPROG-mkdir}"
chmodcmd="$chmodprog 0755"
chowncmd=
chgrpcmd=
stripcmd=
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=
dst=
dir_arg=
dstarg=
no_target_directory=
usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
or: $0 [OPTION]... SRCFILES... DIRECTORY
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
or: $0 [OPTION]... -d DIRECTORIES...
In the 1st form, copy SRCFILE to DSTFILE.
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
In the 4th, create DIRECTORIES.
Options:
-c (ignored)
-d create directories instead of installing files.
-g GROUP $chgrpprog installed files to GROUP.
-m MODE $chmodprog installed files to MODE.
-o USER $chownprog installed files to USER.
-s $stripprog installed files.
-t DIRECTORY install into DIRECTORY.
-T report an error if DSTFILE is a directory.
--help display this help and exit.
--version display version info and exit.
Environment variables override the default commands:
CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG
"
while test -n "$1"; do
case $1 in
-c) shift
continue;;
-d) dir_arg=true
shift
continue;;
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
--help) echo "$usage"; exit $?;;
-m) chmodcmd="$chmodprog $2"
shift
shift
continue;;
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
-s) stripcmd=$stripprog
shift
continue;;
-t) dstarg=$2
shift
shift
continue;;
-T) no_target_directory=true
shift
continue;;
--version) echo "$0 $scriptversion"; exit $?;;
*) # When -d is used, all remaining arguments are directories to create.
# When -t is used, the destination is already specified.
test -n "$dir_arg$dstarg" && break
# Otherwise, the last argument is the destination. Remove it from $@.
for arg
do
if test -n "$dstarg"; then
# $@ is not empty: it contains at least $arg.
set fnord "$@" "$dstarg"
shift # fnord
fi
shift # arg
dstarg=$arg
done
break;;
esac
done
if test -z "$1"; then
if test -z "$dir_arg"; then
echo "$0: no input file specified." >&2
exit 1
fi
# It's OK to call `install-sh -d' without argument.
# This can happen when creating conditional directories.
exit 0
fi
for src
do
# Protect names starting with `-'.
case $src in
-*) src=./$src ;;
esac
if test -n "$dir_arg"; then
dst=$src
src=
if test -d "$dst"; then
mkdircmd=:
chmodcmd=
else
mkdircmd=$mkdirprog
fi
else
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if test ! -f "$src" && test ! -d "$src"; then
echo "$0: $src does not exist." >&2
exit 1
fi
if test -z "$dstarg"; then
echo "$0: no destination specified." >&2
exit 1
fi
dst=$dstarg
# Protect names starting with `-'.
case $dst in
-*) dst=./$dst ;;
esac
# If destination is a directory, append the input filename; won't work
# if double slashes aren't ignored.
if test -d "$dst"; then
if test -n "$no_target_directory"; then
echo "$0: $dstarg: Is a directory" >&2
exit 1
fi
dst=$dst/`basename "$src"`
fi
fi
# This sed command emulates the dirname command.
dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
# Make sure that the destination directory exists.
# Skip lots of stat calls in the usual case.
if test ! -d "$dstdir"; then
defaultIFS='
'
IFS="${IFS-$defaultIFS}"
oIFS=$IFS
# Some sh's can't handle IFS=/ for some reason.
IFS='%'
set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
shift
IFS=$oIFS
pathcomp=
while test $# -ne 0 ; do
pathcomp=$pathcomp$1
shift
if test ! -d "$pathcomp"; then
$mkdirprog "$pathcomp"
# mkdir can fail with a `File exist' error in case several
# install-sh are creating the directory concurrently. This
# is OK.
test -d "$pathcomp" || exit
fi
pathcomp=$pathcomp/
done
fi
if test -n "$dir_arg"; then
$doit $mkdircmd "$dst" \
&& { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \
&& { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \
&& { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; }
else
dstfile=`basename "$dst"`
# Make a couple of temp file names in the proper directory.
dsttmp=$dstdir/_inst.$$_
rmtmp=$dstdir/_rm.$$_
# Trap to clean up those temp files at exit.
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
trap '(exit $?); exit' 1 2 13 15
# Copy the file name to the temp name.
$doit $cpprog "$src" "$dsttmp" &&
# and set any options; do chmod last to preserve setuid bits.
#
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $cpprog $src $dsttmp" command.
#
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \
&& { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \
&& { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \
&& { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } &&
# Now rename the file to the real destination.
{ $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \
|| {
# The rename failed, perhaps because mv can't rename something else
# to itself, or perhaps because mv is so ancient that it does not
# support -f.
# Now remove or move aside any old file at destination location.
# We try this two ways since rm can't unlink itself on some
# systems and the destination file might be busy for other
# reasons. In this case, the final cleanup might fail but the new
# file should still install successfully.
{
if test -f "$dstdir/$dstfile"; then
$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \
|| $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \
|| {
echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
(exit 1); exit 1
}
else
:
fi
} &&
# Now rename the file to the real destination.
$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
}
}
fi || { (exit 1); exit 1; }
done
# The final little trick to "correctly" pass the exit status to the exit trap.
{
(exit 0); exit 0
}
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-end: "$"
# End:

View File

@@ -1,155 +0,0 @@
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_prog_cc_for_build.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_PROG_CC_FOR_BUILD
#
# DESCRIPTION
#
# This macro searches for a C compiler that generates native executables,
# that is a C compiler that surely is not a cross-compiler. This can be
# useful if you have to generate source code at compile-time like for
# example GCC does.
#
# The macro sets the CC_FOR_BUILD and CPP_FOR_BUILD macros to anything
# needed to compile or link (CC_FOR_BUILD) and preprocess (CPP_FOR_BUILD).
# The value of these variables can be overridden by the user by specifying
# a compiler with an environment variable (like you do for standard CC).
#
# It also sets BUILD_EXEEXT and BUILD_OBJEXT to the executable and object
# file extensions for the build platform, and GCC_FOR_BUILD to `yes' if
# the compiler we found is GCC. All these variables but GCC_FOR_BUILD are
# substituted in the Makefile.
#
# LICENSE
#
# Copyright (c) 2008 Paolo Bonzini <bonzini@gnu.org>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 21
AU_ALIAS([AC_PROG_CC_FOR_BUILD], [AX_PROG_CC_FOR_BUILD])
AC_DEFUN([AX_PROG_CC_FOR_BUILD], [dnl
AC_REQUIRE([AC_PROG_CC])dnl
AC_REQUIRE([AC_PROG_CPP])dnl
AC_REQUIRE([AC_CANONICAL_BUILD])dnl
dnl Use the standard macros, but make them use other variable names
dnl
pushdef([ac_cv_prog_CPP], ac_cv_build_prog_CPP)dnl
pushdef([ac_cv_prog_cc_c89], ac_cv_build_prog_cc_c89)dnl
pushdef([ac_cv_prog_cc_c99], ac_cv_build_prog_cc_c99)dnl
pushdef([ac_cv_prog_cc_c11], ac_cv_build_prog_cc_c11)dnl
pushdef([ac_cv_prog_gcc], ac_cv_build_prog_gcc)dnl
pushdef([ac_cv_prog_cc_works], ac_cv_build_prog_cc_works)dnl
pushdef([ac_cv_prog_cc_cross], ac_cv_build_prog_cc_cross)dnl
pushdef([ac_cv_prog_cc_g], ac_cv_build_prog_cc_g)dnl
pushdef([ac_cv_c_compiler_gnu], ac_cv_build_c_compiler_gnu)dnl
pushdef([ac_cv_exeext], ac_cv_build_exeext)dnl
pushdef([ac_cv_objext], ac_cv_build_objext)dnl
pushdef([ac_exeext], ac_build_exeext)dnl
pushdef([ac_objext], ac_build_objext)dnl
pushdef([CC], CC_FOR_BUILD)dnl
pushdef([CPP], CPP_FOR_BUILD)dnl
pushdef([GCC], GCC_FOR_BUILD)dnl
pushdef([CFLAGS], CFLAGS_FOR_BUILD)dnl
pushdef([CPPFLAGS], CPPFLAGS_FOR_BUILD)dnl
pushdef([EXEEXT], BUILD_EXEEXT)dnl
pushdef([LDFLAGS], LDFLAGS_FOR_BUILD)dnl
pushdef([OBJEXT], BUILD_OBJEXT)dnl
pushdef([host], build)dnl
pushdef([host_alias], build_alias)dnl
pushdef([host_cpu], build_cpu)dnl
pushdef([host_vendor], build_vendor)dnl
pushdef([host_os], build_os)dnl
pushdef([ac_cv_host], ac_cv_build)dnl
pushdef([ac_cv_host_alias], ac_cv_build_alias)dnl
pushdef([ac_cv_host_cpu], ac_cv_build_cpu)dnl
pushdef([ac_cv_host_vendor], ac_cv_build_vendor)dnl
pushdef([ac_cv_host_os], ac_cv_build_os)dnl
pushdef([ac_tool_prefix], ac_build_tool_prefix)dnl
pushdef([am_cv_CC_dependencies_compiler_type], am_cv_build_CC_dependencies_compiler_type)dnl
pushdef([am_cv_prog_cc_c_o], am_cv_build_prog_cc_c_o)dnl
pushdef([cross_compiling], cross_compiling_build)dnl
cross_compiling_build=no
ac_build_tool_prefix=
AS_IF([test -n "$build"], [ac_build_tool_prefix="$build-"],
[test -n "$build_alias"],[ac_build_tool_prefix="$build_alias-"])
AC_LANG_PUSH([C])
dnl The pushdef([ac_cv_c_compiler_gnu], ...) currently does not cover
dnl the use of this variable in _AC_LANG_COMPILER_GNU called by
dnl AC_PROG_CC. Unset this cache variable temporarily as a workaround.
was_set_c_compiler_gnu=${[ac_cv_c_compiler_gnu]+y}
AS_IF([test ${was_set_c_compiler_gnu}],
[saved_c_compiler_gnu=$[ac_cv_c_compiler_gnu]
AS_UNSET([[ac_cv_c_compiler_gnu]])])
AC_PROG_CC
dnl Restore ac_cv_c_compiler_gnu
AS_IF([test ${was_set_c_compiler_gnu}],
[[ac_cv_c_compiler_gnu]=$[saved_c_compiler_gnu]])
_AC_COMPILER_EXEEXT
_AC_COMPILER_OBJEXT
AC_PROG_CPP
dnl Restore the old definitions
dnl
popdef([cross_compiling])dnl
popdef([am_cv_prog_cc_c_o])dnl
popdef([am_cv_CC_dependencies_compiler_type])dnl
popdef([ac_tool_prefix])dnl
popdef([ac_cv_host_os])dnl
popdef([ac_cv_host_vendor])dnl
popdef([ac_cv_host_cpu])dnl
popdef([ac_cv_host_alias])dnl
popdef([ac_cv_host])dnl
popdef([host_os])dnl
popdef([host_vendor])dnl
popdef([host_cpu])dnl
popdef([host_alias])dnl
popdef([host])dnl
popdef([OBJEXT])dnl
popdef([LDFLAGS])dnl
popdef([EXEEXT])dnl
popdef([CPPFLAGS])dnl
popdef([CFLAGS])dnl
popdef([GCC])dnl
popdef([CPP])dnl
popdef([CC])dnl
popdef([ac_objext])dnl
popdef([ac_exeext])dnl
popdef([ac_cv_objext])dnl
popdef([ac_cv_exeext])dnl
popdef([ac_cv_c_compiler_gnu])dnl
popdef([ac_cv_prog_cc_g])dnl
popdef([ac_cv_prog_cc_cross])dnl
popdef([ac_cv_prog_cc_works])dnl
popdef([ac_cv_prog_cc_c89])dnl
popdef([ac_cv_prog_gcc])dnl
popdef([ac_cv_prog_CPP])dnl
dnl restore global variables ac_ext, ac_cpp, ac_compile,
dnl ac_link, ac_compiler_gnu (dependant on the current
dnl language after popping):
AC_LANG_POP([C])
dnl Finally, set Makefile variables
dnl
AC_SUBST(BUILD_EXEEXT)dnl
AC_SUBST(BUILD_OBJEXT)dnl
AC_SUBST([CFLAGS_FOR_BUILD])dnl
AC_SUBST([CPPFLAGS_FOR_BUILD])dnl
AC_SUBST([LDFLAGS_FOR_BUILD])dnl
])

View File

@@ -9,8 +9,7 @@ MANPAGES = dosemu.1 dosemu.bin.1 ru/dosemu.1 ru/dosemu.bin.1
default all: $(MANPAGES)
.NOTPARALLEL: $(MANPAGES)
$(MANPAGES): $(top_builddir)/config.status $(wildcard $(top_srcdir)/man/*.1.in) \
$(wildcard $(top_srcdir)/man/ru/*.1.in)
$(MANPAGES): $(top_builddir)/config.status $(wildcard $(top_srcdir)/man/*.1.in)
cd $(top_builddir) && ./config.status
install: all
@@ -25,5 +24,6 @@ install: all
clean realclean:
for i in `ls $(top_srcdir)/man/*.1.in $(top_srcdir)/man/ru/*.1.in` ; do \
rm -f `echo $$i | sed -E -e 's=$(top_srcdir)/man/(.+).in$$=\1='`; \
rm -f `echo $$i | sed -s -e 's/\.in$$//' \
-e 's=$(top_srcdir)/man/=='`; \
done

View File

@@ -1,7 +1,7 @@
.\" -*- nroff -*- (This is for Emacs)
.TH DOSEMU 1 "@RELEASE_DATE@" "Version @PACKAGE_VERSION@" "DOS Emulation"
.SH NAME
dosemu \- run DOS and DOS programs under Linux
dosemu, xdosemu \- run DOS and DOS programs under Linux
.SH SYNOPSIS
.B dosemu
[
@@ -15,19 +15,31 @@ dosemu \- run DOS and DOS programs under Linux
.B \-s
]
[
.I env1=val1
.I ...
.B \-install
.I [ bootdir ]
]
[
.I unix_path_to_dos_prog
[
.I --
]
[
.I dos_cmd_args
]
.B args
]
.PP
.B xdosemu
[
.B \-dumb
]
[
.B \-input
.I keystroke-string
]
[
.B \-s
]
[
.B \-install
.I [ bootdir ]
]
[
.B args
]
.SH DESCRIPTION
.B dosemu
is the wrapper script for
@@ -35,6 +47,9 @@ is the wrapper script for
(1)
which invokes the Linux dos emulator, also known as
.BR DOSEMU .
The wrapper also takes care of (eventually) installing the private instance of
.BR DOSEMU
in the user's $HOME, if this doesn't exist.
.br
.SH OPTIONS
@@ -68,7 +83,17 @@ of the string look at README.txt.
Invoke dosemu via sudo. This is necessary to get access to certain I/O ports
and to get graphics on the Linux console. Please refer to the documentation
(INSTALL and README.txt) to see which files need to be adjusted before
attempting this.
attempting this.
.TP
.I -install [ bootdir ]
launched as part of a systemwide installation, this option (re-)installs
a DOS that is used in DOSEMU (this can be the DOSEMU distributed
FreeDOS or any proprietary DOS, which is bootable via fatfs).
.I bootdir
is the base name of a directory. The symbolic link ~/.dosemu/drives/c
will be changed to point to this directory.
Re-installing is only rarely necessary, since in practise the symbolic
link(s) will automatically point to updated files.
.TP
.I --version
print version of dosemu and list of available options.

View File

@@ -64,7 +64,11 @@ dosemu.bin, dosdebug \- run DOS and DOS programs under Linux
]
[
.B \-i
.I \h'-1' input_data
.I \h'-1'[bootdir]
]
[
.B \-U
.I number of path components
]
[
.B \-E
@@ -72,20 +76,7 @@ dosemu.bin, dosdebug \- run DOS and DOS programs under Linux
]
[
.B \-K
.I unix_path[:dos_path]
]
[
.I env1=val1
.I ...
]
[
.I unix_path_to_dos_prog
[
.I --
]
[
.I dos_cmd_args
]
.I unix_path
]
.sp
.B dosdebug
@@ -170,28 +161,18 @@ command.
.TP
.I -K unix_path[:dos_path]
Specify unix path for the program running with \-E.
You can omit \-E and specify the full unix path with \-K, but it is
not recommended and may be removed in the future. You need to specify
a directory path to \-K.
.br
If dos_path is specified, then it is used as a current directory when
invoking the command. If unix_path is empty then the drive letter is
taken from dos_path:
You can omit \-E and specify the full unix path with \-K, but passing
command-line arguments via \-K is not recommended and may be removed
in the future. The following may nevertheless work:
.nf
dosemu -K :C:\\\\games\\\\carma -E carma.exe
dosemu -K "/home/joeuser/dosemu/freedos/bin/xcopy.exe my_file my_dir"
.fi
This runs carma.exe from C:\\games\\carma
If dos_path is specified, then it is used as a current directory when
invoking the command.
.TP
.I -T[flags]
Sets flags for -E and -K commands. "flags" is the string of the
following chars:
1: don't terminate DOSEMU after running the command specified either
.I -T
Don't terminate DOSEMU after running the command specified either
with -E or -K.
h: try to load the specified command into UMB (loadhigh).
If -T is specified without flags, then "1h" flags string is assumed.
.TP
.I -q
Quiet mode. Suppress all DOS output except that of the command specified
@@ -219,12 +200,10 @@ Bypass the default directory for bootdirectory and hdimages (DOSEMU_IMAGE_DIR)
and use this directory instead.
.TP
.I -f
Parse this config-file instead of .dosemurc. If -n is also specified, then
this config file is parsed instead of the primary dosemu.conf.
Parse this config-file instead of .dosemurc
.TP
.I -n
Bypass (don't use) default user's config .dosemurc. The config specified
with -f is still parsed, but in that case it replaces the main dosemu.conf.
Bypass (don't use) user's config .dosemurc.
.TP
.I -L <log_string>
Writes provided <log_string> to a log.
@@ -255,12 +234,15 @@ because it is expected to be
.I one
argument.
.TP
.I -i input_data
Type
.I input_data
on the emulated keyboard. Use \\r for Enter. Various other special escapes
are available, for example you can insert pauses with "\\p10;" where
10 is a delay in tens of milliseconds.
.I -i[bootdir]
launched as part of a systemwide installation, this option (re-)installs
a DOS that is used in DOSEMU (this can be the DOSEMU distributed
FreeDOS or any proprietary DOS, which is bootable via fatfs).
.I bootdir
is the base name of a directory. The symbolic link ~/.dosemu/drives/c
will be changed to point to this directory.
Re-installing is only rarely necessary, since in practise the symbolic
link(s) will automatically point to updated files.
.TP
.I -D
specify which Debugging messages to allow/suppress
@@ -309,13 +291,11 @@ DIRECT HARDWARE ACCESS TO DOS PROGRAMS MAY GIVE THESE THE ABILITY
TO LOCK YOUR COMPUTER, OR (IN RARE CASES) EVEN DAMAGE HARDWARE.
ONLY TRUSTED LOCAL USERS SHOULD BE GIVEN THIS TYPE OF ACCESS.
.TP
.I -t[de[flag]]
.I -t[de]
terminal mode: run using the S-Lang library by default, or, if 'd'
is specified - use "dumb" terminal mode. If 'de' is specified,
use stderr in dumb terminal mode, except for the output of the
program started with -E that still goes to stdout. If 'de2' is
specified (flag==2), then also the output of -E-started program
goes to stderr.
program started with -E that still goes to stdout.
.TP
.I -V
use direct console video with VGA graphics and use the native graphics

View File

@@ -1,7 +1,7 @@
.\" -*- nroff -*- (This is for Emacs)
.TH DOSEMU 1 "@RELEASE_DATE@" "Версия @PACKAGE_VERSION@" "Эмуляция DOS"
.SH ИМЯ
dosemu \- запускает DOS и приложения DOS под Linux
dosemu, xdosemu \- запускает DOS и приложения DOS под Linux
.SH СИНТАКСИС
.B dosemu
[
@@ -15,18 +15,31 @@ dosemu \- запускает DOS и приложения DOS под Linux
.I строка_клавиш
]
[
.I env1=val1
.I ...
.B \-install
.I загрузочный_каталог
]
[
.I unix_путь_к_дос_программе
[
.I --
]
[
.I аргументы_досоманды
.B аргументы
]
.PP
.B xdosemu
[
.B \-dumb
]
[
.B \-home
]
[
.B \-input
.I строка_клавиш
]
[
.B \-install
.I загрузочный_каталог
]
[
.B аргументы
]
.SH ОПИСАНИЕ
.B dosemu
является оберточным скриптом для
@@ -75,6 +88,16 @@ dosemu \- запускает DOS и приложения DOS под Linux
нажатия на клавишу F8. Так в этом случае всегда необходимо добавлять символ
"\\r" в начало строки_клавиш. Как побочный эффект это даст проход ожидания
"F8", и FreeDos будет загружаться быстрее ;-)
.TP
.I -install
стартуя как часть общесистемной установки, такая опция устанавливает
частный вариант отличающегося от распространяемого с DOSEMU dosemu-freedos-bin
DOS (возможен любой проприетарный DOS, который загружается через fatfs).
.I загрузочный_каталог
является базовым именем каталога, пользователи имеют возможность
установки его внутри аналогичного каталога, где будет создан вариант
DOSEMU. Настройки в файле conf/dosemu.conf будут перекрыты этим
загрузочным каталогом.
.SH АВТОРЫ
.B DOSEMU

View File

@@ -63,24 +63,8 @@ dosemu.bin, dosdebug \- запускает DOS и приложения DOS по
.I опции_настройки
]
[
.B \-E
.I dos-команда
]
[
.B \-K
.I unix_путь[:dos_путь]
]
[
.I env1=val1
.I ...
]
[
.I unix_путь_к_дос_программе
[
.I --
]
[
.I аргументы_досоманды
.B \-U
.I вханал[:выханал]
]
.sp
.B dosdebug
@@ -154,31 +138,6 @@ facilities, смотрите
монтировать путь path как дополнительный диск в DOS.
Можно указывать более одного раза.
.TP
.I -E dos-команда
Запуск команды DOS в DOSEMU.
Путь к бинарнику можно указать с помощью опции \-K.
Например,
.nf
dosemu -K /home/joeuser/dosemu/freedos/bin -E "xcopy my_file my_dir"
.fi
запустит /home/joeuser/dosemu/freedos/bin/xcopy.exe с 2 аргументами.
.br
Замечание: это только работает с дефолтным autoexec.bat, в котором
есть вызов "system \-e".
.TP
.I -K unix_путь[:dos_путь]
Указать путь unix к программе, запускаемой через \-E.
Можно не использовать \-E, а указать полный путь через \-K, но это не
рекомендуется, и может быть удалено в будущем. Указывать в \-K надо
только путь к каталогу.
.br
Если указан dos_путь, тогда он используется в качестве директории запуска
dos-программы. Если unix_путь не указан, то буква диска берётся из dos_пути:
.nf
dosemu -K :C:\\\\games\\\\carma -E carma.exe
.fi
Так запустится carma.exe из C:\\games\\carma
.TP
.I -V
использовать VGA спефицичную оптимизацию видео
.TP
@@ -209,14 +168,7 @@ dosemu.users) и использовать предоставленный кат
имеет флага suid-root).
.TP
.I -f
Разобрать предоставленный конфигурационный файл вместо .dosemurc. Если
задействована опция -n, то указанный здесь конфигурационный файл будет
использован вместо основного dosemu.conf.
.TP
.I -n
Пропустить (не разбирать) пользовательский файл конфигурации .dosemurc.
Конфигурационный файл, указанный в -f, будет разобран, но, в этом случае,
он заменит основной конфиг dosemu.conf.
Разобрать предоставленный настроечный файл вместо .dosemurc
.TP
.I -L <log_string>
Записывает <log_string> в лог-файл.
@@ -248,14 +200,6 @@ dosemu.users) и использовать предоставленный кат
.I один
аргумент.
.TP
.I -i input_data
Вводит
.I input_data
с эмулируемой клавиатуры. Можно использовать \\r в качестве Enter.
Так же обрабатываются другие эскейп-последовательности, например
можно вставлять задержки с помощью конструкций вида "\\p10;", где
10 - величина задержки в десятках миллисекунд.
.TP
.I -D
определяет какие отладочные сообщения позволить, а какие запретить
.TP
@@ -297,6 +241,53 @@ DOSEMU будет затем заблокирован перед переход
.B DOSEMU
в режим 286.)
.TP
.I -U
определяет входной и выходной каналы для асинхронного управления
.B DOSEMU
из других процессов. Формат такой (без пробелов между словами):
.TP
вханал:выханал
где `:выханал' может быть опущен. В последнем случае можно не ожидать
обратной связи от
.B DOSEMU.
По соображениям безопастности
.B DOSEMU
не создает именованные каналы самому себе, так пользователь отвечает за
установку корректных прав доступа на каналы. Заметьте, что при использовании
этих опций, инородный процесс может контроллировать сессию
.B DOSEMU
(типа ввода с клавиатуры). Опция будет следоватьльно использована только
внешними интерфейсами (типа kdos), которые вначале содадут соответствующие
именованные каналы и затем запустят на исполнение
.B DOSEMU.
Специальные управляющяя команда (
.I ack on
) может быть использована, чтобы принудить
.B DOSEMU
возвратить признаки установки связи через `выханал' такой, чтобы внешний
интерфейс знал когда управляющая команда началась или закончилась и была ли
она успешна. Формат такого диалога признаков показан ниже
.TP
SYN: <имя_команды>
.TP
<различный вывод от команды>
.TP
ACK: code=n
где
.I n
равно 0 в случае успеха.
Простой управляющий терминал, который служит как пример, замещается программой
.I dosctrl.
Она берет только два канала как аргументы и дает возможность затем
вводить управляющие команды, из которых `help' наиболее важна ;-)
Заметьте,
.I dosctrl
не запускает на выполнение
.B DOSEMU,
что необходимо сделать вручную.
.PD 1
.SH ЖЕСТКИЕ ДИСКИ

View File

@@ -21,4 +21,3 @@ doscmd
periph
debugger
fdpp
dj64

View File

@@ -1,5 +1,3 @@
#!/bin/sh
if [ $# != 2 ]; then
exit 1
fi

View File

@@ -50,7 +50,7 @@ fi
# make distclean
if grep -q fdpp-build-path default-configure ; then
CC=clang ./default-configure -d fdpp-build-path=${FDPP_LIBRARY_SOURCE}/fdpp \
./default-configure -d fdpp-build-path=${FDPP_LIBRARY_SOURCE}/fdpp \
fdpp-include-path=${FDPP_LIBRARY_SOURCE}/include && make
else
[ -d pkgconfig ] || mkdir pkgconfig
@@ -60,5 +60,5 @@ else
-e "s,^includedir=.*$,includedir=${FDPP_LIBRARY_SOURCE},g" \
${FDPP_LIBRARY_SOURCE}/fdpp/fdpp.pc > pkgconfig/fdpp.pc
env PKG_CONFIG_PATH=`pwd`/pkgconfig CC=clang ./default-configure -d && make
env PKG_CONFIG_PATH=`pwd`/pkgconfig ./default-configure -d && make
fi

1480
scripts/config.guess vendored

File diff suppressed because it is too large Load Diff

1801
scripts/config.sub vendored

File diff suppressed because it is too large Load Diff

View File

@@ -1,541 +0,0 @@
#!/bin/sh
# install - install a program, script, or datafile
scriptversion=2020-11-14.01; # UTC
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
# following copyright and license.
#
# Copyright (C) 1994 X Consortium
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of the X Consortium shall not
# be used in advertising or otherwise to promote the sale, use or other deal-
# ings in this Software without prior written authorization from the X Consor-
# tium.
#
#
# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# 'make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch.
tab=' '
nl='
'
IFS=" $tab$nl"
# Set DOITPROG to "echo" to test this script.
doit=${DOITPROG-}
doit_exec=${doit:-exec}
# Put in absolute file names if you don't have them in your path;
# or use environment vars.
chgrpprog=${CHGRPPROG-chgrp}
chmodprog=${CHMODPROG-chmod}
chownprog=${CHOWNPROG-chown}
cmpprog=${CMPPROG-cmp}
cpprog=${CPPROG-cp}
mkdirprog=${MKDIRPROG-mkdir}
mvprog=${MVPROG-mv}
rmprog=${RMPROG-rm}
stripprog=${STRIPPROG-strip}
posix_mkdir=
# Desired mode of installed file.
mode=0755
# Create dirs (including intermediate dirs) using mode 755.
# This is like GNU 'install' as of coreutils 8.32 (2020).
mkdir_umask=22
backupsuffix=
chgrpcmd=
chmodcmd=$chmodprog
chowncmd=
mvcmd=$mvprog
rmcmd="$rmprog -f"
stripcmd=
src=
dst=
dir_arg=
dst_arg=
copy_on_change=false
is_target_a_directory=possibly
usage="\
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
or: $0 [OPTION]... SRCFILES... DIRECTORY
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
or: $0 [OPTION]... -d DIRECTORIES...
In the 1st form, copy SRCFILE to DSTFILE.
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
In the 4th, create DIRECTORIES.
Options:
--help display this help and exit.
--version display version info and exit.
-c (ignored)
-C install only if different (preserve data modification time)
-d create directories instead of installing files.
-g GROUP $chgrpprog installed files to GROUP.
-m MODE $chmodprog installed files to MODE.
-o USER $chownprog installed files to USER.
-p pass -p to $cpprog.
-s $stripprog installed files.
-S SUFFIX attempt to back up existing files, with suffix SUFFIX.
-t DIRECTORY install into DIRECTORY.
-T report an error if DSTFILE is a directory.
Environment variables override the default commands:
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
RMPROG STRIPPROG
By default, rm is invoked with -f; when overridden with RMPROG,
it's up to you to specify -f if you want it.
If -S is not specified, no backups are attempted.
Email bug reports to bug-automake@gnu.org.
Automake home page: https://www.gnu.org/software/automake/
"
while test $# -ne 0; do
case $1 in
-c) ;;
-C) copy_on_change=true;;
-d) dir_arg=true;;
-g) chgrpcmd="$chgrpprog $2"
shift;;
--help) echo "$usage"; exit $?;;
-m) mode=$2
case $mode in
*' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
echo "$0: invalid mode: $mode" >&2
exit 1;;
esac
shift;;
-o) chowncmd="$chownprog $2"
shift;;
-p) cpprog="$cpprog -p";;
-s) stripcmd=$stripprog;;
-S) backupsuffix="$2"
shift;;
-t)
is_target_a_directory=always
dst_arg=$2
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
shift;;
-T) is_target_a_directory=never;;
--version) echo "$0 $scriptversion"; exit $?;;
--) shift
break;;
-*) echo "$0: invalid option: $1" >&2
exit 1;;
*) break;;
esac
shift
done
# We allow the use of options -d and -T together, by making -d
# take the precedence; this is for compatibility with GNU install.
if test -n "$dir_arg"; then
if test -n "$dst_arg"; then
echo "$0: target directory not allowed when installing a directory." >&2
exit 1
fi
fi
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
# When -d is used, all remaining arguments are directories to create.
# When -t is used, the destination is already specified.
# Otherwise, the last argument is the destination. Remove it from $@.
for arg
do
if test -n "$dst_arg"; then
# $@ is not empty: it contains at least $arg.
set fnord "$@" "$dst_arg"
shift # fnord
fi
shift # arg
dst_arg=$arg
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
done
fi
if test $# -eq 0; then
if test -z "$dir_arg"; then
echo "$0: no input file specified." >&2
exit 1
fi
# It's OK to call 'install-sh -d' without argument.
# This can happen when creating conditional directories.
exit 0
fi
if test -z "$dir_arg"; then
if test $# -gt 1 || test "$is_target_a_directory" = always; then
if test ! -d "$dst_arg"; then
echo "$0: $dst_arg: Is not a directory." >&2
exit 1
fi
fi
fi
if test -z "$dir_arg"; then
do_exit='(exit $ret); exit $ret'
trap "ret=129; $do_exit" 1
trap "ret=130; $do_exit" 2
trap "ret=141; $do_exit" 13
trap "ret=143; $do_exit" 15
# Set umask so as not to create temps with too-generous modes.
# However, 'strip' requires both read and write access to temps.
case $mode in
# Optimize common cases.
*644) cp_umask=133;;
*755) cp_umask=22;;
*[0-7])
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw='% 200'
fi
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
*)
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw=,u+rw
fi
cp_umask=$mode$u_plus_rw;;
esac
fi
for src
do
# Protect names problematic for 'test' and other utilities.
case $src in
-* | [=\(\)!]) src=./$src;;
esac
if test -n "$dir_arg"; then
dst=$src
dstdir=$dst
test -d "$dstdir"
dstdir_status=$?
# Don't chown directories that already exist.
if test $dstdir_status = 0; then
chowncmd=""
fi
else
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if test ! -f "$src" && test ! -d "$src"; then
echo "$0: $src does not exist." >&2
exit 1
fi
if test -z "$dst_arg"; then
echo "$0: no destination specified." >&2
exit 1
fi
dst=$dst_arg
# If destination is a directory, append the input filename.
if test -d "$dst"; then
if test "$is_target_a_directory" = never; then
echo "$0: $dst_arg: Is a directory" >&2
exit 1
fi
dstdir=$dst
dstbase=`basename "$src"`
case $dst in
*/) dst=$dst$dstbase;;
*) dst=$dst/$dstbase;;
esac
dstdir_status=0
else
dstdir=`dirname "$dst"`
test -d "$dstdir"
dstdir_status=$?
fi
fi
case $dstdir in
*/) dstdirslash=$dstdir;;
*) dstdirslash=$dstdir/;;
esac
obsolete_mkdir_used=false
if test $dstdir_status != 0; then
case $posix_mkdir in
'')
# With -d, create the new directory with the user-specified mode.
# Otherwise, rely on $mkdir_umask.
if test -n "$dir_arg"; then
mkdir_mode=-m$mode
else
mkdir_mode=
fi
posix_mkdir=false
# The $RANDOM variable is not portable (e.g., dash). Use it
# here however when possible just to lower collision chance.
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
trap '
ret=$?
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
exit $ret
' 0
# Because "mkdir -p" follows existing symlinks and we likely work
# directly in world-writeable /tmp, make sure that the '$tmpdir'
# directory is successfully created first before we actually test
# 'mkdir -p'.
if (umask $mkdir_umask &&
$mkdirprog $mkdir_mode "$tmpdir" &&
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
then
if test -z "$dir_arg" || {
# Check for POSIX incompatibilities with -m.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
# other-writable bit of parent directory when it shouldn't.
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
test_tmpdir="$tmpdir/a"
ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
case $ls_ld_tmpdir in
d????-?r-*) different_mode=700;;
d????-?--*) different_mode=755;;
*) false;;
esac &&
$mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
}
}
then posix_mkdir=:
fi
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
else
# Remove any dirs left behind by ancient mkdir implementations.
rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
fi
trap '' 0;;
esac
if
$posix_mkdir && (
umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
)
then :
else
# mkdir does not conform to POSIX,
# or it failed possibly due to a race condition. Create the
# directory the slow way, step by step, checking for races as we go.
case $dstdir in
/*) prefix='/';;
[-=\(\)!]*) prefix='./';;
*) prefix='';;
esac
oIFS=$IFS
IFS=/
set -f
set fnord $dstdir
shift
set +f
IFS=$oIFS
prefixes=
for d
do
test X"$d" = X && continue
prefix=$prefix$d
if test -d "$prefix"; then
prefixes=
else
if $posix_mkdir; then
(umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
# Don't fail if two instances are running concurrently.
test -d "$prefix" || exit 1
else
case $prefix in
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
*) qprefix=$prefix;;
esac
prefixes="$prefixes '$qprefix'"
fi
fi
prefix=$prefix/
done
if test -n "$prefixes"; then
# Don't fail if two instances are running concurrently.
(umask $mkdir_umask &&
eval "\$doit_exec \$mkdirprog $prefixes") ||
test -d "$dstdir" || exit 1
obsolete_mkdir_used=true
fi
fi
fi
if test -n "$dir_arg"; then
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
else
# Make a couple of temp file names in the proper directory.
dsttmp=${dstdirslash}_inst.$$_
rmtmp=${dstdirslash}_rm.$$_
# Trap to clean up those temp files at exit.
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
# Copy the file name to the temp name.
(umask $cp_umask &&
{ test -z "$stripcmd" || {
# Create $dsttmp read-write so that cp doesn't create it read-only,
# which would cause strip to fail.
if test -z "$doit"; then
: >"$dsttmp" # No need to fork-exec 'touch'.
else
$doit touch "$dsttmp"
fi
}
} &&
$doit_exec $cpprog "$src" "$dsttmp") &&
# and set any options; do chmod last to preserve setuid bits.
#
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $cpprog $src $dsttmp" command.
#
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
# If -C, don't bother to copy if it wouldn't change the file.
if $copy_on_change &&
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
set -f &&
set X $old && old=:$2:$4:$5:$6 &&
set X $new && new=:$2:$4:$5:$6 &&
set +f &&
test "$old" = "$new" &&
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
then
rm -f "$dsttmp"
else
# If $backupsuffix is set, and the file being installed
# already exists, attempt a backup. Don't worry if it fails,
# e.g., if mv doesn't support -f.
if test -n "$backupsuffix" && test -f "$dst"; then
$doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
fi
# Rename the file to the real destination.
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
# The rename failed, perhaps because mv can't rename something else
# to itself, or perhaps because mv is so ancient that it does not
# support -f.
{
# Now remove or move aside any old file at destination location.
# We try this two ways since rm can't unlink itself on some
# systems and the destination file might be busy for other
# reasons. In this case, the final cleanup might fail but the new
# file should still install successfully.
{
test ! -f "$dst" ||
$doit $rmcmd "$dst" 2>/dev/null ||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
{ $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
} ||
{ echo "$0: cannot unlink or rename $dst" >&2
(exit 1); exit 1
}
} &&
# Now rename the file to the real destination.
$doit $mvcmd "$dsttmp" "$dst"
}
fi || exit 1
trap '' 0
fi
done
# Local variables:
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:

View File

@@ -20,7 +20,7 @@ gendummy() {
if [ "$1" = "clean" ]; then
rm -f $INC/$HDR
else
printf "" >$INC/$HDR.$$
echo -n "" >$INC/$HDR.$$
fi
done
}

View File

@@ -22,7 +22,7 @@ if [ "$on" = "yes" -a -f $SRCDIR/$dir/$CONFIGURE ]; then
ln -s $SRCDIR/$dir/Makefile.conf.in Makefile.conf.in
echo "=== configuring in $dir"
trap "echo ; exit 130" INT
${MAKE} ./configure REALTOPDIR="$TOP" srcdir="$SRCDIR/$dir"
make ./configure REALTOPDIR="$TOP" srcdir="$SRCDIR/$dir"
if [ ! -f ./configure ]; then
on="no"
else

View File

@@ -8,4 +8,4 @@ all: default
top_builddir=..
include $(top_builddir)/Makefile.conf
include $(REALTOPDIR)/src/Makefile.common
include $(REALTOPDIR)/src/arch/linux/Makefile.main
include $(REALTOPDIR)/src/arch/$(OS)/Makefile.main

View File

@@ -5,6 +5,5 @@ LIBNAME := $(subst /,_,$(SUBDIR))
vpath %.c $(srcdir)
vpath %.h $(srcdir)
vpath %.S $(srcdir)
vpath %.SS $(srcdir)
vpath %.s $(srcdir)
vpath %.sgml $(srcdir)

View File

@@ -1,15 +1,17 @@
ifndef OBJS
OBJS=$(CFILES:.c=.o) $(SFILES:.S=.o) $(XSFILES:.s=.o) $(SSFILES:.SS=.o)
OBJS=$(CFILES:.c=.o) $(SFILES:.S=.o)
endif
GENOBJS = $(GENSRC:.c=.o)
ifndef DEPENDS
DEPENDS=$(OBJS:.o=.d)
DEPENDS=$(OBJS:.o=.d) $(XSFILES:.s=.d)
endif
GENERATED = $(top_builddir)/src/include/version.hh \
$(top_builddir)/src/plugin/include/plugin_config.hh
$(top_builddir)/src/plugin/include/plugin_config.hh \
$(top_builddir)/src/base/bios/x86/bios_offsets.hh \
$(top_builddir)/src/base/bios/x86/bios_data.xxd
ifneq ($(GENHDRS),)
GENERATED += $(GENHDRS)
@@ -26,23 +28,23 @@ $(BINPATH) $(BINPATH)/bin $(BINPATH)/commands $(BINPATH)/lib:
mkdir -p $@
$(BINPATH)/bat: | $(BINPATH)
$(LN_SFT) ../src/bindist/bat $@
ln -sfT ../src/bindist/bat $@
$(top_builddir)/commands: | $(BINPATH)/commands $(BINPATH)/bat
rm -rf $@
mkdir $@
mkdir $@/dosemu
$(LN_S) -f ../src/bindist/fdppconf.sys $@/fdppconf.sys
$(LN_S) -f ../src/bindist/fdppauto.bat $@/fdppauto.bat
for i in `ls $(BINPATH)/bat/`; do $(LN_SFT) ../../$(THISVERSION)/bat/$$i $@/dosemu/$$i; done
ln -sf ../src/bindist/fdppconf.sys $@/fdppconf.sys
ln -sf ../src/bindist/fdppauto.bat $@/fdppauto.bat
for i in `ls $(BINPATH)/bat/`; do ln -sfT ../../$(THISVERSION)/bat/$$i $@/dosemu/$$i; done
$(top_builddir)/bin: | $(BINPATH)/bin
rm -f $@
$(LN_S) -f $(THISVERSION)/bin $@
ln -sf $(THISVERSION)/bin $@
$(top_builddir)/lib: | $(BINPATH)/lib
rm -f $@
$(LN_S) -f $(THISVERSION)/lib $@
ln -sf $(THISVERSION)/lib $@
GIT_REV := $(shell $(REALTOPDIR)/git-rev.sh $(REALTOPDIR) $(top_builddir))
.LOW_RESOLUTION_TIME: $(GIT_REV)
@@ -58,6 +60,12 @@ $(top_builddir)/src/include/version.hh: $(top_builddir)/Makefile.conf $(REALTOPD
echo "#define VERDATE \"$(RELEASE_DATE)\"" >> $@; \
echo "#endif /* VERSION_H */" >> $@
$(top_builddir)/src/base/bios/x86/bios_offsets.hh \
$(top_builddir)/src/base/bios/x86/bios_data.xxd : \
$(REALTOPDIR)/src/base/bios/x86/bios.s \
$(top_builddir)/src/include/version.hh
$(MAKE) -C $(top_builddir)/src/base/bios/x86 SUBDIR=base/bios/x86 $(notdir $@)
$(LIB): $(OBJS) $(GENOBJS) | $(BINPATH)/lib
rm -f $@
$(AR) cr $@ $^
@@ -65,12 +73,11 @@ $(LIB): $(OBJS) $(GENOBJS) | $(BINPATH)/lib
.PHONY: clean realclean lib echo all install default
# Use wildcards instead of OBJS and DEPENDS because they may depend on
# a make target. The reason is that on clean we do not include Makefile.conf.
clean::
-rm -f *.o $(LIB) $(GENSRC) *.d $(GENHDRS) configure *~
-rm -f $(OBJS) $(LIB) $(GENSRC) $(DEPENDS) $(GENHDRS) configure *~
realclean:: clean
rm -f $(DEPENDS)
rm -rf autom4te*.cache
rm -f Makefile.conf config.log config.status configure aclocal.m4
rm -rf plugin/include
@@ -81,46 +88,10 @@ $(GENOBJS): $(GENSRC)
%.o: %.c
$(CC) -c $(ALL_CPPFLAGS) $(ALL_CFLAGS) -o $@ $<
%.o: %.s $(top_builddir)/src/include/version.hh
$(XSFILES:.s=.o): %.o: %.s $(top_builddir)/src/include/version.hh
$(CPP) $(ALL_CPPFLAGS) -x assembler-with-cpp $< | $(XAS) $(XASFLAGS) -o $@
VS = $(subst .,_,$(notdir $(1)))_START
%.o: %.S $(top_builddir)/src/include/version.hh
$(CPP) $(ALL_CPPFLAGS) -x assembler-with-cpp $< | $(XAS) $(XASFLAGS) -o _$@
$(AS_LD) $(AS_LDFLAGS) -static $(if $($(call VS,$<)), \
--section-start .text=$($(call VS,$<))) -o $@.elf _$@
$(XOBJCOPY) -j .text -O binary $@.elf $@.bin
nm -g -n _$@ | gawk '\
BEGIN {\
print "// Warning: autogenerated";\
print "";\
print "asm(";\
print "\".data\\n\"";\
print "\".globl _binary_$(@:.o=)_o_bin_start\\n\"";\
print "\"_binary_$(@:.o=)_o_bin_start:\\n\"";\
print "\".incbin \\\"$@.bin\\\"\\n\"";\
print "\".globl _binary_$(@:.o=)_o_bin_end\\n\"";\
print "\"_binary_$(@:.o=)_o_bin_end:\\n\"";\
print "\".previous\\n\"";\
print ");";\
print "#include \"$(srcdir)/$(@:.o=)_offsets.h\"";\
}\
{\
HEXSTR = sprintf("0x%s", $$1);\
ADDR = strtonum(HEXSTR) $(if $($(call VS,$<)),+ $($(call VS,$<)));\
if ($$3 != "_start") {\
printf "const unsigned %s = 0x%04x;\n", $$3, ADDR;\
}\
}\
END {\
print "";\
}\
' > $@_offsets.c
$(CC) -c -o $@ $@_offsets.c
$(RM) _$@ $@.bin $@.elf $@_offsets.c
%.o: %.SS
$(CPP) $(ALL_CPPFLAGS) -x assembler-with-cpp $< | $(AS) $(ASFLAGS) -o $@
ifndef CLEANING

View File

@@ -17,32 +17,24 @@ NET=dosext/net
# This is defined when the SB Emulation is required. You should re-configure,
# rather than just change this.
#
SBEMU=base/dev/sb16 base/dev/sb16/softmpu base/sound
SBEMU=base/dev/sb16 base/sound
#
# This is defined when the CPU emulator is required. You should
# re-configure, rather than just change this.
#
ifeq ($(X86_EMULATOR),1)
XCPUEMU = base/emu-i386/simx86
ifeq ($(USE_SOFTFLOAT),1)
XCPUEMU += base/emu-i386/simx86/softfloat
endif
ifdef X86_EMULATOR
XCPUEMU=base/emu-i386/simx86
endif
ifeq ($(MCONTEXT),1)
LIBMC = base/lib/mcontext
endif
# No longer need midid
#REQUIRED += $(MIDID)
DPMI = dosext/dpmi dosext/dpmi/msdos dosext/dpmi/doslib
ifeq ($(DNATIVE),1)
DPMI += dosext/dpmi/dnative
endif
DPMI = dosext/dpmi dosext/dpmi/msdos
_LIBSUBDIRS=base/video base/dev/vga base/core base/kbd_unicode \
arch/linux/async base/lib/mapping $(LIBMC) \
base/misc base/lib/misc base/lib/libpcl base/lib/timer \
base/dev/misc \
arch/linux/async arch/linux/mapping base/lib/mcontext \
base/misc base/lib/misc base/lib/libpcl base/dev/misc \
base/emu-i386 $(XCPUEMU) base/speaker \
base/dev/pic base/dev/ne2k \
dosext/mfs dosext/misc dosext/builtins \
@@ -80,15 +72,9 @@ $(top_builddir)/etc/Xfonts/%.pcf.gz: $(REALTOPDIR)/etc/%.bdf | $(top_builddir)/e
$(LIBS_): | $(top_builddir)/lib
$(BINPATH)/bin/$(DOSBIN): $(LIBS_)
ifeq ($(OS),Darwin)
$(LD) $(ALL_LDFLAGS) $(DOSBIN_LDFLAGS) -o $@ \
-Wl,-all_load $(LIBS_) $(LIBS) \
-Wl,-map,$(BINPATH)/bin/dosemu.map
else
$(LD) $(ALL_LDFLAGS) $(DOSBIN_LDFLAGS) -o $@ \
-Wl,--whole-archive $(LIBS_) -Wl,--no-whole-archive $(LIBS) \
-Wl,-Map=$(BINPATH)/bin/dosemu.map
endif
$(BINPATH)/bin/dosemu: $(SRCPATH)/dosemu.systemwide $(SRCPATH)/dosemu
cp $< $@
@@ -135,14 +121,17 @@ install:
for i in `find $(SRCPATH)/bindist -maxdepth 1 -type f`; do \
$(INSTALL) -m 0644 $$i $(sysdir); \
done
$(INSTALL) -d $(sysdir)/c
$(INSTALL) -m 0644 -D $(SRCPATH)/bindist/c/* -t $(sysdir)/c
$(INSTALL) -m 0644 -D $(SRCPATH)/bindist/bat/*.bat -t $(sysdir)/dosemu
$(INSTALL) -m 0644 -D $(SRCPATH)/bindist/bat/dosrc.d/* -t $(sysdir)/dosemu/dosrc.d
$(INSTALL) -d $(cmddir)
$(INSTALL) -d $(cmddir)/dosrc.d
$(INSTALL) -m 0644 -D $(SRCPATH)/bindist/c/* $(sysdir)/c
$(INSTALL) -m 0644 -D $(SRCPATH)/bindist/bat/*.bat $(cmddir)
$(INSTALL) -m 0644 -D $(SRCPATH)/bindist/bat/dosrc.d/* $(cmddir)/dosrc.d
cp -f -d $(SYS)/* $(cmddir)
$(LN_S) -f $(cmdsuff) $(DESTDIR)$(dosemudir)/commands
for i in `find -L $(SYS) -xtype f`; do \
$(INSTALL) -m 0644 $$i $(cmddir); \
done
cd $(SYS); for i in `find * -type l`; do \
ln -sf generic.com $(cmddir)/$$i; \
done
ln -sf $(cmdsuff) $(DESTDIR)$(dosemudir)/commands
if [ ! -f $(DESTDIR)$(etcdir)/dosemu.conf ]; then \
$(INSTALL) -m 0644 $(REALTOPDIR)/etc/dosemu.conf $(DESTDIR)$(etcdir); \
fi
@@ -167,7 +156,7 @@ install:
fi; \
done
$(INSTALL) -d $(DESTDIR)$(docdir)
for i in NEWS.md THANKS BUGS; do \
for i in NEWS THANKS BUGS; do \
$(INSTALL) -m 0644 $(REALTOPDIR)/$$i $(DESTDIR)$(docdir); \
done
$(INSTALL) -m 0644 $(top_builddir)/changelog $(DESTDIR)$(docdir)
@@ -186,7 +175,7 @@ install:
! which mkfontdir >/dev/null || mkfontdir $(DESTDIR)$(x11fontdir)
if [ -d "$(DESTDIR)$(sysconfdir)/X11/fontpath.d" ]; then \
rm -f $(DESTDIR)$(sysconfdir)/X11/fontpath.d/$(PACKAGE_NAME):unscaled:pri=20; \
$(LN_S) -f $(x11fontdir) $(DESTDIR)$(sysconfdir)/X11/fontpath.d/$(PACKAGE_NAME):unscaled:pri=20; \
ln -sf $(x11fontdir) $(DESTDIR)$(sysconfdir)/X11/fontpath.d/$(PACKAGE_NAME):unscaled:pri=20; \
fi
install -m 0644 -D $(REALTOPDIR)/etc/ttf/* $(DESTDIR)$(ttffontdir)
@@ -206,9 +195,9 @@ install:
rm -rf $(DESTDIR)$(dosemuxdir)/fdboot; \
$(INSTALL) -d $(DESTDIR)$(dosemuxdir)/fdboot; \
cd $(DESTDIR)$(dosemuxdir)/fdboot; \
$(LN_S) ../../dosemu/commands/c/fdconfig.sys fdconfig.sys; \
$(LN_S) ../freedos/kernel.sys kernel.sys; \
$(LN_S) ../freedos/command.com command.com; \
ln -s ../../dosemu/commands/c/fdconfig.sys fdconfig.sys; \
ln -s ../freedos/kernel.sys kernel.sys; \
ln -s ../freedos/command.com command.com; \
fi
@if test $(etcdir) != /etc; then \

View File

@@ -1,11 +1,13 @@
top_builddir=../../../..
include $(top_builddir)/Makefile.conf
CFILES = signal.c debug.c
CFILES=sigsegv.c signal.c debug.c
ifeq ($(HAVE_LIBBFD),1)
CFILES += backtrace-symbols.c
endif
ALL_CPPFLAGS += -I$(REALTOPDIR)/src/base/lib/mcontext
include $(REALTOPDIR)/src/Makefile.common
all: lib

View File

@@ -145,7 +145,7 @@ static char** translate_addresses_buf(bfd * abfd, bfd_vma *addr, int naddr)
char *buf = &b;
int len = 0;
char **ret_buf = NULL;
/* iterate over the formatting twice.
/* iterate over the formating twice.
* the first time we count how much space we need
* the second time we do the actual printing */
for (state=Count; state<=Print; state++) {

View File

@@ -1,8 +1,6 @@
#include "emu.h"
#include "dosemu_config.h"
#include "debug.h"
#include "emudpmi.h"
#include "cpu-emu.h"
#include "sig.h"
#include <stdio.h>
#include <stdlib.h>
@@ -35,11 +33,7 @@ static int start_gdb(pid_t dosemu_pid)
printf("Debug info:\n");
fflush(stdout);
#ifdef __APPLE__
ret = asprintf(&buf, "lldb %s", dosemu_proc_self_exe);
#else
ret = asprintf(&buf, "gdb --readnow %s", dosemu_proc_self_exe);
#endif
ret = asprintf(&buf, "gdb %s", dosemu_proc_self_exe);
assert(ret != -1);
printf("%s", buf);
@@ -63,15 +57,9 @@ static int start_gdb(pid_t dosemu_pid)
static void do_debug(void)
{
#ifdef __APPLE__
const char *cmd1 = "register read\n";
// const char *cmd2 = "bt\n";
const char *cmd3 = "thread backtrace all\n";
#else
const char *cmd1 = "info registers\n";
// const char *cmd2 = "backtrace\n";
const char *cmd3 = "thread apply all backtrace full\n";
#endif
gdb_command(cmd1);
// gdb_command(cmd2);
@@ -165,7 +153,7 @@ static int do_gdb_debug(void)
pid_t dosemu_pid = getpid();
pid_t dbg_pid;
int status;
sigset_t oset;
sigset_t set, oset;
if (getuid() != geteuid())
return 0;
@@ -173,7 +161,10 @@ static int do_gdb_debug(void)
#ifdef __linux__
prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY);
#endif
sigprocmask(SIG_BLOCK, &q_mask, &oset);
sigemptyset(&set);
sigaddset(&set, SIGIO);
sigaddset(&set, SIGALRM);
sigprocmask(SIG_BLOCK, &set, &oset);
switch ((dbg_pid = fork())) {
case 0:
signal_done();
@@ -221,14 +212,8 @@ void gdb_debug(void)
#else
/* the problem with the above is that gdb usually doesn't work
* because of the security restrictions */
error("Please ");
if (!ret)
error("@install gdb, ");
error("@update dosemu from git, compile it with debug\n"
"info and make a bug report with the content of ~/.dosemu/boot.log at\n"
"https://github.com/dosemu2/dosemu2/issues\n");
error("@Please provide any additional info you can, like the test-cases,\n"
"URLs and all the rest that fits.\n\n");
error("Please install gdb!\n");
#ifdef HAVE_BACKTRACE
print_trace();
#endif
@@ -238,23 +223,3 @@ void gdb_debug(void)
fflush(dbg_fd);
dump_state();
}
void siginfo_debug(const siginfo_t *si)
{
error("@\n");
error("cpu exception in dosemu code outside of %s!\n",
(in_dpmi_pm() ? "DPMI client" : "VM86()"));
#ifdef __linux__
psiginfo(si, "");
#endif
error("@\n");
dbug_printf("%s\nsig: %i code: 0x%02x errno: 0x%08x fault address: %p\n",
strsignal(si->si_signo),
si->si_signo, si->si_code, si->si_errno, si->si_addr);
#ifdef X86_EMULATOR
/* gdb_debug() will crash in jit code doing backtrace() */
if (!(IS_EMU_JIT() && e_in_compiled_code()))
#endif
gdb_debug();
}

View File

@@ -1,7 +1,6 @@
#ifndef __DEBUG_H
#define __DEBUG_H
void siginfo_debug(const siginfo_t *si);
void gdb_debug(void);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,553 @@
#include "mhpdbg.h"
#include "mapping.h"
#include "debug.h"
/* Define if we want graphics in X (of course we want :-) (root@zaphod) */
/* WARNING: This may not work in BSD, because it was written for Linux! */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <signal.h>
#include <unistd.h>
#include <pthread.h>
#ifdef __linux__
#include <linux/version.h>
#endif
#include "emu.h"
#include "utilities.h"
#include "int.h"
#include "video.h"
#include "vgaemu.h" /* root@zaphod */
#include "emudpmi.h"
#include "cpu-emu.h"
#include "dosemu_config.h"
#include "sig.h"
/*
* All of the functions in this module need to be declared with
* __attribute__((no_instrument_function))
* so that they can safely handle signals that occur in DPMI context when
* DOSEMU is built with the "-pg" gcc flag (which enables instrumentation for
* gprof profiling).
*
* The reason for this is that mcount(), implicitly called from functions
* instrumented with "-pg", requires access to thread-local state, and on x86,
* TLS is implemented using the GS to refer to a segment in which the
* thread-local variables are stored.
*
* However, in DPMI context, GS does not refer to this segment, and the kernel
* does not (cannot?) restore it to do so when it invokes a signal handler, so
* we must prevent mcount() from being called at all in this context.
*/
/*
* DANG_BEGIN_FUNCTION dosemu_fault(int, sigcontext_t);
*
* All CPU exceptions (except 13=general_protection from V86 mode,
* which is directly scanned by the kernel) are handled here.
*
* We have 4 main cases:
* 1. VM86 faults from vm86() (i386 only)
* 2. DPMI faults with LDT _cs (native DPMI only)
* 3. Faults (PF/DE) generated from cpuemu. In this case _cs is the Linux
* userspace _cs
* 4. DOSEMU itself crashes (bad!)
*
* DANG_END_FUNCTION
*/
static void dosemu_fault1(int signum, sigcontext_t *scp)
{
if (fault_cnt > 1) {
error("Fault handler re-entered! signal=%i _trapno=0x%X\n",
signum, _trapno);
if (!in_vm86 && !DPMIValidSelector(_cs)) {
gdb_debug();
_exit(43);
} else {
error("BUG: Fault handler re-entered not within dosemu code! in_vm86=%i\n",
in_vm86);
}
goto bad;
}
#ifdef __x86_64__
if (_trapno == 0x0e && _cr2 > 0xffffffff)
{
#ifdef X86_EMULATOR
if (IS_EMU() && !CONFIG_CPUSIM && e_in_compiled_code()) {
int i;
/* dosemu_error() will SIGSEGV in backtrace(). */
error("JIT fault accessing invalid address 0x%08"PRI_RG", "
"RIP=0x%08"PRI_RG"\n", _cr2, _rip);
if (mapping_find_hole(_rip, _rip + 64, 1) == MAP_FAILED) {
error("@Generated code dump:\n");
for (i = 0; i < 64; i++) {
error("@ %02x", *(unsigned char *)(_rip + i));
if ((i & 15) == 15)
error("@\n");
}
}
goto bad;
}
#endif
dosemu_error("Accessing invalid address 0x%08"PRI_RG"\n", _cr2);
goto bad;
}
#endif
#ifdef __i386__
/* case 1: note that _cr2 must be 0-based */
if (in_vm86 && config.cpu_vm == CPUVM_VM86) {
if (_trapno == 0x0e) {
/* we can get to instremu from here, so unblock SIGALRM & friends.
* It is needed to interrupt instremu when it runs for too long. */
signal_unblock_async_sigs();
if (vga_emu_fault(_cr2, _err, NULL) == True)
return;
}
vm86_fault(_trapno, _err, _cr2);
return;
}
#endif
/* case 2: At first let's find out where we came from */
if (DPMIValidSelector(_cs)) {
int ret = DPMI_RET_FAULT;
assert(config.cpu_vm_dpmi == CPUVM_NATIVE);
if (_trapno == 0x0e) {
int rc;
dosaddr_t cr2 = DOSADDR_REL(LINP(_cr2));
#ifdef X86_EMULATOR
#ifdef HOST_ARCH_X86
/* DPMI code touches cpuemu prot */
if (EMU_V86() && !CONFIG_CPUSIM &&
e_handle_pagefault(cr2, _err, scp))
return;
#endif
#endif
signal_unblock_async_sigs();
rc = vga_emu_fault(cr2, _err, scp);
/* going for dpmi_fault() or deinit_handler(),
* careful with async signals and sas_wa */
signal_restore_async_sigs();
if (rc == True)
ret = dpmi_check_return();
}
if (_trapno == 0x10) {
dbug_printf("coprocessor exception, calling IRQ13\n");
print_exception_info(scp);
pic_request(PIC_IRQ13);
dpmi_return(scp, DPMI_RET_DOSEMU);
return;
}
/* Not in dosemu code: dpmi_fault() will handle that */
if (ret == DPMI_RET_FAULT)
ret = dpmi_fault(scp);
if (ret != DPMI_RET_CLIENT)
dpmi_return(scp, ret);
return;
}
#ifdef X86_EMULATOR
/* case 3 */
if (IS_EMU()) {
/* Possibilities:
* 1. Compiled code touches VGA prot
* 2. Compiled code touches cpuemu prot
* 3. Compiled code touches DPMI prot
* 4. fullsim code touches DPMI prot
* 5. dosemu code touches cpuemu prot (bug)
* Compiled code means dpmi-jit, otherwise vm86 not here.
*/
if (_trapno == 0x0e) {
/* cases 1, 2, 3, 4 */
if ((in_vm86 || EMU_DPMI()) && e_emu_pagefault(scp, !in_vm86))
return;
if (!CONFIG_CPUSIM &&
e_handle_pagefault(DOSADDR_REL(LINP(_cr2)), _err, scp)) {
/* case 5, any jit, bug */
dosemu_error("touched jit-protected page%s\n",
in_vm86 ? " in vm86-emu" : "");
return;
}
} else if ((in_vm86 || EMU_DPMI()) &&
!CONFIG_CPUSIM && e_handle_fault(scp)) {
/* compiled code can cause fault (usually DE, Divide Exception) */
return;
}
}
#endif
/* case 4 */
error("Fault in dosemu code, in_dpmi=%i\n", dpmi_active());
/* TODO - we can start gdb here */
/* start_gdb() */
/* Going to die from here */
bad:
/* All recovery attempts failed, going to die :( */
{
#ifdef __x86_64__
unsigned char *fsbase, *gsbase;
#endif
error("cpu exception in dosemu code outside of %s!\n"
"sig: %i trapno: 0x%02x errorcode: 0x%08x cr2: 0x%08"PRI_RG"\n"
"eip: 0x%08"PRI_RG" esp: 0x%08"PRI_RG" eflags: 0x%08x\n"
"cs: 0x%04x ds: 0x%04x es: 0x%04x ss: 0x%04x\n"
"fs: 0x%04x gs: 0x%04x\n",
(in_dpmi_pm() ? "DPMI client" : "VM86()"),
signum, _trapno, _err, _cr2,
_rip, _rsp, _eflags, _cs, _ds, _es, _ss, _fs, _gs);
#ifdef __x86_64__
dosemu_arch_prctl(ARCH_GET_FS, &fsbase);
dosemu_arch_prctl(ARCH_GET_GS, &gsbase);
error("@fsbase: %p gsbase: %p\n", fsbase, gsbase);
#endif
error("@\n");
error("Please install gdb, update dosemu from git, compile it with debug\n"
"info and make a bug report with the content of ~/.dosemu/boot.log at\n"
"https://github.com/dosemu2/dosemu2/issues\n");
error("@Please provide any additional info you can, like the test-cases,\n"
"URLs and all the rest that fits.\n\n");
#ifdef X86_EMULATOR
/* gdb_debug() will crash in jit code doing backtrace() */
if (!(IS_EMU() && !CONFIG_CPUSIM && e_in_compiled_code()))
#endif
gdb_debug();
if (DPMIValidSelector(_cs))
print_exception_info(scp);
if (in_vm86)
show_regs();
fatalerr = 4;
_leavedos_main(0, signum); /* shouldn't return */
}
}
/* noinline is to prevent gcc from moving TLS access around init_handler() */
__attribute__((noinline))
static void dosemu_fault0(int signum, sigcontext_t *scp)
{
pthread_t tid;
if (fault_cnt > 2) {
/*
* At this point we already tried leavedos(). Now try _exit()
* and NOT exit(3), because glibc is probably malfunctions if
* we are here.
*/
_exit(255);
}
tid = pthread_self();
if (!pthread_equal(tid, dosemu_pthread_self)) {
#ifdef __GLIBC__
char name[128];
#endif
/* disable cancellation to prevent main thread from terminating
* this one due to SIGSEGV elsewhere while we are doing backtrace */
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
#if defined(HAVE_PTHREAD_GETNAME_NP) && defined(__GLIBC__)
pthread_getname_np(tid, name, sizeof(name));
dosemu_error("thread %s got signal %i, cr2=%llx\n", name, signum,
(unsigned long long)_cr2);
#else
dosemu_error("thread got signal %i, cr2=%llx\n", signum,
(unsigned long long)_cr2);
#endif
signal(signum, SIG_DFL);
pthread_kill(tid, signum); // dump core
_exit(23);
return;
}
#ifdef __linux__
if (kernel_version_code < KERNEL_VERSION(2, 6, 14)) {
sigset_t set;
/* this emulates SA_NODEFER, so that we can double fault.
SA_NODEFER only works as documented in Linux kernels >= 2.6.14.
*/
sigemptyset(&set);
sigaddset(&set, signum);
sigprocmask(SIG_UNBLOCK, &set, NULL);
}
#endif
if (debug_level('g')>7)
g_printf("Entering fault handler, signal=%i _trapno=0x%X\n",
signum, _trapno);
dosemu_fault1(signum, scp);
if (debug_level('g')>8)
g_printf("Returning from the fault handler\n");
}
SIG_PROTO_PFX
void dosemu_fault(int signum, siginfo_t *si, void *uc)
{
ucontext_t *uct = uc;
sigcontext_t *scp = &uct->uc_mcontext;
/* need to call init_handler() before any syscall.
* Additionally, TLS access should be done in a separate no-inline
* function, so that gcc not to move the TLS access around init_handler(). */
init_handler(scp, uct->uc_flags);
#if defined(__FreeBSD__)
/* freebsd does not provide cr2 */
_cr2 = (uintptr_t)si->si_addr;
#endif
fault_cnt++;
dosemu_fault0(signum, scp);
fault_cnt--;
deinit_handler(scp, &uct->uc_flags);
}
/*
* DANG_BEGIN_FUNCTION print_exception_info
*
* Prints information about an exception: exception number, error code,
* address, reason, etc.
*
* DANG_END_FUNCTION
*
*/
void print_exception_info(sigcontext_t *scp)
{
int i;
switch(_trapno)
{
case 0:
error("@Division by zero\n");
break;
case 1:
error("@Debug exception\n");
break;
case 3:
error("@Breakpoint exception (caused by INT 3 instruction)\n");
break;
case 4:
error("@Overflow exception (caused by INTO instruction)\n");
break;
case 5:
error("@Bound exception (caused by BOUND instruction)\n");
break;
case 6: {
unsigned char *csp;
int ps = getpagesize();
unsigned pa = _rip & (ps - 1);
int sub = _min(pa, 10);
int sup = _min(ps - pa, 10);
error("@Invalid opcode\n");
error("@Opcodes: ");
csp = (unsigned char *) _rip - sub;
for (i = 0; i < 10 - sub; i++)
error("@XX ");
for (i = 0; i < sub; i++)
error("@%02x ", *csp++);
error("@-> ");
for (i = 0; i < sup; i++)
error("@%02x ", *csp++);
for (i = 0; i < 10 - sup; i++)
error("@XX ");
error("@\n");
break;
}
case 7:
error("@Coprocessor exception (coprocessor not available)\n");
/* I'd like to print some info on the EM, MP, and TS flags in CR0,
* but I don't know where I can get that information :-(
* Anyway, this exception should not happen... (Erik Mouw)
*/
break;
case 8:
error("@Double fault\n");
break;
case 9:
error("@Coprocessor segment overflow\n");
break;
case 0xa:
error("@Invalid TSS\n");
if(_err & 0x02)
error("@IDT");
else if(_err & 0x04)
error("@LDT");
else
error("@GDT");
error("@ selector: 0x%04x\n", ((_err >> 3) & 0x1fff ));
if(_err & 0x01)
error("@Exception was not caused by DOSEMU\n");
else
error("@Exception was caused by DOSEMU\n");
break;
case 0xb:
error("@Segment not available\n");
/* This is the same code as case 0x0a; the compiler merges these
* blocks, so I don't have to edit some dirty constructions to
* generate one block of code. (Erik Mouw)
*/
if(_err & 0x02)
error("@IDT");
else if(_err & 0x04)
error("@LDT");
else
error("@GDT");
error("@ selector: 0x%04x\n", ((_err >> 3) & 0x1fff ));
if(_err & 0x01)
error("@Exception was not caused by DOSEMU\n");
else
error("@Exception was caused by DOSEMU\n");
break;
case 0xc:
error("@Stack exception\n");
break;
case 0xd:
error("@General protection exception\n");
/* This is the same code as case 0x0a; the compiler merges these
* blocks, so I don't have to edit some dirty constructions to
* generate one block of code. (Erik Mouw)
*/
if(_err & 0x02)
error("@IDT");
else if(_err & 0x04)
error("@LDT");
else
error("@GDT");
error("@ selector: 0x%04x\n", ((_err >> 3) & 0x1fff ));
if(_err & 0x01)
error("@Exception was not caused by DOSEMU\n");
else
error("@Exception was caused by DOSEMU\n");
break;
case 0xe:
error("@Page fault: ");
if(_err & 0x02)
error("@write");
else
error("@read");
error("@ instruction to linear address: 0x%08"PRI_RG"\n", _cr2);
error("@CPU was in ");
if(_err & 0x04)
error("@user mode\n");
else
error("@supervisor mode\n");
error("@Exception was caused by ");
if(_err & 0x01)
error("@insufficient privilege\n");
else
error("@non-available page\n");
break;
case 0x10: {
int i, n;
unsigned short sw;
fpregset_t p = __fpstate;
error ("@Coprocessor Error:\n");
#ifdef __x86_64__
error ("@cwd=%04x swd=%04x ftw=%04x\n", p->cwd, p->swd, p->ftw);
error ("@cs:rip=%04x:%08lx ds:data=%04x:%08lx\n", _cs,p->rip,_ds,p->rdp);
sw = p->swd;
#else
error ("@cw=%04x sw=%04x tag=%04x\n",
((unsigned short)(p->cw)),((unsigned short)(p->sw)),
((unsigned short)(p->tag)));
error ("@cs:eip=%04x:%08x ds:data=%04x:%08x\n",
((unsigned short)(p->cssel)),(unsigned)p->ipoff,
((unsigned short)(p->datasel)),(unsigned)p->dataoff);
sw = p->sw;
#endif
if ((sw&0x80)==0) error("@No error summary bit,why?\n");
else {
if (sw&0x20) error("@Precision\n");
if (sw&0x10) error("@Underflow\n");
if (sw&0x08) error("@Overflow\n");
if (sw&0x04) error("@Divide by 0\n");
if (sw&0x02) error("@Denormalized\n");
if ((sw&0x41)==0x01) error("@Invalid op\n");
else if ((sw&0x41)==0x41) error("@Stack fault\n");
}
n = (sw >> 11) & 7;
for (i=0; i<8; i++) {
unsigned short *r = p->_st[i].significand;
unsigned short e = p->_st[i].exponent;
error ("@fpr[%d] = %04x:%04x%04x%04x%04x\n",n,e,r[3],r[2],r[1],r[0]);
n = (n+1) & 7;
}
} break;
case 0x13: {
#ifdef __x86_64__
int i;
unsigned mxcsr;
fpregset_t p = __fpstate;
error ("@SIMD Floating-Point Exception:\n");
mxcsr = p->mxcsr;
error ("@mxcsr=%08x, mxcr_mask=%08x\n",mxcsr,(unsigned)(p->mxcr_mask));
if (mxcsr&0x40) error("@Denormals are zero\n");
if (mxcsr&0x20) error("@Precision\n");
if (mxcsr&0x10) error("@Underflow\n");
if (mxcsr&0x08) error("@Overflow\n");
if (mxcsr&0x04) error("@Divide by 0\n");
if (mxcsr&0x02) error("@Denormalized\n");
if (mxcsr&0x01) error("@Invalid op\n");
for (i=0; i<sizeof(p->_xmm)/sizeof(p->_xmm[0]); i++)
{
error ("@xmm[%d] = %08x:%08x:%08x:%08x\n",i,
(unsigned)p->_xmm[i].element[0], (unsigned)p->_xmm[i].element[1],
(unsigned)p->_xmm[i].element[2], (unsigned)p->_xmm[i].element[3]);
}
#else
error ("@SIMD Floating-Point Exception\n");
#endif
break;
}
default:
error("@Unknown exception\n");
break;
}
}

View File

@@ -12,7 +12,7 @@ include $(top_builddir)/Makefile.conf
#The C files, include files and dependancies here.
CFILES = mapping.c mapfile.c mapashm.c
CFILES = mapping.c mapshm.c mapfile.c
DEPENDS = $(CFILES:.c=.d)
HFILES =

View File

@@ -0,0 +1,329 @@
/*
* (C) Copyright 1992, ..., 2014 the "DOSEMU-Development-Team".
*
* for details see file COPYING in the DOSEMU distribution
*/
/*
* Purpose: memory mapping library, posix SHM and file backends.
*
* Authors: Stas Sergeev, Bart Oldeman.
* Initially started by Hans Lermen, old copyrights below:
*/
/* file mapfile.c
* file mapping driver
* Hans Lermen, lermen@fgan.de
*/
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <assert.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "emu.h"
#include "mapping.h"
#include "smalloc.h"
#include "utilities.h"
/* ------------------------------------------------------------ */
static smpool pgmpool;
static int mpool_numpages = (32 * 1024) / 4;
static char *mpool = 0;
static int tmpfile_fd = -1;
static void *alias_mapping_file(int cap, void *target, size_t mapsize, int protect, void *source)
{
int fixed = 0;
off_t offs = (char *)source - mpool;
void *addr;
if (offs < 0 || (offs+mapsize >= (mpool_numpages*PAGE_SIZE))) {
Q_printf("MAPPING: alias_map to address outside of temp file\n");
errno = EINVAL;
return MAP_FAILED;
}
if (target != (void *)-1)
fixed = MAP_FIXED;
else
target = NULL;
addr = mmap(target, mapsize, protect, MAP_SHARED | fixed, tmpfile_fd, offs);
if (addr == MAP_FAILED) {
addr = mmap(target, mapsize, protect & ~PROT_EXEC, MAP_SHARED | fixed,
tmpfile_fd, offs);
if (addr != MAP_FAILED) {
int ret = mprotect(addr, mapsize, protect);
if (ret == -1) {
perror("mprotect()");
error("shared memory mprotect failed, exiting\n");
leavedos(2);
return NULL;
}
}
}
#if 1
Q_printf("MAPPING: alias_map, fileoffs %llx to %p size %zx, result %p\n",
(long long)offs, target, mapsize, addr);
#endif
return addr;
}
static void discardtempfile(void)
{
close(tmpfile_fd);
tmpfile_fd = -1;
}
static int open_mapping_f(int cap)
{
int mapsize, estsize, padsize;
if (cap) Q_printf("MAPPING: open, cap=%s\n",
decode_mapping_cap(cap));
padsize = 4*1024;
/* first estimate the needed size of the mapfile */
mapsize = HMASIZE >> 10; /* HMA */
/* VGAEMU */
mapsize += config.vgaemu_memsize ? config.vgaemu_memsize : 1024;
mapsize += config.ems_size; /* EMS */
mapsize += LOWMEM_SIZE >> 10; /* Low Mem */
estsize = mapsize;
/* keep heap fragmentation in mind */
mapsize += (mapsize/4 < padsize ? padsize : mapsize/4);
mpool_numpages = mapsize / 4;
mapsize = mpool_numpages * PAGE_SIZE; /* make sure we are page aligned */
ftruncate(tmpfile_fd, 0);
if (ftruncate(tmpfile_fd, mapsize) == -1) {
if (!cap)
error("MAPPING: cannot size temp file pool, %s\n",strerror(errno));
discardtempfile();
if (!cap)return 0;
leavedos(2);
}
/* /dev/shm may be mounted noexec, and then mounting PROT_EXEC fails.
However mprotect may work around this (maybe not in future kernels)
*/
mpool = mmap(0, mapsize, PROT_READ|PROT_WRITE,
MAP_SHARED, tmpfile_fd, 0);
if (mpool == MAP_FAILED ||
mprotect(mpool, mapsize, PROT_READ|PROT_WRITE|PROT_EXEC) == -1) {
error("MAPPING: cannot mmap shared memory pool, %s\n", strerror(errno));
discardtempfile();
if (!cap)
return 0;
leavedos(2);
}
/* the memory pool itself can just be rw though */
mprotect(mpool, mapsize, PROT_READ|PROT_WRITE);
Q_printf("MAPPING: open, mpool (min %dK) is %d Kbytes at %p-%p\n",
estsize, mapsize/1024, mpool, mpool+mapsize-1);
sminit(&pgmpool, mpool, mapsize);
/*
* Now handle individual cases.
* Don't forget that each of the below code pieces should only
* be executed once !
*/
#if 0
if (cap & MAPPING_OTHER) {
/* none for now */
}
#endif
#if 0
if (cap & MAPPING_EMS) {
/* none for now */
}
#endif
#if 0
if (cap & MAPPING_DPMI) {
/* none for now */
}
#endif
#if 0
if (cap & MAPPING_VIDEO) {
/* none for now */
}
#endif
#if 0
if (cap & MAPPING_VGAEMU) {
/* none for now */
}
#endif
#if 0
if (cap & MAPPING_HGC) {
/* none for now */
}
#endif
#if 0
if (cap & MAPPING_HMA) {
/* none for now */
}
#endif
#if 0
if (cap & MAPPING_SHARED) {
/* none for now */
}
#endif
#if 0
if (cap & MAPPING_INIT_HWRAM) {
/* none for now */
}
#endif
#if 0
if (cap & MAPPING_INIT_LOWRAM) {
/* none for now */
}
#endif
return 1;
}
static int open_mapping_file(int cap)
{
if (tmpfile_fd < 0) {
// Requires a Linux kernel version >= 3.11.0
tmpfile_fd = open("/tmp", O_TMPFILE | O_RDWR | O_CLOEXEC, S_IRUSR | S_IWUSR);
open_mapping_f(cap);
}
return 1;
}
#ifdef HAVE_SHM_OPEN
static int open_mapping_pshm(int cap)
{
char *name;
int ret;
if (tmpfile_fd < 0) {
ret = asprintf(&name, "/dosemu_%d", getpid());
assert(ret != -1);
/* FD_CLOEXEC is set by default */
tmpfile_fd = shm_open(name, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
if (tmpfile_fd == -1) {
free(name);
return 0;
}
shm_unlink(name);
free(name);
if (!open_mapping_f(cap))
return 0;
}
return 1;
}
#endif
#ifdef HAVE_MEMFD_CREATE
static int open_mapping_mshm(int cap)
{
char *name;
int ret;
if (tmpfile_fd < 0) {
ret = asprintf(&name, "dosemu_%d", getpid());
assert(ret != -1);
tmpfile_fd = memfd_create(name, MFD_CLOEXEC);
free(name);
if (tmpfile_fd == -1)
return 0;
if (!open_mapping_f(cap))
return 0;
}
return 1;
}
#endif
static void close_mapping_file(int cap)
{
Q_printf("MAPPING: close, cap=%s\n", decode_mapping_cap(cap));
if (cap == MAPPING_ALL && tmpfile_fd != -1) discardtempfile();
}
static void *alloc_mapping_file(int cap, size_t mapsize)
{
Q__printf("MAPPING: alloc, cap=%s, mapsize=%zx\n", cap, mapsize);
return smalloc(&pgmpool, mapsize);
}
static void free_mapping_file(int cap, void *addr, size_t mapsize)
/* NOTE: addr needs to be the same as what was supplied by alloc_mapping_file */
{
Q__printf("MAPPING: free, cap=%s, addr=%p, mapsize=%zx\n",
cap, addr, mapsize);
smfree(&pgmpool, addr);
}
/*
* NOTE: DPMI relies on realloc_mapping() _not_ changing the address ('addr'),
* when shrinking the memory region.
*/
static void *realloc_mapping_file(int cap, void *addr, size_t oldsize, size_t newsize)
{
Q__printf("MAPPING: realloc, cap=%s, addr=%p, oldsize=%zx, newsize=%zx\n",
cap, addr, oldsize, newsize);
if (cap & (MAPPING_EMS | MAPPING_DPMI)) {
int size = smget_area_size(&pgmpool, addr);
void *addr_;
if (!size || size != oldsize) return (void *)-1;
if (size == newsize) return addr;
/* NOTE: smrealloc() does not change addr,
* when shrinking the memory region.
*/
addr_ = smrealloc(&pgmpool, addr, newsize);
if (!addr_) {
Q_printf("MAPPING: pgrealloc(0x%p,0x%zx,) failed\n",
addr, newsize);
return (void *)-1;
}
return addr_;
}
return (void *)-1;
}
#ifdef HAVE_SHM_OPEN
struct mappingdrivers mappingdriver_shm = {
"mapshm",
"Posix SHM mapping",
open_mapping_pshm,
close_mapping_file,
alloc_mapping_file,
free_mapping_file,
realloc_mapping_file,
alias_mapping_file
};
#endif
#ifdef HAVE_MEMFD_CREATE
struct mappingdrivers mappingdriver_mshm = {
"mapmshm",
"memfd mapping",
open_mapping_mshm,
close_mapping_file,
alloc_mapping_file,
free_mapping_file,
realloc_mapping_file,
alias_mapping_file
};
#endif
struct mappingdrivers mappingdriver_file = {
"mapfile",
"temp file mapping",
open_mapping_file,
close_mapping_file,
alloc_mapping_file,
free_mapping_file,
realloc_mapping_file,
alias_mapping_file
};

View File

@@ -0,0 +1,184 @@
/*
* (C) Copyright 1992, ..., 2014 the "DOSEMU-Development-Team".
*
* for details see file COPYING in the DOSEMU distribution
*/
/*
* Purpose: memory mapping library, anon-SHM backend.
*
* Authors: Stas Sergeev, Bart Oldeman.
*
*/
#ifdef __linux__
#include "emu.h"
#include <unistd.h>
#include <string.h>
#include <sys/mman.h>
#include "dosemu_config.h"
#include "mapping.h"
/* ------------------------------------------------------------ */
#define Q__printf(f,cap,a...) ({\
Q_printf(f,decode_mapping_cap(cap),##a); \
})
static void *alias_mapping_shm(int cap, void *target, size_t mapsize, int protect, void *source)
{
int flags = MREMAP_MAYMOVE;
/* The trick is to set old_len = 0,
* this won't unmap at the old address, but with
* shared mem the 'nopage' vm_op will map in the right
* pages. We need however to take care not to map
* past the end of the shm area
*/
if (target != (void *)-1)
flags |= MREMAP_FIXED;
else
target = NULL;
target = mremap(source, 0, mapsize, flags, target);
if (target == MAP_FAILED) return MAP_FAILED;
mprotect(target, mapsize, protect);
return target;
}
static int open_mapping_shm(int cap)
{
static int first =1;
if (cap) Q_printf("MAPPING: open, cap=%s\n",
decode_mapping_cap(cap));
if (first) {
void *ptr1, *ptr2 = MAP_FAILED;
first = 0;
/* do a test alias mapping. kernel 2.6.1 doesn't support our mremap trick */
ptr1 = mmap(0, PAGE_SIZE, PROT_NONE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
if (ptr1 != MAP_FAILED) {
ptr2 = mremap(ptr1, 0, PAGE_SIZE, MREMAP_MAYMOVE);
munmap(ptr1, PAGE_SIZE);
if (ptr2 != MAP_FAILED)
munmap(ptr2, PAGE_SIZE);
}
if (ptr2 == MAP_FAILED) {
Q_printf("MAPPING: not using mapshm because alias mapping does not work\n");
if (!cap)return 0;
leavedos(2);
}
}
/*
* Now handle individual cases.
* Don't forget that each of the below code pieces should only
* be executed once !
*/
#if 0
if (cap & MAPPING_OTHER) {
/* none for now */
}
#endif
#if 0
if (cap & MAPPING_EMS) {
/* none for now */
}
#endif
#if 0
if (cap & MAPPING_DPMI) {
/* none for now */
}
#endif
#if 0
if (cap & MAPPING_VIDEO) {
/* none for now */
}
#endif
#if 0
if (cap & MAPPING_VGAEMU) {
/* none for now */
}
#endif
#if 0
if (cap & MAPPING_HGC) {
/* none for now */
}
#endif
#if 0
if (cap & MAPPING_HMA) {
/* none for now */
}
#endif
#if 0
if (cap & MAPPING_SHARED) {
/* none for now */
}
#endif
#if 0
if (cap & MAPPING_INIT_HWRAM) {
/* none for now */
}
#endif
#if 0
if (cap & MAPPING_INIT_LOWRAM) {
/* none for now */
}
#endif
return 1;
}
static void close_mapping_shm(int cap)
{
Q_printf("MAPPING: close, cap=%s\n", decode_mapping_cap(cap));
}
static void *alloc_mapping_shm(int cap, size_t mapsize)
{
Q__printf("MAPPING: alloc, cap=%s, mapsize=%zx\n", cap, mapsize);
return mmap(0, mapsize, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
}
static void free_mapping_shm(int cap, void *addr, size_t mapsize)
/* NOTE: addr needs to be the same as what was supplied by alloc_mapping_shm */
{
Q__printf("MAPPING: free, cap=%s, addr=%p, mapsize=%zx\n",
cap, addr, mapsize);
munmap(addr, mapsize);
}
static void *realloc_mapping_shm(int cap, void *addr, size_t oldsize, size_t newsize)
{
void *ret;
Q__printf("MAPPING: realloc, cap=%s, addr=%p, oldsize=%zx, newsize=%zx\n",
cap, addr, oldsize, newsize);
if (newsize <= oldsize)
return mremap(addr, oldsize, newsize, MREMAP_MAYMOVE);
/* we can't expand shared anonymous memory using mremap
so we must allocate a new region and memcpy to it */
ret = alloc_mapping_shm(cap, newsize);
if (ret != MAP_FAILED) {
memcpy(ret, addr, oldsize);
free_mapping_shm(cap, addr, oldsize);
}
return ret;
}
struct mappingdrivers mappingdriver_ashm = {
"mapashm",
"anonymous non-expandable shared memory mapping",
open_mapping_shm,
close_mapping_shm,
alloc_mapping_shm,
free_mapping_shm,
realloc_mapping_shm,
alias_mapping_shm,
};
#endif

View File

@@ -19,7 +19,7 @@
* changed int10() to make graphics work with X.
*
* 1998/04/05: Put some work into set_video_mode() (made it
* more VGA compatible) and removed new_set_video_mode().
* more VGA comaptible) and removed new_set_video_mode().
* Removed (useless) global variable "gfx_mode".
* -- sw (Steffen Winterfeldt <wfeldt@suse.de>)
*
@@ -35,7 +35,7 @@
* cursor shape is now initialized during mode set.
* -- sw
*
* 2000/05/18: Split int10() into a X and non-X part. Reworked to X part so
* 2000/05/18: Splitted int10() into a X and non-X part. Reworked to X part so
* that it supports fonts in gfx modes.
* -- sw
*
@@ -88,7 +88,7 @@ unsigned screen_adr(int page)
/* this maps the cursor shape given by int10, fn1 to the actually
displayed cursor start&end values in cursor_shape. This seems
to be typical IBM Black Compatibility Magic.
to be typical IBM Black Compatiblity Magic.
I modeled it approximately from the behaviour of my own
VGA's BIOS.
I'm not sure if it is correct for start=end and for font_heights
@@ -113,34 +113,17 @@ static void crt_outw(unsigned index, unsigned value)
port_outw(port, (index + 1) | ((value & 0xff) << 8));
}
static unsigned do_set_cursor_pos(unsigned page, int x, int y)
static void set_cursor_pos(unsigned page, int x, int y)
{
unsigned co, old_y;
unsigned co;
old_y = get_bios_cursor_y_position(page);
set_bios_cursor_x_position(page, x);
set_bios_cursor_y_position(page, y);
co = READ_WORD(BIOS_SCREEN_COLUMNS);
crt_outw(0xe, READ_WORD(BIOS_VIDEO_MEMORY_ADDRESS)/2 + y * co + x);
return old_y;
}
static void set_cursor_pos(unsigned page, int x, int y)
{
unsigned old_y = do_set_cursor_pos(page, x, y);
if (config.dumb_video && y > old_y) {
int i;
if (no_local_video && !config.tty_stderr)
return;
for (i = 0; i < y - old_y; i++)
fputs("\r\n", config.tty_stderr ? stderr : stdout);
}
}
static void set_cursor_shape(uint16_t shape)
{
static inline void set_cursor_shape(ushort shape) {
int cs,ce;
cshape cursor_shape;
cursor_shape.w = shape;
@@ -183,8 +166,8 @@ bios_scroll(int x0, int y0, int x1, int y1, int l, int att)
int dx = x1 - x0 + 1;
int dy = y1 - y0 + 1;
int x, y, co, li;
uint16_t blank = ' ' | (att << 8);
uint16_t tbuf[MAX_COLUMNS];
us blank = ' ' | (att << 8);
us tbuf[MAX_COLUMNS];
unsigned sadr;
if (config.dumb_video)
@@ -260,6 +243,12 @@ static int using_mono_mode(void)
return ((READ_BYTE(BIOS_VDU_CONTROL) & 0xc) == 0xc);
}
/* Output a character to the screen. */
void char_out(unsigned char ch, int page)
{
tty_char_out(ch, page, -1);
}
/*
* Output a character to the screen.
* If attr != -1, set the attribute byte, too.
@@ -278,7 +267,7 @@ void tty_char_out(unsigned char ch, int s, int attr)
unsigned char buff[MB_LEN_MAX + 1];
int num, i;
if (no_local_video && !config.tty_stderr)
if (no_local_video)
return;
init_charset_state(&term_state, trconfig.output_charset);
@@ -287,6 +276,7 @@ void tty_char_out(unsigned char ch, int s, int attr)
return;
for (i = 0; i < num; i++)
fputc(buff[i], config.tty_stderr ? stderr : stdout);
return;
}
li= READ_BYTE(BIOS_ROWS_ON_SCREEN_MINUS_1) + 1;
@@ -314,8 +304,8 @@ void tty_char_out(unsigned char ch, int s, int attr)
case '\t': /* Tab */
i10_deb("char_out: tab\n");
do {
tty_char_out(' ', s, -1);
xpos = get_bios_cursor_x_position(s);
char_out(' ', s);
xpos = get_bios_cursor_x_position(s);
} while (xpos % 8 != 0);
break;
@@ -330,8 +320,8 @@ void tty_char_out(unsigned char ch, int s, int attr)
else
{
dst = screen_adr(s) + 2 * (ypos*co + xpos);
WRITE_BYTE(dst, ch);
if(attr != -1) WRITE_BYTE(dst + 1, attr);
vga_write(dst, ch);
if(attr != -1) vga_write(dst + 1, attr);
}
xpos++;
}
@@ -350,7 +340,7 @@ void tty_char_out(unsigned char ch, int s, int attr)
vga_read(screen_adr(s) + 2*(ypos*co + xpos) + 1));
}
}
do_set_cursor_pos(s, xpos, ypos);
set_cursor_pos(s, xpos, ypos);
}
/* The following clears the screen buffer. It does it only to the screen
@@ -369,42 +359,45 @@ static void clear_screen(void)
v_printf("INT10: cleared screen: screen_adr %x\n", screen_adr(0));
for (schar = screen_adr(0), lx = 0; lx < 16*1024;
WRITE_WORD(schar, blank), lx++, schar+=2);
vga_write_word(schar, blank), lx++, schar+=2);
for (s = 0; s < 8; s++)
do_set_cursor_pos(s, 0, 0);
set_cursor_pos(s, 0, 0);
}
#if 0
/* return number of vertical scanlines based on the bytes at
40:88 and 40:89 */
static int get_text_scanlines(void)
{
int info = READ_BYTE(BIOS_VIDEO_INFO_2);
int info = READ_WORD(BIOS_VIDEO_INFO_1);
v_printf("scanlines=%x\n", info);
if ((info & 0x80) && !(info & 0x10))
if ((info & 1) == 0)
return 200;
if (!(info & 0x80) && !(info & 0x10))
if ((info & 0x1000) == 0)
return 350;
if (!(info & 0x80))
if ((info & 0x8000) == 0)
return 400;
return 480;
}
#endif
/* set number of vertical scanlines at the bytes at
40:88 and 40:89 */
static void set_text_scanlines(int lines)
{
int info = READ_BYTE(BIOS_VIDEO_INFO_2) & ~0x90;
int info = READ_WORD(BIOS_VIDEO_INFO_1) & ~0x9001;
if (lines == 200)
info |= 0x80;
info |= 0x8000;
else {
info |= 1;
if (lines == 400)
info |= 0x10;
info |= 0x1000;
else if (lines == 480)
info |= 0x90;
info |= 0x9000;
}
v_printf("scanlines=%x %d\n", info, lines);
WRITE_BYTE(BIOS_VIDEO_INFO_2, info);
WRITE_WORD(BIOS_VIDEO_INFO_1, info);
}
static int adjust_font_size(int vga_font_height)
@@ -464,7 +457,7 @@ static int adjust_font_size(int vga_font_height)
* -- 1998/04/04 sw
*/
bool set_video_mode(int mode)
boolean set_video_mode(int mode)
{
vga_mode_info *vmi;
int clear_mem = 1;
@@ -483,29 +476,6 @@ bool set_video_mode(int mode)
i10_msg("set_video_mode: undefined video mode\n");
return 0;
}
if (vmi->mode_class == TEXT) {
vga_mode_info *vmi2 = vmi;
vga_mode_info *vmi_best = vmi;
int ts = get_text_scanlines();
int delta = ts - vmi2->height;
i10_msg("look for mode with scan=%i font_height=%i\n",
ts, READ_BYTE(BIOS_FONT_HEIGHT));
while ((vmi2 = vga_emu_find_mode(mode, vmi2))) {
if (vmi2->height > ts ||
vmi2->char_height != READ_BYTE(BIOS_FONT_HEIGHT))
continue;
if (delta < 0 || ts - vmi2->height < delta) {
i10_msg("better mode found: %ix%i %ix%i scan=%i\n",
vmi2->text_width, vmi2->text_height,
vmi2->char_width, vmi2->char_height,
vmi2->height);
vmi_best = vmi2;
delta = ts - vmi2->height;
}
vmi = vmi_best;
}
}
if (vmi->mode_class == GRAPH && config.term) {
error("Cannot set graphics mode under terminal!\n");
return 0;
@@ -627,9 +597,11 @@ bool set_video_mode(int mode)
page_size = vga.mem.bank_pages * 4096;
WRITE_WORD(BIOS_VIDEO_MEMORY_USED, page_size);
}
WRITE_WORD(BIOS_FONT_HEIGHT, vga_font_height);
WRITE_BYTE(BIOS_ROWS_ON_SCREEN_MINUS_1, li - 1);
WRITE_WORD(BIOS_SCREEN_COLUMNS, co);
}
set_cursor_shape(vmi->type == TEXT_MONO ? 0x0b0d : 0x0607);
switch(vga_font_height) {
case 14:
@@ -641,9 +613,6 @@ bool set_video_mode(int mode)
default:
u = vgaemu_bios.font_8;
}
SETIVEC(0x43, 0xc000, u);
WRITE_WORD(BIOS_FONT_HEIGHT, vga_font_height); // before set_cursor_shape()
set_cursor_shape(vmi->type == TEXT_MONO ? 0x0b0d : 0x0607);
if (using_text_mode()) {
v_printf("INT10: X_set_video_mode: 8x%d ROM font -> bank 0\n",
@@ -652,6 +621,9 @@ bool set_video_mode(int mode)
i10_msg("activated font bank 0\n");
}
SETIVEC(0x43, 0xc000, u);
set_text_scanlines(vmi->height);
return 1;
}
@@ -754,7 +726,6 @@ static void vga_ROM_to_RAM(unsigned height, int bank)
ofs = vgaemu_bios.font_16;
}
vga_RAM_to_RAM(height,0,256,seg,ofs,bank);
memcpy(vga.backup_font, vga.mem.base + 0x20000, 256 * 32);
}
/******************************************************************/
@@ -944,19 +915,7 @@ int int10(void) /* with dualmon */
"rep char: page %u, char 0x%02x '%c', attr 0x%02x\n",
HI(bx), LO(ax), LO(ax) > ' ' && LO(ax) < 0x7f ? LO(ax) : ' ', LO(bx)
);
if (config.dumb_video) {
FILE *f = config.tty_stderr ? stderr : stdout;
int i;
if (no_local_video && !config.tty_stderr)
break;
for (i = 0; i < LWORD(ecx); i++)
fputc(LO(ax), f);
/* cursor must not move when printing */
fputc('\r', f);
} else {
vgaemu_repeat_char_attr(LO(ax), HI(bx), LO(bx), LWORD(ecx));
}
vgaemu_repeat_char_attr(LO(ax), HI(bx), LO(bx), LWORD(ecx));
break;
case 0x0a: /* write char */
@@ -1011,7 +970,7 @@ int int10(void) /* with dualmon */
"tty put char: page %u, char 0x%02x '%c'\n",
HI(bx), LO(ax), LO(ax) > ' ' && LO(ax) < 0x7f ? LO(ax) : ' '
);
tty_char_out(LO(ax), READ_BYTE(BIOS_CURRENT_SCREEN_PAGE), -1);
char_out(LO(ax), READ_BYTE(BIOS_CURRENT_SCREEN_PAGE));
}
else {
i10_deb(
@@ -1033,7 +992,7 @@ int int10(void) /* with dualmon */
HI(ax) = co & 0xff;
HI(bx) = READ_BYTE(BIOS_CURRENT_SCREEN_PAGE);
i10_deb(
"get video mode: mode 0x%02x, page %u, %u columns\n",
"get video mode: mode 0x%02x, page %u, %u colums\n",
LO(ax), HI(bx), HI(ax)
);
break;
@@ -1518,7 +1477,7 @@ int int10(void) /* with dualmon */
unsigned crtc, ind;
/* select crtc base address */
crtc = (port_inb(MISC_OUTPUT_R) & 1) ? 0x3d4 : 0x3b4;
crtc = (inb(MISC_OUTPUT_R) & 1) ? 0x3d4 : 0x3b4;
buf[0x0] = port_inb(SEQUENCER_INDEX);
buf[0x1] = port_inb(crtc);
@@ -1596,7 +1555,7 @@ int int10(void) /* with dualmon */
for (ind = 0; ind < 25; ind++)
port_outw(crtc, ind | (buf[0x0a+ind] << 8));
/* select crtc base address */
port_outb(MISC_OUTPUT_W, (port_inb(MISC_OUTPUT_R) & ~0x01) | (crtc == 0x3d4));
outb(MISC_OUTPUT_W, (inb(MISC_OUTPUT_R) & ~0x01) | (crtc == 0x3d4));
/* reset flipflop ! */
port_inb(crtc + 0x6);
for (ind = 0; ind < 20; ind++) {

View File

@@ -122,7 +122,7 @@ static unsigned check_key_available(int extended)
trigger_idle();
else
reset_idle(0);
idle_enable2(500, 20, 2, "int16");
idle_enable(500, 20, 2, "int16");
} else {
reset_idle(1);
}
@@ -193,12 +193,7 @@ static void store_key_in_buffer(void)
LO(ax) = (store_key(LWORD(ecx)) ? 0 : 1);
}
static void get_kbd_features(void)
{
_AX = 0x20; /* enh kbd functionality, nothing else */
}
int ___int16(void)
int int16(void)
{
switch(HI(ax))
{
@@ -224,9 +219,6 @@ int ___int16(void)
case 5:
store_key_in_buffer();
break;
case 0x9:
get_kbd_features();
break;
case 0x10:
int_yield();
read_key(EXTENDED);

View File

@@ -259,17 +259,6 @@ pciRec *pcibios_find_class(unsigned long cls, int num)
return NULL;
}
pciRec *pcibios_find_primary_vga(void)
{
int i = 0;
pciRec *ret;
do {
ret = pcibios_find_class(PCI_CLASS_DISPLAY_VGA << 8, i++);
} while (ret && !ret->enabled);
return ret;
}
pciRec *pcibios_find_bdf(unsigned short bdf)
{
pciPtr pci = pciList;
@@ -442,17 +431,15 @@ interpretCfgSpace(unsigned int *pciheader,unsigned int *pcibuses,int busidx,
{
static const char *typestr[] = { "MEM", "IO", "ROM" };
int tmp, i;
uint16_t command;
pciPtr pciTmp = (pciPtr)malloc(sizeof(pciRec));
pciTmp->next = pciList;
pciList = pciTmp;
pciTmp->enabled = config.pci;
pciTmp->bdf = pcibuses[busidx] << 8 | dev << 3 | func;
pciTmp->vendor = pciheader[0] & 0xffff;
pciTmp->device = pciheader[0] >> 16;
command = pciheader[1] & 0xffff;
pciTmp->cls = pciheader[0x02] >> 8;
pciTmp->enabled = ((command & 3) == 3);
if (PCI_BRIDGE_CLASS(pciTmp->cls)) {
if (PCI_BRIDGE_PCI_CLASS(pciTmp->cls)) { /*PCI-PCI*/
Z_printf("PCI-PCI bridge:\n");

View File

@@ -15,8 +15,6 @@
#include "lowmem.h"
#include "int.h"
#include "iodev.h"
#include "virq.h"
#include "vint.h"
#include "emm.h"
#include "xms.h"
#include "hma.h"
@@ -104,9 +102,6 @@ static void late_init_thr(void *arg)
return;
/* if something else is to be added here,
* add the "late_init" member into dev_list instead */
virq_setup();
vint_setup();
pit_late_init();
video_late_init();
mouse_late_init();
mouse_client_post_init();
@@ -133,7 +128,7 @@ static void bios_setup(void)
/* init trapped interrupts called via jump */
for (i = 0; i < 256; i++) {
if (config.vga) {
if (config.vga && !config.vbios_post) {
uint16_t seg, off;
unsigned int addr;
@@ -142,47 +137,31 @@ static void bios_setup(void)
v_printf("int0x%x was 0x%04x:0x%04x\n", i, seg, off);
addr = SEGOFF2LINEAR(seg, off);
if (addr >= VBIOS_START && addr < VBIOS_START + VBIOS_SIZE) {
v_printf("Setting int0x%x to 0x%04x:0x%04x\n", i, seg, off);
g_printf("Setting int0x%x to 0x%04x:0x%04x\n", i, seg, off);
SETIVEC(i, seg, off);
continue;
}
}
switch (i) {
case 0x60 ... 0x67:
case 0x79 ... 0xff:
/* interrupts >= 0xc0 are NULL unless defined by DOSEMU */
SETIVEC(i, 0, 0);
break;
case 0x68 ... 0x6f:
/* 0x68-0x6f are usually set to iret */
SETIVEC(i, IRET_SEG, IRET_OFF);
break;
case 0x70 ... 0x78:
SETIVEC(i, BIOSSEG, EOI2_OFF);
break;
case 0 ... 7:
case 0x10 ... 0x5f:
SETIVEC(i, BIOSSEG, INT_OFF(i));
break;
case 8: // timer
case 9: // kbd
case 11: // com2,4
case 12: // com1,3
case 14: // floppy
case 15: // spurious
SETIVEC(i, BIOSSEG, EOI_OFF);
break;
case 10: // re-routed from irq9/int71h (mt32)
case 13: // exception D (GPF) or SB16 IRQ
SETIVEC(i, IRET_SEG, IRET_OFF);
break;
/* interrupts >= 0xc0 are scratch (BIOS stack),
unless defined by DOSEMU */
if ((i & 0xf8) == 0x60 || (i >= 0x78 && i < 0xc0)) { /* user interrupts */
/* show also EMS (int0x67) as disabled */
SETIVEC(i, 0, 0);
} else if ((i & 0xf8) == 0x68) {
SETIVEC(i, IRET_SEG, IRET_OFF);
} else if (i < 0x78 || i == DOS_HELPER_INT || i == 0xe7) {
SETIVEC(i, BIOSSEG, INT_OFF(i));
}
}
SETIVEC(DOS_HELPER_INT, BIOSSEG, INT_OFF(DOS_HELPER_INT));
SETIVEC(0xe7, BIOSSEG, INT_OFF(0xe7));
/* Let kernel handle this, no need to return to DOSEMU */
#if 0
SETIVEC(0x1c, BIOSSEG + 0x10, INT_OFF(0x1c) +2 - 0x100);
#endif
SETIVEC(0x09, INT09_SEG, INT09_OFF);
SETIVEC(0x0a, BIOSSEG, EOI_OFF);
SETIVEC(0x08, INT08_SEG, INT08_OFF);
/* 0x30 and 0x31 are not vectors, they are the 5-byte long jump.
* While 0x30 is overwritten entirely, only one byte is overwritten
@@ -200,21 +179,11 @@ static void bios_setup(void)
SETIVEC(0x67, BIOSSEG, INT_OFF(0x67));
if (config.pktdrv)
SETIVEC(0x60, PKTDRV_SEG, PKTDRV_OFF);
if (config.ipxsup)
SETIVEC(0x7a, BIOSSEG, INT_OFF(0x7a));
if (config.mouse.intdrv)
SETIVEC(0x74, BIOSSEG, Mouse_ROUTINE_OFF);
/* set up PIC */
port_outb(0x20, 0x10); // ICW1
port_outb(0x21, 8); // ICW2, set irq to 8
port_outb(0x21, 1 << 2); // ICW3m, slave on irq2
port_outb(0xa0, 0x10); // ICW1
port_outb(0xa1, 0x70); // ICW2, set irq to 0x70
port_outb(0xa1, 2); // ICW3s, master uses irq2
/* mask out SB irqs or Blood game crashes */
if (config.sound)
port_outb(0x21, (1 << config.sb_irq) | port_inb(0x21));
/* IPX. Dummy but should not crash */
if (config.ipxsup)
SETIVEC(0x7a, BIOSSEG, INT_OFF(0x7a));
/* Install new handler for video-interrupt into bios_f000_int10ptr,
* for video initialization at f800:4200
@@ -223,6 +192,14 @@ static void bios_setup(void)
*/
install_int_10_handler();
{
/* update boot drive in Banner-code */
unsigned ptr;
ptr = SEGOFF2LINEAR(BIOSSEG, bios_f000_bootdrive);
WRITE_BYTE(ptr, (config.hdiskboot >= 2 || config.hdiskboot == -1) ? 0x80 : 0);
}
bios_mem_setup(); /* setup values in BIOS area */
}
@@ -230,6 +207,7 @@ static void dosemu_reset(void)
{
initialized = 0;
dos_post_boot_reset();
mfs_reset();
iodev_reset(); /* reset all i/o devices */
commands_plugin_inte6_reset();
lowmem_reset(); /* release memory used by helper utilities */

View File

@@ -31,7 +31,7 @@
// - rombios.c of plex86
//
// This VGA Bios contains fonts from :
// - fntcol16.zip (c) by Joseph Gil available at :
// - fntcol16.zip (c) by Joseph Gil avalable at :
// ftp://ftp.simtel.net/pub/simtelnet/msdos/screen/fntcol16.zip
// These fonts are public domain
//
@@ -97,12 +97,12 @@ Bit8u xstart,Bit8u ysrc,Bit8u ydest,Bit8u cols,Bit8u nbcols,Bit8u cheight)
src=ysrc*cheight*nbcols+xstart+vstart;
dest=ydest*cheight*nbcols+xstart+vstart;
port_outw(VGAREG_GRDC_ADDRESS, 0x0105);
outw(VGAREG_GRDC_ADDRESS, 0x0105);
for(i=0;i<cheight;i++)
{
memcpyb(0xa000,dest+i*nbcols,0xa000,src+i*nbcols,cols);
}
port_outw(VGAREG_GRDC_ADDRESS, 0x0005);
outw(VGAREG_GRDC_ADDRESS, 0x0005);
}
// --------------------------------------------------------------------------------------------
@@ -113,12 +113,12 @@ Bit8u xstart,Bit8u ystart,Bit8u cols,Bit8u nbcols,Bit8u cheight,Bit8u attr)
Bit8u i;
dest=ystart*cheight*nbcols+xstart+vstart;
port_outw(VGAREG_GRDC_ADDRESS, 0x0205);
outw(VGAREG_GRDC_ADDRESS, 0x0205);
for(i=0;i<cheight;i++)
{
memsetb(0xa000,dest+i*nbcols,attr,cols);
}
port_outw(VGAREG_GRDC_ADDRESS, 0x0005);
outw(VGAREG_GRDC_ADDRESS, 0x0005);
}
// --------------------------------------------------------------------------------------------
@@ -231,9 +231,9 @@ Bit8u dir)
case PLANAR1:
if(nblines==0&&rul==0&&cul==0&&rlr==nbrows-1&&clr==nbcols-1)
{
port_outw(VGAREG_GRDC_ADDRESS, 0x0205);
outw(VGAREG_GRDC_ADDRESS, 0x0205);
memsetb(vmi->buffer_start,address,attr,nbrows*nbcols*cheight);
port_outw(VGAREG_GRDC_ADDRESS, 0x0005);
outw(VGAREG_GRDC_ADDRESS, 0x0005);
}
else
{// if Scroll up
@@ -346,15 +346,15 @@ static void write_gfx_char_pl4(Bit16u vstart,Bit8u car,Bit8u attr,
fdata = MEM_BASE32(IVEC(0x43));
addr=xcurs+ycurs*cheight*nbcols+vstart;
src = car * cheight;
port_outw(VGAREG_SEQU_ADDRESS, 0x0f02);
port_outw(VGAREG_GRDC_ADDRESS, 0x0205);
outw(VGAREG_SEQU_ADDRESS, 0x0f02);
outw(VGAREG_GRDC_ADDRESS, 0x0205);
if(attr&0x80)
{
port_outw(VGAREG_GRDC_ADDRESS, 0x1803);
outw(VGAREG_GRDC_ADDRESS, 0x1803);
}
else
{
port_outw(VGAREG_GRDC_ADDRESS, 0x0003);
outw(VGAREG_GRDC_ADDRESS, 0x0003);
}
for(i=0;i<cheight;i++)
{
@@ -362,7 +362,7 @@ static void write_gfx_char_pl4(Bit16u vstart,Bit8u car,Bit8u attr,
for(j=0;j<8;j++)
{
mask=0x80>>j;
port_outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08);
outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08);
read_byte(0xa000,dest);
if(fdata[src+i]&mask)
{
@@ -385,9 +385,9 @@ ASM_START
out dx, ax
ASM_END
#else
port_outw(VGAREG_GRDC_ADDRESS, 0xff08);
port_outw(VGAREG_GRDC_ADDRESS, 0x0005);
port_outw(VGAREG_GRDC_ADDRESS, 0x0003);
outw(VGAREG_GRDC_ADDRESS, 0xff08);
outw(VGAREG_GRDC_ADDRESS, 0x0005);
outw(VGAREG_GRDC_ADDRESS, 0x0003);
#endif
}
@@ -531,10 +531,10 @@ static void biosfn_set_cursor_pos(Bit8u page,Bit16u cursor)
// CRTC regs 0x0e and 0x0f
crtc_addr=read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS);
port_outb(crtc_addr,0x0e);
port_outb(crtc_addr+1,(address&0xff00)>>8);
port_outb(crtc_addr,0x0f);
port_outb(crtc_addr+1,address&0x00ff);
outb(crtc_addr,0x0e);
outb(crtc_addr+1,(address&0xff00)>>8);
outb(crtc_addr,0x0f);
outb(crtc_addr+1,address&0x00ff);
}
}
@@ -851,12 +851,12 @@ static void biosfn_write_pixel(Bit8u BH,Bit8u AL,Bit16u CX,Bit16u DX)
addr = CX/8+DX*read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)+
READ_WORD(BIOS_VIDEO_MEMORY_USED)*BH;
mask = 0x80 >> (CX & 0x07);
port_outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08);
port_outw(VGAREG_GRDC_ADDRESS, 0x0205);
outw(VGAREG_GRDC_ADDRESS, (mask << 8) | 0x08);
outw(VGAREG_GRDC_ADDRESS, 0x0205);
data = read_byte(0xa000,addr);
if (AL & 0x80)
{
port_outw(VGAREG_GRDC_ADDRESS, 0x1803);
outw(VGAREG_GRDC_ADDRESS, 0x1803);
}
write_byte(0xa000,addr,AL);
#if 0
@@ -870,9 +870,9 @@ ASM_START
out dx, ax
ASM_END
#else
port_outw(VGAREG_GRDC_ADDRESS, 0xff08);
port_outw(VGAREG_GRDC_ADDRESS, 0x0005);
port_outw(VGAREG_GRDC_ADDRESS, 0x0003);
outw(VGAREG_GRDC_ADDRESS, 0xff08);
outw(VGAREG_GRDC_ADDRESS, 0x0005);
outw(VGAREG_GRDC_ADDRESS, 0x0003);
#endif
break;
case CGA:
@@ -947,7 +947,7 @@ static unsigned char biosfn_read_pixel(Bit8u BH,Bit16u CX,Bit16u DX)
attr = 0x00;
for(i=0;i<4;i++)
{
port_outw(VGAREG_GRDC_ADDRESS, (i << 8) | 0x04);
outw(VGAREG_GRDC_ADDRESS, (i << 8) | 0x04);
data = read_byte(0xa000,addr) & mask;
if (data > 0) attr |= (0x01 << i);
}

View File

@@ -2,21 +2,37 @@ top_builddir=../../../..
include $(top_builddir)/Makefile.conf
GENSRC = bios_symbols.c
SFILES = bios.S
bios_S_START = 0xe000
ALL_CPPFLAGS += -DBIOS_START=$(bios_S_START)
XSFILES = bios.s
BIOS_START = 0xe000
ALL_CPPFLAGS += -DBIOS_START=$(BIOS_START)
all: lib
# unused target, for testing
everyth: lib bios_offsets.hh bios_data.xxd
include $(REALTOPDIR)/src/Makefile.common
# to support parallel build, we need a separate .o and .elf for every gen target
bios1.o: $(srcdir)/bios.S $(srcdir)/Makefile $(top_builddir)/src/include/version.hh
$(CPP) $(ALL_CPPFLAGS) -x assembler-with-cpp $< | $(XAS) $(XASFLAGS) -o $@
bios0.o bios1.o bios2.o: $(srcdir)/bios.s $(srcdir)/Makefile $(top_builddir)/src/include/version.hh
$(CPP) $(ALL_CPPFLAGS) -x assembler-with-cpp $< | $(AS) --32 -o $@
.INTERMEDIATE: bios1.o
.INTERMEDIATE: bios_data bios0.elf bios1.elf bios2.elf bios0.o bios1.o bios2.o
bios_symbols.c: bios1.o
bios_data: bios0.elf
$(OBJCOPY) -j .text -O binary $< $@
# Makefile defines BIOS_START so add to deps
bios%.elf: bios%.o $(srcdir)/Makefile
# formal intermediate filename is necessary for xxd to name structure
$(AS_LD) $(AS_LDFLAGS) -static --section-start .text=$(BIOS_START) -e bios_data_start -Map bios.map -o $@ $<
chmod -x $@
bios_data.xxd: bios_data
echo "const char *bios_data = \"\\" >$@
hexdump -v -e '"\\" "x" 1/1 "%02X"' $< >>$@
echo "\";" >>$@
bios_symbols.c: bios1.elf
nm -g -n $< | gawk '\
BEGIN {\
COUNT=0;\
@@ -28,7 +44,7 @@ bios_symbols.c: bios1.o
}\
{\
HEXSTR = sprintf("0x%s", $$1);\
ADDR = strtonum(HEXSTR) + $(bios_S_START);\
ADDR = strtonum(HEXSTR);\
if (ADDR <= 0xffff) {\
COUNT++;\
printf " { 0x%04x, \"%s\" },\n", ADDR, $$3;\
@@ -41,5 +57,23 @@ bios_symbols.c: bios1.o
}\
' > $@ || (rm -f $@ ; false)
bios_offsets.hh: bios2.elf
nm -g -n $< | gawk '\
BEGIN {\
print "// Warning: autogenerated";\
print "";\
}\
{\
HEXSTR = sprintf("0x%s", $$1);\
ADDR = strtonum(HEXSTR);\
if (ADDR <= 0xffff) {\
printf "#define %s 0x%04x\n", $$3, ADDR;\
}\
}\
END {\
print "";\
}\
' > $@ || (rm -f $@ ; false)
clean::
rm -f *.o *.d bios_symbols.c *.map
rm -f *.o *.d bios_symbols.c bios_offsets.hh bios_data.xxd bios_data bios*.elf bios.map

View File

@@ -16,7 +16,6 @@
/* some other useful definitions */
#define BIOSSEG 0xf000
/* below block is used in int 9 with DS=BIOS_DATA */
#define BIOS_DATA 0x40
#define KEYBUF_READ_PTR 0x1a
#define KEYBUF_WRITE_PTR 0x1c
@@ -25,10 +24,6 @@
#define KEYSHIFT_FLAGS 0x17
#define KEYBOARD_FLAGS_2 0x18
#define KEYBOARD_STATUS_3 0x96
#define BIOS_FLAGS_1 0x71
#define BIOS_FLAGS_2 0x72
/* end int 9 defines */
#define BIOS_TIMER 0x46c
#define BIOS_TIMER_OVERFLOW 0x470
#define HOUR24_ADJUST 0x1800B0
@@ -54,8 +49,6 @@ _ORG(0xe000)
_ORG(ROM_BIOS_SELFTEST)
/* COMPAS FE05B jmp to POST */
/* COMPAS FE05E-FE2C2 reserved */
.global _start
_start:
hlt
sti
@@ -75,6 +68,7 @@ _start:
lcall *%cs:bios_f000_int10ptr
popw %ds
sti
jmp video_init_done
/* ----------------------------------------------------------------- */
/* Post-less video init
@@ -85,6 +79,8 @@ no_vbios_post:
video_init_done:
movb $DOS_HELPER_SHOW_BANNER,%al
int $DOS_HELPER_INT
movb %cs:bios_f000_bootdrive,%dl
movb $DOS_HELPER_READ_MBR,%al
int $DOS_HELPER_INT
ljmp $0x0, $0x7c00 /* Some boot sectors require cs=0 */
@@ -106,9 +102,16 @@ GET_RETCODE_HELPER:
int $DOS_HELPER_INT
lret
/* This is the int74 handler */
.globl Mouse_ROUTINE_OFF
/* ----------------------------------------------------------------- */
/* this is IRET */
.globl IRET_OFF
IRET_OFF:
iret
.globl Mouse_ROUTINE_OFF
Mouse_ROUTINE_OFF:
/* This is the int74 handler */
pushw %ax /* save everything */
pushw %bx
movw $DOS_HELPER_MOUSE_HELPER,%ax /* mouse helper */
@@ -119,10 +122,11 @@ Mouse_ROUTINE_OFF:
ljmp $BIOSSEG, $EOI2_OFF
/* ----------------------------------------------------------------- */
/* this is IRET */
.globl IRET_OFF
IRET_OFF:
iret
.globl IPX_OFF
IPX_OFF:
ipx_handler:
int $0x7a
lret
/* ----------------------------------------------------------------- */
/* This is an int e7 used for FCB opens */
@@ -351,8 +355,6 @@ int09_cont:
check_special:
cmpw $SP_BREAK, %ax
je kbd_do_break
cmpw $SP_CC, %ax
je kbd_do_cc
cmpw $SP_PRTSCR, %ax
je kbd_do_prtscr
cmpw $SP_SYSRQ_MAKE, %ax
@@ -383,12 +385,6 @@ no_wrap:
buffer_full:
ret
clear_kbd_buffer:
movw KEYBUFFER_START,%bx
movw %bx,KEYBUF_WRITE_PTR
movw %bx,KEYBUF_READ_PTR
ret
kbd_do_pause:
testb $PAUSE_MASK,KEYBOARD_FLAGS_2 /* already paused? */
jnz kbd_done /* do nothing */
@@ -404,37 +400,24 @@ kbd_do_pause:
jmp kbd_done2
kbd_do_break: /* CTRL-BREAK pressed */
movw $0,%ax
kbd_do_cc: /* CTRL-c pressed */
call clear_kbd_buffer
movw $0x100,%ax
call store_key
orb $0x80,BIOS_FLAGS_1
call kbd_EOI
sti
int $0x1b /* call BREAK interrupt */
jmp kbd_done2
jmp kbd_done
kbd_do_prtscr: /* PRINT SCREEN pressed */
call kbd_EOI
sti
int $0x05
jmp kbd_done2
jmp kbd_done
kbd_do_sysrq_make: /* Alt-SYSRQ pressed */
orb $4,KEYBOARD_FLAGS_2 /* set sysrq bit */
call kbd_EOI
sti
movw $0x8500,%ax
int $0x15
jmp kbd_done2
jmp kbd_done
kbd_do_sysrq_break: /* ALT-SYSRQ released */
andb $~4,KEYBOARD_FLAGS_2 /* clear sysrq bit */
call kbd_EOI
sti
movw $0x8501,%ax
int $0x15
jmp kbd_done2
jmp kbd_done
kbd_do_CAD:
call kbd_EOI
@@ -467,6 +450,10 @@ bios_f000_int10_old:
bios_in_int10_callback:
.byte 0
.globl bios_f000_bootdrive
bios_f000_bootdrive:
.byte 0
/* this is the paramblock, we told DOS to use for INT21 AX=4B01 */
.align 16,0
.globl DBGload_parblock
@@ -579,22 +566,12 @@ DPMI_return_from_realmode:
.globl DPMI_return_from_dos_memory
DPMI_return_from_dos_memory:
hlt
.macro ihdr n
.globl \n
\n:
.rept DPMI_MAX_CLIENTS
.globl DPMI_int1c
DPMI_int1c:
hlt
jmp \n\()_end
.endr
.globl \n\()_end
\n\()_end:
.endm
ihdr DPMI_int1c
iret
ihdr DPMI_int23
.globl DPMI_int23
DPMI_int23:
pushw %ax
pushw %bx
movw $0x6200, %ax /* get PSP */
@@ -611,10 +588,10 @@ DPMI_int23_2:
iret
1: /* leave flags on stack */
lret
ihdr DPMI_int24
.globl DPMI_int24
DPMI_int24:
hlt
iret
.globl DPMI_raw_mode_switch_rm
DPMI_raw_mode_switch_rm:
hlt
@@ -622,13 +599,6 @@ DPMI_raw_mode_switch_rm:
DPMI_save_restore_rm:
hlt
lret
.globl DPMI_exit
DPMI_exit:
jnz 1f
/* last client terminated, reinit FPU */
fninit
1:
int $0x21
.globl DPMI_end
DPMI_end:
@@ -643,16 +613,14 @@ XMSControl_OFF:
.globl EOI_OFF
EOI_OFF:
cli
pushw %ax
movb $0x20,%al
outb %al,$0x20 /* flag interrupt complete */
movb $0x20,%al
outb %al,$0x20 /* flag interrupt complete */
popw %ax
iret
.globl EOI2_OFF
EOI2_OFF:
cli
pushw %ax
movb $0x20,%al
outb %al,$0xa0
@@ -755,9 +723,8 @@ LFN_42_A6_HELPER_COMMON:
movw $0x1216, %ax
int $0x2f
jc 1f
popw %ax /* restore function number */
orb $0x80, %al /* add extension bit */
stc
popw %ax /* restore function number */
int $0x2f
jmp 3f
1:
@@ -934,18 +901,13 @@ bios_text_font:
_ORG(0xfea6)
.globl INT75_OFF
INT75_OFF:
int $2 /* Bochs does this; RBIL says: redirected to INT 02 */
/* by the BIOS, for compatibility with the PC */
fnclex /* Clear FP exceptions just in case a hooked
handler hasn't already done so, so we won't
get stuck (in real mode IGNNE would prevent
further exceptions but we don't emulate that) */
xorb %al, %al
outb %al, $0xf0
movb $0x20, %al
outb %al, $0xa0
outb %al, $0x20
iret
int $2 /* Bochs does this; RBIL says: redirected to INT 02 */
iret /* by the BIOS, for compatibility with the PC */
/* ----------------------------------------------------------------- */
.globl INT08_OFF
@@ -1000,15 +962,12 @@ INT08_L2:
.globl INT71_OFF
INT71_OFF:
push %ax
/* EOI to PIC1 */
/* EOI to PIC2 */
movb $0x20, %al
outb %al, $0xa0
pop %ax
/* Then invoke IRQ2 */
int $0x0a
/* Specific EOI */
movb $0x62, %al
outb %al, $0x20
pop %ax
iret /* return to interrupted code */
/* COMPAS FFEF3 vector table for INT08-INT1F */

View File

@@ -1,88 +0,0 @@
extern const unsigned bios_data_start;
extern const unsigned ROM_BIOS_EXIT;
extern const unsigned GET_RETCODE_HELPER;
extern const unsigned Mouse_ROUTINE_OFF;
extern const unsigned IRET_OFF;
extern const unsigned FCB_HLP_OFF;
extern const unsigned INT10_WATCHER_OFF;
extern const unsigned MOUSE_INT33_OFF;
extern const unsigned INT70_OFF;
extern const unsigned INT70_end;
extern const unsigned HD_parameter_table0;
extern const unsigned HD_parameter_table1;
extern const unsigned bios_f000_int10ptr;
extern const unsigned bios_f000_int10_old;
extern const unsigned bios_in_int10_callback;
extern const unsigned DBGload_parblock;
extern const unsigned DBGload_CSIP;
extern const unsigned PKTDRV_param;
extern const unsigned PKTDRV_stats;
extern const unsigned LFN_short_name;
extern const unsigned bios_hlt_blk;
extern const unsigned DPMI_OFF;
extern const unsigned DPMI_dpmi_init;
extern const unsigned DPMI_return_from_dos;
extern const unsigned DPMI_return_from_rmint;
extern const unsigned DPMI_return_from_realmode;
extern const unsigned DPMI_return_from_dos_memory;
extern const unsigned DPMI_int1c;
extern const unsigned DPMI_int1c_end;
extern const unsigned DPMI_int23;
extern const unsigned DPMI_int23_end;
extern const unsigned DPMI_int23_1;
extern const unsigned DPMI_int23_2;
extern const unsigned DPMI_int24;
extern const unsigned DPMI_int24_end;
extern const unsigned DPMI_raw_mode_switch_rm;
extern const unsigned DPMI_save_restore_rm;
extern const unsigned DPMI_exit;
extern const unsigned DPMI_end;
extern const unsigned XMSControl_OFF;
extern const unsigned EOI_OFF;
extern const unsigned EOI2_OFF;
extern const unsigned PKTDRV_OFF;
extern const unsigned PKTDRV_driver_name;
extern const unsigned PKTDRV_driver_entry_ip;
extern const unsigned PKTDRV_driver_entry_cs;
extern const unsigned FOSSIL_isr;
extern const unsigned FOSSIL_oldisr;
extern const unsigned FOSSIL_magic;
extern const unsigned FOSSIL_maxfun;
extern const unsigned FOSSIL_idstring;
extern const unsigned LFN_HELPER_OFF;
extern const unsigned LFN_42_HELPER_OFF;
extern const unsigned LFN_A6_HELPER_OFF;
extern const unsigned DBGload_OFF;
extern const unsigned INT_RVC_21_OFF;
extern const unsigned int_rvc_ip_21;
extern const unsigned int_rvc_cs_21;
extern const unsigned int_rvc_ret_ip_21;
extern const unsigned int_rvc_ret_cs_21;
extern const unsigned int_rvc_disp_ip_21;
extern const unsigned int_rvc_disp_cs_21;
extern const unsigned INT_RVC_28_OFF;
extern const unsigned int_rvc_ip_28;
extern const unsigned int_rvc_cs_28;
extern const unsigned int_rvc_ret_ip_28;
extern const unsigned int_rvc_ret_cs_28;
extern const unsigned int_rvc_disp_ip_28;
extern const unsigned int_rvc_disp_cs_28;
extern const unsigned INT_RVC_2f_OFF;
extern const unsigned int_rvc_ip_2f;
extern const unsigned int_rvc_cs_2f;
extern const unsigned int_rvc_ret_ip_2f;
extern const unsigned int_rvc_ret_cs_2f;
extern const unsigned int_rvc_disp_ip_2f;
extern const unsigned int_rvc_disp_cs_2f;
extern const unsigned INT_RVC_33_OFF;
extern const unsigned int_rvc_ip_33;
extern const unsigned int_rvc_cs_33;
extern const unsigned int_rvc_ret_ip_33;
extern const unsigned int_rvc_ret_cs_33;
extern const unsigned int_rvc_disp_ip_33;
extern const unsigned int_rvc_disp_cs_33;
extern const unsigned bios_text_font;
extern const unsigned INT75_OFF;
extern const unsigned INT08_OFF;
extern const unsigned INT71_OFF;
extern const unsigned bios_f000_end;

View File

@@ -1,7 +1,15 @@
top_builddir=../../..
include $(top_builddir)/Makefile.conf
CFILES = dyndeb.c int.c hlt.c emu.c ports.c coopth.c dump.c lowmem.c priv.c \
vint.c
# src/base/misc/dyndeb.c -> ../async/dyndeb.c
# src/base/misc/int.c -> ../async/int.c
CFILES = dyndeb.c int.c hlt.c emu.c ports.c coopth.c dump.c lowmem.c priv.c
include $(REALTOPDIR)/src/Makefile.common
all: lib
install: all

View File

@@ -30,11 +30,9 @@
#include <unistd.h>
#include <sys/mman.h>
#include <assert.h>
#include <pthread.h>
#ifdef HAVE_EXECINFO
#include <execinfo.h>
#endif
#include "emu.h"
#include "utilities.h"
#include "libpcl/pcl.h"
#include "coopth.h"
@@ -70,11 +68,11 @@ struct coopth_thrdata_t {
struct coopth_thrfunc_t clnup;
struct coopth_thrfunc_t uhook;
jmp_buf exit_jmp;
unsigned int canc_disabled:1;
unsigned int attached:1;
unsigned int cancelled:1;
unsigned int left:1;
unsigned int atomic_switch:1;
int canc_disabled:1;
int attached:1;
int cancelled:1;
int left:1;
int atomic_switch:1;
};
struct coopth_ctx_handlers_t {
@@ -108,7 +106,7 @@ struct coopth_per_thread_t {
struct coopth_starter_args_t args;
void *stack;
size_t stk_size;
unsigned int quick_sched:1;
int quick_sched:1;
void (*retf)(int tid, int idx);
};
@@ -119,8 +117,8 @@ struct coopth_t {
int len;
int cur_thr;
int max_thr;
unsigned int detached:1;
unsigned int custom:1;
int detached:1;
int custom:1;
coopth_func_t func;
struct coopth_ctx_handlers_t ctxh;
struct coopth_sleep_handlers_t sleeph;
@@ -128,23 +126,22 @@ struct coopth_t {
struct coopth_per_thread_t pth[MAX_COOP_RECUR_DEPTH];
struct coopth_per_thread_t *post_pth;
const struct coopth_be_ops *ops;
pthread_t pthread;
};
static __TLS cohandle_t co_handle;
static cohandle_t co_handle;
static struct coopth_t coopthreads[MAX_COOPTHREADS];
static int coopth_num;
static __TLS int thread_running;
static __TLS int joinable_running;
static __TLS int left_running;
static int thread_running;
static int joinable_running;
static int left_running;
#define DETACHED_RUNNING (thread_running - joinable_running - left_running)
static __TLS int threads_joinable;
static __TLS int threads_left;
static __TLS int threads_total;
static int threads_joinable;
static int threads_left;
static int threads_total;
#define MAX_ACT_THRS 10
static __TLS int threads_active;
static __TLS int active_tids[MAX_ACT_THRS];
static __TLS void (*nothread_notifier)(int);
static int threads_active;
static int active_tids[MAX_ACT_THRS];
static void (*nothread_notifier)(void);
static void coopth_callf_chk(struct coopth_t *thr,
struct coopth_per_thread_t *pth);
@@ -320,8 +317,8 @@ static void do_del_thread(struct coopth_t *thr,
thr->post_pth = pth;
}
}
if (nothread_notifier)
nothread_notifier(threads_joinable + threads_left);
if (threads_joinable + threads_left == 0 && nothread_notifier)
nothread_notifier();
}
static void coopth_retf(struct coopth_t *thr, struct coopth_per_thread_t *pth,
@@ -366,7 +363,7 @@ static struct coopth_per_thread_t *current_thr(struct coopth_t *thr)
struct coopth_per_thread_t *pth;
assert(thr - coopthreads < MAX_COOPTHREADS);
if (!thr->cur_thr) {
error("coopth: schedule to inactive thread %i\n", thr->tid);
error("coopth: schedule to inactive thread\n");
exit(2);
return NULL;
}
@@ -570,7 +567,7 @@ int coopth_create_internal(const char *name, coopth_func_t func,
struct coopth_t *thr;
assert(coopth_num < MAX_COOPTHREADS);
num = __sync_fetch_and_add(&coopth_num, 1);
num = coopth_num++;
thr = &coopthreads[num];
thr->name = name;
thr->cur_thr = 0;
@@ -579,7 +576,6 @@ int coopth_create_internal(const char *name, coopth_func_t func,
thr->len = 1;
thr->func = func;
thr->ops = ops;
thr->pthread = pthread_self();
call_prep(thr);
return num;
}
@@ -592,7 +588,7 @@ int coopth_create_multi_internal(const char *name, int len,
assert(len && coopth_num + len <= MAX_COOPTHREADS);
num = coopth_num;
__sync_fetch_and_add(&coopth_num, len);
coopth_num += len;
for (i = 0; i < len; i++) {
struct coopth_t *thr = &coopthreads[num + i];
thr->name = name;
@@ -602,7 +598,6 @@ int coopth_create_multi_internal(const char *name, int len,
thr->len = (i == 0 ? len : 1);
thr->func = func;
thr->ops = ops;
thr->pthread = pthread_self();
call_prep(thr);
}
return num;
@@ -649,8 +644,11 @@ static int do_start(struct coopth_t *thr, struct coopth_state_t st, void *arg)
if (thr->cur_thr > thr->max_thr) {
size_t stk_size = COOP_STK_SIZE();
thr->max_thr = thr->cur_thr;
#ifndef MAP_STACK
#define MAP_STACK 0
#endif
pth->stack = mmap(NULL, stk_size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
if (pth->stack == MAP_FAILED) {
error("Unable to allocate stack\n");
exit(21);
@@ -821,7 +819,12 @@ static int detach_sw(struct coopth_t *thr, struct coopth_per_thread_t *pth)
/* this is special: thread already finished, can't be ran */
do_del_thread(thr, pth);
return 1;
default:
case idx_LEAVE:
case idx_SCHED:
case idx_ATTACH:
case idx_AWAKEN:
case idx_YIELD:
case idx_WAIT:
sw_list[pth->st.sw_idx](thr, pth);
break;
}
@@ -938,8 +941,7 @@ static int __coopth_is_in_thread(int warn, const char *f)
int coopth_get_tid(void)
{
struct coopth_thrdata_t *thdata;
if (!_coopth_is_in_thread_nowarn())
return -1;
assert(_coopth_is_in_thread());
thdata = co_get_data(co_current(co_handle));
return *thdata->tid;
}
@@ -1069,6 +1071,13 @@ static int check_cancel(void)
return -1; /* never reached */
}
static void check_cancel_chk(void)
{
/* normal (non-disabled) cancellation case */
int can = check_cancel();
assert(!can);
}
static struct coopth_t *on_thread(unsigned id)
{
int i;
@@ -1092,13 +1101,11 @@ static int current_active(void)
return thr->ops->is_active(CIDX2(tid, thr->cur_thr - 1));
}
int coopth_yield(void)
void coopth_yield(void)
{
assert(_coopth_is_in_thread());
switch_state(COOPTH_YIELD);
if (check_cancel())
return -1;
return 1;
check_cancel_chk();
}
int coopth_sched(void)
@@ -1125,27 +1132,23 @@ int coopth_sched_cond(void)
return 1;
}
int coopth_wait(void)
void coopth_wait(void)
{
assert(_coopth_is_in_thread());
ensure_attached();
switch_state(COOPTH_WAIT);
if (check_cancel())
return -1;
return 1;
check_cancel_chk();
}
int coopth_sleep(void)
void coopth_sleep(void)
{
int tid = coopth_get_tid();
assert(_coopth_is_in_thread());
if (!is_detached())
coopthreads[tid].ops->to_sleep(tid);
coopthreads[tid].ops->to_sleep();
switch_state(COOPTH_SLEEP);
if (check_cancel())
return -1;
return 1;
check_cancel_chk();
}
static void ensure_single(struct coopth_thrdata_t *thdata)
@@ -1235,17 +1238,6 @@ void coopth_abandon(void)
* has a separate entry point (via coopth_run()), the left thread must
* not have a separate entry point. So it appeared better to return the
* special type "left" threads. */
static void do_leave(struct coopth_thrdata_t *thdata)
{
if (thdata->posth_num)
dosemu_error("coopth: leaving thread with active post handlers\n");
if (!current_active())
dosemu_error("coopth: leaving descheduled thread\n");
if (!thdata->attached)
dosemu_error("coopth: leaving detached thread\n");
switch_state(COOPTH_LEAVE);
}
void coopth_leave(void)
{
struct coopth_thrdata_t *thdata;
@@ -1254,19 +1246,13 @@ void coopth_leave(void)
thdata = co_get_data(co_current(co_handle));
if (thdata->left)
return;
do_leave(thdata);
}
void coopth_leave_internal(void)
{
struct coopth_thrdata_t *thdata;
if (!_coopth_is_in_thread_nowarn())
return;
thdata = co_get_data(co_current(co_handle));
if (thdata->left)
return;
assert(coopthreads[*thdata->tid].custom);
do_leave(thdata);
if (thdata->posth_num)
dosemu_error("coopth: leaving thread with active post handlers\n");
if (!current_active())
dosemu_error("coopth: leaving descheduled thread\n");
if (!thdata->attached)
dosemu_error("coopth: leaving detached thread\n");
switch_state(COOPTH_LEAVE);
}
static void do_awake(struct coopth_per_thread_t *pth)
@@ -1320,7 +1306,7 @@ again:
struct coopth_per_thread_t *pth = current_thr(thr);
if (!pth->data.attached)
continue;
/* don't cancel own thread */
/* dont cancel own thread */
assert(!thdata || *thdata->tid != tid);
do_cancel(thr, pth);
do_detach(thr, pth);
@@ -1414,7 +1400,7 @@ again:
int tid = active_tids[i];
struct coopth_t *thr = &coopthreads[tid];
struct coopth_per_thread_t *pth = current_thr(thr);
/* don't cancel own thread */
/* dont cancel own thread */
if (thdata && *thdata->tid == tid)
continue;
if (!pth->data.attached) {
@@ -1436,10 +1422,7 @@ again:
for (i = 0; i < coopth_num; i++) {
struct coopth_t *thr = &coopthreads[i];
int j;
if (!pthread_equal(thr->pthread, pthread_self()))
continue;
/* don't free own thread */
/* dont free own thread */
if (thdata && *thdata->tid == i)
continue;
for (j = thr->cur_thr; j < thr->max_thr; j++) {
@@ -1464,12 +1447,12 @@ int coopth_wants_sleep_internal(unsigned id)
pth->st.state == COOPTHS_SWITCH);
}
void coopth_set_nothread_notifier(void (*notifier)(int))
void coopth_set_nothread_notifier(void (*notifier)(void))
{
nothread_notifier = notifier;
}
void coopth_cancel_disable_cur(void)
void coopth_cancel_disable(void)
{
struct coopth_thrdata_t *thdata;
assert(_coopth_is_in_thread());
@@ -1477,7 +1460,7 @@ void coopth_cancel_disable_cur(void)
thdata->canc_disabled = 1;
}
void coopth_cancel_enable_cur(void)
void coopth_cancel_enable(void)
{
struct coopth_thrdata_t *thdata;
assert(_coopth_is_in_thread());

View File

@@ -19,9 +19,9 @@
char *emu_disasm(unsigned int ip)
{
static char buf[2048];
static char buf[512];
#ifdef USE_MHPDBG
char frmtbuf[1024];
char frmtbuf[256];
int rc, i;
unsigned int cp;
char *p;
@@ -154,7 +154,7 @@ show_ints(int min, int max)
void dump_state(void)
{
cpuctx_t *scp = dpmi_get_scp();
sigcontext_t *scp = dpmi_get_scp();
show_regs();
if (scp)
dbug_printf("\nProtected-mode state dump:\n%s\n", DPMI_show_state(scp));

View File

@@ -57,10 +57,11 @@
#include "version.h"
#include "memory.h"
#include "mhpdbg.h"
#include "debug.h"
#include "emu.h"
#include "mhpdbg.h"
#include "bios.h"
#include "video.h"
#include "timers.h"
@@ -83,7 +84,7 @@
#include "iodev.h"
#include "mapping.h"
#include "dosemu_config.h"
#include "libpacket.h"
#include "pktdrvr.h"
#include "ne2000.h"
#include "dma.h"
#include "hlt.h"
@@ -91,7 +92,6 @@
#include "keyboard/keyb_server.h"
#include "sig.h"
#include "sound.h"
#include "ioselect.h"
#ifdef X86_EMULATOR
#include "cpu-emu.h"
#endif
@@ -102,7 +102,7 @@ static int can_leavedos;
static int leavedos_code;
static int leavedos_called;
static pthread_mutex_t ld_mtx = PTHREAD_MUTEX_INITIALIZER;
__TLS union vm86_union vm86u;
union vm86_union vm86u;
volatile __thread int fault_cnt;
volatile int in_vm86;
@@ -144,7 +144,7 @@ static int find_boot_drive(void)
void boot(void)
{
unsigned buffer;
struct disk *dp = NULL;
struct disk *dp = NULL;
if (config.try_freedos && config.hdiskboot == -1 &&
config.hdisks > 0 && !disk_is_bootable(&hdisktab[0])) {
@@ -246,9 +246,6 @@ mbr:
}
}
disk_close();
/* put boot drive to dl */
_DX = dp->drive_num;
}
static int c_chk(void)
@@ -257,6 +254,14 @@ static int c_chk(void)
return !in_dpmi_pm();
}
static void c_nothr(void)
{
/* here we can start snapshotting.
* See https://github.com/dosemu2/dosemu2/issues/1005
*/
// error("No threads\n");
}
/*
* DANG_BEGIN_FUNCTION emulate
*
@@ -309,6 +314,7 @@ int main(int argc, char **argv, char * const *envp)
get_time_init();
print_version(); /* log version information */
memcheck_init();
time_setting_init(); /* get the startup time */
/* threads can be created only after signal_pre_init() so
* it should be above device_init(), iodev_init(), cpu_setup() etc */
signal_pre_init(); /* initialize sig's & sig handlers */
@@ -317,9 +323,11 @@ int main(int argc, char **argv, char * const *envp)
device_init(); /* priv initialization of video etc. */
extra_port_init(); /* setup ports dependent on config */
SIG_init(); /* Silly Interrupt Generator */
LibpacketInit(); /* initialize network packet interfaces */
pkt_priv_init(); /* initialize the packet driver interface */
ne2000_priv_init();
mapping_init(); /* initialize mapping drivers */
low_mem_init(); /* initialize the lower 1Meg */
if (can_do_root_stuff && !under_root_login) {
g_printf("dropping root privileges\n");
@@ -327,8 +335,7 @@ int main(int argc, char **argv, char * const *envp)
}
priv_drop();
map_memory_space(); /* maps all DOS memory (low, dpmi, xms...) */
init_hardware_ram(); /* map the direct hardware ram */
init_hardware_ram(); /* map the direct hardware ram */
map_video_bios(); /* map (really: copy) the video bios */
close_kmem();
@@ -336,6 +343,7 @@ int main(int argc, char **argv, char * const *envp)
vm86_hlt_state = hlt_init(BIOS_HLT_BLK_SIZE);
coopth_init();
coopth_set_ctx_checker_vm86(c_chk);
coopth_set_nothread_notifier(c_nothr);
ld_tid = coopth_create("leavedos", leavedos_thr);
coopth_set_ctx_handlers(ld_tid, sig_ctx_prepare, sig_ctx_restore, NULL);
@@ -344,13 +352,13 @@ int main(int argc, char **argv, char * const *envp)
HMA_init(); /* HMA can only be done now after mapping
is initialized*/
memory_init(); /* initialize the memory contents */
ioselect_init();
/* iodev_init() can load plugins, like SDL, that can spawn a thread.
* This must be done before initializing signals, or problems ensue.
* This also must be done when the signals are blocked, so after
* the signal_pre_init(), which right now blocks the signals. */
iodev_init(); /* initialize devices */
init_all_DOS_tables(); /* longest init function! needs to be optimized */
dos2tty_init();
signal_init(); /* initialize sig's & sig handlers */
if (config.exitearly) {
dbug_printf("Leaving DOS before booting\n");
@@ -370,8 +378,7 @@ int main(int argc, char **argv, char * const *envp)
set_kvm_memory_regions();
cpu_reset();
if (config.cpu_vm == CPUVM_KVM)
kvm_enter(0);
can_leavedos = 1;
while (!fatalerr && !config.exitearly) {
@@ -444,8 +451,9 @@ void __leavedos(int code, int sig, const char *s, int num)
keyb_close();
/* abandon current thread if any */
coopth_abandon();
/* switch to RM before closing coopthreads-related stuff */
dpmi_done0();
/* close coopthreads-related stuff first */
dpmi_done();
dos2tty_done();
if (!config.exitearly) { // in exitearly case nothing to join
/* try to clean up threads */
tmp = coopth_flush_vm86();
@@ -462,18 +470,13 @@ static void __leavedos_main(int code, int sig)
{
int i;
/* async signals must be disabled first or pthread_cancel() hangs on arm */
signal_done();
dpmi_done();
/* now safe to stop io thread */
ioselect_done();
/* then stop device threads, which also stops any remaining vm86() uses */
iodev_term();
#ifdef USE_MHPDBG
g_printf("closing debugger pipes\n");
/* after vm86() is no longer used, we can do this */
mhp_close();
#endif
/* async signals must be disabled after coopthreads are joined, but
* before coopth_done(). */
signal_done();
/* now it is safe to shut down coopth. Can be done any later, if need be */
coopth_done();
dbug_printf("coopthreads stopped\n");
@@ -493,13 +496,16 @@ static void __leavedos_main(int code, int sig)
* My port logic is actually stolen from kd_nosound in the kernel.
* --EB 21 September 1997
*/
port_outb(0x61, port_inb(0x61)&0xFC); /* turn off any sound */
port_safe_outb(0x61, port_safe_inb(0x61)&0xFC); /* turn off any sound */
}
free(vm86_hlt_state);
SIG_close();
g_printf("calling keyboard_close\n");
iodev_term();
#if defined(X86_EMULATOR)
/* if we are here with config.cpuemu>1 something went wrong... */
if (IS_EMU()) {
@@ -531,20 +537,15 @@ static void __leavedos_main(int code, int sig)
g_printf("calling close_all_printers\n");
close_all_printers();
ioselect_done();
for (i = 0; i < exit_hndl_num; i++)
exit_hndl[i].handler();
flush_log();
if (sig < 0)
code = -sig;
else if (sig > 0)
code = sig + 128;
else
code &= 0x7f;
/* We don't need to use _exit() here; this is the graceful exit path. */
exit(code);
exit(sig ? sig + 128 : code);
}
void __leavedos_main_wrp(int code, int sig, const char *s, int num)

View File

@@ -12,14 +12,9 @@
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef __linux__
#include <sys/vfs.h>
#else
#include <sys/param.h>
#include <sys/mount.h>
#endif
#include <sys/statvfs.h>
#include "Linux/magic.h"
#include <linux/magic.h>
#include <signal.h>
#include <sys/wait.h>
#include <errno.h>
@@ -41,10 +36,8 @@
#include "hma.h"
#include "xms.h"
#include "int.h"
#include "vint.h"
#include "dos2linux.h"
#include "video.h"
#include "clipboard.h"
#include "priv.h"
#include "doshelpers.h"
#include "lowmem.h"
@@ -187,8 +180,13 @@ static void process_master_boot_record(void)
* SS:BP,DS:SI pointing to the boot partition entry within 0:600 MBR
* DI = 0x7dfe
*/
struct on_disk_mbr *mbr = LOWMEM(0x600);
struct on_disk_mbr *bootrec = LOWMEM(0x7c00);
struct mbr {
char code[PART_INFO_START];
struct on_disk_partition partition[4];
unsigned short bootmagic;
} __attribute__ ((packed));
struct mbr *mbr = LOWMEM(0x600);
struct mbr *bootrec = LOWMEM(0x7c00);
int i;
unsigned offs;
@@ -200,7 +198,7 @@ static void process_master_boot_record(void)
}
if (i >= 4) {
/* aiee... no bootflags sets */
error("no bootflag set, Leaving DOS...\n");
p_dos_str("\n\rno bootflag set, Leaving DOS...\n\r");
leavedos(99);
}
LO(dx) = 0x80; /* drive C:, DOS boots only from C: */
@@ -212,13 +210,13 @@ static void process_master_boot_record(void)
LWORD(eax) = 0x0201; /* read one sector */
LWORD(ebx) = 0x7c00; /* target offset, ES is 0 */
do_int_call_back(0x13);
if ((REG(eflags) & CF) || (bootrec->signature != MBR_SIG)) {
if ((REG(eflags) & CF) || (bootrec->bootmagic != 0xaa55)) {
/* error while booting */
error("error on reading bootsector, Leaving DOS...\n");
leavedos(99);
}
offs = 0x600 + offsetof(struct on_disk_mbr, partition) + sizeof(mbr->partition[0]) * i;
offs = 0x600 + offsetof(struct mbr, partition) + sizeof(mbr->partition[0]) * i;
coopth_add_post_handler(mbr_jmp, (void *) (long) offs);
}
@@ -374,7 +372,7 @@ static int dos_helper(int stk_offs, int revect)
LWORD(eax) = DOS_HELPER_MAGIC;
LWORD(ebx) = VERSION_NUM * 0x100 + SUBLEVEL; /* major version 0.49 -> 0049 */
/* The patch level in the form n.n is a float...
* ...we let GCC at compile time translate it to 0xHHLL, HH=major, LL=minor.
* ...we let GCC at compiletime translate it to 0xHHLL, HH=major, LL=minor.
* This way we avoid usage of float instructions.
*/
LWORD(ecx) = REVISION;
@@ -393,7 +391,8 @@ static int dos_helper(int stk_offs, int revect)
break;
case DOS_HELPER_PRINT_STRING: /* PRINT STRING ES:DX */
dbug_printf("DOS to EMU: \"%s\"\n", SEG_ADR((char *), es, dx));
g_printf("DOS likes us to print a string\n");
ds_printf("DOS to EMU: \"%s\"\n", SEG_ADR((char *), es, dx));
break;
case DOS_HELPER_ADJUST_IOPERMS: /* SET IOPERMS: bx=start, cx=range,
@@ -473,10 +472,6 @@ static int dos_helper(int stk_offs, int revect)
p_dos_str("\n");
break;
case DOS_HELPER_PRESTROKES_START:
start_pre_strokes();
break;
case DOS_HELPER_INSERT_INTO_KEYBUFFER:
k_printf
("KBD: WARNING: outdated keyboard helper fn 6 was called!\n");
@@ -511,10 +506,6 @@ static int dos_helper(int stk_offs, int revect)
config.hogthreshold = LWORD(ebx);
break;
case DOS_HELPER_TEST_MODE:
config.test_mode = LO(bx);
return 1;
case DOS_HELPER_MFS_HELPER:
mfs_inte6();
return 1;
@@ -564,7 +555,7 @@ static int dos_helper(int stk_offs, int revect)
case DOS_HELPER_GARROT_HELPER: /* Mouse garrot helper */
if (!LWORD(ebx)) /* Wait sub-function requested */
idle_enable(50, 0, "mouse_garrot");
idle_enable(0, 50, 0, "mouse_garrot");
else { /* Get Hogthreshold value sub-function */
LWORD(ebx) = config.hogthreshold;
LWORD(eax) = config.hogthreshold;
@@ -673,7 +664,10 @@ static int dos_helper(int stk_offs, int revect)
case DOS_HELPER_GET_CPU_SPEED:
{
REG(eax) = 0;
if (config.rdtsc)
REG(eax) = (LLF_US << 16) / config.cpu_spd;
else
REG(eax) = 0;
break;
}
@@ -715,12 +709,10 @@ static int dos_helper(int stk_offs, int revect)
buf == NULL ? 0 : (SEGOFF2LINEAR(_ES, _DX) & 0xffff);
break;
}
case DOS_HELPER_GETPID: {
pid_t pid = getpid();
LWORD(eax) = pid;
LWORD(ebx) = pid >> 16;
case DOS_HELPER_GETPID:
LWORD(eax) = getpid();
LWORD(ebx) = getppid();
break;
}
case DOS_HELPER_CHDIR:
LWORD(eax) = chdir(SEG_ADR((char *), es, dx));
@@ -800,7 +792,7 @@ static int int15(void)
case 0x10: /* TopView/DESQview */
switch (LO(ax)) {
case 0x00:{ /* giveup timeslice */
idle_enable(100, 0, "topview");
idle_enable(0, 100, 0, "topview");
break;
}
}
@@ -895,9 +887,6 @@ static int int15(void)
unsigned src_addr, dst_addr;
unsigned src_limit, dst_limit;
unsigned int length;
void *s, *d;
unsigned int old_a20 = a20;
lp = SEG_ADR((unsigned int *), es, si);
lp += 4;
src_addr = (*lp >> 16) & 0x0000FFFF;
@@ -918,52 +907,19 @@ static int int15(void)
src_addr, dst_addr, length);
if (src_limit < length - 1 || dst_limit < length - 1 ||
src_addr + length > LOWMEM_SIZE + EXTMEM_SIZE ||
dst_addr + length > LOWMEM_SIZE + EXTMEM_SIZE) {
src_addr + length > LOWMEM_SIZE + HMASIZE + EXTMEM_SIZE ||
dst_addr + length > LOWMEM_SIZE + HMASIZE + EXTMEM_SIZE) {
x_printf("block move failed\n");
LWORD(eax) = 0x0200;
CARRY;
break;
}
/* Have to enable a20 before translating addresses */
if (!a20)
set_a20(1);
while (length) {
/* avoid crossing page boundaries */
int s_al = PAGE_ALIGN(src_addr) - src_addr;
int d_al = PAGE_ALIGN(dst_addr) - dst_addr;
int todo;
if (!s_al)
s_al += PAGE_SIZE;
if (!d_al)
d_al += PAGE_SIZE;
todo = _min(s_al, d_al);
todo = _min(todo, length);
x_printf("int 15: copy subblock: src=%#x dst=%#x len=%#x\n",
src_addr, dst_addr, todo);
s = physaddr_to_unixaddr(src_addr);
if (s == MAP_FAILED) {
error("error mapping %x to addr\n", src_addr);
break;
}
d = physaddr_to_unixaddr(dst_addr);
if (d == MAP_FAILED) {
error("error mapping %x to addr\n", dst_addr);
break;
}
e_invalidate_pa(dst_addr, todo);
memcpy(d, s, todo);
src_addr += todo;
dst_addr += todo;
length -= todo;
}
if (old_a20 != a20)
set_a20(old_a20);
if (length) {
LWORD(eax) = 0x0200;
CARRY;
} else {
unsigned int old_a20 = a20;
/* Have to enable a20 before moving */
if (!a20)
set_a20(1);
extmem_copy(dst_addr, src_addr, length);
if (old_a20 != a20)
set_a20(old_a20);
LWORD(eax) = 0;
NOCARRY;
}
@@ -971,7 +927,10 @@ static int int15(void)
}
case 0x88:
LWORD(eax) = EXTMEM_SIZE >> 10;
if (xms_intdrv())
LWORD(eax) = 0;
else
LWORD(eax) = (EXTMEM_SIZE + HMASIZE) >> 10;
NOCARRY;
break;
@@ -1053,7 +1012,7 @@ static int int15(void)
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
#endif
if (LO(ax) == 1) {
Bit32u mem = EXTMEM_SIZE >> 10;
Bit32u mem = (EXTMEM_SIZE + HMASIZE) >> 10;
if (mem < 0x3c00) {
LWORD(eax) = mem;
LWORD(ebx) = 0;
@@ -1124,8 +1083,6 @@ static void set_ticks(unsigned long new_ticks)
static int int1a(void)
{
int_yield();
switch (HI(ax)) {
/*
@@ -1149,7 +1106,7 @@ increments AL so we *don't* lose a day if two consecutive midnights pass.
case 0: /* read time counter */
{
int day_rollover;
idle_enable2(50, 50, 0, "int1a:0");
idle(50, 50, 0, "int1a:0");
if (config.timemode == TM_LINUX) {
/* Set BIOS area flags to LINUX time computed values always */
last_ticks = get_linux_ticks(0, &day_rollover);
@@ -1461,7 +1418,7 @@ static int msdos(void)
#endif
case 0x2C:{ /* get time & date */
idle_enable(100, 0, "dos_time");
idle(2, 100, 0, "dos_time");
return 0;
}
@@ -1607,10 +1564,10 @@ static void do_ret_from_int(int inum, const char *pfx)
ssp = SEGOFF2LINEAR(SREG(ss), 0);
sp = LWORD(esp);
_SP += 6;
_IP = popw(ssp, sp);
_CS = popw(ssp, sp);
flgs = popw(ssp, sp);
_SP += 6;
if (flgs & IF)
set_IF();
else
@@ -1721,11 +1678,9 @@ static far_t int##x##_unrevect(uint16_t seg, uint16_t offs) \
return ret; \
int##x##_hooked = 1; \
di_printf("int_rvc: unrevect 0x%s\n", #x); \
if (test_bit(0x##x, &vm86s.int_revectored)) { \
if (!mhp_revectored(0x##x)) \
clear_bit(0x##x, &vm86s.int_revectored); \
else \
mhp_adjust_revectored(0x##x); \
if (is_revectored(0x##x, &vm86s.int_revectored)) { \
assert(!mhp_revectored(0x##x)); \
reset_revectored(0x##x, &vm86s.int_revectored); \
} else { \
di_printf("int_rvc: revectoring of 0x%s was not enabled\n", #x); \
} \
@@ -1740,7 +1695,7 @@ static int int##x##_unrevect_simple(void) \
return 0; \
int##x##_hooked = 1; \
di_printf("int_rvc: unrevect 0x%s\n", #x); \
clear_bit(0x##x, &vm86s.int_revectored); \
reset_revectored(0x##x, &vm86s.int_revectored); \
int##x##_rvc_setup(); \
SETIVEC(0x##x, INT_RVC_SEG, INT_RVC_##x##_OFF); \
return 1; \
@@ -1809,7 +1764,7 @@ static void msdos_xtra(uint16_t old_ax, uint16_t old_flags)
di_printf("int_rvc 0x21 call for ax=0x%04x %x\n", LWORD(eax), old_ax);
CARRY;
switch (HI_BYTE(old_ax)) {
switch (HI_BYTE_d(old_ax)) {
case 0x71:
if (LWORD(eax) != 0x7100)
break;
@@ -1963,10 +1918,8 @@ static int int19(void)
{
int stal;
coopth_leave();
dpmi_done0();
if (clnup_handler)
clnup_handler();
clnup_handler = NULL;
stal = coopth_flush_vm86();
if (stal) {
error("stalled %i threads on reboot\n", stal);
@@ -2070,10 +2023,8 @@ static int redir_printers(void)
/* drive for -K (aka system.com) */
struct drive_syscom {
char *path;
int drv_num;
int mfs_idx;
#define SCUSERS 5
uint8_t *drv_num[SCUSERS];
int num_scusers;
};
static struct drive_syscom syscomdrv;
/* drive for -d */
@@ -2095,18 +2046,14 @@ static int num_x_drives;
#define REDIR_F_GRP 1
void add_syscom_drive(char *path, uint8_t *user)
int *add_syscom_drive(char *path)
{
assert(syscomdrv.num_scusers == 0);
syscomdrv.path = expand_path(path);
syscomdrv.mfs_idx = mfs_define_drive(syscomdrv.path);
syscomdrv.drv_num[0] = user;
}
void add_syscom_user(uint8_t *user)
{
assert(1 + syscomdrv.num_scusers < SCUSERS);
syscomdrv.drv_num[1 + syscomdrv.num_scusers++] = user;
struct drive_syscom *drv = &syscomdrv;
assert(drv->drv_num == 0);
drv->path = expand_path(path);
drv->drv_num = -1;
drv->mfs_idx = mfs_define_drive(drv->path);
return &drv->drv_num;
}
int add_extra_drive(char *path, int ro, int cd, int grp)
@@ -2463,9 +2410,7 @@ static int redir_one_drive(const char *path, int ro, int cdrom, int prm,
int drv = find_free_drive();
if (drv < 0) {
error("no free drives\n");
if (get_lastdrive() < 7)
error("@Set LASTDRIVE=Z in your fdconfig.sys\n");
else if (config.boot_dos == FATFS_FD_D) {
if (config.boot_dos == FATFS_FD_D) {
error("@-d/-K is not supported with this freedos version\n");
leavedos(26);
}
@@ -2475,9 +2420,7 @@ static int redir_one_drive(const char *path, int ro, int cdrom, int prm,
grp ? REDIR_F_GRP : 0);
if (ret != CC_SUCCESS) {
error("INT21: redirecting %s failed (err = %d)\n", path, ret);
if (get_lastdrive() < 7)
error("@Set LASTDRIVE=Z in your fdconfig.sys\n");
else if (config.boot_dos == FATFS_FD_D && (ret == 0x55 /* duplicate redirect */
if (config.boot_dos == FATFS_FD_D && (ret == 0x55 /* duplicate redirect */
|| ret == 0xf /* invalid drive */)) {
error("-d/-K is not supported with this freedos version\n");
leavedos(26);
@@ -2652,15 +2595,13 @@ static void redir_extra_drives(void)
{
int i, ret, drv;
if (syscomdrv.path) {
if (syscomdrv.drv_num != 0) {
drv = redir_one_drive(syscomdrv.path, 0, 0, 1, 0, syscomdrv.mfs_idx);
if (drv < 0) {
leavedos(26);
return;
}
/* notify all users about this drive */
for (i = 0; i < 1 + syscomdrv.num_scusers; i++)
*syscomdrv.drv_num[i] = drv;
syscomdrv.drv_num = drv;
}
for (i = 0; i < num_x_drives; i++) {
@@ -2841,10 +2782,6 @@ void dos_post_boot_reset(void)
if (clnup_handler)
clnup_handler();
clnup_handler = NULL;
syscomdrv.num_scusers = 0;
#ifdef USE_MHPDBG
mhp_reset_hma();
#endif
}
static void dos_post_boot(void)
@@ -2852,9 +2789,6 @@ static void dos_post_boot(void)
if (!post_boot) {
post_boot = 1;
post_boot_unrevect();
/* call vint_setup() again to avoid DOS STACKS hooks, see
* https://github.com/dosemu2/dosemu2/issues/1607 */
vint_setup();
if (config.force_redir) {
if (!redir_state) {
redir_it();
@@ -2863,22 +2797,13 @@ static void dos_post_boot(void)
enable_redirect();
}
}
#ifdef USE_MHPDBG
/*
* Let's set up the hma start address for dosdebug use. There's no
* specific reason it should be here other than it needs to be done
* sometime after DOS has started.
*/
mhp_init_hma();
#endif
start_pre_strokes();
}
}
/* KEYBOARD BUSY LOOP */
static int int28(void)
{
idle_enable(50, 0, "int28");
idle_enable(0, 50, 0, "int28");
return 1;
}
@@ -2938,7 +2863,7 @@ done:
static unsigned short do_get_psp(int parent)
{
/* don't care about parent, as command.com is primary */
/* dont care about parent, as command.com is primary */
return sda_cur_psp(sda);
}
@@ -2957,9 +2882,6 @@ static void do_run_cmd(struct lowstring *str, struct ae00_tab *cmd)
_AL = 0xff;
}
/* size not propagated through DOS API, so we cache it */
static int clipb_size;
static int int2f(int stk_offs, int revect)
{
reset_idle(0);
@@ -3021,16 +2943,14 @@ hint_done:
memcpy(cmdname, str->s, len);
cmdname[len] = 0;
ptr = cmdname + strspn(cmdname, " \t");
if (!ptr[0])
return 0;
tmp_ptr = ptr;
while (*tmp_ptr) { /* Check whether the name is valid */
if (iscntrlDOS(*tmp_ptr++))
return 0;
}
strcpy(title_current, title_hint);
if (!ptr[0]) {
change_window_title(title_current);
return 0;
}
snprintf(appname, sizeof(appname), "%s ( %s )",
title_current, strlowerDOS(ptr));
change_window_title(appname);
@@ -3092,7 +3012,7 @@ hint_done:
break;
case 0x80: /* give up time slice */
idle_enable(100, 0, "int2f_idle_magic");
idle_enable(0, 100, 0, "int2f_idle_magic");
if (config.hogthreshold) {
LO(ax) = 0;
return 1;
@@ -3101,11 +3021,8 @@ hint_done:
case 0x83:
if (dpmi_active() && win3x_mode != INACTIVE) {
LWORD(ebx) = 1; /* W95: number of virtual machine */
return 1;
}
break;
if (dpmi_active() && win3x_mode != INACTIVE)
LWORD(ebx) = 0; /* W95: number of virtual machine */
case 0x81: /* W95: enter critical section */
if (dpmi_active() && win3x_mode != INACTIVE) {
D_printf("WIN: enter critical section\n");
@@ -3141,81 +3058,13 @@ hint_done:
}
break;
case 0x17: /* MS Windows WINOLDAP functions */
switch (LO(ax)) {
case 0x00: /* IDENTIFY WinOldAp VERSION */
LO(ax) = 0x01; // major version
HI(ax) = 0x00; // minor version
v_printf("Check for WinOldAp\n"); // Installed == (AX != 1700)
return 1;
case 0x01: /* OPEN CLIPBOARD */
LWORD(eax) = 1; // success (AX != 0)
v_printf("Open clipboard\n");
return 1;
case 0x02: /* EMPTY CLIPBOARD */
v_printf("Clear clipboard\n");
if (Clipboard && Clipboard->clear)
LWORD(eax) = Clipboard->clear();
else
LWORD(eax) = 0;
return 1;
case 0x03: /* WRITE CLIPBOARD */
v_printf("Write clipboard\n");
if (Clipboard && Clipboard->write) {
char *pbuf = MK_FP32(SREG(es), LWORD(ebx));
unsigned int bsize = LWORD(esi) << 16 | LWORD(ecx);
LWORD(eax) = Clipboard->write(LWORD(edx), pbuf, bsize);
} else
LWORD(eax) = 0;
return 1;
case 0x04: /* GET CLIPBOARD DATA SIZE */
v_printf("Get clipboard size\n");
if (Clipboard && Clipboard->getsize) {
clipb_size = Clipboard->getsize(LWORD(edx));
LWORD(edx) = (clipb_size >> 16);
LWORD(eax) = (clipb_size & 0xffff);
} else {
LWORD(edx) = LWORD(eax) = 0;
}
return 1;
case 0x05: /* GET CLIPBOARD DATA */
v_printf("Get clipboard data\n");
if (Clipboard && Clipboard->getdata) {
char *pbuf = MK_FP32(SREG(es), LWORD(ebx));
LWORD(eax) = Clipboard->getdata(LWORD(edx), pbuf,
clipb_size);
} else
LWORD(eax) = 0;
return 1;
case 0x08: /* CLOSE CLIPBOARD */
LWORD(eax) = 1; // success (AX != 0)
v_printf("Close clipboard\n");
return 1;
case 0x09: /* COMPACT CLIPBOARD */
// SI:CX = desired size in bytes
// DX:AX = number of bytes in largest block of free memory
LWORD(edx) = 0;
LWORD(eax) = 0x1000; // 4K should indicate enough room
v_printf("Compact clipboard\n");
return 1;
case 0x0a: /* GET DEVICE CAPABILITIES */
LWORD(eax) = 0; // Not sure if we should "support" this
// function, but doesn't seem possible to
// indicate otherwise.
v_printf("Get device capabilities (0x%02x)\n", LWORD(edx));
return 1;
default:
v_printf("BAD WinOldAp func int 2f/ax=0x%04x\n", LWORD(eax));
}
break;
case INT2F_XMS_MAGIC:
if (!xms_intdrv())
break;
switch (LO(ax)) {
case 0: /* check for XMS */
x_printf("Check for XMS\n");
LWORD(eax) = xms_install_check();
LO(ax) = 0x80;
break;
case 0x10:
x_printf("Get XMSControl address\n");
@@ -3413,7 +3262,7 @@ void do_int(int i)
}
#endif
if (test_bit(i, &vm86s.int_revectored) && !mhp_revectored(i)) {
if (is_revectored(i, &vm86s.int_revectored) && !mhp_revectored(i)) {
assert(int_handlers[i].interrupt_function[REVECT]);
if (debug_level('#') > 2)
debug_int("Do rvc", i);
@@ -3526,10 +3375,10 @@ void fake_iret(void)
ssp = SEGOFF2LINEAR(SREG(ss), 0);
sp = LWORD(esp);
_SP += 6;
_IP = popw(ssp, sp);
_CS = popw(ssp, sp);
set_FLAGS(popw(ssp, sp));
_SP += 6;
#ifdef USE_MHPDBG
if (mhpdbg.active && old_tf)
set_TF();
@@ -3548,12 +3397,6 @@ void do_eoi2_iret(void)
_IP = EOI2_OFF;
}
void do_iret(void)
{
_CS = BIOSSEG;
_IP = IRET_OFF;
}
static void rvc_int_pre(int tid, void *arg, void *arg2)
{
coopth_push_user_data(tid, (void *) (long) get_FLAGS(REG(eflags)));
@@ -3592,14 +3435,6 @@ static int _int##n##_(int stk_offs, int revect) \
return int##n(); \
}
/* Needed for int16, which can clash with type name.
* Under clang, both _int16 and __int16 are also occupied. */
#define INT_WRP2(n) \
static int _int##n##_(int stk_offs, int revect) \
{ \
return ___int##n(); \
}
INT_WRP(05)
INT_WRP(10)
INT_WRP(11)
@@ -3607,7 +3442,7 @@ INT_WRP(12)
INT_WRP(13)
INT_WRP(14)
INT_WRP(15)
INT_WRP2(16)
INT_WRP(16)
INT_WRP(17)
INT_WRP(18)
INT_WRP(19)
@@ -3635,7 +3470,7 @@ static void revect_setup(void)
if (config.force_revect != 0) {
for (i = 0; i < 0x100; i++) {
if (int_handlers[i].interrupt_function[REVECT])
set_bit(i, &vm86s.int_revectored);
set_revectored(i, &vm86s.int_revectored);
}
}
@@ -3736,15 +3571,10 @@ void setup_interrupts(void)
void int_try_disable_revect(void)
{
int i;
if (config.force_revect != -1)
return;
config.force_revect = 0;
for (i = 0; i < 256; i++) {
if (test_bit(i, &vm86s.int_revectored) && !mhp_revectored(i))
clear_bit(i, &vm86s.int_revectored);
}
memset(&vm86s.int_revectored, 0x00, sizeof(vm86s.int_revectored));
}
void update_xtitle(void)
@@ -3893,7 +3723,7 @@ far_t get_int_vector(int vec)
{
far_t addr;
if (test_bit(vec, &vm86s.int_revectored)) {
if (is_revectored(vec, &vm86s.int_revectored)) {
addr.segment = INT_RVC_SEG;
switch (vec) {
case 0x21:

View File

@@ -33,7 +33,7 @@
static smpool mp;
unsigned char *dosemu_lmheap_base;
static void *rm_stack;
#define RM_STACK_SIZE 0x200
#define RM_STACK_SIZE 0x400
static void do_sm_error(int prio, const char *fmt, ...)
{
@@ -49,11 +49,11 @@ static void do_sm_error(int prio, const char *fmt, ...)
dbug_printf("%s\n", buf);
}
int lowmem_init(void)
int lowmem_init()
{
dosemu_lmheap_base = MK_FP32(DOSEMU_LMHEAP_SEG, DOSEMU_LMHEAP_OFF);
smregister_default_error_notifier(do_sm_error);
sminit(&mp, dosemu_lmheap_base, DOSEMU_LMHEAP_SIZE);
smregister_error_notifier(&mp, do_sm_error);
return 1;
}
@@ -152,27 +152,6 @@ void rm_stack_enter(void)
void rm_stack_leave(void)
{
int old_tf = isset_TF();
put_rm_stack(NULL);
REGS = rm_regs_stack[in_rm_stack];
if (old_tf)
set_TF();
}
#define LMHEAP_OFF 0xa000
#define LMHEAP_SIZE 0x4000
static uint16_t lmheap_add(void)
{
return (config.dos_up == 2 ? FDPP_LMHEAP_ADD : 0);
}
uint16_t lmheap_off(void)
{
return LMHEAP_OFF + lmheap_add();
}
uint16_t lmheap_size(void)
{
return LMHEAP_SIZE - lmheap_add();
}

View File

@@ -29,7 +29,7 @@
#include <string.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#ifdef HAVE_SYS_IO_H
#ifdef __linux__
#include <sys/io.h>
#endif
#include <sys/types.h>
@@ -61,6 +61,8 @@ static pid_t portserver_pid = 0;
static unsigned char port_handles; /* number of io_handler's */
static const char *irq_handler_name[EMU_MAX_IRQS];
int in_crit_section = 0;
static const char *crit_sect_caller;
@@ -189,7 +191,7 @@ static void log_port_write_d(ioport_t port, Bit32u w)
Bit8u port_inb(ioport_t port)
{
Bit8u res;
res = EMU_HANDLER(port).read_portb(port, EMU_HANDLER(port).arg);
res = EMU_HANDLER(port).read_portb(port);
return LOG_PORT_READ(port, res);
}
@@ -203,7 +205,7 @@ Bit8u port_inb(ioport_t port)
void port_outb(ioport_t port, Bit8u byte)
{
LOG_PORT_WRITE(port, byte);
EMU_HANDLER(port).write_portb(port, byte, EMU_HANDLER(port).arg);
EMU_HANDLER(port).write_portb(port,byte);
}
/*
@@ -219,10 +221,8 @@ Bit16u port_inw(ioport_t port)
{
Bit16u res;
if (EMU_HANDLER(port).read_portw != NULL &&
EMU_HANDLER(port).read_portb == EMU_HANDLER(port + 1).read_portb
) {
res = EMU_HANDLER(port).read_portw(port, EMU_HANDLER(port).arg);
if (EMU_HANDLER(port).read_portw != NULL) {
res = EMU_HANDLER(port).read_portw(port);
return LOG_PORT_READ_W(port, res);
}
else {
@@ -240,11 +240,9 @@ Bit16u port_inw(ioport_t port)
*/
void port_outw(ioport_t port, Bit16u word)
{
if (EMU_HANDLER(port).write_portw != NULL &&
EMU_HANDLER(port).write_portb == EMU_HANDLER(port + 1).write_portb
) {
if (EMU_HANDLER(port).write_portw != NULL) {
LOG_PORT_WRITE_W(port, word);
EMU_HANDLER(port).write_portw(port, word, EMU_HANDLER(port).arg);
EMU_HANDLER(port).write_portw(port, word);
}
else {
port_outb(port, word & 0xff);
@@ -264,12 +262,8 @@ Bit32u port_ind(ioport_t port)
{
Bit32u res;
if (EMU_HANDLER(port).read_portd != NULL &&
EMU_HANDLER(port).read_portb == EMU_HANDLER(port + 1).read_portb &&
EMU_HANDLER(port).read_portb == EMU_HANDLER(port + 2).read_portb &&
EMU_HANDLER(port).read_portb == EMU_HANDLER(port + 3).read_portb
) {
res = EMU_HANDLER(port).read_portd(port, EMU_HANDLER(port).arg);
if (EMU_HANDLER(port).read_portd != NULL) {
res = EMU_HANDLER(port).read_portd(port);
}
else {
res = (Bit32u) port_inw(port) | (((Bit32u) port_inw(port + 2)) << 16);
@@ -280,12 +274,8 @@ Bit32u port_ind(ioport_t port)
void port_outd(ioport_t port, Bit32u dword)
{
LOG_PORT_WRITE_D(port, dword);
if (EMU_HANDLER(port).write_portd != NULL &&
EMU_HANDLER(port).write_portb == EMU_HANDLER(port + 1).write_portb &&
EMU_HANDLER(port).write_portb == EMU_HANDLER(port + 2).write_portb &&
EMU_HANDLER(port).write_portb == EMU_HANDLER(port + 3).write_portb
) {
EMU_HANDLER(port).write_portd(port, dword, EMU_HANDLER(port).arg);
if (EMU_HANDLER(port).write_portd != NULL) {
EMU_HANDLER(port).write_portd(port, dword);
}
else {
port_outw(port, dword & 0xffff);
@@ -313,7 +303,7 @@ static void check_crit_section(ioport_t port, const char *function)
}
}
static Bit8u port_not_avail_inb(ioport_t port, void *arg)
static Bit8u port_not_avail_inb(ioport_t port)
{
/* it is a fact of (hardware) life that unused locations return all
(or almost all) the bits at 1; some software can try to detect a
@@ -330,33 +320,33 @@ static Bit8u port_not_avail_inb(ioport_t port, void *arg)
return 0xff;
}
static void port_not_avail_outb(ioport_t port, Bit8u byte, void *arg)
static void port_not_avail_outb(ioport_t port, Bit8u byte)
{
check_crit_section(port, "outb");
if (debug_level('i')) pna_emsg(port,'b',"write");
}
static Bit16u port_not_avail_inw(ioport_t port, void *arg)
static Bit16u port_not_avail_inw(ioport_t port)
{
if (debug_level('i')) pna_emsg(port,'w',"read");
// idle(0, 50, 0, "inw");
return 0xffff;
}
static void port_not_avail_outw(ioport_t port, Bit16u value, void *arg)
static void port_not_avail_outw(ioport_t port, Bit16u value)
{
check_crit_section(port, "outw");
if (debug_level('i')) pna_emsg(port,'w',"write");
}
static Bit32u port_not_avail_ind(ioport_t port, void *arg)
static Bit32u port_not_avail_ind(ioport_t port)
{
if (debug_level('i')) pna_emsg(port,'d',"read");
// idle(0, 50, 0, "ind");
return 0xffffffff;
}
static void port_not_avail_outd(ioport_t port, Bit32u value, void *arg)
static void port_not_avail_outd(ioport_t port, Bit32u value)
{
check_crit_section(port, "outd");
if (debug_level('i')) pna_emsg(port,'d',"write");
@@ -386,7 +376,7 @@ Bit8u std_port_inb(ioport_t port)
}
if (!portserver_pid) {
error ("std_port_inb(0x%X): port server unavailable\n", port);
return port_not_avail_inb (port, NULL);
return port_not_avail_inb (port);
}
pr.port = port;
pr.type = TYPE_INB;
@@ -395,11 +385,6 @@ Bit8u std_port_inb(ioport_t port)
return pr.word;
}
static Bit8u std_port_inb_h(ioport_t port, void *arg)
{
return std_port_inb(port);
}
void std_port_outb(ioport_t port, Bit8u byte)
{
struct portreq pr;
@@ -411,7 +396,7 @@ void std_port_outb(ioport_t port, Bit8u byte)
if (!portserver_pid) {
error ("std_port_outb(0x%X,0x%X): port server unavailable\n",
port, byte);
port_not_avail_outb (port, byte, NULL);
port_not_avail_outb (port, byte);
return;
}
pr.word = byte;
@@ -421,23 +406,16 @@ void std_port_outb(ioport_t port, Bit8u byte)
read(port_fd_in[0], &pr, sizeof(pr));
}
static void std_port_outb_h(ioport_t port, Bit8u byte, void *arg)
{
std_port_outb(port, byte);
}
Bit16u std_port_inw(ioport_t port)
{
struct portreq pr;
if (current_iopl == 3 || (test_bit(port, emu_io_bitmap) +
test_bit(port + 1, emu_io_bitmap)
== 2)) {
if (current_iopl == 3 || test_bit(port, emu_io_bitmap)) {
return port_real_inw(port);
}
if (!portserver_pid) {
error ("std_port_inw(0x%X): port server unavailable\n", port);
return port_not_avail_inw (port, NULL);
return port_not_avail_inw (port);
}
pr.port = port;
pr.type = TYPE_INW;
@@ -446,25 +424,18 @@ Bit16u std_port_inw(ioport_t port)
return pr.word;
}
static Bit16u std_port_inw_h(ioport_t port, void *arg)
{
return std_port_inw(port);
}
void std_port_outw(ioport_t port, Bit16u word)
{
struct portreq pr;
if (current_iopl == 3 || (test_bit(port, emu_io_bitmap) +
test_bit(port + 1, emu_io_bitmap)
== 2)) {
if (current_iopl == 3 || test_bit(port, emu_io_bitmap)) {
port_real_outw(port, word);
return;
}
if (!portserver_pid) {
error ("std_port_outw(0x%X,0x%X): port server unavailable\n",
port, word);
port_not_avail_outw (port, word, NULL);
port_not_avail_outw (port, word);
return;
}
pr.word = word;
@@ -474,25 +445,16 @@ void std_port_outw(ioport_t port, Bit16u word)
read(port_fd_in[0], &pr, sizeof(pr));
}
static void std_port_outw_h(ioport_t port, Bit16u word, void *arg)
{
std_port_outw(port, word);
}
Bit32u std_port_ind(ioport_t port)
{
struct portreq pr;
if (current_iopl == 3 || (test_bit(port, emu_io_bitmap) +
test_bit(port + 1, emu_io_bitmap) +
test_bit(port + 2, emu_io_bitmap) +
test_bit(port + 3, emu_io_bitmap)
== 4)) {
if (current_iopl == 3 || test_bit(port, emu_io_bitmap)) {
return port_real_ind(port);
}
if (!portserver_pid) {
error ("std_port_ind(0x%X): port server unavailable\n", port);
return port_not_avail_ind (port, NULL);
return port_not_avail_ind (port);
}
pr.port = port;
pr.type = TYPE_IND;
@@ -501,27 +463,18 @@ Bit32u std_port_ind(ioport_t port)
return pr.word;
}
static Bit32u std_port_ind_h(ioport_t port, void *arg)
{
return std_port_ind(port);
}
static int do_port_outd(ioport_t port, Bit32u dword, int pci)
{
struct portreq pr;
if (current_iopl == 3 || (test_bit(port, emu_io_bitmap) +
test_bit(port + 1, emu_io_bitmap) +
test_bit(port + 2, emu_io_bitmap) +
test_bit(port + 3, emu_io_bitmap)
== 4)) {
if (current_iopl == 3 || test_bit(port, emu_io_bitmap)) {
port_real_outd(port, dword);
return 0;
}
if (!portserver_pid) {
error ("std_port_outd(0x%X,0x%X): port server unavailable\n",
port, dword);
port_not_avail_outd (port, dword, NULL);
port_not_avail_outd (port, dword);
return 0;
}
pr.word = dword;
@@ -538,11 +491,6 @@ void std_port_outd(ioport_t port, Bit32u dword)
read(port_fd_in[0], &pr, sizeof(pr));
}
static void std_port_outd_h(ioport_t port, Bit32u dword, void *arg)
{
std_port_outd(port, dword);
}
void pci_port_outd(ioport_t port, Bit32u dword)
{
do_port_outd(port, dword, 1);
@@ -568,9 +516,17 @@ int port_rep_inb(ioport_t port, Bit8u *base, int df, Bit32u count)
if (count==0) return 0;
i_printf("Doing REP insb(%#x) %d bytes at %p, DF %d\n", port,
count, base, df);
while (count--) {
*dest = port_inb(port);
if (EMU_HANDLER(port).read_portb == std_port_inb) {
while (count--) {
*dest = std_port_inb(port);
dest += incr;
}
}
else {
while (count--) {
*dest = EMU_HANDLER(port).read_portb(port);
dest += incr;
}
}
if (debug_level('T')) {
dest = base;
@@ -591,9 +547,17 @@ int port_rep_outb(ioport_t port, Bit8u *base, int df, Bit32u count)
if (count==0) return 0;
i_printf("Doing REP outsb(%#x) %d bytes at %p, DF %d\n", port,
count, base, df);
while (count--) {
port_outb(port, *dest);
if (EMU_HANDLER(port).write_portb == std_port_outb) {
while (count--) {
std_port_outb(port, *dest);
dest += incr;
}
}
else {
while (count--) {
EMU_HANDLER(port).write_portb(port, *dest);
dest += incr;
}
}
if (debug_level('T')) {
dest = base;
@@ -614,17 +578,23 @@ int port_rep_inw(ioport_t port, Bit16u *base, int df, Bit32u count)
if (count==0) return 0;
i_printf("Doing REP insw(%#x) %d words at %p, DF %d\n", port,
count, base, df);
if (EMU_HANDLER(port).read_portw == NULL) {
if (EMU_HANDLER(port).read_portw == std_port_inw) {
while (count--) {
*dest = std_port_inw(port);
dest += incr;
}
}
else if (EMU_HANDLER(port).read_portw == NULL) {
Bit16u res;
while (count--) {
res = port_inb(port);
*dest = ((Bit16u)port_inb(port+1) <<8) | res;
res = EMU_HANDLER(port).read_portb(port);
*dest = ((Bit16u)EMU_HANDLER(port).read_portb(port+1) <<8) | res;
dest += incr;
}
}
else {
while (count--) {
*dest = port_inw(port);
*dest = EMU_HANDLER(port).read_portw(port);
dest += incr;
}
}
@@ -647,17 +617,23 @@ int port_rep_outw(ioport_t port, Bit16u *base, int df, Bit32u count)
if (count==0) return 0;
i_printf("Doing REP outsw(%#x) %d words at %p, DF %d\n", port,
count, base, df);
if (EMU_HANDLER(port).write_portw == NULL) {
if (EMU_HANDLER(port).write_portw == std_port_outw) {
while (count--) {
std_port_outw(port, *dest);
dest += incr;
}
}
else if (EMU_HANDLER(port).write_portw == NULL) {
Bit16u res;
while (count--) {
res = *dest, dest += incr;
port_outb(port, res);
port_outb(port+1, res>>8);
EMU_HANDLER(port).write_portb(port, res);
EMU_HANDLER(port).write_portb(port+1, res>>8);
}
}
else {
while (count--) {
port_outw(port, *dest);
EMU_HANDLER(port).write_portw(port, *dest);
dest += incr;
}
}
@@ -721,7 +697,7 @@ void do_r3da_pending (void)
}
}
static Bit8u special_port_inb(ioport_t port, void *arg)
static Bit8u special_port_inb(ioport_t port)
{
Bit8u res = 0xff;
@@ -740,7 +716,7 @@ static Bit8u special_port_inb(ioport_t port, void *arg)
return res;
}
static void special_port_outb(ioport_t port, Bit8u byte, void *arg)
static void special_port_outb(ioport_t port, Bit8u byte)
{
if (current_iopl == 3 || test_bit(port, emu_io_bitmap)) {
port_real_outb(port, byte);
@@ -762,16 +738,16 @@ static void special_port_outb(ioport_t port, Bit8u byte, void *arg)
* This way we avoid extra port accesses when the program
* is only looking for the sync bits, and we don't miss
* the case where the read to 0x3da is used to reset the
* index/data flipflop for port 0x3c0. Further accesses to
* index/data flipflop for port 0x3c0. Futher accesses to
* port 0x3c0 are handled at full speed.
*
* SIDOC_END_REMARK
*/
if (config.vga && (config.emuretrace>1)) {
if (r3da_pending) {
(void)std_port_inb_h(r3da_pending, arg);
(void)std_port_inb(r3da_pending);
r3da_pending = 0;
std_port_outb_h(0x3c0, byte, arg);
std_port_outb(0x3c0, byte);
return;
}
goto defout;
@@ -788,7 +764,7 @@ static void special_port_outb(ioport_t port, Bit8u byte, void *arg)
}
defout:
std_port_outb_h (port, byte, arg);
std_port_outb (port, byte);
}
/* ---------------------------------------------------------------------- */
@@ -814,6 +790,8 @@ int port_init(void)
port_handler[i].write_portw = NULL;
port_handler[i].read_portd = NULL;
port_handler[i].write_portd = NULL;
port_handler[i].irq = EMU_NO_IRQ;
port_handler[i].fd = -1;
}
/* handle 0 maps to the unmapped IO device handler. Basically any
@@ -831,28 +809,28 @@ int port_init(void)
/* the STD handles will be in use by many devices, and their fd
will always be -1
*/
port_handler[HANDLE_STD_IO].read_portb = std_port_inb_h;
port_handler[HANDLE_STD_IO].write_portb = std_port_outb_h;
port_handler[HANDLE_STD_IO].read_portw = std_port_inw_h;
port_handler[HANDLE_STD_IO].write_portw = std_port_outw_h;
port_handler[HANDLE_STD_IO].read_portd = std_port_ind_h;
port_handler[HANDLE_STD_IO].write_portd = std_port_outd_h;
port_handler[HANDLE_STD_IO].read_portb = std_port_inb;
port_handler[HANDLE_STD_IO].write_portb = std_port_outb;
port_handler[HANDLE_STD_IO].read_portw = std_port_inw;
port_handler[HANDLE_STD_IO].write_portw = std_port_outw;
port_handler[HANDLE_STD_IO].read_portd = std_port_ind;
port_handler[HANDLE_STD_IO].write_portd = std_port_outd;
port_handler[HANDLE_STD_IO].handler_name = "std port io";
port_handler[HANDLE_STD_RD].read_portb = std_port_inb_h;
port_handler[HANDLE_STD_RD].read_portb = std_port_inb;
port_handler[HANDLE_STD_RD].write_portb = port_not_avail_outb;
port_handler[HANDLE_STD_RD].read_portw = std_port_inw_h;
port_handler[HANDLE_STD_RD].read_portw = std_port_inw;
port_handler[HANDLE_STD_RD].write_portw = port_not_avail_outw;
port_handler[HANDLE_STD_RD].read_portd = std_port_ind_h;
port_handler[HANDLE_STD_RD].read_portd = std_port_ind;
port_handler[HANDLE_STD_RD].write_portd = port_not_avail_outd;
port_handler[HANDLE_STD_RD].handler_name = "std port read";
port_handler[HANDLE_STD_WR].read_portb = port_not_avail_inb;
port_handler[HANDLE_STD_WR].write_portb = std_port_outb_h;
port_handler[HANDLE_STD_WR].write_portb = std_port_outb;
port_handler[HANDLE_STD_WR].read_portw = port_not_avail_inw;
port_handler[HANDLE_STD_WR].write_portw = std_port_outw_h;
port_handler[HANDLE_STD_WR].write_portw = std_port_outw;
port_handler[HANDLE_STD_WR].read_portd = port_not_avail_ind;
port_handler[HANDLE_STD_WR].write_portd = std_port_outd_h;
port_handler[HANDLE_STD_WR].write_portd = std_port_outd;
port_handler[HANDLE_STD_WR].handler_name = "std port write";
#if 0
port_handler[HANDLE_VID_IO].read_portb = video_port_in;
@@ -863,12 +841,12 @@ int port_init(void)
port_handler[HANDLE_VID_IO].write_portd = NULL;
port_handler[HANDLE_VID_IO].handler_name = "video port io";
#else
port_handler[HANDLE_VID_IO].read_portb = std_port_inb_h;
port_handler[HANDLE_VID_IO].write_portb = std_port_outb_h;
port_handler[HANDLE_VID_IO].read_portw = std_port_inw_h;
port_handler[HANDLE_VID_IO].write_portw = std_port_outw_h;
port_handler[HANDLE_VID_IO].read_portd = std_port_ind_h;
port_handler[HANDLE_VID_IO].write_portd = std_port_outd_h;
port_handler[HANDLE_VID_IO].read_portb = std_port_inb;
port_handler[HANDLE_VID_IO].write_portb = std_port_outb;
port_handler[HANDLE_VID_IO].read_portw = std_port_inw;
port_handler[HANDLE_VID_IO].write_portw = std_port_outw;
port_handler[HANDLE_VID_IO].read_portd = std_port_ind;
port_handler[HANDLE_VID_IO].write_portd = std_port_outd;
port_handler[HANDLE_VID_IO].handler_name = "std port io";
#endif
@@ -889,13 +867,13 @@ int port_init(void)
return port_handles; /* unused but useful */
}
static void portserver_exit(void *arg)
static void portserver_exit(void)
{
error("port server terminated, exiting\n");
leavedos(1);
}
/* port server: this function runs in a separate process from the main
/* port server: this function runs in a seperate process from the main
DOSEMU. This enables the main DOSEMU to drop root privileges. The
server can do that as well: by setting iopl(3).
Maybe this server should wrap DOSEMU rather than be forked from
@@ -905,7 +883,7 @@ static void port_server(void)
{
sigset_t set;
struct portreq pr;
_port_handler *ph, *ph1, *ph2, *ph3;
_port_handler *ph;
signal(SIGINT, SIG_DFL);
signal(SIGPIPE, SIG_DFL);
signal(SIGHUP, SIG_DFL);
@@ -926,70 +904,33 @@ static void port_server(void)
if (pr.type >= TYPE_EXIT)
_exit(0);
ph = &EMU_HANDLER(pr.port);
ph1 = &EMU_HANDLER(pr.port + 1);
ph2 = &EMU_HANDLER(pr.port + 2);
ph3 = &EMU_HANDLER(pr.port + 3);
if (pr.type == TYPE_PCI) {
/* get addr and data i/o access as close to each other
as possible, both to minimize possible races, and
for speed */
struct portreq pr2;
read(port_fd_out[0], &pr2, sizeof(pr2));
ph->write_portd(pr.port, pr.word, ph->arg);
ph->write_portd(pr.port, pr.word);
pr = pr2;
}
switch (pr.type) {
case TYPE_INB:
pr.word = ph->read_portb(pr.port, ph->arg);
pr.word = ph->read_portb(pr.port);
break;
case TYPE_OUTB:
ph->write_portb(pr.port, pr.word, ph->arg);
ph->write_portb(pr.port, pr.word);
break;
case TYPE_INW:
if (ph->read_portb == ph1->read_portb) {
pr.word = ph->read_portw(pr.port, ph->arg);
} else {
i_printf("PORT: splitting inw(0x%x)\n", pr.port);
pr.word = ph->read_portb(pr.port, ph->arg) |
(ph1->read_portb(pr.port + 1, ph->arg) << 8);
}
pr.word = ph->read_portw(pr.port);
break;
case TYPE_OUTW:
if (ph->write_portb == ph1->write_portb) {
ph->write_portw(pr.port, pr.word, ph->arg);
} else {
i_printf("PORT: splitting outw(0x%x)\n", pr.port);
ph->write_portb(pr.port, pr.word, ph->arg);
ph1->write_portb(pr.port + 1, pr.word >> 8, ph->arg);
}
ph->write_portw(pr.port, pr.word);
break;
case TYPE_IND:
if (ph->read_portb == ph1->read_portb &&
ph->read_portb == ph2->read_portb &&
ph->read_portb == ph3->read_portb
) {
pr.word = ph->read_portd(pr.port, ph->arg);
} else {
i_printf("PORT: splitting ind(0x%x)\n", pr.port);
pr.word = ph->read_portb(pr.port, ph->arg) |
(ph1->read_portb(pr.port + 1, ph->arg) << 8) |
(ph2->read_portb(pr.port + 2, ph->arg) << 16) |
(ph3->read_portb(pr.port + 3, ph->arg) << 24);
}
pr.word = ph->read_portd(pr.port);
break;
case TYPE_OUTD:
if (ph->write_portb == ph1->write_portb &&
ph->write_portb == ph2->write_portb &&
ph->write_portb == ph3->write_portb
) {
ph->write_portd(pr.port, pr.word, ph->arg);
} else {
i_printf("PORT: splitting outd(0x%x)\n", pr.port);
ph->write_portb(pr.port, pr.word, ph->arg);
ph1->write_portb(pr.port + 1, pr.word >> 8, ph->arg);
ph2->write_portb(pr.port + 2, pr.word >> 16, ph->arg);
ph3->write_portb(pr.port + 3, pr.word >> 24, ph->arg);
}
ph->write_portd(pr.port, pr.word);
break;
}
write(port_fd_in[1], &pr, sizeof(pr));
@@ -1047,7 +988,7 @@ int extra_port_init(void)
close(port_fd_in[1]);
close(port_fd_out[0]);
sigchld_register_handler(portserver_pid,
portserver_exit, NULL);
portserver_exit);
break;
}
}
@@ -1070,11 +1011,21 @@ void port_exit(void)
void release_ports (void)
{
int i;
for (i=0; i < port_handles; i++) {
if (port_handler[i].fd >= 2) {
close(port_handler[i].fd);
/* DANG_FIXTHIS we should free the name but we are going to exit anyway
*/
/* free(port_handler[i].handler_name); */
}
}
memset (port_handle_table, NO_HANDLE, sizeof(port_handle_table));
memset (port_andmask, 0xff, sizeof(port_andmask));
memset (port_ormask, 0, sizeof(port_ormask));
}
}
/* ---------------------------------------------------------------------- */
/*
@@ -1089,6 +1040,12 @@ int port_register_handler(emu_iodev_t device, int flags)
{
int handle, i;
if (device.irq != EMU_NO_IRQ && device.irq >= EMU_MAX_IRQS) {
dbug_printf("PORT: IO device %s registered with IRQ=%d above %u\n",
device.handler_name, device.irq, EMU_MAX_IRQS - 1);
return 1;
}
/* first find existing handle for function or create new one */
for (handle=0; handle < port_handles; handle++) {
if (!strcmp(port_handler[handle].handler_name, device.handler_name))
@@ -1102,17 +1059,34 @@ int port_register_handler(emu_iodev_t device, int flags)
leavedos(77);
}
if (device.irq != EMU_NO_IRQ && irq_handler_name[device.irq]) {
error("PORT: IRQ %d conflict. IO devices %s & %s\n",
device.irq, irq_handler_name[device.irq], device.handler_name);
if (device.fd) close(device.fd);
return 2;
}
if (device.irq != EMU_NO_IRQ && device.irq < EMU_MAX_IRQS)
irq_handler_name[device.irq] = device.handler_name;
port_handles++;
port_handler[handle] = device;
/*
* for byte and double, a NULL function means that the port
* access is not available, while for word means that it will
* be translated into 2 byte accesses
*/
if (!device.read_portb)
port_handler[handle].read_portb = port_not_avail_inb;
if (!device.write_portb)
port_handler[handle].write_portb = port_not_avail_outb;
port_handler[handle].read_portb =
(device.read_portb? : port_not_avail_inb);
port_handler[handle].write_portb =
(device.write_portb? : port_not_avail_outb);
port_handler[handle].read_portw = device.read_portw;
port_handler[handle].write_portw = device.write_portw;
port_handler[handle].read_portd =
(device.read_portd? : port_not_avail_ind);
port_handler[handle].write_portd =
(device.write_portd? : port_not_avail_outd);
port_handler[handle].handler_name = device.handler_name;
port_handler[handle].irq = device.irq;
port_handler[handle].fd = -1;
}
/* change table to reflect new handler id for that address */
@@ -1121,7 +1095,7 @@ int port_register_handler(emu_iodev_t device, int flags)
error("PORT: conflicting devices: %s & %s for port %#x\n",
port_handler[handle].handler_name,
EMU_HANDLER(i).handler_name, i);
config.exitearly = 1;
if (device.fd) close(device.fd);
return 4;
}
port_handle_table[i] = handle;
@@ -1129,9 +1103,9 @@ int port_register_handler(emu_iodev_t device, int flags)
set_bit(i, portfast_map);
}
i_printf("PORT: registered \"%s\" handle 0x%02x [0x%04x-0x%04x]\n",
i_printf("PORT: registered \"%s\" handle 0x%02x [0x%04x-0x%04x] fd=%d\n",
port_handler[handle].handler_name, handle, device.start_addr,
device.end_addr);
device.end_addr, device.fd);
if (flags & PORT_FAST) {
i_printf("PORT: trying to give fast access to ports [0x%04x-0x%04x]\n",
@@ -1152,10 +1126,17 @@ int port_register_handler(emu_iodev_t device, int flags)
* SIDOC_END_FUNCTION
*/
Boolean port_allow_io(ioport_t start, Bit16u size, int permission, Bit8u ormask,
Bit8u andmask, int portspeed)
Bit8u andmask, int portspeed, char *device)
{
static emu_iodev_t io_device;
int usemasks = 0;
FILE *fp;
unsigned int beg, end, newbeg, newend;
size_t len;
ssize_t bytes;
char *line, *portname, lock_file[64];
unsigned char mapped;
char *devrname;
int fd, usemasks = 0;
unsigned int flags = 0;
if (!can_do_root_stuff) {
@@ -1173,6 +1154,117 @@ Boolean port_allow_io(ioport_t start, Bit16u size, int permission, Bit8u ormask,
usemasks = 1;
}
/* SIDOC_BEGIN_REMARK
* find out whether the port address request is available;
* this way, try to deny uncoordinated access
*
* If it is not listed in /proc/ioports, register them
* (we need some syscall to do so bo 960609)...
* (we have a module to do so AV 970813)
* if it is registered, we need the name of a device to open
* if we can't open it, we disallow access to that port
* SIDOC_END_REMARK
*/
if ((fp = fopen("/proc/ioports", "r")) == NULL) {
i_printf("PORT: can't open /proc/ioports\n");
return FALSE;
}
mapped = beg = end = len = 0;
portname = line = NULL;
while ((bytes = getline(&line, &len, fp)) != -1) {
int i;
if (bytes > 0 && line[bytes-1] == '\n')
line[bytes-1] = '\0';
if (sscanf(line, "%x-%x : %n", &newbeg, &newend, &i) < 2)
break;
if (mapped) {
/* only break if no overlap with previous line */
if (newend > end) break;
free(portname);
mapped = 0;
}
beg = newbeg;
end = newend;
if ((start <= end) && ((start+size) > beg)) {
/* ports are besetzt, try to open the according device */
portname = strdup(&line[i]);
mapped = 1;
}
}
fclose (fp);
if (mapped) {
const char *name = portname ? portname : "";
i_printf("PORT: range 0x%04x-0x%04x already registered as %s\n",
beg, end, name);
if (!strncasecmp(name,"dosemu",6)) return FALSE;
if (device==NULL || *device==0) {
i_printf ("PORT: no device specified for %s\n", name);
return FALSE;
}
free (portname);
}
io_device.fd = -1;
if (device && *device) {
/* SIDOC_BEGIN_REMARK
* We need to check if our required port range is in use
* by some device. So we look into proc/ioports to check
* the addresses. Fine, but at this point we must supply
* a device name ourselves, and we can't check from here
* if it's the right one. The device is then open and left
* open until dosemu ends; for the rest, in the original
* code the device wasn't used, just locked, and only then
* port access was granted.
* SIDOC_END_REMARK
*/
int devperm;
devrname=strrchr(device,'/');
if (devrname==NULL) devrname=device; else devrname++;
sprintf(lock_file, "%s/%s%s", PATH_LOCKD, NAME_LOCKF, devrname);
switch (permission) {
case IO_READ: devperm = O_RDONLY;
flags |= PORT_DEV_RD;
break;
case IO_WRITE: devperm = O_WRONLY;
flags |= PORT_DEV_WR;
break;
default: devperm = O_RDWR;
flags |= (PORT_DEV_RD|PORT_DEV_WR);
}
io_device.fd = open(device, devperm);
if (io_device.fd == -1) {
switch (errno) {
case EBUSY:
i_printf("PORT: Device %s busy\n", device);
return FALSE;
case EACCES:
i_printf("PORT: Device %s, access not allowed\n", device);
return FALSE;
case ENOENT:
case ENXIO:
i_printf("PORT: No such Device '%s'\n", device);
return FALSE;
default:
i_printf("PORT: Device %s error %d\n", device, errno);
return FALSE;
}
}
fd = open(lock_file, O_RDONLY);
if (fd >= 0) {
close(fd);
i_printf("PORT: Device %s is locked\n", device);
return FALSE;
}
i_printf("PORT: Device %s opened successfully = %d\n", device,
io_device.fd);
}
if (permission == IO_RDWR)
io_device.handler_name = "std port io";
else if (permission == IO_READ)
@@ -1182,6 +1274,7 @@ Boolean port_allow_io(ioport_t start, Bit16u size, int permission, Bit8u ormask,
io_device.start_addr = start;
io_device.end_addr = start + size - 1;
io_device.irq = EMU_NO_IRQ;
if (usemasks) {
port_andmask[start] = andmask;
@@ -1206,7 +1299,7 @@ Boolean port_allow_io(ioport_t start, Bit16u size, int permission, Bit8u ormask,
int
set_ioperm(int start, int size, int flag)
{
#ifdef HAVE_SYS_IO_H
#ifdef __linux__
PRIV_SAVE_AREA
int tmp;

View File

@@ -4,7 +4,7 @@
#include <unistd.h>
#include <fcntl.h>
#include <grp.h>
#ifdef HAVE_SYS_IO_H
#ifdef __linux__
#include <sys/io.h>
#endif
#include "emu.h"
@@ -58,7 +58,7 @@ static int pop_priv(saved_priv_status *privs)
leavedos(99);
}
#ifdef PRIV_TESTING
c_printf("PRIV: popping %d privs_ptr=%p\n", *privs, privs);
c_printf("PRIV: poping %d privs_ptr=%p\n", *privs, privs);
#endif
ret = (int)*privs;
*privs = PRIV_MAGIC;
@@ -138,7 +138,7 @@ int real_leave_priv_setting(saved_priv_status *privs)
int priv_iopl(int pl)
{
#ifdef HAVE_SYS_IO_H
#ifdef __linux__
int ret;
if (PRIVS_ARE_OFF) {
_priv_on();
@@ -201,16 +201,28 @@ int priv_drop(void)
return 1;
}
#define MAXGROUPS 20
static gid_t *groups;
static int num_groups = 0;
int is_in_groups(gid_t gid)
{
int i;
for (i=0; i<num_groups; i++) {
if (gid == groups[i]) return 1;
}
return 0;
}
void priv_init(void)
{
const char *sh = getenv("SUDO_HOME"); // theoretical future var
const char *h = getenv("HOME");
uid = cur_uid = getuid();
/* suid bit only sets euid & suid but not uid, sudo sets all 3 */
if (!uid) under_root_login = 1;
if (!uid) under_root_login =1;
euid = cur_euid = geteuid();
if (!euid) can_do_root_stuff = 1;
if (!uid && !euid) skip_priv_setting = 1;
if (!uid) skip_priv_setting = 1;
gid = cur_gid = getgid();
egid = cur_egid = getegid();
@@ -219,10 +231,7 @@ void priv_init(void)
dosemu_proc_self_exe = readlink_malloc("/proc/self/exe");
/* For Fedora we must also save a file descriptor to /proc/self/maps */
dosemu_proc_self_maps_fd = open("/proc/self/maps", O_RDONLY | O_CLOEXEC);
if (!sh)
sh = getenv("DOSEMU_SUDO_HOME");
/* see if -E was used */
if (under_root_login && sh && h && strcmp(sh, h) == 0)
if (under_root_login)
{
/* check for sudo and set to original user */
char *s = getenv("SUDO_GID");
@@ -236,6 +245,12 @@ void priv_init(void)
if (s) {
uid = cur_uid = atoi(s);
if (uid) {
pid_t ppid;
char *path;
FILE *fp;
size_t n;
char *line;
skip_priv_setting = under_root_login = 0;
using_sudo = 1;
s = getenv("SUDO_USER");
@@ -244,6 +259,22 @@ void priv_init(void)
setenv("USER", s, 1);
}
setreuid(uid, euid);
/* retrieve $HOME from sudo's (the parent process') environment */
ppid = getppid();
if (asprintf(&path, "/proc/%d/environ", ppid) != -1) {
if ((fp = fopen(path, "r"))) {
line = NULL;
while(getdelim(&line, &n, '\0', fp) != -1) {
if(n>5 && memcmp(line, "HOME=", 5) == 0) {
setenv("HOME", line+5, 1);
}
}
free(line);
fclose(fp);
}
free(path);
}
}
}
}
@@ -253,5 +284,28 @@ void priv_init(void)
skip_priv_setting = 1;
}
if ((num_groups = getgroups(0, NULL)) <= 0) {
error("priv_init(): getgroups() size returned %d!\n", num_groups);
goto error_exit;
}
if ((groups = malloc(num_groups * sizeof(gid_t))) == NULL) {
error("priv_init(): malloc() failed!\n");
goto error_exit;
}
if (getgroups(num_groups, groups) == -1) {
error("priv_init(): getgroups() failed '%s'!\n", strerror(errno));
free(groups);
goto error_exit;
}
goto done;
error_exit:
num_groups = 0;
groups = NULL;
done:
if (!skip_priv_setting) _priv_off();
}

View File

@@ -1,181 +0,0 @@
/*
* This program 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 program 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
* Purpose: virtual interrupt router (another one)
*
* Author: Stas Sergeev.
*
*/
#include <stdint.h>
#include <assert.h>
#include "cpu.h"
#include "int.h"
#include "hlt.h"
#include "memory.h"
#include "port.h"
#include "chipset.h"
#include "emu.h"
#include "vint.h"
#define VINT_MAX 2
static int vi_used;
static uint16_t vint_hlt;
#define ON_PIC1(n) (vih[n].orig_irq >= 8)
struct vihandler {
void (*handler)(int, int);
void (*mask)(int, int);
uint8_t irq;
uint8_t orig_irq;
uint8_t interrupt;
int tweaked;
unsigned tw_flags;
};
struct vihandler vih[VINT_MAX];
static void poll_pic0(uint8_t irq)
{
port_outb(0x20, 0x0c); // OCW3, enter poll mode
port_outb(0x20, irq); // extension, may not work on real PIC
/* see if it worked */
assert(pic_get_isr() & (1 << irq));
}
static void poll_pic1(uint8_t irq)
{
port_outb(0x20, 0x0c); // OCW3, enter poll mode
port_outb(0x20, 2); // extension, may not work on real PIC
port_outb(0xa0, 0x0c);
port_outb(0xa0, irq - 8);
/* see if it worked */
assert((pic_get_isr() & ((1 << irq) | 4)) == ((1 << irq) | 4));
}
static void full_eoi(void)
{
port_outb(0xa0, 0x20);
port_outb(0x20, 0x20);
}
static void do_ret(int vi_num)
{
clear_IF();
vih[vi_num].mask(vi_num, 0);
do_iret();
}
int vint_is_masked(int vi_num, uint8_t *imr)
{
uint16_t real_imr = (imr[1] << 8) | imr[0];
return !!(real_imr & (1 << vih[vi_num].orig_irq));
}
static void vint_handler(uint16_t idx, HLT_ARG(arg))
{
uint8_t imr[2];
int masked;
int vi_num = idx >> 1;
if (idx & 1) {
do_ret(vi_num);
return;
}
imr[0] = port_inb(0x21);
imr[1] = port_inb(0xa1);
masked = vint_is_masked(vi_num, imr);
if (masked) {
h_printf("vint: masked, iret\n");
do_eoi2_iret();
} else {
uint8_t irq = vih[vi_num].orig_irq;
uint16_t port = (irq >= 8 ? PIC1_VECBASE_PORT : PIC0_VECBASE_PORT);
uint8_t inum = port_inb(port) + (irq & 7);
full_eoi();
if (ON_PIC1(vi_num))
poll_pic1(irq);
else
poll_pic0(irq);
if (vih[vi_num].tweaked) {
_IP++; // skip hlt
h_printf("vint: call to inum %x\n", inum);
real_run_int(inum);
vih[vi_num].mask(vi_num, 1);
} else {
h_printf("vint: jump to inum %x\n", inum);
jmp_to(ISEG(inum), IOFF(inum));
}
}
if (vih[vi_num].handler)
vih[vi_num].handler(vi_num, masked);
}
void vint_post_irq_dpmi(int vi_num, int masked)
{
full_eoi();
if (!masked) {
uint8_t irq = vih[vi_num].orig_irq;
if (ON_PIC1(vi_num))
poll_pic1(irq);
else
poll_pic0(irq);
}
}
void vint_init(void)
{
emu_hlt_t hlt_hdlr = HLT_INITIALIZER;
hlt_hdlr.name = "vint";
hlt_hdlr.func = vint_handler;
hlt_hdlr.len = VINT_MAX * 2;
vint_hlt = hlt_register_handler_vm86(hlt_hdlr);
}
void vint_setup(void)
{
int i;
for (i = 0; i < VINT_MAX; i++) {
if (vih[i].interrupt)
SETIVEC(vih[i].interrupt, BIOS_HLT_BLK_SEG, vint_hlt + 2 * i);
}
}
int vint_register(void (*ack_handler)(int, int),
void (*mask_handler)(int, int),
int irq, int orig_irq, int inum)
{
struct vihandler *vi = &vih[vi_used];
assert(vi_used < VINT_MAX);
vi->handler = ack_handler;
vi->mask = mask_handler;
vi->irq = irq;
vi->orig_irq = orig_irq;
vi->interrupt = inum;
return vi_used++;
}
void vint_set_tweaked(int vi_num, int on, unsigned flags)
{
struct vihandler *vi = &vih[vi_num];
assert(vi_num < VINT_MAX);
vi->tweaked = on;
vi->tw_flags = flags;
}

View File

@@ -32,7 +32,6 @@
#include "utilities.h"
#include "port.h"
#include "timers.h"
#include "cpu-emu.h"
#include "dma.h"
#include "dmaregs.h"
#include <string.h>
@@ -127,8 +126,8 @@ static void dma_update_DRQ(int dma_idx, int chan_idx)
static void dma_process_channel(int dma_idx, int chan_idx)
{
struct dma_channel *chan = &dma[dma_idx].chans[chan_idx];
unsigned pa = (chan->page << 16) | (chan->cur_addr.value << dma_idx);
void *addr = physaddr_to_unixaddr(pa);
void *addr = physaddr_to_unixaddr(
(chan->page << 16) | (chan->cur_addr.value << dma_idx));
/* first, do the transfer */
switch (DMA_TRANSFER_OP(chan->mode)) {
@@ -136,22 +135,10 @@ static void dma_process_channel(int dma_idx, int chan_idx)
q_printf("DMA: verify mode does nothing\n");
break;
case WRITE:
if (addr != MAP_FAILED) {
e_invalidate_pa(pa, 1 << dma_idx);
memcpy(addr, dma_data_bus, 1 << dma_idx);
} else {
error_once0("DMA: write to unmapped address\n");
q_printf("DMA: write to unmapped address %#x\n", pa);
}
memcpy(addr, dma_data_bus, 1 << dma_idx);
break;
case READ:
if (addr != MAP_FAILED)
memcpy(dma_data_bus, addr, 1 << dma_idx);
else {
error_once0("DMA: read from unmapped address\n");
q_printf("DMA: read from unmapped address %#x\n", pa);
memset(dma_data_bus, 0xff, sizeof(dma_data_bus));
}
memcpy(dma_data_bus, addr, 1 << dma_idx);
break;
case INVALID:
q_printf("DMA: invalid mode does nothing\n");
@@ -257,7 +244,7 @@ int dma_pulse_DRQ(int ch, Bit8u * buf)
HANDLE_##n(2, 2); \
HANDLE_##n(2, 3); \
HANDLE_##n(2, 4)
static Bit8u dma_io_read(ioport_t port, void *arg)
static Bit8u dma_io_read(ioport_t port)
{
Bit8u r = 0xff;
switch (port) {
@@ -319,7 +306,7 @@ static Bit8u dma_io_read(ioport_t port, void *arg)
return r;
}
static void dma_io_write(ioport_t port, Bit8u value, void *arg)
static void dma_io_write(ioport_t port, Bit8u value)
{
switch (port) {
@@ -475,6 +462,8 @@ void dma_init(void)
io_device.write_portw = NULL;
io_device.read_portd = NULL;
io_device.write_portd = NULL;
io_device.irq = EMU_NO_IRQ;
io_device.fd = -1;
/*
* XT Controller

View File

@@ -1,17 +1,7 @@
/*
* This program 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.
* (C) Copyright 1992, ..., 2014 the "DOSEMU-Development-Team".
*
* This program 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* for details see file COPYING in the DOSEMU distribution
*/
#ifndef __DMAREGS_H__

View File

@@ -76,7 +76,7 @@ void output_byte_8042(Bit8u value)
port60_ready=1;
if (keyb_ctrl_command & 0x01) { /* if interrupt enabled */
k_printf("8042: scheduling IRQ1\n");
pic_request(1);
pic_request(PIC_IRQ1);
}
else
k_printf("8042: interrupt flag OFF!\n");
@@ -303,7 +303,7 @@ static Bit8u read_port60(void)
if (kbd_disabled && last_read_valid) {
r = last_read_data;
if (port60_ready && (keyb_ctrl_command & 0x01)) /* if interrupt enabled */
pic_request(1);
pic_request(PIC_IRQ1);
} else {
r = port60_buffer;
port60_ready = 0;
@@ -343,7 +343,7 @@ static Bit8u read_port60(void)
}
Bit8u keyb_io_read(ioport_t port, void *arg)
Bit8u keyb_io_read(ioport_t port)
{
Bit8u r = 0;
@@ -351,7 +351,7 @@ Bit8u keyb_io_read(ioport_t port, void *arg)
case 0x60:
r = read_port60();
if (!port60_ready)
pic_untrigger(1);
pic_untrigger(PIC_IRQ1);
k_printf("8042: read port 0x60 read=0x%02x\n",r);
break;
@@ -368,7 +368,7 @@ Bit8u keyb_io_read(ioport_t port, void *arg)
return r;
}
void keyb_io_write(ioport_t port, Bit8u value, void *arg)
void keyb_io_write(ioport_t port, Bit8u value)
{
switch (port) {
case 0x60:
@@ -407,11 +407,14 @@ void keyb_8042_init(void)
io_device.handler_name = "8042 Keyboard data";
io_device.start_addr = 0x0060;
io_device.end_addr = 0x0060;
io_device.irq = 1;
io_device.fd = -1;
port_register_handler(io_device, 0);
io_device.handler_name = "8042 Keyboard command";
io_device.start_addr = 0x0064;
io_device.end_addr = 0x0064;
io_device.irq = EMU_NO_IRQ;
port_register_handler(io_device, 0);
io_device.handler_name = "Keyboard controller port B";

View File

@@ -6,11 +6,7 @@ include $(top_builddir)/Makefile.conf
# src/base/misc/timers.c -> ../dev/misc/timers.c
CFILES = cmos.c timers.c lpt.c rtc.c pci.c chipset.c 8042.c kbd.c \
virq.c vtmr.c
ifeq ($(OS),Linux)
CFILES += joystick.c
endif
CFILES=cmos.c timers.c lpt.c rtc.c pci.c joystick.c chipset.c 8042.c kbd.c
include $(REALTOPDIR)/src/Makefile.common

View File

@@ -13,7 +13,7 @@
#define CONTROL_A20GATE_MASK 2
static Bit8u port92h_io_read(ioport_t port, void *arg)
static Bit8u port92h_io_read(ioport_t port)
{
Bit8u ret = 0;
if (a20)
@@ -21,50 +21,27 @@ static Bit8u port92h_io_read(ioport_t port, void *arg)
return ret;
}
static void port92h_io_write(ioport_t port, Bit8u val, void *arg)
static void port92h_io_write(ioport_t port, Bit8u val)
{
int enA20 = (val & CONTROL_A20GATE_MASK) ? 1 : 0;
if (val & CONTROL_RESET_MASK) cpu_reset();
set_a20(enA20);
}
static Bit8u picext_io_read(ioport_t port, void *arg)
{
Bit8u val = 0xff;
switch (port) {
case PIC0_VECBASE_PORT:
val = pic0_get_base();
break;
case PIC1_VECBASE_PORT:
val = pic1_get_base();
break;
}
return val;
}
void chipset_init(void)
{
emu_iodev_t io_dev = {};
emu_iodev_t io_dev;
io_dev.read_portb = port92h_io_read;
io_dev.write_portb = port92h_io_write;
io_dev.read_portw = NULL;
io_dev.write_portw = NULL;
io_dev.read_portd = NULL;
io_dev.write_portd = NULL;
io_dev.irq = EMU_NO_IRQ;
io_dev.fd = -1;
io_dev.start_addr = 0x92;
io_dev.end_addr = 0x92;
io_dev.handler_name = "Chipset Control Port A";
port_register_handler(io_dev, 0);
memset(&io_dev, 0, sizeof(io_dev));
io_dev.read_portb = picext_io_read;
io_dev.start_addr = PIC0_EXTPORT_START;
io_dev.end_addr = PIC0_EXTPORT_START + PICx_EXT_PORTS - 1;
io_dev.handler_name = "PIC0 extensions";
port_register_handler(io_dev, 0);
memset(&io_dev, 0, sizeof(io_dev));
io_dev.read_portb = picext_io_read;
io_dev.start_addr = PIC1_EXTPORT_START;
io_dev.end_addr = PIC1_EXTPORT_START + PICx_EXT_PORTS - 1;
io_dev.handler_name = "PIC1 extensions";
port_register_handler(io_dev, 0);
}

View File

@@ -19,7 +19,7 @@
#include "disks.h"
#define PEXTMEM_SIZE EXTMEM_SIZE
#define PEXTMEM_SIZE (EXTMEM_SIZE + HMASIZE)
struct CMOS cmos;
@@ -37,7 +37,7 @@ cmos_chksum(void)
return sum;
}
Bit8u cmos_read(ioport_t port, void *arg)
Bit8u cmos_read(ioport_t port)
{
unsigned char holder = 0;
@@ -67,7 +67,7 @@ Bit8u cmos_read(ioport_t port, void *arg)
return holder;
}
void cmos_write(ioport_t port, Bit8u byte, void *arg)
void cmos_write(ioport_t port, Bit8u byte)
{
if (port == 0x70)
cmos.address = byte & ~0xc0;/* get true address */
@@ -99,12 +99,14 @@ void cmos_init(void)
io_device.handler_name = "CMOS RAM";
io_device.start_addr = 0x0070;
io_device.end_addr = 0x0071;
io_device.irq = EMU_NO_IRQ;
io_device.fd = -1;
port_register_handler(io_device, 0);
for (i = 0; i < 64; i++)
cmos.subst[i] = cmos.flag[i] = 0;
rtc_setup();
rtc_init();
/* CMOS floppies...is this correct? */
SET_CMOS(CMOS_DISKTYPE,
@@ -145,8 +147,8 @@ void cmos_init(void)
SET_CMOS(CMOS_BASEMEML, config.mem_size & 0xff); /* base mem LSB */
SET_CMOS(CMOS_BASEMEMM, config.mem_size >> 8); /* base mem MSB */
SET_CMOS(CMOS_EXTMEML, EXTMEM_SIZE & 0xff);
SET_CMOS(CMOS_EXTMEMM, EXTMEM_SIZE >> 8);
SET_CMOS(CMOS_EXTMEML, (EXTMEM_SIZE + HMASIZE) & 0xff);
SET_CMOS(CMOS_EXTMEMM, (EXTMEM_SIZE + HMASIZE) >> 8);
SET_CMOS(CMOS_PEXTMEML, PEXTMEM_SIZE & 0xff);
SET_CMOS(CMOS_PEXTMEMM, PEXTMEM_SIZE >> 8);

View File

@@ -68,6 +68,7 @@
* Includes
*/
#ifdef __linux__
#include "joystick.h"
#include <stdio.h>
@@ -151,8 +152,8 @@ static void joy_emu_axis_set (const int joynum, const int axis, const int value)
static int joy_emu_axis_conv (const int linux_val, const int invalid_val);
/* port emulation */
Bit8u joy_port_inb (ioport_t port, void *arg);
void joy_port_outb (ioport_t port, Bit8u value, void *arg);
Bit8u joy_port_inb (ioport_t port);
void joy_port_outb (ioport_t port, Bit8u value);
/*
@@ -537,9 +538,6 @@ void joy_init (void)
else /* successfully switched device to NONBLOCKing mode... */
joy_driver_set (&joy_driver_new);
}
#if defined(HAVE_PTHREAD_SETNAME_NP) && defined(__GLIBC__)
pthread_setname_np(thread [joynum], "dosemu: joy");
#endif
}
#endif /* USE_PTHREADS */
}
@@ -575,6 +573,8 @@ void joy_init (void)
io_device.handler_name = "Joystick Port Emulation";
io_device.start_addr = 0x200;
io_device.end_addr = 0x20F;
io_device.irq = EMU_NO_IRQ;
io_device.fd = -1;
if (port_register_handler (io_device, 0) != 0)
{
@@ -597,10 +597,8 @@ void joy_uninit (void)
for (joynum = 0; joynum < 2; joynum++)
{
#ifdef USE_PTHREADS
if (joy_driver == &joy_driver_new_threaded && thread [joynum]) {
if (joy_driver == &joy_driver_new_threaded)
pthread_cancel (thread [joynum]);
pthread_join (thread [joynum], NULL);
}
#endif
if (joy_fd [joynum] >= 0)
@@ -1178,7 +1176,7 @@ static int joy_linux_read_axis_new_threaded (const int joynum, const int axis,
* whether or not you have a joystick?
*
* I have never seen a real BIOS set the Carry Flag on this call, even
* on a computer without a joystick -- so to mimic what happens in the
* on a computer without a joystick -- so to mimick what happens in the
* real world, I just clear the Carry Flag regardless of whether the user
* has a joystick or not. This could be incorrect behaviour so it may
* have to be changed in the future.
@@ -1205,7 +1203,7 @@ static int joy_linux_read_axis_new_threaded (const int joynum, const int axis,
*
* Because of this, it returns the joystick axis values with the same
* range as port 0x201 BUT the range for a real BIOS varies between
* computers as it is dependent on how it reads from the port
* computers as it is dependant on how it reads from the port
* (hopefully this won't cause any problems).
*
* DANG_END_FUNCTION
@@ -1286,7 +1284,7 @@ int joy_bios_read (void)
*
* DANG_END_FUNCTION
*/
Bit8u joy_port_inb (ioport_t port, void *arg)
Bit8u joy_port_inb (ioport_t port)
{
Bit8u ret = 0;
int joynum;
@@ -1352,7 +1350,7 @@ Bit8u joy_port_inb (ioport_t port, void *arg)
return ret;
}
void joy_port_outb (ioport_t port, Bit8u value, void *arg)
void joy_port_outb (ioport_t port, Bit8u value)
{
#ifdef JOY_PORT_DEBUG
joy_port_printf ("port 0x%X: outb()\n", port);
@@ -1399,3 +1397,4 @@ void joy_port_outb (ioport_t port, Bit8u value, void *arg)
}
/* end of joystick.c */
#endif

View File

@@ -64,7 +64,7 @@
* one keypress or release event. [The exception are the braindead
* 0xe02a / 0xe0aa shift key emulation codes the keyboard processor
* 'decorates' some kinds of keyboard events, which for convenience
* are treated as separate events.]
* are treated as seperate events.]
* Each queue entry holds a up to 4 bytes of raw keycodes for the
* port 60h emulation, along with a 2-byte translated int16h keycode
* and the shift state after this event was processed.
@@ -98,7 +98,7 @@ static inline Boolean queue_full(struct keyboard_queue *q)
}
/*
* this has to work even if the variables are uninitialized!
* this has to work even if the variables are uninitailized!
*/
void clear_queue(struct keyboard_queue *q)
{
@@ -223,7 +223,7 @@ void int_check_queue(void)
#if KBD_PIC_HACK
/* HACK - extra sentinel needed, timing is not
* a reliable measure under heavy loads */
if (pic_irq_active(1))
if (pic_irq_active(PIC_IRQ1))
return;
#endif

View File

@@ -20,7 +20,6 @@
#include "lpt.h"
#include "utilities.h"
#include "dos2linux.h"
#include "ioselect.h"
/* status bits, Centronics */
#define CTS_STAT_NOIOERR LPT_STAT_NOIOERR
@@ -69,7 +68,7 @@ static int get_printer(ioport_t port)
return -1;
}
static Bit8u printer_io_read(ioport_t port, void *arg)
static Bit8u printer_io_read(ioport_t port)
{
int i = get_printer(port);
Bit8u val;
@@ -104,7 +103,7 @@ static Bit8u printer_io_read(ioport_t port, void *arg)
return val;
}
static void printer_io_write(ioport_t port, Bit8u value, void *arg)
static void printer_io_write(ioport_t port, Bit8u value)
{
int i = get_printer(port);
if (i == -1)
@@ -138,7 +137,9 @@ static void printer_io_write(ioport_t port, Bit8u value, void *arg)
static int dev_printer_open(int prnum)
{
int um = umask(026);
lpt[prnum].dev_fd = open(lpt[prnum].dev, O_WRONLY);
umask(um);
if (lpt[prnum].dev_fd == -1) {
error("LPT%i: error opening %s: %s\n", prnum+1, lpt[prnum].dev,
strerror(errno));
@@ -148,7 +149,7 @@ static int dev_printer_open(int prnum)
return 0;
}
static void pipe_callback(int fd, void *arg)
static void pipe_callback(void *arg)
{
char buf[1024];
int num = (long)arg;
@@ -157,7 +158,6 @@ static void pipe_callback(int fd, void *arg)
buf[n] = 0;
error("LPT%i: %s\n", num+1, buf);
}
ioselect_complete(fd);
}
static int pipe_printer_open(int prnum)
@@ -270,6 +270,8 @@ printer_init(void)
io_device.read_portd = NULL;
io_device.write_portd = NULL;
io_device.handler_name = "Parallel printer";
io_device.irq = EMU_NO_IRQ;
io_device.fd = -1;
for (i = 0; i < NUM_PRINTERS; i++) {
lpt[i].initialized = 0;

View File

@@ -366,8 +366,8 @@ struct pci_funcs *pci_check_conf(void)
port_real_outb(PCI_MODE2_ENABLE_REG, 0x00);
port_real_outb(PCI_MODE2_FORWARD_REG, 0x00);
m = (port_inb(PCI_MODE2_ENABLE_REG) == 0x00 &&
port_inb(PCI_MODE2_FORWARD_REG) == 0x00) ? &pci_cfg2 : NULL;
m = (inb(PCI_MODE2_ENABLE_REG) == 0x00 &&
inb(PCI_MODE2_FORWARD_REG) == 0x00) ? &pci_cfg2 : NULL;
}
priv_iopl(0);
@@ -376,14 +376,14 @@ struct pci_funcs *pci_check_conf(void)
return NULL;
}
static Bit8u pci_port_inb(ioport_t port, void *arg)
static Bit8u pci_port_inb(ioport_t port)
{
if (port != 0xcf9)
return std_port_inb(port);
return 0;
}
static void pci_port_outb(ioport_t port, Bit8u byte, void *arg)
static void pci_port_outb(ioport_t port, Bit8u byte)
{
/* don't allow DOSEMU to reset the CPU */
if (port != 0xcf9)
@@ -398,13 +398,19 @@ static void pci_port_outb(ioport_t port, Bit8u byte, void *arg)
*/
int pci_setup (void)
{
emu_iodev_t io_device = {};
emu_iodev_t io_device;
if (config.pci) {
pcibios_init();
/* register PCI ports */
io_device.read_portb = pci_port_inb;
io_device.write_portb = pci_port_outb;
io_device.read_portw = std_port_inw;
io_device.write_portw = std_port_outw;
io_device.read_portd = std_port_ind;
io_device.write_portd = std_port_outd;
io_device.irq = EMU_NO_IRQ;
io_device.fd = -1;
if (pciConfigType->name[0] == '1') {
io_device.handler_name = "PCI Config Type 1";
@@ -522,7 +528,7 @@ static void pciemu_port_write(ioport_t port, unsigned long val, int len)
Z_printf("PCIEMU: writing 0x%lx to %#x, len=%d\n",val,num,len);
}
static Bit8u pciemu_port_inb(ioport_t port, void *arg)
static Bit8u pciemu_port_inb(ioport_t port)
{
/* 0xcf8 -- 0xcfb as bytes or words don't access sub-parts;
for instance writing to 0xcf9 as a byte may reset the CPU */
@@ -533,26 +539,26 @@ static Bit8u pciemu_port_inb(ioport_t port, void *arg)
return 0xff;
}
static void pciemu_port_outb(ioport_t port, Bit8u byte, void *arg)
static void pciemu_port_outb(ioport_t port, Bit8u byte)
{
if (port >= PCI_CONF_DATA)
pciemu_port_write(port, byte, 1);
}
static Bit16u pciemu_port_inw(ioport_t port, void *arg)
static Bit16u pciemu_port_inw(ioport_t port)
{
if (port == PCI_CONF_DATA || port == PCI_CONF_DATA + 2)
return pciemu_port_read(port, 2);
return 0xffff;
}
static void pciemu_port_outw(ioport_t port, Bit16u value, void *arg)
static void pciemu_port_outw(ioport_t port, Bit16u value)
{
if (port == PCI_CONF_DATA || port == PCI_CONF_DATA + 2)
pciemu_port_write(port, value, 2);
}
static Bit32u pciemu_port_ind(ioport_t port, void *arg)
static Bit32u pciemu_port_ind(ioport_t port)
{
if (port == PCI_CONF_DATA)
return pciemu_port_read(port, 4);
@@ -561,7 +567,7 @@ static Bit32u pciemu_port_ind(ioport_t port, void *arg)
return 0xffffffff;
}
static void pciemu_port_outd(ioport_t port, Bit32u value, void *arg)
static void pciemu_port_outd(ioport_t port, Bit32u value)
{
if (port == PCI_CONF_ADDR)
current_pci_reg = value & 0x80fffffc;
@@ -579,8 +585,7 @@ pciRec *pciemu_setup(unsigned long cls)
Z_printf("PCI: initializing, class=%lx\n", cls);
pcibios_init();
}
// pci = pcibios_find_class(cls, 0);
pci = pcibios_find_primary_vga(); // XXX
pci = pcibios_find_class(cls, 0);
if (pci == NULL) {
Z_printf("PCI: class %lx not found\n", cls);
return pci;
@@ -596,6 +601,8 @@ pciRec *pciemu_setup(unsigned long cls)
io_device.write_portw = pciemu_port_outw;
io_device.read_portd = pciemu_port_ind;
io_device.write_portd = pciemu_port_outd;
io_device.irq = EMU_NO_IRQ;
io_device.fd = -1;
io_device.handler_name = "PCI Emulated Config";
io_device.start_addr = PCI_CONF_ADDR;

View File

@@ -17,7 +17,6 @@
#include "disks.h"
#include "timers.h"
#include "int.h"
#include "vtmr.h"
#include "iodev.h"
long sys_base_ticks = 0;
@@ -25,6 +24,7 @@ long usr_delta_ticks = 0;
unsigned long last_ticks = 0;
static unsigned long long q_ticks_m = 0;
static int rtc_get_rate(Bit8u div)
{
if (!div)
@@ -60,11 +60,7 @@ void rtc_run(void)
if (debug_level('h') > 7)
h_printf("RTC: periodic IRQ, queued=%lli, added=%lli\n",
(long long)q_ticks_m, (long long)ticks_m);
/* we only use vtmr in tweaked mode */
if (config.timer_tweaks)
vtmr_raise(VTMR_RTC);
else
pic_request(8);
pic_request(PIC_IRQ8);
}
if (!(old_c & 0x40))
q_ticks_m -= 1000000;
@@ -105,14 +101,11 @@ Bit8u rtc_read(Bit8u reg)
if (debug_level('h') > 8)
h_printf("RTC: Read C=%hhx\n", ret);
SET_CMOS(CMOS_STATUSC, 0);
pic_untrigger(8);
pic_untrigger(PIC_IRQ8);
rtc_run();
break;
}
/* below slows down streetfighter2 game so commented out */
// vtmr_sync(VTMR_RTC);
return ret;
}
@@ -181,7 +174,7 @@ static void rtc_alarm_check (void)
if ((GET_CMOS(CMOS_STATUSB) & 0x20) && !(GET_CMOS(CMOS_STATUSC) & 0x80)) {
SET_CMOS(CMOS_STATUSC, GET_CMOS(CMOS_STATUSC) | 0x80);
h_printf("RTC: alarm IRQ\n");
pic_request(8);
pic_request(PIC_IRQ8);
}
}
}
@@ -259,7 +252,7 @@ void rtc_update (void) /* called every 1s from SIGALRM */
if ((GET_CMOS(CMOS_STATUSB) & 0x10) && !(GET_CMOS(CMOS_STATUSC) & 0x80)) {
SET_CMOS(CMOS_STATUSC, GET_CMOS(CMOS_STATUSC) | 0x80);
h_printf("RTC: update IRQ\n");
pic_request(8);
pic_request(PIC_IRQ8);
}
SET_CMOS(CMOS_STATUSA, GET_CMOS(CMOS_STATUSA)&~0x80);
@@ -269,30 +262,16 @@ void rtc_update (void) /* called every 1s from SIGALRM */
* Initialise the RTC. Key work is now in get_linux_ticks() where we initialise
* all of the RTC time/date fields, and only zero the alarm stuff here.
*/
void rtc_setup(void)
void rtc_init (void)
{
usr_delta_ticks = 0;
last_ticks = sys_base_ticks = get_linux_ticks(1, NULL);
SET_CMOS(CMOS_HOURALRM, 0);
SET_CMOS(CMOS_MINALRM, 0);
SET_CMOS(CMOS_SECALRM, 0);
}
static int rtc_vint(int masked)
{
if (masked)
pic_request(8);
return 0;
}
void rtc_init(void)
{
usr_delta_ticks = 0;
last_ticks = sys_base_ticks = get_linux_ticks(1, NULL);
vtmr_register(VTMR_RTC, rtc_vint);
/* NOTE: vtmr is only used in tweaked mode, so we set it to 1 beforehands,
* but may not actually use */
vtmr_set_tweaked(VTMR_RTC, 1, 0);
}
/* ========================================================================= */
@@ -352,8 +331,8 @@ void rtc_init(void)
* to be used for both the INT-1A AH=0 function (get ticks) and the AH=2 or 4 (get RTC time/date)
* without confusing the once per day roll-over count.
*
* In addition, should the LINUX time go backwards over midnight (very unfortunate occurrence, but
* it is just possible if ntpdate was used to get things correct at once, rather then the ntm daemon
* In addition, should the LINUX time go backwards over midnight (very unfortunate occurance, but
* it is just possible if ntpdate was used to get things correct at once, rather then the ntm deamon
* running to slew time to correctness slowly) it will hold the DOS notion of time at 00:00:00
* until the LINUX time crosses the midnight boundary again, but without producing two day counts.
*
@@ -364,11 +343,11 @@ void rtc_init(void)
* day_rollover : Non-NULL pointer if checking for the day crossing for INT-1A AH=0 use.
*
* The return value is the DOS 'ticks' from 00:00:00 for this day.
* An error results in -1 return (e.g. from problems converting time, perhaps bad TZ environment).
* An error results in -1 retun (e.g. from problems converting time, perhaps bad TZ environment).
*
* NOTE: A check in the freedos source shows a *slightly* different value for the nominal tick count
* spanning one day, compared to the PIT_TICK_RATE value in timers.h (which is correct, I think). So
* if you compile with the freedos values for 100% time conversion compatibility with it, that is fine
* if you compile with the freedos values for 100% time conversion compatability with it, that is fine
* but if you compile with the 'correct' PIT_TICK_RATE value, it limits it near midnight so freedos
* never gets a value corresponding equal to, or more than, 24 hours.
*
@@ -402,7 +381,7 @@ unsigned long get_linux_ticks(int set_cmos, int *day_rollover)
/* Compute time of day in 1/100 second units, then to DOS ticks. */
tt = isec * 100 + (tv.tv_usec / 10000);
#ifdef USE_PIT_TICK_RATE
#if USE_PIT_TICK_RATE
tt = (tt * PIT_TICK_RATE) / 6553600; /* Correct as per LINUX code, 44-bit intermediate product.*/
if(tt > FREEDOS_TICKS_IN_A_DAY) tt = FREEDOS_TICKS_IN_A_DAY;
#else

View File

@@ -9,7 +9,7 @@
* REMARK
* This is the timer emulation for DOSEMU. It emulates the Programmable
* Interval Timer (PIT), and also handles IRQ0 interrupt events.
* A lot of animation and video game software are dependent on this module
* A lot of animation and video game software are dependant on this module
* for high frequency timer interrupts (IRQ0).
*
* This code will actually generate 18.2 DOS interrupts/second (the code
@@ -33,58 +33,73 @@
#include "emu.h"
#include "port.h"
#include "timers.h"
#include "iodev.h"
#include "int.h"
#include "pic.h"
#include "emudpmi.h"
#include "vtmr.h"
#include "evtimer.h"
#include "timers.h"
#undef DEBUG_PIT
#undef ONE_MINUTE_TEST
/*******************************************************************
* Programmable Interrupt Timer (PIT) chip *
*******************************************************************/
pit_latch_struct pit[PIT_TIMERS]; /* values of 3 PIT counters */
typedef struct {
Bit16u read_state;
Bit16u write_state;
Bit8u mode, outpin;
Bit32u read_latch;
Bit16u write_latch;
Bit32s cntr;
hitimer_u time;
uint32_t q_ticks;
void *evtmr;
int tmr_skip;
} pit_latch_struct;
static pit_latch_struct pit[PIT_TIMERS]; /* values of 3 PIT counters */
hitimer_t pic_sys_time; /* system time set by pic_watch */
static int irq0_cnt;
#define NEVER -1
static hitimer_t pic_itime[33] = /* time to trigger next interrupt */
{NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER,
NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER,
NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER,
NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER,
NEVER};
static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
{
return /*(__int128_t)*/a * b / c;
}
#define TICKS_TO_NS(t) muldiv64(t, NANOSECONDS_PER_SECOND, PIT_TICK_RATE)
#define NS_TO_TICKS(n) muldiv64(n, PIT_TICK_RATE, NANOSECONDS_PER_SECOND)
static u_long timer_div; /* used by timer int code */
static u_long ticks_accum; /* For timer_tick function, 100usec ticks */
static Bit8u port61 = 0x0c;
int is_cli;
/*
* DANG_BEGIN_FUNCTION initialize_timers
*
* description:
* ensure the 0x40 port timer is initially set correctly
*
* DANG_END_FUNCTION
*/
void initialize_timers(void)
{
hitimer_t cur_time;
cur_time = GETtickTIME(0);
pit[0].mode = 3;
pit[0].outpin = 0;
pit[0].cntr = 0x10000;
pit[0].time.td = cur_time;
pit[0].read_latch = -1;
pit[0].write_latch = 0;
pit[0].read_state = 3;
pit[0].write_state = 3;
pit[1].mode = 2;
pit[1].outpin = 0;
pit[1].cntr = 18;
pit[1].time.td = cur_time;
pit[1].read_latch = -1;
pit[1].write_latch = 18;
pit[1].read_state = 3;
pit[1].write_state = 3;
pit[2].mode = 0;
pit[2].outpin = 0;
pit[2].cntr = -1;
pit[2].time.td = cur_time;
pit[2].read_latch = -1;
pit[2].write_latch = 0;
pit[2].read_state = 3;
pit[2].write_state = 3;
ticks_accum = 0;
timer_div = (pit[0].cntr * 10000) / PIT_TICK_RATE;
timer_tick(); /* a starting tick! */
port61 = 0x0c;
}
/*
* DANG_BEGIN_FUNCTION timer_tick
*
@@ -97,7 +112,30 @@ int is_cli;
*/
void timer_tick(void)
{
pic_sys_time = GETtickTIME(0);
#ifdef ONE_MINUTE_TEST
static int dbug_count = 0;
#endif
hitimer_u tp;
u_long time_curr;
static u_long time_old = 0; /* Preserve value for next call */
/* Get system time in ticks */
tp.td = GETtickTIME(0);
#ifdef ONE_MINUTE_TEST
if (++dbug_count > 6000) leavedos(0);
#endif
/* compute the number of 100ticks since we started */
time_curr = (tp.td - pit[0].time.td) / 100;
/* Reset old timer value to 0 if time_curr wrapped around back to 0 */
if (time_curr < time_old) time_old = 0;
/* Compute number of 100ticks ticks since the last time this function ran */
ticks_accum += (time_curr - time_old);
/* Save old value of the timer */
time_old = time_curr;
if (config.cli_timeout && is_cli) {
if (isset_IF()) {
@@ -109,6 +147,9 @@ void timer_tick(void)
}
}
dpmi_timer();
/* test for stuck interrupts, trigger any scheduled interrupts */
pic_watch(&tp);
}
@@ -148,7 +189,7 @@ void do_sound(Bit16u period)
*
* But if you set it too low, then sounds can be cut off - clarence
*/
static const unsigned sound_duration = 30000; /* in milliseconds */
static const unsigned sound_duration = 30000; /* in miliseconds */
switch (port61 & 3) {
case 3: /* speaker on & speaker control through timer channel 2 */
if ((pit[2].mode == 2) || (pit[2].mode == 3)) { /* is this test needed? */
@@ -168,11 +209,11 @@ void do_sound(Bit16u period)
}
}
static int _pit_latch(int latch, uint64_t cur)
static void pit_latch(int latch)
{
int ret = 0;
hitimer_u cur_time;
long ticks=0;
u_long ticks=0;
pit_latch_struct *p = &pit[latch];
/* check for special 'read latch status' mode */
@@ -191,10 +232,10 @@ static int _pit_latch(int latch, uint64_t cur)
if (p->cntr == -1)
p->read_latch |= 0x40;
p->mode &= ~0x80;
return ret; /* let bit 7 on */
return; /* let bit 7 on */
}
cur_time.td = cur;
cur_time.td = GETtickTIME(0);
if ((p->mode & 2)==0) {
/* non-periodical modes 0,1,4,5 - used mainly by games
@@ -210,7 +251,7 @@ static int _pit_latch(int latch, uint64_t cur)
/* should have been initialized to the value in write_latch */
if (p->cntr != -1) {
ticks = NS_TO_TICKS(cur_time.td - p->time.td);
ticks = (cur_time.td - p->time.td);
if (ticks > p->cntr) { /* time has elapsed */
if ((p->mode&0x40)==0)
@@ -231,28 +272,24 @@ static int _pit_latch(int latch, uint64_t cur)
/* mode 6 -- ??? */
/* mode 3 -- square-wave generator, countdown by 2 */
/* mode 7 -- ??? */
pic_sys_time = cur_time.td; /* full counter */
/* NEVER is a special invalid value... skip it if found */
pic_sys_time += (pic_sys_time == NEVER);
if (latch == 0) {
#if 0
/* when current time is greater than irq time, call pic_request
which will then point pic_itime to next interrupt */
if (((p->mode&0x40)==0) && (pic_sys_time > pic_itime[PIC_IRQ0])) {
if (pic_request(PIC_IRQ0)==PIC_REQ_OK)
{ r_printf("PIT: pit_latch, pic_request IRQ0 mode 2/3\n"); }
}
#endif
/* while current time is less than next irq time, ticks decrease;
* ticks can go out of bounds or negative when the interrupt
* is lost or pending */
if (cur > pic_itime[latch]) {
ticks = 1;
ret++; // underflow seen
} else {
ticks = NS_TO_TICKS(pic_itime[latch] - cur) + 1;
if (ticks > p->cntr)
ticks = 0; // should not be here
}
ticks = (pic_itime[PIC_IRQ0] - pic_sys_time) % p->cntr;
} else {
ticks = p->cntr - (cur % p->cntr);
ticks = p->cntr - (pic_sys_time % p->cntr);
}
if ((p->mode & 3)==3) {
@@ -276,57 +313,20 @@ static int _pit_latch(int latch, uint64_t cur)
i_printf("PIT%d: ticks=%lx latch=%x pin=%d\n",latch,ticks,
p->read_latch,(p->outpin!=0));
#endif
return ret;
}
static int do_pit_latch(int latch)
{
int ret;
uint64_t cur_time;
evtimer_block(pit[latch].evtmr);
cur_time = evtimer_gettime(pit[latch].evtmr);
/* if timer is lagging we run it by hands */
if (cur_time > pic_itime[latch] &&
__sync_bool_compare_and_swap(&pit[latch].q_ticks, 0, 1)) {
/* timer thread blocked, we can increment vars w/o sync/atomics */
pit[latch].tmr_skip++;
if (!latch)
vtmr_raise(VTMR_PIT);
else
pit[latch].q_ticks--;
pit[latch].time.td = pic_itime[latch];
pic_itime[latch] += TICKS_TO_NS(pit[latch].cntr);
}
ret = _pit_latch(latch, cur_time);
vtmr_sync(VTMR_PIT);
evtimer_unblock(pit[latch].evtmr);
return ret;
}
static int pit_latch_hndl(void)
{
return do_pit_latch(0);
}
static void pit_latch(int latch)
{
if (latch == 0)
vtmr_latch(VTMR_PIT);
else
do_pit_latch(latch);
}
/* This is called also by port 0x61 - some programs can use timer #2
* as a GP timer and read bit 5 of port 0x61 (e.g. Matrox BIOS)
*/
Bit8u pit_inp(ioport_t port, void *arg)
Bit8u pit_inp(ioport_t port)
{
int ret = 0;
port -= 0x40;
if ((port == 2) && (config.speaker == SPKR_NATIVE))
return std_port_inb(0x42);
if ((port == 2) && (config.speaker == SPKR_NATIVE)) {
error ("pit_inp() - how could we come here if we defined PORT_FAST?\n");
return safe_port_in_byte(0x42);
}
else if (port == 1)
i_printf("PIT: someone is reading the CMOS refresh time?!?");
@@ -360,14 +360,15 @@ Bit8u pit_inp(ioport_t port, void *arg)
return ret;
}
void pit_outp(ioport_t port, Bit8u val, void *arg)
void pit_outp(ioport_t port, Bit8u val)
{
port -= 0x40;
if (port == 1)
i_printf("PORT: someone is writing the CMOS refresh time?!?");
else if (port == 2 && config.speaker == SPKR_NATIVE) {
std_port_outb(0x42, val);
error ("pit_outp() - how could we come here if we defined PORT_FAST?\n");
safe_port_out_byte(0x42, val);
return;
}
@@ -402,28 +403,36 @@ void pit_outp(ioport_t port, Bit8u val, void *arg)
if (pit[port].write_state != 0) {
if (pit[port].write_latch == 0)
pit[port].cntr = 0xffff;
pit[port].cntr = 0x10000;
else
pit[port].cntr = pit[port].write_latch;
if (!port)
evtimer_set_rel(pit[port].evtmr, TICKS_TO_NS(pit[port].cntr), 1);
else
evtimer_stop(pit[port].evtmr);
h_printf("PIT: timer %i set to %i ticks\n", port, pit[port].cntr);
pit[port].time.td = 0;
pic_itime[port] = TICKS_TO_NS(pit[port].cntr);
if (port == 2 && (port61 & 3) == 3)
do_sound(pit[port].cntr);
pit[port].time.td = GETtickTIME(0);
if (port == 0) {
ticks_accum = 0;
timer_div = (pit[0].cntr * 10000) / PIT_TICK_RATE;
if (timer_div == 0)
timer_div = 1;
#if 1
i_printf("timer_interrupt_rate count %i, requested %.3g Hz, granted %.3g Hz\n",
pit[0].cntr, PIT_TICK_RATE/(double)pit[0].cntr, 10000.0/timer_div);
#endif
}
#if 0
else if (port == 2 && config.speaker == SPKR_EMULATED) {
do_sound(pit[2].write_latch & 0xffff);
}
#endif
}
}
Bit8u pit_control_inp(ioport_t port, void *arg)
Bit8u pit_control_inp(ioport_t port)
{
return 0;
}
void pit_control_outp(ioport_t port, Bit8u val, void *arg)
void pit_control_outp(ioport_t port, Bit8u val)
{
int latch = (val >> 6) & 0x03;
@@ -454,7 +463,7 @@ void pit_control_outp(ioport_t port, Bit8u val, void *arg)
switch (latch) {
case 2:
if (config.speaker == SPKR_NATIVE) {
std_port_outb(0x43, val);
safe_port_out_byte(0x43, val);
break;
}
/* nobreak; */
@@ -470,7 +479,7 @@ void pit_control_outp(ioport_t port, Bit8u val, void *arg)
/* set the time base for the counter - safety code for programs
* which use a non-periodical mode without reloading the counter
*/
pit[latch].time.td = evtimer_gettime(pit[latch].evtmr);
pit[latch].time.td = GETtickTIME(0);
}
}
#ifdef DEBUG_PIT
@@ -494,47 +503,32 @@ void pit_control_outp(ioport_t port, Bit8u val, void *arg)
}
}
static void timer_activate(int ticks, void *arg)
/* DANG_BEGIN_FUNCTION timer_int_engine
*
* This is experimental TIMER-IRQ CHAIN code!
* This is a function to determine whether it is time to invoke a
* new timer irq 0 event. Normally it is 18 times a second, but
* many video games set it to 100 times per second or more. Since
* the kernel cannot keep an accurate timer interrupt, the job of this
* routine is to perform a chained timer irq 0 right after the previous
* timer irq 0. This routine should, ideally, be called right after
* the end of a timer irq, if possible.
*
* This would speed up high frequency timer interrupts if this code
* can be converted into an assembly macro equivalent!
*
* PLEASE NOTE
*
* This code has been replaced by interrupt scheduling code in pic.
* The result is that we simply call pic_sched and run the dos interrupt.
* If the new code causes no problems, I'll revise this section permanently.
*
* DANG_END_FUNCTION
*/
static int timer_int_engine(int ilevel)
{
int pit_num = (uintptr_t)arg;
uint32_t q;
if (pit[pit_num].tmr_skip) {
pit[pit_num].tmr_skip--;
return;
}
if (!ticks) {
error("0 ticks on PIT\n");
return;
}
q = __sync_fetch_and_add(&pit[pit_num].q_ticks, ticks);
h_printf("PIT: timer %i expired, %i\n", pit_num, q);
if (pit_num) {
pit[pit_num].time.td = evtimer_gettime(pit[pit_num].evtmr);
return;
}
if (!q) {
vtmr_raise(VTMR_PIT);
pit[0].time.td = pic_itime[0];
pic_itime[0] += TICKS_TO_NS(pit[0].cntr);
}
}
static int timer_irq_ack(int masked)
{
uint32_t q = __sync_sub_and_fetch(&pit[0].q_ticks, 1);
int ret = 0;
h_printf("PIT: timer 0 acknowledged, %i\n", q);
if (q) {
pit[0].time.td = pic_itime[0];
pic_itime[0] += TICKS_TO_NS(pit[0].cntr);
ret = 1;
}
if (!masked)
irq0_cnt++;
return ret;
pic_sched(PIC_IRQ0,pit[0].cntr);
return 1;
}
/* reads/writes to the speaker control port (0x61)
@@ -562,7 +556,7 @@ static int timer_irq_ack(int masked)
Bit8u spkr_io_read(ioport_t port) {
if (port==0x61) {
if (config.speaker == SPKR_NATIVE)
return std_port_inb(0x61);
return port_safe_inb(0x61);
else {
/* keep the connection between port 0x61 and PIT timer#2 */
pit_latch(2);
@@ -578,7 +572,7 @@ void spkr_io_write(ioport_t port, Bit8u value) {
if (port==0x61) {
switch (config.speaker) {
case SPKR_NATIVE:
std_port_outb(0x61, value & 0x03);
port_safe_outb(0x61, value & 0x03);
break;
case SPKR_EMULATED:
@@ -609,11 +603,14 @@ void pit_init(void)
io_device.handler_name = "8254 Timer0";
io_device.start_addr = 0x0040;
io_device.end_addr = 0x0040;
io_device.irq = 0;
io_device.fd = -1;
port_register_handler(io_device, 0);
io_device.handler_name = "8254 Timer1";
io_device.start_addr = 0x0041;
io_device.end_addr = 0x0041;
io_device.irq = EMU_NO_IRQ;
port_register_handler(io_device, 0);
io_device.handler_name = "8254 Timer2";
@@ -636,82 +633,54 @@ void pit_init(void)
port_register_handler(io_device, 0);
#endif
vtmr_register(VTMR_PIT, timer_irq_ack);
vtmr_register_latch(VTMR_PIT, pit_latch_hndl);
vtmr_set_tweaked(VTMR_PIT, config.timer_tweaks, 0);
pit[0].evtmr = evtimer_create(timer_activate, (void *)(uintptr_t)0);
pit[1].evtmr = evtimer_create(timer_activate, (void *)(uintptr_t)1);
pit[2].evtmr = evtimer_create(timer_activate, (void *)(uintptr_t)2);
}
void pit_done(void)
{
evtimer_delete(pit[0].evtmr);
evtimer_delete(pit[1].evtmr);
evtimer_delete(pit[2].evtmr);
pic_seti(PIC_IRQ0, timer_int_engine, 0, NULL); /* do_irq0 in pic.c */
pic_request(PIC_IRQ0); /* start timer */
}
void pit_reset(void)
{
hitimer_t cur_time;
cur_time = GETtickTIME(0);
pit[0].mode = 3;
pit[0].outpin = 0;
pit[0].cntr = 0xffff;
pit[0].time.td = 0;
pit[0].cntr = 0x10000;
pit[0].time.td = cur_time;
pit[0].read_latch = 0xffffffff;
pit[0].write_latch = 0;
pit[0].read_state = 3;
pit[0].write_state = 3;
pit[0].q_ticks = 0;
evtimer_stop(pit[0].evtmr);
pit[1].mode = 2;
pit[1].outpin = 0;
pit[1].cntr = 18;
pit[1].time.td = 0;
pit[1].time.td = cur_time;
pit[1].read_latch = 0xffffffff;
pit[1].write_latch = 18;
pit[1].read_state = 3;
pit[1].write_state = 3;
pit[1].q_ticks = 0;
evtimer_stop(pit[1].evtmr);
pit[2].mode = 0;
pit[2].outpin = 0;
pit[2].cntr = 0xffff;
pit[2].time.td = 0;
pit[2].cntr = 0x10000;
pit[2].time.td = cur_time;
pit[2].read_latch = 0xffffffff;
pit[2].write_latch = 0;
pit[2].read_state = 3;
pit[2].write_state = 3;
pit[2].q_ticks = 0;
evtimer_stop(pit[2].evtmr);
pit[3].mode = 0;
pit[3].outpin = 0;
pit[3].cntr = 0xffff;
pit[3].time.td = 0;
pit[3].cntr = 0x10000;
pit[3].time.td = cur_time;
pit[3].read_latch = 0xffffffff;
pit[3].write_latch = 0;
pit[3].read_state = 3;
pit[3].write_state = 3;
#if 0
timer_handle = timer_create(pit_timer_func, NULL, pit_timer_usecs(0x10000));
#endif
port61 = 0x0c;
pic_sys_time = GETtickTIME(0);
}
void pit_late_init(void)
{
evtimer_set_rel(pit[0].evtmr, TICKS_TO_NS(pit[0].cntr), 1);
pit[0].time.td = 0;
pic_itime[0] = TICKS_TO_NS(pit[0].cntr);
}
#define TIMER0_FLOOD_THRESHOLD 50
int CAN_SLEEP(void)
{
return (!(pic_get_isr() || (REG(eflags) & VIP) || signal_pending() ||
(pit[0].q_ticks > TIMER0_FLOOD_THRESHOLD) || in_leavedos));
}

View File

@@ -1,196 +0,0 @@
/*
* This program 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 program 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
* Purpose: virtual IRQ router
*
* Author: Stas Sergeev.
*
*/
#include <stdint.h>
#include <assert.h>
#include <pthread.h>
#include "port.h"
#include "pic.h"
#include "hlt.h"
#include "cpu.h"
#include "int.h"
#include "bitops.h"
#include "emu.h"
#include "virq.h"
#define VIRQ_IRR_PORT 0x50a
#define VIRQ_HWC_PORT (VIRQ_IRR_PORT + 2)
#define VIRQ_RST_PORT (VIRQ_IRR_PORT + 3)
#define VIRQ_TOTAL_PORTS 4
#define VIRQ_IRQ_NUM 0xf
#define VIRQ_INTERRUPT (VIRQ_IRQ_NUM - 8 + 0x70)
static uint16_t virq_irr;
static pthread_mutex_t irr_mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t hndl_mtx = PTHREAD_MUTEX_INITIALIZER;
static uint16_t virq_hlt;
struct vhandler_s {
enum VirqHwRet (*hw_handler)(void *);
enum VirqSwRet (*sw_handler)(void *);
void *arg;
};
struct vhandler_s vhandlers[VIRQ_MAX];
static void virq_lower(int virq_num);
static Bit16u virq_irr_read(ioport_t port, void *arg)
{
uint16_t irr;
pthread_mutex_lock(&irr_mtx);
irr = virq_irr;
pthread_mutex_unlock(&irr_mtx);
return irr;
}
static void virq_hwc_write(ioport_t port, Bit8u value, void *arg)
{
struct vhandler_s *vh;
enum VirqHwRet rc = VIRQ_HWRET_DONE;
switch (port) {
case VIRQ_RST_PORT:
switch (value) {
case 1:
/* re-assert irqs */
if (virq_irr)
pic_request(VIRQ_IRQ_NUM);
break;
}
break;
case VIRQ_HWC_PORT:
assert(value < VIRQ_MAX);
vh = &vhandlers[value];
pthread_mutex_lock(&hndl_mtx);
if (vh->hw_handler)
rc = vh->hw_handler(vh->arg);
if (rc == VIRQ_HWRET_DONE)
virq_lower(value);
pthread_mutex_unlock(&hndl_mtx);
break;
}
}
static void virq_handler(uint16_t idx, HLT_ARG(arg))
{
uint16_t irr;
while ((irr = port_inw(VIRQ_IRR_PORT))) {
struct vhandler_s *vh;
int inum = find_bit(irr);
assert(inum < VIRQ_MAX);
port_outb(VIRQ_HWC_PORT, inum);
vh = &vhandlers[inum];
if (vh->sw_handler) {
enum VirqSwRet rc = vh->sw_handler(vh->arg);
if (rc == VIRQ_SWRET_BH) {
assert(_IP != virq_hlt);
/* If BH is scheduled, we just return and switch back later. */
set_IF();
return;
}
} else {
error("virq: no handler for %i\n", inum);
}
}
assert(_IP == virq_hlt);
do_eoi2_iret();
}
void virq_init(void)
{
emu_iodev_t io_dev = {};
emu_hlt_t hlt_hdlr = HLT_INITIALIZER;
io_dev.write_portb = virq_hwc_write;
io_dev.read_portw = virq_irr_read;
io_dev.start_addr = VIRQ_IRR_PORT;
io_dev.end_addr = VIRQ_IRR_PORT + VIRQ_TOTAL_PORTS - 1;
io_dev.handler_name = "virtual IRQ router";
port_register_handler(io_dev, 0);
hlt_hdlr.name = "virq";
hlt_hdlr.func = virq_handler;
virq_hlt = hlt_register_handler_vm86(hlt_hdlr);
}
void virq_reset(void)
{
pic_untrigger(VIRQ_IRQ_NUM);
}
void virq_setup(void)
{
SETIVEC(VIRQ_INTERRUPT, BIOS_HLT_BLK_SEG, virq_hlt);
port_outb(VIRQ_RST_PORT, 1);
}
void virq_raise(int virq_num)
{
uint16_t irr;
uint16_t mask = 1 << virq_num;
assert(virq_num < VIRQ_MAX);
pthread_mutex_lock(&hndl_mtx);
pthread_mutex_lock(&irr_mtx);
/* __sync_fetch_and_or() */
irr = virq_irr;
virq_irr |= mask;
if (!irr)
pic_request(VIRQ_IRQ_NUM);
pthread_mutex_unlock(&irr_mtx);
pthread_mutex_unlock(&hndl_mtx);
}
static void virq_lower(int virq_num)
{
uint16_t irr;
uint16_t mask = 1 << virq_num;
assert(virq_num < VIRQ_MAX);
pthread_mutex_lock(&irr_mtx);
/* __sync_and_and_fetch() */
virq_irr &= ~mask;
irr = virq_irr;
if (!irr)
pic_untrigger(VIRQ_IRQ_NUM);
pthread_mutex_unlock(&irr_mtx);
}
void virq_register(int virq_num, enum VirqHwRet (*hw_handler)(void *),
enum VirqSwRet (*sw_handler)(void *), void *arg)
{
if (virq_num >= VIRQ_MAX)
return;
vhandlers[virq_num].hw_handler = hw_handler;
vhandlers[virq_num].sw_handler = sw_handler;
vhandlers[virq_num].arg = arg;
}
void virq_unregister(int virq_num)
{
vhandlers[virq_num].hw_handler = NULL;
vhandlers[virq_num].sw_handler = NULL;
}

View File

@@ -1,496 +0,0 @@
/*
* This program 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 program 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
* Purpose: virtual timer device extension
*
* Author: Stas Sergeev.
*
* Note: this code shows how to run coopth in a separate thread.
* Many things are written here just as an example.
* Perhaps in the future the example should be moved elsewhere.
*/
#include <stdint.h>
#include <assert.h>
#include <pthread.h>
#include <semaphore.h>
#include "port.h"
#include "pic.h"
#include "cpu.h"
#include "int.h"
#include "bitops.h"
#include "emudpmi.h"
#include "emu.h"
#include "coopth.h"
#if MULTICORE_EXAMPLE
#include "lowmem.h"
#include "hlt.h"
#endif
#include "utilities.h"
#include "timers.h"
#include "chipset.h"
#include "vint.h"
#include "vtmr.h"
#define VTMR_FIRST_PORT 0x550
#define VTMR_VPEND_PORT VTMR_FIRST_PORT
#define VTMR_IRR_PORT (VTMR_FIRST_PORT + 2)
#define VTMR_ACK_PORT (VTMR_FIRST_PORT + 3)
#define VTMR_REQUEST_PORT (VTMR_FIRST_PORT + 4)
#define VTMR_MASK_PORT (VTMR_FIRST_PORT + 5)
#define VTMR_UNMASK_PORT (VTMR_FIRST_PORT + 6)
#define VTMR_LATCH_PORT (VTMR_FIRST_PORT + 7)
#define VTMR_TOTAL_PORTS 8
static uint16_t vtmr_irr;
static uint16_t vtmr_imr;
static uint16_t vtmr_pirr;
static pthread_t vtmr_thr;
static sem_t vtmr_sem;
static int latch_tid;
static pthread_mutex_t irr_mtx = PTHREAD_MUTEX_INITIALIZER;
#if MULTICORE_EXAMPLE
static int smi_tid;
static char *rmstack;
static uint16_t hlt_off;
#endif
struct vthandler {
int (*handler)(int);
int (*latch)(void);
int vint;
int done_pred;
pthread_mutex_t done_mtx;
pthread_cond_t done_cnd;
};
struct vthandler vth[VTMR_MAX];
struct vint_presets {
uint8_t irq;
uint8_t orig_irq;
uint8_t interrupt;
};
static struct vint_presets vip[VTMR_MAX] = {
[VTMR_PIT] = { .irq = VTMR_IRQ, .orig_irq = 0,
.interrupt = VTMR_INTERRUPT },
[VTMR_RTC] = { .irq = VRTC_IRQ, .orig_irq = 8,
.interrupt = VRTC_INTERRUPT },
};
static int do_vtmr_raise(int timer);
static Bit8u vtmr_irr_read(ioport_t port, void *arg)
{
return vtmr_irr;
}
static Bit16u vtmr_vpend_read(ioport_t port, void *arg)
{
/* clang has __atomic_swap() */
return __atomic_exchange_n(&vtmr_pirr, 0, __ATOMIC_ACQ_REL);
}
static void post_req(int timer)
{
if (vth[timer].handler) {
int rc = vth[timer].handler(0);
if (rc)
do_vtmr_raise(timer);
}
h_printf("vtmr: post-REQ on %i, irr=%x\n", timer, vtmr_irr);
}
static void vtmr_io_write(ioport_t port, Bit8u value, void *arg)
{
int masked = (value >> 7) & 1;
int timer = value & 0x7f;
uint16_t msk = 1 << timer;
if (timer >= VTMR_MAX)
return;
switch (port) {
case VTMR_REQUEST_PORT:
if (!masked) {
uint16_t irr;
pthread_mutex_lock(&irr_mtx);
irr = __sync_fetch_and_or(&vtmr_irr, msk);
if (!(irr & msk)) {
if (!(vtmr_imr & msk))
pic_request(vip[timer].irq);
} else {
error("vtmr %i already requested\n", timer);
}
pthread_mutex_unlock(&irr_mtx);
} else {
pic_untrigger(vip[timer].orig_irq);
pic_request(vip[timer].orig_irq);
post_req(timer);
}
h_printf("vtmr: REQ on %i, irr=%x, pirr=%x masked=%i\n", timer,
vtmr_irr, vtmr_pirr, masked);
break;
case VTMR_MASK_PORT: {
uint16_t imr = __sync_fetch_and_or(&vtmr_imr, msk);
if (!(imr & msk)) {
if (vtmr_irr & msk)
pic_untrigger(vip[timer].irq);
}
break;
}
case VTMR_UNMASK_PORT: {
uint16_t imr = __sync_fetch_and_and(&vtmr_imr, ~msk);
if (imr & msk) {
if (vtmr_irr & msk)
pic_request(vip[timer].irq);
}
break;
}
case VTMR_ACK_PORT: {
uint16_t irr;
pthread_mutex_lock(&irr_mtx);
irr = __sync_fetch_and_and(&vtmr_irr, ~msk);
if (irr & msk) {
pic_untrigger(vip[timer].irq);
if (vth[timer].handler) {
int rc = vth[timer].handler(masked);
if (rc)
do_vtmr_raise(timer);
}
} else {
error("vtmr %i not requested\n", timer);
}
pthread_mutex_unlock(&irr_mtx);
h_printf("vtmr: ACK on %i, irr=%x pirr=%x\n", timer, vtmr_irr,
vtmr_pirr);
break;
}
case VTMR_LATCH_PORT: {
int from_irq = masked;
if (vth[timer].latch) {
int rc = vth[timer].latch();
if (rc && !from_irq) { // underflow seen not from IRQ
uint16_t irr;
pthread_mutex_lock(&irr_mtx);
irr = __sync_fetch_and_and(&vtmr_irr, ~msk);
if (irr & msk) {
pic_untrigger(vip[timer].irq);
if (vth[timer].handler) {
rc = vth[timer].handler(1);
if (rc)
do_vtmr_raise(timer);
}
}
pthread_mutex_unlock(&irr_mtx);
}
}
h_printf("vtmr: LATCH on %i, irr=%x pirr=%x\n", timer, vtmr_irr,
vtmr_pirr);
break;
}
}
}
static void do_ack(int timer, int masked)
{
port_outb(VTMR_ACK_PORT, timer | (masked << 7));
}
static void ack_handler(int vint, int masked)
{
int i;
for (i = 0; i < VTMR_MAX; i++) {
if (vth[i].vint == vint) {
do_ack(i, masked);
break;
}
}
}
static void do_mask(int timer)
{
port_outb(VTMR_MASK_PORT, timer);
}
static void do_unmask(int timer)
{
port_outb(VTMR_UNMASK_PORT, timer);
}
static void mask_handler(int vint, int masked)
{
int i;
for (i = 0; i < VTMR_MAX; i++) {
if (vth[i].vint == vint) {
if (masked)
do_mask(i);
else
do_unmask(i);
break;
}
}
}
int vtmr_pre_irq_dpmi(uint8_t *imr)
{
int masked = vint_is_masked(vth[VTMR_PIT].vint, imr);
do_mask(VTMR_PIT);
do_ack(VTMR_PIT, masked);
vint_post_irq_dpmi(vth[VTMR_PIT].vint, masked);
return masked;
}
void vtmr_post_irq_dpmi(int masked)
{
do_unmask(VTMR_PIT);
}
int vrtc_pre_irq_dpmi(uint8_t *imr)
{
int masked = vint_is_masked(vth[VTMR_RTC].vint, imr);
do_mask(VTMR_RTC);
do_ack(VTMR_RTC, masked);
vint_post_irq_dpmi(vth[VTMR_RTC].vint, masked);
return masked;
}
void vrtc_post_irq_dpmi(int masked)
{
do_unmask(VTMR_RTC);
}
static int vtmr_is_masked(int timer)
{
uint8_t imr[2] = { [0] = port_inb(0x21), [1] = port_inb(0xa1) };
uint16_t real_imr = (imr[1] << 8) | imr[0];
return ((imr[0] & 4) || !!(real_imr & (1 << vip[timer].irq)));
}
static void vtmr_smi(void *arg)
{
int timer;
uint16_t pirr = port_inw(VTMR_VPEND_PORT);
while ((timer = find_bit(pirr)) != -1) {
int masked = vtmr_is_masked(timer);
pirr &= ~(1 << timer);
port_outb(VTMR_REQUEST_PORT, timer | (masked << 7));
if (!masked)
port_outb(0x4d2, 1); // set fake IRR
pthread_mutex_lock(&vth[timer].done_mtx);
vth[timer].done_pred = 1;
pthread_mutex_unlock(&vth[timer].done_mtx);
pthread_cond_signal(&vth[timer].done_cnd);
}
}
static void vtmr_latch_smi(void *arg)
{
uint16_t isr;
int from_irq;
int timer = (uintptr_t)arg;
assert(timer < VTMR_MAX);
port_outb(0x20, 0xb);
isr = port_inb(0x20);
port_outb(0xa0, 0xb);
isr = (port_inb(0xa0) << 8);
from_irq = !!(isr & (1 << vip[timer].orig_irq));
port_outb(VTMR_LATCH_PORT, timer | (from_irq << 7));
}
#if MULTICORE_EXAMPLE
static void thr_cleanup(void *arg)
{
coopth_done();
lowmem_free(rmstack);
}
#endif
#define RMSTACK_SIZE 32
static void *vtmr_thread(void *arg)
{
#if MULTICORE_EXAMPLE
/* init coopth in new thread */
coopth_init();
pthread_cleanup_push(thr_cleanup, NULL);
smi_tid = coopth_create("vtmr smi", vtmr_smi);
cpu_reset();
_SS = DOSEMU_LMHEAP_SEG;
_SP = DOSEMU_LMHEAP_OFFS_OF(rmstack) + RMSTACK_SIZE;
_CS = BIOS_HLT_BLK_SEG;
_IP = hlt_off;
clear_IF();
/* run our fake core */
while (1)
run_vm86();
pthread_cleanup_pop(1);
#else
while (1) {
sem_wait(&vtmr_sem);
vtmr_smi(NULL);
}
#endif
return NULL;
}
#if MULTICORE_EXAMPLE
static void vtmr_hlt(Bit16u idx, HLT_ARG(arg))
{
sem_wait(&vtmr_sem);
coopth_start(smi_tid, NULL);
}
#endif
void vtmr_init(void)
{
emu_iodev_t io_dev = {};
#if MULTICORE_EXAMPLE
emu_hlt_t hlt_hdlr = HLT_INITIALIZER;
#endif
int i;
io_dev.write_portb = vtmr_io_write;
io_dev.read_portb = vtmr_irr_read;
io_dev.read_portw = vtmr_vpend_read;
io_dev.start_addr = VTMR_FIRST_PORT;
io_dev.end_addr = VTMR_FIRST_PORT + VTMR_TOTAL_PORTS - 1;
io_dev.handler_name = "virtual timer";
port_register_handler(io_dev, 0);
#if MULTICORE_EXAMPLE
rmstack = lowmem_alloc(RMSTACK_SIZE);
hlt_hdlr.name = "vtmr sleep";
hlt_hdlr.func = vtmr_hlt;
hlt_off = hlt_register_handler_vm86(hlt_hdlr);
#endif
latch_tid = coopth_create("vtmr latch smi", vtmr_latch_smi);
coopth_set_ctx_handlers(latch_tid, sig_ctx_prepare, sig_ctx_restore, NULL);
sem_init(&vtmr_sem, 0, 0);
for (i = 0; i < VTMR_MAX; i++) {
pthread_mutex_init(&vth[i].done_mtx, NULL);
pthread_cond_init(&vth[i].done_cnd, NULL);
vth[i].done_pred = 1;
}
pthread_create(&vtmr_thr, NULL, vtmr_thread, NULL);
#if defined(HAVE_PTHREAD_SETNAME_NP) && defined(__GLIBC__)
pthread_setname_np(vtmr_thr, "dosemu: vtmr");
#endif
}
void vtmr_done(void)
{
int i;
pthread_cancel(vtmr_thr);
pthread_join(vtmr_thr, NULL);
sem_destroy(&vtmr_sem);
for (i = 0; i < VTMR_MAX; i++) {
pthread_mutex_destroy(&vth[i].done_mtx);
pthread_cond_destroy(&vth[i].done_cnd);
}
#if MULTICORE_EXAMPLE
lowmem_free(rmstack);
#endif
}
void vtmr_reset(void)
{
int i;
vtmr_irr = 0;
vtmr_imr = 0;
vtmr_pirr = 0;
for (i = 0; i < VTMR_MAX; i++)
pic_untrigger(vip[i].irq);
}
static int do_vtmr_raise(int timer)
{
uint16_t pirr;
uint16_t mask = 1 << timer;
assert(timer < VTMR_MAX);
h_printf("vtmr: raise timer %i\n", timer);
pirr = __sync_fetch_and_or(&vtmr_pirr, mask);
if (!(pirr & mask)) {
h_printf("vtmr: posting timer event\n");
sem_post(&vtmr_sem);
return 1;
}
return 0;
}
void vtmr_raise(int timer)
{
int rc;
pthread_mutex_lock(&vth[timer].done_mtx);
vth[timer].done_pred = 0;
pthread_mutex_unlock(&vth[timer].done_mtx);
rc = do_vtmr_raise(timer);
if (!rc) {
pthread_mutex_lock(&vth[timer].done_mtx);
vth[timer].done_pred = 1;
pthread_mutex_unlock(&vth[timer].done_mtx);
pthread_cond_signal(&vth[timer].done_cnd);
}
}
void vtmr_latch(int timer)
{
if (in_dpmi_pm())
fake_pm_int();
coopth_start(latch_tid, (void *)(uintptr_t)timer);
}
void vtmr_sync(int timer)
{
pthread_mutex_lock(&vth[timer].done_mtx);
while (!vth[timer].done_pred)
cond_wait(&vth[timer].done_cnd, &vth[timer].done_mtx);
pthread_mutex_unlock(&vth[timer].done_mtx);
}
void vtmr_register(int timer, int (*handler)(int))
{
struct vthandler *vt = &vth[timer];
struct vint_presets *vp = &vip[timer];
assert(timer < VTMR_MAX);
vt->handler = handler;
vt->vint = vint_register(ack_handler, mask_handler, vp->irq,
vp->orig_irq, vp->interrupt);
}
void vtmr_register_latch(int timer, int (*handler)(void))
{
struct vthandler *vt = &vth[timer];
assert(timer < VTMR_MAX);
vt->latch = handler;
}
void vtmr_set_tweaked(int timer, int on, unsigned flags)
{
vint_set_tweaked(vth[timer].vint, on, flags);
}

View File

@@ -25,10 +25,9 @@
#include <errno.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include "emu.h"
#include "dosemu_debug.h"
#include "ioselect.h"
#include "emu.h"
#include "pic.h"
#include "port.h"
#include "libpacket.h"
@@ -124,7 +123,7 @@
#define ENTSR_OWC 0x80 /* There was an out-of-window collision. */
#define NE2000_IRQ 10
#define NE2000_IOBASE 0x310
#define NE2000_IOBASE 0x300
#define NE2000_PMEM_SIZE (32 * 1024)
#define NE2000_PMEM_START (16 * 1024)
@@ -170,15 +169,14 @@ typedef struct NE2000State {
static NE2000State ne2000state;
// For io_device
Bit16u ne2000_io_read16(ioport_t port, void *arg);
void ne2000_io_write16(ioport_t port, Bit16u value, void *arg);
Bit8u ne2000_io_read8(ioport_t port, void *arg);
void ne2000_io_write8(ioport_t port, Bit8u value, void *arg);
Bit16u ne2000_io_read16(ioport_t port);
void ne2000_io_write16(ioport_t port, Bit16u value);
Bit8u ne2000_io_read8(ioport_t port);
void ne2000_io_write8(ioport_t port, Bit8u value);
static void ne2000_irq_activate(int);
static void ne2000_receive_req_async(int fd, void *arg);
static void ne2000_receive_req_async(void *arg);
static size_t ne2000_receive(NE2000State *s, const uint8_t *buf, size_t size_);
static int ne2000_buffer_full(NE2000State *s);
#ifdef DEBUG_NE2000
static void N_printhdr(uint8_t *buf);
@@ -189,6 +187,13 @@ static void init_cbk(int fd, int mode)
ne2000state.fdnet = fd;
}
void ne2000_priv_init(void)
{
if (!config.ne2k)
return;
LibpacketInit();
}
void ne2000_init(void)
{
NE2000State *s = &ne2000state;
@@ -218,6 +223,8 @@ void ne2000_init(void)
io_device.handler_name = "NE2000 Emulation";
io_device.start_addr = /* config.ne2000_base */ NE2000_IOBASE;
io_device.end_addr = /* config.ne2000_base */ NE2000_IOBASE + 0x1f;
io_device.irq = /* config.ne2000_irq */ NE2000_IRQ;
io_device.fd = -1;
if (port_register_handler(io_device, 0) != 0) {
N_printf("NE2000: Error registering NE2000 port handler\n");
ne2000_done();
@@ -225,7 +232,13 @@ void ne2000_init(void)
}
/* init control defaults */
s->irq = NE2000_IRQ;
s->irq = pic_irq_list[NE2000_IRQ];
/* We let DOSEMU handle the interrupt */
pic_seti(s->irq, NULL, 0, NULL);
/* Connect up the receiver */
add_to_io_select(s->fdnet, ne2000_receive_req_async, NULL);
N_printf("NE2000: Initialisation - Base 0x%03x, IRQ %d\n", NE2000_IOBASE, NE2000_IRQ);
}
@@ -241,7 +254,6 @@ static void _ne2000_reset(NE2000State *s)
N_printf("NE2000: ne2000_reset()\n");
s->isr = ENISR_RESET;
s->cmd = E8390_STOP;
s->mem[0] = NE2000_EADDR0;
s->mem[1] = NE2000_EADDR1;
s->mem[2] = NE2000_EADDR2;
@@ -279,9 +291,7 @@ void ne2000_done(void)
N_printf("NE2000: ne2000_done()\n");
if (!(s->cmd & E8390_STOP))
remove_from_io_select(s->fdnet);
CloseNetworkLink(s->fdnet);
close(s->fdnet);
s->fdnet = -1;
}
@@ -302,10 +312,29 @@ static void ne2000_ether_send(NE2000State *s, uint8_t *buf, int len)
static int ne2000_ether_recv(NE2000State *s, uint8_t *buf, int bufsiz)
{
struct timeval tv;
fd_set readset;
int ret;
tv.tv_sec = 0;
tv.tv_usec = 0;
/* anything ready? */
FD_ZERO(&readset);
FD_SET(s->fdnet, &readset);
/* anything ready? */
if (select(s->fdnet + 1, &readset, NULL, NULL, &tv) <= 0) {
N_printf("NE2000: ne2000_ether_recv() select failed\n");
return -1;
}
if (!FD_ISSET(s->fdnet, &readset)) {
N_printf("NE2000: ne2000_ether_recv() nothing to read\n");
return -1;
}
ret = read(s->fdnet, buf, bufsiz);
ioselect_complete(s->fdnet);
if (ret < 0) {
N_printf("NE2000: ne2000_ether_recv() read failed\n");
return -1;
@@ -316,17 +345,12 @@ static int ne2000_ether_recv(NE2000State *s, uint8_t *buf, int bufsiz)
return ret;
}
static void ne2000_receive_req_async(int fd, void *arg)
static void ne2000_receive_req_async(void *arg)
{
NE2000State *s = &ne2000state;
uint8_t mybuf[MAX_ETH_FRAME_SIZE];
int ret;
if (ne2000_buffer_full(s)) {
N_printf("NE2000: ne2000_receive_req_async() called but buffer full\n");
return;
}
N_printf("NE2000: ne2000_receive_req_async() called\n");
ret = ne2000_ether_recv(s, mybuf, sizeof mybuf);
@@ -470,7 +494,6 @@ static size_t ne2000_receive(NE2000State *s, const uint8_t *buf, size_t size_)
static void ne2000_ioport_write(NE2000State *s, uint32_t addr, uint32_t val)
{
int offset, page, index;
int old_full = ne2000_buffer_full(s);
N_printf("NE2000: ne2000_ioport_write()\n");
@@ -479,14 +502,9 @@ static void ne2000_ioport_write(NE2000State *s, uint32_t addr, uint32_t val)
N_printf("NE2000: write addr=0x%x val=0x%02x\n", addr, val);
#endif
if (addr == E8390_CMD) {
uint32_t old_cmd = s->cmd;
/* control register */
s->cmd = val;
if (!(val & E8390_STOP)) { /* START bit makes no sense on RTL8029... */
if (old_cmd & E8390_STOP) {
N_printf("NE2000: enable receiver\n");
add_to_io_select(s->fdnet, ne2000_receive_req_async, NULL);
}
s->isr &= ~ENISR_RESET;
/* test specific case: zero length transfer */
if ((val & (E8390_RREAD | E8390_RWRITE)) &&
@@ -509,11 +527,6 @@ static void ne2000_ioport_write(NE2000State *s, uint32_t addr, uint32_t val)
s->cmd &= ~E8390_TRANS;
ne2000_update_irq(s);
}
} else {
if (!(old_cmd & E8390_STOP)) {
N_printf("NE2000: disable receiver\n");
remove_from_io_select(s->fdnet);
}
}
} else {
page = s->cmd >> 6;
@@ -574,10 +587,6 @@ static void ne2000_ioport_write(NE2000State *s, uint32_t addr, uint32_t val)
break;
}
}
/* flush if buffer was full */
if (old_full && !ne2000_buffer_full(s))
ioselect_complete(s->fdnet);
}
static uint32_t ne2000_ioport_read(NE2000State *s, uint32_t addr)
@@ -869,7 +878,7 @@ static void ne2000_write(NE2000State *s, uint32_t addr, uint64_t data, unsigned
/* --------------------------------- */
/* 16 bit io functions - only on data port */
Bit16u ne2000_io_read16(ioport_t port, void *arg)
Bit16u ne2000_io_read16(ioport_t port)
{
NE2000State *s = &ne2000state;
ioport_t addr = port - NE2000_IOBASE;
@@ -882,7 +891,7 @@ Bit16u ne2000_io_read16(ioport_t port, void *arg)
return ne2000_read(s, addr, 1);
}
void ne2000_io_write16(ioport_t port, Bit16u value, void *arg)
void ne2000_io_write16(ioport_t port, Bit16u value)
{
NE2000State *s = &ne2000state;
ioport_t addr = port - NE2000_IOBASE;
@@ -899,7 +908,7 @@ void ne2000_io_write16(ioport_t port, Bit16u value, void *arg)
/* handle io reads from ne2000 */
Bit8u ne2000_io_read8(ioport_t port, void *arg)
Bit8u ne2000_io_read8(ioport_t port)
{
NE2000State *s = &ne2000state;
ioport_t addr = port - NE2000_IOBASE;
@@ -912,7 +921,7 @@ Bit8u ne2000_io_read8(ioport_t port, void *arg)
/* handle io writes to ne2000 */
void ne2000_io_write8(ioport_t port, Bit8u value, void *arg)
void ne2000_io_write8(ioport_t port, Bit8u value)
{
NE2000State *s = &ne2000state;
ioport_t addr = port - NE2000_IOBASE;

View File

@@ -2,7 +2,15 @@
top_builddir=../../../..
include $(top_builddir)/Makefile.conf
CFILES = pic.c irq.c i8259.c i8259_common.c
CFILES = pic.c
HFILES =
DEPENDS= pic.d
ALL = $(CFILES) $(HFILES) README.pic
OBJS = pic.o
all: lib

View File

@@ -1,359 +0,0 @@
/*
* QEMU 8259 interrupt controller emulation
*
* Copyright (c) 2003-2004 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "i8259.h"
#include "i8259_internal.h"
/* debug PIC */
//#define DEBUG_PIC
//#define DEBUG_IRQ_LATENCY
#define trace_pic_update_irq(...)
#define trace_pic_set_irq(...)
#define trace_pic_interrupt(...)
#define trace_pic_ioport_write(...)
#define trace_pic_ioport_read(...)
#define qemu_log_mask(...)
#define TYPE_I8259 "isa-i8259"
#ifdef DEBUG_IRQ_LATENCY
static int64_t irq_time[16];
#endif
extern PICCommonState *slave_pic;
/* return the highest priority found in mask (highest = smallest
number). Return 8 if no irq */
static int get_priority(PICCommonState *s, int mask)
{
int priority;
if (mask == 0) {
return 8;
}
priority = 0;
while ((mask & (1 << ((priority + s->priority_add) & 7))) == 0) {
priority++;
}
return priority;
}
/* return the pic wanted interrupt. return -1 if none */
static int pic_get_irq(PICCommonState *s)
{
int mask, cur_priority, priority;
mask = s->irr & ~s->imr;
priority = get_priority(s, mask);
if (priority == 8) {
return -1;
}
/* compute current priority. If special fully nested mode on the
master, the IRQ coming from the slave is not taken into account
for the priority computation. */
mask = s->isr;
if (s->special_mask) {
mask &= ~s->imr;
}
if (s->special_fully_nested_mode && s->master) {
mask &= ~(1 << 2);
}
cur_priority = get_priority(s, mask);
if (priority < cur_priority) {
/* higher priority found: an irq should be generated */
return (priority + s->priority_add) & 7;
} else {
return -1;
}
}
/* Update INT output. Must be called every time the output may have changed. */
static void pic_update_irq(PICCommonState *s)
{
int irq;
irq = pic_get_irq(s);
if (irq >= 0) {
trace_pic_update_irq(s->master, s->imr, s->irr, s->priority_add);
qemu_irq_raise(s->int_out[0]);
} else {
qemu_irq_lower(s->int_out[0]);
}
}
/* set irq level. If an edge is detected, then the IRR is set to 1 */
void pic_set_irq(PICCommonState *s, int irq, int level)
{
int mask = 1 << irq;
int irq_index = s->master ? irq : irq + 8;
trace_pic_set_irq(s->master, irq, level);
pic_stat_update_irq(irq_index, level);
#ifdef DEBUG_IRQ_LATENCY
if (level) {
irq_time[irq_index] = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
}
#endif
if (s->elcr & mask) {
/* level triggered */
if (level) {
s->irr |= mask;
s->last_irr |= mask;
} else {
s->irr &= ~mask;
s->last_irr &= ~mask;
}
} else {
/* edge triggered */
if (level) {
if ((s->last_irr & mask) == 0) {
s->irr |= mask;
}
s->last_irr |= mask;
} else {
s->irr &= ~mask; // dosemu2 mod: clear IRR bit even in edge mode
s->last_irr &= ~mask;
}
}
pic_update_irq(s);
}
/* acknowledge interrupt 'irq' */
static void pic_intack(PICCommonState *s, int irq)
{
if (s->auto_eoi) {
if (s->rotate_on_auto_eoi) {
s->priority_add = (irq + 1) & 7;
}
} else {
s->isr |= (1 << irq);
}
/* We don't clear a level sensitive interrupt here */
if (!(s->elcr & (1 << irq))) {
s->irr &= ~(1 << irq);
}
pic_update_irq(s);
}
int pic_read_irq(PICCommonState *s)
{
int irq, irq2, intno;
irq = pic_get_irq(s);
if (irq >= 0) {
if (irq == 2) {
irq2 = pic_get_irq(slave_pic);
if (irq2 >= 0) {
pic_intack(slave_pic, irq2);
} else {
/* spurious IRQ on slave controller */
irq2 = 7;
}
intno = slave_pic->irq_base + irq2;
} else {
intno = s->irq_base + irq;
}
pic_intack(s, irq);
} else {
/* spurious IRQ on host controller */
irq = 7;
intno = s->irq_base + irq;
}
if (irq == 2) {
irq = irq2 + 8;
}
#ifdef DEBUG_IRQ_LATENCY
printf("IRQ%d latency=%0.3fus\n",
irq,
(double)(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) -
irq_time[irq]) * 1000000.0 / NANOSECONDS_PER_SECOND);
#endif
trace_pic_interrupt(irq, intno);
return intno;
}
static void pic_init_reset(PICCommonState *s)
{
pic_reset_common(s);
pic_update_irq(s);
}
void qemu_pic_reset(PICCommonState *s)
{
s->elcr = 0;
pic_init_reset(s);
}
void pic_ioport_write(PICCommonState *s, hwaddr addr64,
uint64_t val64, unsigned size)
{
uint32_t addr = addr64;
uint32_t val = val64;
int priority, cmd, irq;
trace_pic_ioport_write(s->master, addr, val);
if (s->poll) { // dosemu2 mod: poll extension
s->fake_irr &= ~(1 << val);
pic_intack(s, val);
s->poll = 0;
} else if (addr == 0) {
if (val & 0x10) {
pic_init_reset(s);
s->init_state = 1;
s->init4 = val & 1;
s->single_mode = val & 2;
if (val & 0x08) {
qemu_log_mask(LOG_UNIMP,
"i8259: level sensitive irq not supported\n");
}
} else if (val & 0x08) {
if (val & 0x04) {
s->poll = 1;
}
if (val & 0x02) {
s->read_reg_select = val & 1;
}
if (val & 0x40) {
s->special_mask = (val >> 5) & 1;
}
} else {
cmd = val >> 5;
switch (cmd) {
case 0:
case 4:
s->rotate_on_auto_eoi = cmd >> 2;
break;
case 1: /* end of interrupt */
case 5:
priority = get_priority(s, s->isr);
if (priority != 8) {
irq = (priority + s->priority_add) & 7;
s->isr &= ~(1 << irq);
if (cmd == 5) {
s->priority_add = (irq + 1) & 7;
}
pic_update_irq(s);
}
break;
case 3:
irq = val & 7;
s->isr &= ~(1 << irq);
pic_update_irq(s);
break;
case 6:
s->priority_add = (val + 1) & 7;
pic_update_irq(s);
break;
case 7:
irq = val & 7;
s->isr &= ~(1 << irq);
s->priority_add = (irq + 1) & 7;
pic_update_irq(s);
break;
default:
/* no operation */
break;
}
}
} else {
switch (s->init_state) {
case 0:
/* normal mode */
s->imr = val;
pic_update_irq(s);
break;
case 1:
s->irq_base = val & 0xf8;
s->init_state = s->single_mode ? (s->init4 ? 3 : 0) : 2;
break;
case 2:
if (s->init4) {
s->init_state = 3;
} else {
s->init_state = 0;
}
break;
case 3:
s->special_fully_nested_mode = (val >> 4) & 1;
s->auto_eoi = (val >> 1) & 1;
s->init_state = 0;
break;
}
}
}
uint64_t pic_ioport_read(PICCommonState *s, hwaddr addr, unsigned size)
{
int ret;
#if 0
if (s->poll) {
#else
if (s->poll && addr == 0) { // dosemu2 mod
#endif
ret = pic_get_irq(s);
if (ret >= 0) {
pic_intack(s, ret);
ret |= 0x80;
} else {
ret = 0;
}
s->poll = 0;
} else {
if (addr == 0) {
if (s->read_reg_select) {
ret = s->isr;
} else {
ret = s->irr | s->fake_irr;
}
} else {
ret = s->imr;
}
}
trace_pic_ioport_read(s->master, addr, ret);
return ret;
}
int pic_get_output(PICCommonState *s)
{
return (pic_get_irq(s) >= 0);
}
void elcr_ioport_write(PICCommonState *s, hwaddr addr,
uint64_t val, unsigned size)
{
s->elcr = val & s->elcr_mask;
}
uint64_t elcr_ioport_read(PICCommonState *s, hwaddr addr, unsigned size)
{
return s->elcr;
}

View File

@@ -1,23 +0,0 @@
#ifndef HW_I8259_H
#define HW_I8259_H
#include <stdint.h>
typedef uint32_t hwaddr;
/* i8259.c */
typedef struct PICCommonState PICCommonState;
int pic_get_output(PICCommonState *s);
int pic_read_irq(PICCommonState *s);
void qemu_pic_reset(PICCommonState *s);
void pic_set_irq(PICCommonState *s, int irq, int level);
void pic_ioport_write(PICCommonState *s, hwaddr addr64,
uint64_t val64, unsigned size);
uint64_t pic_ioport_read(PICCommonState *s, hwaddr addr, unsigned size);
void elcr_ioport_write(PICCommonState *s, hwaddr addr,
uint64_t val, unsigned size);
uint64_t elcr_ioport_read(PICCommonState *s, hwaddr addr, unsigned size);
#endif

View File

@@ -1,76 +0,0 @@
/*
* QEMU 8259 - common bits of emulated and KVM kernel model
*
* Copyright (c) 2003-2004 Fabrice Bellard
* Copyright (c) 2011 Jan Kiszka, Siemens AG
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "utilities.h"
#include "i8259.h"
#include "i8259_internal.h"
static int irq_level[16];
static uint64_t irq_count[16];
void pic_reset_common(PICCommonState *s)
{
s->last_irr = 0;
s->irr &= s->elcr;
s->imr = 0;
s->isr = 0;
s->priority_add = 0;
s->irq_base = 0;
s->read_reg_select = 0;
s->poll = 0;
s->special_mask = 0;
s->init_state = 0;
s->auto_eoi = 0;
s->rotate_on_auto_eoi = 0;
s->special_fully_nested_mode = 0;
s->init4 = 0;
s->single_mode = 0;
/* Note: ELCR is not reset */
s->fake_irr = 0;
}
void pic_stat_update_irq(int irq, int level)
{
if (level != irq_level[irq]) {
irq_level[irq] = level;
if (level == 1) {
irq_count[irq]++;
}
}
}
bool pic_get_statistics(PICCommonState *s,
uint64_t **irq_counts, unsigned int *nb_irqs)
{
if (s->master) {
*irq_counts = irq_count;
*nb_irqs = ARRAY_SIZE(irq_count);
} else {
*irq_counts = NULL;
*nb_irqs = 0;
}
return true;
}

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