Compare commits
3 Commits
d57de82949
...
b3fc3e05d5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b3fc3e05d5 | ||
|
|
ef0334b333 | ||
|
|
17bb5d7efa |
3
.github/FUNDING.yml
vendored
3
.github/FUNDING.yml
vendored
@@ -1,3 +0,0 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
patreon: stsp
|
||||
13
.github/ISSUE_TEMPLATE/bug_report.md
vendored
13
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -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
|
||||
|
||||
42
.github/workflows/ci-build.yml
vendored
42
.github/workflows/ci-build.yml
vendored
@@ -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_*
|
||||
|
||||
12
.github/workflows/ci-manual-asan.yml
vendored
12
.github/workflows/ci-manual-asan.yml
vendored
@@ -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'
|
||||
12
.github/workflows/ci-manual-full.yml
vendored
12
.github/workflows/ci-manual-full.yml
vendored
@@ -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'
|
||||
12
.github/workflows/ci-manual-normal.yml
vendored
12
.github/workflows/ci-manual-normal.yml
vendored
@@ -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'
|
||||
73
.github/workflows/ci-master.yml
vendored
73
.github/workflows/ci-master.yml
vendored
@@ -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
39
.gitignore
vendored
@@ -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
|
||||
@@ -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.
|
||||
@@ -1 +0,0 @@
|
||||
2.0pre9-2 ./
|
||||
@@ -1,6 +0,0 @@
|
||||
[buildconfig]
|
||||
builder = tito.builder.Builder
|
||||
tagger = tito.tagger.VersionTagger
|
||||
changelog_do_not_remove_cherrypick = 0
|
||||
changelog_format = %s (%ae)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
language: c
|
||||
|
||||
os: linux
|
||||
sudo: true
|
||||
dist: focal
|
||||
|
||||
if: type = cron
|
||||
|
||||
@@ -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
|
||||
|
||||
7
INSTALL
7
INSTALL
@@ -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,
|
||||
|
||||
4
Makefile
4
Makefile
@@ -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 \
|
||||
|
||||
@@ -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
|
||||
|
||||
38
README.md
38
README.md
@@ -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
11
THANKS
@@ -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
|
||||
|
||||
10
autogen.sh
10
autogen.sh
@@ -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"
|
||||
|
||||
36
ci_build.sh
36
ci_build.sh
@@ -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
|
||||
|
||||
55
ci_prereq.sh
55
ci_prereq.sh
@@ -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
|
||||
|
||||
71
ci_test.sh
71
ci_test.sh
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -1,9 +1,7 @@
|
||||
config {
|
||||
experimental on
|
||||
debug on
|
||||
asan off
|
||||
lsan off
|
||||
tsan off
|
||||
asan on
|
||||
ubsan on
|
||||
optimize off
|
||||
system-wa off
|
||||
|
||||
348
configure.ac
348
configure.ac
@@ -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
2
debian/changelog
vendored
@@ -1,4 +1,4 @@
|
||||
dosemu2 (2.0pre9-2) focal; urgency=low
|
||||
dosemu2 (2.0-0.9) focal; urgency=low
|
||||
|
||||
* pre9-2
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
246
doc/tweaks.html
246
doc/tweaks.html
@@ -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
|
||||
|
||||
119
dosemu2.spec
119
dosemu2.spec
@@ -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)
|
||||
@@ -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
|
||||
|
||||
197
etc/dosemu.conf
197
etc/dosemu.conf
@@ -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 = ""
|
||||
|
||||
|
||||
114
etc/global.conf
114
etc/global.conf
@@ -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
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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
323
install-sh
Executable 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:
|
||||
@@ -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
|
||||
])
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ЖЕСТКИЕ ДИСКИ
|
||||
|
||||
@@ -21,4 +21,3 @@ doscmd
|
||||
periph
|
||||
debugger
|
||||
fdpp
|
||||
dj64
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ $# != 2 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -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
1480
scripts/config.guess
vendored
File diff suppressed because it is too large
Load Diff
1801
scripts/config.sub
vendored
1801
scripts/config.sub
vendored
File diff suppressed because it is too large
Load Diff
@@ -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:
|
||||
@@ -20,7 +20,7 @@ gendummy() {
|
||||
if [ "$1" = "clean" ]; then
|
||||
rm -f $INC/$HDR
|
||||
else
|
||||
printf "" >$INC/$HDR.$$
|
||||
echo -n "" >$INC/$HDR.$$
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
553
src/arch/linux/async/sigsegv.c
Normal file
553
src/arch/linux/async/sigsegv.c
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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 =
|
||||
|
||||
329
src/arch/linux/mapping/mapfile.c
Normal file
329
src/arch/linux/mapping/mapfile.c
Normal 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
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
184
src/arch/linux/mapping/mapshm.c
Normal file
184
src/arch/linux/mapping/mapshm.c
Normal 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
|
||||
@@ -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++) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
@@ -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;
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
Reference in New Issue
Block a user