| Home | | Developer Releases | | Stable Releases | | Documentation |

Technical README
DANG  - 0.99
Next Previous Contents

7. The Misc group of Modules

These are the remaining important files, that do not really fit into another group. These should not be dismissed as unimportant - rather, they are often amongst the most important.

7.1 dosext/misc/emm.c Information

This provides the EMM Memory Management for DOSEMU. It was originally part of the Mach Dos Emulator.

Recent work in this area has involved a patch to the Kernel. If this is used and the DEFINE MMAP_EMS line used, a faster form of EMS memory support is included, using the /proc filesystem.

In contrast to some of the comments (Yes, _I_ know the adage about that...) we appear to be supporting EMS 4.0, not 3.2. The following EMS 4.0 functions are not supported (yet): 0x4f (partial page map functions), 0x55 (map pages and jump), and 0x56 (map pages and call). OS handle support is missing, and raw page size is 16k (instead of 4k). Other than that, EMS 4.0 support appears complete.

7.2 dosext/misc/xms.c Information

Currently the XMS 3.0 spec is covered in this file. XMS is fairly simple as it only deals with allocating extended memory and then moving it around in specific calls. This spec also includes the allocation of UMB's, so they are also included as part of this file. The amount of xms memory returned to DOS programs via the XMS requests, or int15 fnc88 is set in "/etc/dosemu.conf" via the XMS paramter.

7.3 base/async/int.c Information

7.4 Functions in base/async/int.c

These are the functions defined in base/async/int.c.


DEFAULT_INTERRUPT is the default interrupt service routine called when DOSEMU initializes.


int0x21 call

we trap this for two functions: simulating the EMMXXXX0 device and fudging the CONFIG.XXX and AUTOEXEC.XXX bootup files.

note that the emulation herein may cause problems with programs that like to take control of certain int 21h functions, or that change functions that the true int 21h functions use. An example of the latter is ANSI.SYS, which changes int 10h, and int 21h uses int 10h. for the moment, ANSI.SYS won't work anyway, so it's no problem.

run_caller_func(i, from_int)

This function runs the specified caller function in response to an int instruction. Where i is the interrupt function to execute and from_int specifies if we are comming directly from an int instruction.

This function runs the instruction with the following model _CS:_IP is the address to start executing at after the caller function terminates, and _EFLAGS are the flags to use after termination. For the simple case of an int instruction this is easy. _CS:_IP = retCS:retIP and _FLAGS = retFLAGS as well equally the current values (retIP = curIP +2 technically).

However if the function is called (from dos) by simulating an int instruction (something that is common with chained interrupt vectors) _CS:_IP = BIOS_SEG:HLT_OFF(i) and _FLAGS = curFLAGS while retCS, retIP, and retFlags are on the stack. These I pop and place in the appropriate registers.

This functions actions certainly correct for functions executing an int/iret discipline. And almost certianly correct for functions executing an int/retf#2 discipline (with flag changes), as an iret is always possilbe. However functions like dos int 0x25 and 0x26 executing with a int/retf will not be handled correctlty by this function and if you need to handle them inside dosemu use a halt handler instead.

Finally there is a possible trouble spot lurking in this code. Interrupts are only implicitly disabled when it calls the caller function, so if for some reason the main loop would be entered before the caller function returns wrong code may execute if the retFLAGS have interrupts enabled!

This is only a real handicap for sequences of dosemu code execute for long periods of time as we try to improve timer response and prevent signal queue overflows! -- EB 10 March 1997

Grumble do to code that executes before interrupts, and the semantics of default_interupt, I can't implement this function as I would like. In the tricky case of being called from dos by simulating an int instruction, I must leave retCS, retIP, on the stack. But I can safely read retFlags so I do. I pop retCS, and retIP just before returning to dos, as well as dropping the stack slot that held retFlags.

This improves consistency of interrupt handling, but not quite as much as if I could handle it the way I would like. -- EB 30 Nov 1997


DO_INT is used to deal with interrupts returned to DOSEMU by the kernel.


SETUP_INTERRUPTS is used to initialize the interrupt_function array which directs handling of interrupts in protected mode and also initializes the base vector for interrupts in real mode.


Setup initial interrupts which can be revectored so that the kernel does not need to return to DOSEMU if such an interrupt occurs.

7.5 Remarks in base/async/int.c

Some video BIOSes need access to the PIT timer 2, and some (e.g. Matrox) directly read the timer output on port 0x61. If we don't allow video port access, this will be totally emulated; else, we give temporary access to the needed ports (timer at 0x42, timer config at 0x43 and timer out/speaker at 0x61), provided they were not previously enabled by SPKR_NATIVE - AV


Many video BIOSes use hi interrupt vector locations as scratchpad area - this is because they come before DOS and feel safe to do it. But we are initializing vectors before video, so this only causes trouble. I assume no video BIOS will ever: - change vectors < 0xe0 (0:380-0:3ff area) - change anything in the vector area _after_ installation - AV

7.6 include/int.h Information

7.7 arch/linux/async/sigsegv.c Information

7.8 Functions in arch/linux/async/sigsegv.c

These are the functions defined in arch/linux/async/sigsegv.c.

dosemu_fault(int, struct sigcontext_struct);

All CPU exceptions (except 13=general_protection from V86 mode, which is directly scanned by the kernel) are handled here.


Prints information about an exception: exception number, error code, address, reason, etc.

7.9 arch/linux/async/signal.c Information

7.10 Functions in arch/linux/async/signal.c

These are the functions defined in arch/linux/async/signal.c.


Initialize the signals to have NONE being blocked. Currently this is NOT of much use to DOSEMU.


Stop additional signals from interrupting DOSEMU.


Allow all signals to interrupt DOSEMU.


Due to signals happening at any time, the actual work to be done because a signal occurs is done here in a serial fashion.

The concept, should this eventualy work, is that a signal should only flag that it has occurred and let DOSEMU deal with it in an orderly fashion as it executes the rest of it's code.


Arguments are:

  • context - signal context to save.
  • signal_call - signal handling routine to be called.
Save into an array structure queue the signal context of the current signal as well as the function to call for dealing with this signal. This is a queue because any signal may occur multiple times before DOSEMU deals with it down the road.


Whenever I/O occurs on devices allowing SIGIO to occur, DOSEMU will be flagged to run this call which inturn checks which fd(s) was set and execute the proper routine to get the I/O from that device.

7.11 Remarks in arch/linux/async/signal.c

Check for keyboard coming from client For now, first byte is interrupt requests from Client

7.12 include/ports.h Information

7.13 base/misc/dosio.c Information

7.14 base/misc/disks.c Information

7.15 Functions in base/misc/disks.c

These are the functions defined in base/misc/disks.c.


Test by opening all floppies/hardrives configured.

7.16 dev/misc/lpt.c Information

7.17 base/dev/misc/timers.c Information

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 dependant on this module for high frequency timer interrupts (IRQ0).

This code will actually generate 18.2 DOS interrupts/second (the code here itself will be triggered about 100 times per second). It will even happily attempt to generate faster clocks, right up to the point where it chokes. Since the absolute best case timing we can get out of Linux is 100Hz, figure that anything approaching or exceeding that isn't going to work well. (The code will attempt to generate up to 10Khz interrupts per second at the moment. Too bad that would probably overflow all internal queues really fast. :)

Speaker emulation, now including port 61h, is also in here. [rz]

7.18 Functions in base/dev/misc/timers.c

These are the functions defined in base/dev/misc/timers.c.


ensure the 0x40 port timer is initially set correctly


Every time we get a TIMER signal from Linux, this procedure is called. It checks to see if we should queue a timer interrupt based on the current values.


do_sound handles the _emulated_ mode pc-speaker emulation.

As far as I can determine all cases of the pc-speaker are now emulated. But I am not sure where Rainer Zimmerman got his (pit[2].mode == 2) || (pit[2].mode == 3) test in the original implementation, it doesn't seem to cause problems though.

The implementation of speaker_on & speaker_off can be found in src/base/speaker.c

Major Changes from version written by Rainter Zimmerman.

o Added support for programs that control the directly through bit 1 of port61.

o Added a generic interface to allow multiple speaker backends.

o Implemented X speaker code so the emulated speaker now works in X.

--EB 21 September 1997


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!


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.

7.19 base/speaker/speaker.c Information

The pc-speaker emulator for Dosemu.

This file contains functions to make a pc speaker beep for dosemu.

Actuall emulation is done in src/base/dev/misc/timers.c in do_sound.

Currenly emulation is only done when the new keyboard is enabled but with a little extra work it should be possible to enable it for the old keyboard code if necessary.

For parts of dosemu that want to beep the pc-speaker (say the video bios) #include "speaker.h" Use 'speaker_on(ms, period)' to turn the pc-speaker on for 'ms' milliseconds with period 'period'. The function returns immediately.

Use 'speaker_off()' To turn the pc-speaker definentily off. This is mostly useful when exiting the program to ensure you aren't killy someones ears :)

'speaker_on' always overrides whatever previous speaker sound was previously given. No mixing happens.

For code that wants to implement speaker emulation. The recommeded method is to add a file in src/base/speaker with the necessary code. Declare it's methods in speaker.h (or somewhere accessible to your code). And call

'register_speaker(gp, on, off)' when your speaker code is ready to function.

gp may be any void pointer value.

gp is passed as the first argument to the functions arguments 'on' and 'off' when global functions 'speaker_on' and 'speaker_off' are called. This allows important state information to be passed to the functions. And reduces reliance on global variables.

The functions 'on' and 'off' besides the extra parameter are called just as the global functions 'speaker_on' and 'speaker_off' are called respectively.

Before the registered function is no longer valid call 'register_speaker(NULL, NULL, NULL)' this will reset the speaker code to it's default speaker functions, which will always work.

--EB 20 Sept 1997


Eric W. Biederman <ebiederm+eric@npwt.net>

7.20 base/misc/shared.c Information

Memory areas needed to be shared between the DOSEMU process and other clients.

7.21 Functions in base/misc/shared.c

These are the functions defined in base/misc/shared.c.


Setup all memory areas to be shared with clients.

7.22 Remarks in base/misc/shared.c

Set to 0 all client request area


Output info required for client activity

7.23 base/misc/dos2linux.c Information

This file contains a simple system for passing information through to DOSEMU from the Linux side. It does not allow dynamic message passing, but it intended to provide useful information for the DOS user.

As such, the current set of implemented commands are : GET_USER_ENVVAR and GET_COMMAND

These are made available to the DOSEMU by using the DOS_HELPER interrupt (Currently 0xE6) and writing a string into a location passed to this interrupt handler using the registers. In the case of GET_USER_ENVVAR the string also contains the name of the environment variable to interrogate. (The string is overwritten with the reply).

7.24 Functions in base/misc/dos2linux.c

These are the functions defined in base/misc/dos2linux.c.


Runs a command and prints the (stdout and stderr) output on the dosemu screen.

Return values mean:

Arguments are:

  • buffer - string with command to execute

7.25 base/misc/ioctl.c Information

7.26 Functions in base/misc/ioctl.c

These are the functions defined in base/misc/ioctl.c.


Initialize fd_sets to NULL for both SIGIO and NON-SIGIO.


Arguments are:

  • fd - File handle to add to select statment
  • want_sigio - want SIGIO (1) if it's available, or not (0).
Add file handle to one of 2 select FDS_SET's depending on whether the kernel can handle SIGIO.


Arguments are:

  • fd - File handle to remove from select statment.
  • used_sigio - used SIGIO (1) if it's available, or not (0).
Remove a file handle from one of 2 select FDS_SET's depending on whether the kernel can handle SIGIO.

7.27 base/dev/misc/cmos.c Information

7.28 base/dev/misc/lpt.c Information

7.29 Functions in base/dev/misc/lpt.c

These are the functions defined in base/dev/misc/lpt.c.


Initialize printer control structures

7.30 base/dev/misc/pci.c Information

7.31 Functions in base/dev/misc/pci.c

These are the functions defined in base/dev/misc/pci.c.


Use standard 32-bit (type 1) access method to read PCI configuration space data


32-bit I/O port output on PCI ports (0xcf8=addr,0xcfc=data) Optimization: trap the config writes (outd 0xcf8 with bit31=1). Since this kind of access is always followed by another R/W access to port 0xcfc, we can just set it as pending and merge it with the following operation, saving two calls to priv_iopl().


Register standard PCI ports 0xcf8-0xcff

7.32 include/doshelpers.h Information

7.33 Remarks in include/doshelpers.h

The Helper Interrupt uses the following groups:

0x00 - Check for DOSEMU 0x01-0x11 - Initialisation functions & Debugging 0x12 - Set hogthreshold (aka garrot?) 0x20 - MFS functions 0x21-0x22 - EMS functions 0x28 - Garrot Functions for use with the mouse 0x29 - Serial functions 0x30 - Whether to use the BOOTDISK predicate 0x33 - Mouse Functions 0x40 - CD-ROM functions 0x50-0x52 - DOSEMU/Linux communications 50 -- run unix command in ES:DX 51,52? 53 -- do system(ES:DX) 0x7a - IPX functions 0x8x -- utility functions 0x80 -- getcwd(ES:DX, size AX) 0x81 -- chdir(ES:DX) 0xfe - called from our MBR, emulate MBR-code. 0xff - Terminate DOSEMU

There are (as yet) no guidelines on choosing areas for new functions.

Next Previous Contents
The DOSEMU team