The DOSEMU Alterer Novices Guide DANG Alistair MacDonald, am20@unix.york.ac.uk For DOSEMU v0.53 pl28 This Document is the DOSEMU Alterer Novices Guide. It is known as the DANG. 1. Introduction This document is the preliminary draft of a manual to help people understand the inner workings of dosemu. It is the goal of this document to create new dosemu hackers. This concept was inspired by the linux kernel hackers guide. This Guide was concieved and originally written by "Corey Sweeney" . It has been completely revised. It is now generated automatically directly from the source code. Special thanks to "James B. MacLean" for supplying the original information. (It was mostly ripped out of a mail message.) "Jochen Hein" has made many useful comments & suggestions. At the end if this document is a section detailing how this guide is put together. This may help you when trying to locate the relevant pieces of code. If you add new code, it would be useful if the relevant markers are added where appropriate. This file is a collective effort. If you don't like one of the explanations, or want to add anything, please send me something! 2. The Main group of Modules These files are used to start DOSEMU as well as hold globally called functions and global vars. 2.1. dos.c Information Initial program executed to run DOSEMU. Gets access to libdosemu and sets international character parms. Finally calls entry point of DOSEMU emulate() function which is loaded above the usual DOS memory area from 0 - 1meg. Emulate() is in emu.c. 2.1.1. Functions in dos.c These are the functions defined in dos.c. 2.1.1.1. dosemu o argc - Count of argumnents. o argc - Actual arguments. Function created by entry point into libdosemu. Called to jump into the emulate function of DOSEMU. 2.1.2. Remarks in dos.c Apparently, no-one has anything interesting to say about dos.c. 2.1.3. Items for Fixing in dos.c Apparently, nothing needs fixing in dos.c. 2.1.4. New Ideas for dos.c Apparently, there are no new ideas for dos.c. 2.2. emu.c Information Here is where DOSEMU gets booted. From emu.c external calls are made to the specific I/O systems (video/keyboard/serial/etc...) to initialize them. Memory is cleared/set up and the boot sector is read from the boot drive. Many SIGNALS are set so that DOSEMU can exploit things like timers, I/O signals, illegal instructions, etc... When every system gives the green light, vm86() is called to switch into vm86 mode and start executing i86 code. The vm86() function will return to DOSEMU when certain `exceptions` occur as when some interrupt instructions occur (0xcd). The top level function emulate() is called from dos.c by way of a dll entry point. 2.2.1. Functions in emu.c These are the functions defined in emu.c. 2.2.1.1. jmp_emulate This function allows the startup program `dos` to know how to call the emulate function by way of the dll headers. Always make sure that this line is the first of emu.c and link emu.o as the first object file to the lib 2.2.1.2. DBGTIME o x - character to print with time. Inline function to debug time differences between different points of execution within DOSEMU. Thanks Ronnie :-). Only used by developers and not expected to execute in any general releases. 2.2.1.3. signal_init Initialize the signals to have NONE being blocked. Currently this is NOT of much use to DOSEMU. 2.2.1.4. cli Stop additional signals from interrupting DOSEMU. 2.2.1.5. sti Allow all signals to interrupt DOSEMU. 2.2.1.6. handle_signals 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. 2.2.1.7. run_vm86 Here is where DOSEMU runs VM86 mode with the vm86() call which also has the registers that it will be called with. It will stop vm86 mode for many reasons, like trying to execute an interrupt, doing port I/O to ports not opened for I/O, etc ... 2.2.1.8. memory_init Set up all memory areas as would be present on a typical i86 during the boot phase. 2.2.1.9. SIGNAL_save o context - signal context to save. o 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. 2.2.1.10. SIGIO_call 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. 2.2.1.11. parse_debugflags o s - string of options. This part is fairly flexible...you specify the debugging flags you wish with -D string. The string consists of the following characters: + turns the following options on (initial state) - turns the following options off a turns all the options on/off, depending on whether +/- is set 0-9 sets debug levels (0 is off, 9 is most verbose) # where # is a letter from the valid option list (see docs), turns that option off/on depending on the +/- state. Any option letter can occur in any place. Even meaningless combinations, such as "01-a-1+0vk" will be parsed without error, so be careful. Some options are set by default, some are clear. This is subject to my whim. You can ensure which are set by explicitly specifying. 2.2.1.12. config_defaults Set all values in the `config` structure to their default value. These will be modified by the config parser. 2.2.1.13. SIG_int Allow DOSEMU to be made aware when a hard interrupt occurs Requires the sig/sillyint.o driver loaded (using NEW modules package), or a kernel patch (implementing sig/int.c driver). The IRQ numbers to monitor are taken from config.sillyint, each bit corresponding to one IRQ. The higher 16 bit are defining the use of SIGIO 2.2.1.14. check_special_mapping This is called after all configuration stuff is done to make sure that no mapped areas are overlapping. It checks EMS, VBIOS, HARDWARE_RAM and exits with "false", if any of it overlapp. 2.2.1.15. emulate o argc - Argument count. o argv - Arguments. Emulate gets called from dos.c. It initializes DOSEMU to prepare it for running in vm86 mode. This involves catching signals, preparing memory, calling all the initialization functions for the I/O subsystems (video/serial/etc...), getting the boot sector instructions and calling vm86(). 2.2.1.16. hardware_init Initialize any leftover hardware. 2.2.1.17. version_init Find version of OS running and set necessary global parms. 2.2.1.18. add_to_io_select o fd - File handle to add to select statment. o want_sigio - Specifiy whether you want SIGIO (1) if it's available, or o not (0). Add file handle to one of 2 select FDS_SET's depending on whether the kernel can handle SIGIO. 2.2.2. Remarks in emu.c DOSEMU must not work within the 1 meg DOS limit, so start of code is loaded at a higher address, at some time this could conflict with other shared libs. If DOSEMU is compiled statically (without shared libs), and org instruction is used to provide the jump above 1 meg. ----- DOSEMU keeps system wide configuration status in a structure called config. ----- The `vm86_struct` is used to pass all the necessary status/registers to DOSEMU when running in vm86 mode. ----- The var `fatalerr` can be given a true value at any time to have DOSEMU exit on the next return from vm86 mode. ----- At this time we have to use SIGALRM in addition to SIGIO I don't (yet) know why the SIGIO signal gets lost sometimes (once per minute or longer). But if it happens, we can retrigger this way over SIGALRM. Normally SIGIO happens before SIGALARM, so nothing hurts. (Hans) ----- If DOSEMU starts up with stderr == stdout, then stderr gets redirected to '/dev/null'. ----- For simpler support of X, DOSEMU can be started by a symbolic link called `xdos` which DOSEMU will use to switch into X-mode. 2.2.3. Items for Fixing in emu.c Apparently, nothing needs fixing in emu.c. 2.2.4. New Ideas for emu.c Apparently, there are no new ideas for emu.c. 2.3. emu.h Information There appears to be no MODULE information for this file. 2.3.1. Functions in emu.h These are the functions defined in emu.h. 2.3.1.1. NEWSETQSIG o sig - the signal to have a handler installed to. o fun - the signal handler function to install All signals that wish to be handled properly in context with the execution of vm86() mode, and signals that wish to use non- reentrant functions should add themselves to the SIGNALS_THAT_QUEUE define and use SETQSIG(). To that end they will also need to be set up in an order such as SIGIO. 2.3.2. Remarks in emu.h We assume system call restarting... under linux 0.99pl8 and earlier, this was the default. SA_RESTART was defined in 0.99pl8 to explicitly request restarting (and thus does nothing). However, if this ever changes, I want to be safe 2.3.3. Items for Fixing in emu.h Apparently, nothing needs fixing in emu.h. 2.3.4. New Ideas for emu.h Apparently, there are no new ideas for emu.h. 3. The Clients group of Modules One of the long term aims of the DOSEMU development team is to provide a client-server based system. This will allow people to add different display systems in more simply. Those in current development are detailed in this section. 3.1. clients/ncurses.c Information This is James' client based around NCURSES. It (un-)succesfully demonstrates the procedure for making initial connections to the server. 3.1.1. Functions in clients/ncurses.c These are the functions defined in clients/ncurses.c. 3.1.1.1. main o argc - Number of Command Line arguments. o argv - Command Line arguments - as an array of char*'s This function does all of the work associated with this client. It grabs the shared memory used to hold the current Video data and makes some comments about its current screen. 3.1.2. Remarks in clients/ncurses.c Some of the functions are undocumented. These are the trivial ones. ----- You must be mad if you want to get involved in all of this Shared memory stuff .... 8-) 3.1.3. Items for Fixing in clients/ncurses.c Apparently, nothing needs fixing in clients/ncurses.c. 3.1.4. New Ideas for clients/ncurses.c Apparently, there are no new ideas for clients/ncurses.c. 4. The DPMI group of Modules DPMI is Lutz's Baby. It's a really important part of the Emulator as far as we are concerned, since it will allow us to run so many more programs and, most importantly, bcc. This is the one thing that the WINE developers want that we haven't been able to give them. If you think you can help .... "Away you Go!" (Sorry to those non-UK folks ... Thats a reference to a UK kids sports programme from my youth ... anyway ... enough of this banter. You'll be wanting to know that this is all about DPMI ...) 4.1. dpmi/dpmi.c Information dpmi.c DOS Protected Mode Interface allows DOS programs to run in the protected mode of 2345..86 processors 4.1.1. Functions in dpmi/dpmi.c These are the functions defined in dpmi/dpmi.c. 4.1.1.1. dpmi_control This function is similar to the vm86() syscall in the kernel and switches to dpmi code. 4.1.1.2. do_default_cpu_exception This is the default CPU exception handler. Exceptions 0, 1, 2, 3, 4, 5 and 7 are reflected to real mode. All other exceptions are terminating the client (and may be dosemu too :-)). 4.1.1.3. do_cpu_exception This calls the DPMI client exception handler. If none is installed do_default_cpu_exception() is called. 4.1.1.4. dpmi_fault This is the brain of DPMI. All CPU exceptions are first reflected (from the signal handlers) to this code. Exception from nonpriveleged instructions INT XX, STI, CLI, HLT and from WINDOWS 3.1 are handled here. All here unhandled exceptions are reflected to do_cpu_exception() 4.1.2. Remarks in dpmi/dpmi.c We are caching ldt here for speed reasons and for Windows 3.1. I would love to have an readonly ldt-alias (located in the first 16MByte for use with 16-Bit descriptors (WIN-LDT)). This is on my wish list for the kernel hackers (Linus mainly) :-))))))). ----- DPMI is designed such that the stack change needs a task switch. We are doing it via an SIGSEGV - instead of one task switch we have now four :-(. Arrgh this is the point where I should start to include DPMI stuff in the kernel, but then we could include the rest of dosemu too. Would Linus love this? I don't :-((((. Anyway I would love to see first a working DPMI port, maybe we will later (with version 0.9 or similar :-)) start with it to get a really fast dos emulator............... 4.1.3. Items for Fixing in dpmi/dpmi.c don't free protected mode stack if DPMI client terminates from exception handler ----- not yet implemented ----- not yet implemented 4.1.4. New Ideas for dpmi/dpmi.c Simulate Local Descriptor Table for MS-Windows 3.1 must be read only, so if krnl386.exe/krnl286.exe try to write to this table, we will bomb into sigsegv() and and emulate direct ldt access 5. The Video group of Modules All of the Video handling code is in the "video" subdirectory. There is one file for each video card or chipset and the master file. To Add a new card, it needs a set of save & restore routines putting in a file here. 5.1. video/vc.c Information Here's all the calls to the code to try and properly save & restore the video state between VC's and the attempts to control updates to the VC whilst the user is using another. We map between the real screen address and that used by DOSEMU here too. Attempts to use a cards own bios require the addition of the parameter "graphics" to the video statement in "/etc/dosemu.conf". This will make the emulator try to execute the card's initialization routine which is normally located at address c000:0003. This can now be changed as an option. 5.1.1. Functions in video/vc.c We appear to have no information on the functions in video/vc.c. 5.1.2. Remarks in video/vc.c Apparently, no-one has anything interesting to say about video/vc.c. 5.1.3. Items for Fixing in video/vc.c Apparently, nothing needs fixing in video/vc.c. 5.1.4. New Ideas for video/vc.c Apparently, there are no new ideas for video/vc.c. 5.2. video/video.c Information There appears to be no MODULE information for this file. 5.2.1. Functions in video/video.c These are the functions defined in video/video.c. 5.2.1.1. video_init Set pointer to correct structure of functions to initialize, close, etc... video routines. 5.2.2. Remarks in video/video.c Apparently, no-one has anything interesting to say about video/video.c. 5.2.3. Items for Fixing in video/video.c Apparently, nothing needs fixing in video/video.c. 5.2.4. New Ideas for video/video.c Apparently, there are no new ideas for video/video.c. 5.3. termio.c Information This handles the keyboard. Two keyboard modes are handled 'raw' and 'xlate'. 'Raw' works with codes as sent out by the kernel and 'xlate' uses plain ASCII as used over serial lines. The mapping for different languages & the two ALT- keys is done here, but the definitions are elsewhere. Only the default (US) keymap is stored here. 5.3.1. Functions in termio.c These are the functions defined in termio.c. 5.3.1.1. keyboard_init Initialize the keyboard to DOSEMU deafaults plus those requested in the configs if allowable. 5.3.1.2. convascii o cc - count of characters on queue For dealing with translating esc character sequences received in XLATE mode. Every effort is made to give the characters a time slice of approx. 3/4 of a second to arrive at DOSEMU. Also handles alt-keys and other character translations. 5.3.2. Remarks in termio.c Code is called at start up to set up the terminal line for non-raw mode. 5.3.3. Items for Fixing in termio.c Apparently, nothing needs fixing in termio.c. 5.3.4. New Ideas for termio.c Apparently, there are no new ideas for termio.c. 6. 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. 6.1. bios_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 6.1.1. Functions in bios_emm.c We appear to have no information on the functions in bios_emm.c. 6.1.2. Remarks in bios_emm.c Apparently, no-one has anything interesting to say about bios_emm.c. 6.1.3. Items for Fixing in bios_emm.c Apparently, nothing needs fixing in bios_emm.c. 6.1.4. New Ideas for bios_emm.c Apparently, there are no new ideas for bios_emm.c. 6.2. 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. 6.2.1. Functions in xms.c We appear to have no information on the functions in xms.c. 6.2.2. Remarks in xms.c Apparently, no-one has anything interesting to say about xms.c. 6.2.3. Items for Fixing in xms.c Apparently, nothing needs fixing in xms.c. 6.2.4. New Ideas for xms.c Apparently, there are no new ideas for xms.c. 6.3. keymaps.c Information These are definitions, giving which key is related to which scancode in raw keyboard mode. Basically, the code of 'x' on a US keyboard may be that of a 'Y' on a German keyboard. This way, all types of keyboard can be represented under DOSEMU. Also, the right ALT-key is often a function key in it's own right. 6.3.1. Functions in keymaps.c We appear to have no information on the functions in keymaps.c. 6.3.2. Remarks in keymaps.c Apparently, no-one has anything interesting to say about keymaps.c. 6.3.3. Items for Fixing in keymaps.c Apparently, nothing needs fixing in keymaps.c. 6.3.4. New Ideas for keymaps.c Apparently, there are no new ideas for keymaps.c. 6.4. sigsegv.c Information There appears to be no MODULE information for this file. 6.4.1. Functions in sigsegv.c These are the functions defined in sigsegv.c. 6.4.1.1. vm86_GP_fault All from the kernel unhandled general protection faults from V86 mode are handled here. This are mainly port IO and the HLT instruction. 6.4.1.2. dosemu_fault All CPU exceptions (except 13=general_protection from V86 mode, which is directly scaned by the kernel) are handled here. 6.4.2. Remarks in sigsegv.c In a properly functioning emulator :-), sigsegv's will never come while in a non-reentrant system call (ioctl, select, etc). Therefore, there's really no reason to worry about them, so I say that I'm NOT in a signal handler (I might make this a little clearer later, to show that the purpose of in_sighandler is to stop non-reentrant system calls from being reentered. I reiterate: sigsegv's should only happen when I'm running the vm86 system call, so I really shouldn't be in a non-reentrant system call (except maybe vm86) - Robert Sanders 6.4.3. Items for Fixing in sigsegv.c Apparently, nothing needs fixing in sigsegv.c. 6.4.4. New Ideas for sigsegv.c Apparently, there are no new ideas for sigsegv.c. 6.5. int.h Information Centralized area for interrupt service routine calls and support functions. 6.5.1. Functions in int.h These are the functions defined in int.h. 6.5.1.1. DO_INT DO_INT is used to deal with interrupts returned to DOSEMU by the kernel. 6.5.1.2. DEFAULT_INTERRUPT DEFAULT_INTERRUPT is the default interrupt service routine called when DOSEMU initializes. 6.5.1.3. SETUP_INTERRUPTS SETUP_INTERRUPTS is used to initialize those interrupt calls that we are specifically handling in protected mode. 6.5.2. Remarks in int.h Apparently, no-one has anything interesting to say about int.h. 6.5.3. Items for Fixing in int.h Apparently, nothing needs fixing in int.h. 6.5.4. New Ideas for int.h Apparently, there are no new ideas for int.h. 6.6. ports.h Information There appears to be no MODULE information for this file. 6.6.1. Functions in ports.h These are the functions defined in ports.h. 6.6.1.1. inb INB is used to do controlled emulation of input from ports. 6.6.2. Remarks in ports.h Apparently, no-one has anything interesting to say about ports.h. 6.6.3. Items for Fixing in ports.h Apparently, nothing needs fixing in ports.h. 6.6.4. New Ideas for ports.h Apparently, there are no new ideas for ports.h. 6.7. dosio.c Information There appears to be no MODULE information for this file. 6.7.1. Functions in dosio.c These are the functions defined in dosio.c. 6.7.1.1. memory_setup Setup HMA area via IPC. Call EMS and XMS initialization routines. 6.7.2. Remarks in dosio.c Apparently, no-one has anything interesting to say about dosio.c. 6.7.3. Items for Fixing in dosio.c Apparently, nothing needs fixing in dosio.c. 6.7.4. New Ideas for dosio.c Apparently, there are no new ideas for dosio.c. 6.8. mouse/mouse.c Information There appears to be no MODULE information for this file. 6.8.1. Functions in mouse/mouse.c These are the functions defined in mouse/mouse.c. 6.8.1.1. mouse_init Initialize internal mouse. 6.8.2. Remarks in mouse/mouse.c Apparently, no-one has anything interesting to say about mouse/mouse.c. 6.8.3. Items for Fixing in mouse/mouse.c Apparently, nothing needs fixing in mouse/mouse.c. 6.8.4. New Ideas for mouse/mouse.c Apparently, there are no new ideas for mouse/mouse.c. 6.9. serial.c Information There appears to be no MODULE information for this file. 6.9.1. Functions in serial.c These are the functions defined in serial.c. 6.9.1.1. serial_init The following is the master serial initialization function called externally (from this serial.c module) during DOSEMU startup. It initializes all the configured serial ports. 6.9.2. Remarks in serial.c Apparently, no-one has anything interesting to say about serial.c. 6.9.3. Items for Fixing in serial.c Apparently, nothing needs fixing in serial.c. 6.9.4. New Ideas for serial.c Apparently, there are no new ideas for serial.c. 6.10. disks.c Information There appears to be no MODULE information for this file. 6.10.1. Functions in disks.c These are the functions defined in disks.c. 6.10.1.1. disk_init Test by opening all floppies/hardrives configured. 6.10.2. Remarks in disks.c Apparently, no-one has anything interesting to say about disks.c. 6.10.3. Items for Fixing in disks.c Apparently, nothing needs fixing in disks.c. 6.10.4. New Ideas for disks.c Apparently, there are no new ideas for disks.c. 6.11. cpu.c Information CPU/V86 support for dosemu 6.11.1. Functions in cpu.c These are the functions defined in cpu.c. 6.11.1.1. cpu_init Setup initial interrupts which can be revectored so that the kernel does not need to return to DOSEMU if such an interrupt occurs. 6.11.2. Remarks in cpu.c Apparently, no-one has anything interesting to say about cpu.c. 6.11.3. Items for Fixing in cpu.c Apparently, nothing needs fixing in cpu.c. 6.11.4. New Ideas for cpu.c Apparently, there are no new ideas for cpu.c. 6.12. lpt.c Information There appears to be no MODULE information for this file. 6.12.1. Functions in lpt.c These are the functions defined in lpt.c. 6.12.1.1. printer_init Initialize printer control structures 6.12.2. Remarks in lpt.c Apparently, no-one has anything interesting to say about lpt.c. 6.12.3. Items for Fixing in lpt.c Apparently, nothing needs fixing in lpt.c. 6.12.4. New Ideas for lpt.c Apparently, there are no new ideas for lpt.c. 6.13. sig/int.c Information Silly Interrupt Generator device driver for Linux 1.1.47 or higher. Needs the new modules utilities. The driver uses MAJOR 19, the minors can be from 3 .. 15 and represent the IRQ-level, which is intercepted for use with DOSEMU. This driver must be compiled on the system it is running on, see the doc in the modules packages. To load it (must be the superuser) type insmod sillyint.o or insmod sillyint.o SIG_MAJOR=mm if you want to use MAJOR mm intstead of the default 19. To make the devices go into your /dev directory and create a subdirectory called int. Change into this directory and add a node for the IRQ you wish to use. Bare in mind that in the future if you use another interrupt, you'll have to come to /dev/int and add it too. To MaKe this NODe, type: mknod c 19 where is the IRQ number you wish to use. I will add at this time that SIG will not open an interrupt up that is already in use. This will mean that some applications that access their interrupts from boot up like ethernet cards, must not be configured into the kernel or must be given port bases, that are not probed by the kernel. You may use the kernel command line feature, either from LILO or LOADLIN to change those ports at boot time of Linux. 6.13.1. Functions in sig/int.c We appear to have no information on the functions in sig/int.c. 6.13.2. Remarks in sig/int.c Apparently, no-one has anything interesting to say about sig/int.c. 6.13.3. Items for Fixing in sig/int.c Apparently, nothing needs fixing in sig/int.c. 6.13.4. New Ideas for sig/int.c Apparently, there are no new ideas for sig/int.c. 7. The PIC group of Modules All of the PIC handling code is in the "timer" subdirectory. Odd isn't it. 7.1. timer/pic.c Information pic.c is a fairly complete emulation of both 8259 Priority Interrupt Controllers. It also includes provision for 16 lower level interrupts. This implementation supports the following i/o commands: ICW1 bits 0 and 1 number of ICWs to expect ICW2 bits 3 - 7 base address of IRQs ICW3 no bits accepted but ignored ICW4 no bits accepted but ignored OCW1 all bits sets interrupt mask OCW2 bits 7,5-0 EOI commands only OCW3 bits 0,1,5,6 select read register, select special mask mode Reads of both pic ports are supported completely. An important concept to understand in pic is the interrupt level. This is a value which represents the priority of the current interrupt. It is used to identify interrupts, and IRQs can be mapped to these levels(see pic.h ). The currently active interrupt level is maintained in pic_ilevel, which is globally available, A pic_ilevel of 32 means no interrupts are active; 0, the highest priority, represents the NMI. IRQs 0 through 15 are mapped, in priority order, to values of 1-15 (there is no IRQ2 in an AT). Values of 16 - 31 represent additional interrupt levels available for internal dosemu usage. More detail is available in the file README.pic 7.1.1. Functions in timer/pic.c These are the functions defined in timer/pic.c. 7.1.1.1. write_pic0 write_pic_0() and write_pic1() implement dos writes to the pic ports. They are called by the code that emulates inb and outb instructions. Each function implements both ports for the pic: pic0 is on ports 0x20 and 0x21; pic1 is on ports 0xa0 and 0xa1. These functions take two arguements: a port number (0 or 1) and a value to be written. 7.1.1.2. read_pic0 read_pic0 and read_pic1 return the values for the interrupt mask register (port 1), or either the in service register or interrupt request register, as determined by the last OCW3 command (port 0). These functions take a single parameter, which is a port number (0 or 1). They are called by code that emulates the inb instruction. 7.1.1.3. pic_mask The pic maintains an additional interrupt mask which is not visible to the DOS process. This is normally cleared (enabling an interrupt) when an interrupt is initialized, but dosemu code may choose to use this mask internally. One possible use is to implement the interrupt gate controlled by the OUT2 bit of the 16550A UART's Modem Control Register. This mask is cleared by pic_unmaski() and set by pic_maski() 7.1.1.4. pic_seti pic_seti is used to initialize an interrupt for dosemu. It requires three parameters. The first parameter is the interrupt level, which man select the NMI, any of the IRQs, or any of the 16 extra levels (16 - 31). The second parameter is the dosemu function to be called when the interrupt is activated. This function should call do_irq() if the DOS interruptis really to be activated. If there is no special dosemu code to call, the second parameter can specify do_irq(), but see that description for some special considerations. 7.1.1.5. run_irqs run_irqs, which is initiated via the macro pic_run, is the "brains" of the pic. It is called from the vm86() loop, checks for the highest priority interrupt requested, and executes it. This function is written in assembly language in order to take advantage of atomic (indivisible) instructions, so that it should be safe for a two process model, even in a multiple CPU machine. A c language version was started, but it became impossible, even with in-line assembly macros, because such macros can only return a single result. If I find a way to do it in c, I will, but don't hold your breath. 7.1.1.6. do_irq do_irq() calls the correct do_int(). It then executes a vm86 loop until an outb( end-of-interrupt) is found. For priority levels 0 and >15 (not real IRQs), vm86 executes once, then returns, since no outb20 will come. Returns: 0 = complete, 1 = interrupt not run because it directly calls our "bios" See run_timer_tick() in timer.c for an example This routine is RE-ENTRANT - it calls run_irqs, which which may call an interrupt routine, which may call do_irq(). Be Careful! !!!!!!!!!!!!!!!!!! No single interrupt is ever re-entered. 7.1.1.7. pic_request pic_request triggers an interrupt. There is presently no way to "un- trigger" an interrupt. The interrupt will be initiated the next time pic_run is called, unless masked or superceded by a higher priority interrupt. pic_request takes one arguement, an interrupt level, which specifies the interrupt to be triggered. If that interrupt is already active, the request will be queued until all active interrupts have been completed. The queue is only one request deep for each interrupt, so it is the responsibility of the interrupt code to retrigger itself if more interrupts are needed. 7.1.1.8. pic_iret pic_iret is used to sense that all active interrupts are really complete, so that interrupts queued by pic_request can be triggered. Interrupts end when they issue an outb 0x20 to the pic, however it is not yet safe at that time to retrigger interrupts, since the stack has not been restored to its initial state by an iret. pic_iret is called whenever interrupts have been enabled by a popf, sti, or iret. It determines if an iret was the cause by comparing stack contents with cs and ip. If so, it decrements a count of interrupts on the stack (set by do_irq()). If the count is then zero, pic_iret moves all queued interrupts to the interrupt request register. It is possible for pic_iret to be fooled by dos code; for this reason active interrupts are checked, any queued interrupts that are also active will remain queued. 7.1.2. Remarks in timer/pic.c Apparently, no-one has anything interesting to say about timer/pic.c. 7.1.3. Items for Fixing in timer/pic.c Apparently, nothing needs fixing in timer/pic.c. 7.1.4. New Ideas for timer/pic.c Apparently, there are no new ideas for timer/pic.c. 7.2. timer/pic.h Information There appears to be no MODULE information for this file. 7.2.1. Functions in timer/pic.h We appear to have no information on the functions in timer/pic.h. 7.2.2. Remarks in timer/pic.h Apparently, no-one has anything interesting to say about timer/pic.h. 7.2.3. Items for Fixing in timer/pic.h Apparently, nothing needs fixing in timer/pic.h. 7.2.4. New Ideas for timer/pic.h Apparently, there are no new ideas for timer/pic.h. 8. And Finally ... The Following items are used to delimit the text used to create this file. Whilst it is not necessary to know this, they are included because they may be useful for searching, as they are (at least at the moment) reasonably unique. DANG_BEGIN_MODULE / DANG_END_MODULE This will bracket a description of the file (normally at the start). DANG_BEGIN_FUNCTION / DANG_END_FUNCTION This brackets a description of functions (good this, isn't it!) Not every function needs to be described in this way - just the major ones. DANG_BEGIN_REMARK / DANG_END_REMARK This brackets descriptions of obscure items, like data structures and architecture. DANG_FIXTHIS This is a one line item, indicating a an area requiring a fix, or redesign. DANG_BEGIN_NEWIDEA / DANG_END_NEWIDEA New Ideas Start Here! As Ideas are proposed, that get added with their description, so that future generations can laugh at or code the ideas ..... These bracket the idea description. DANG_BEGIN_CHANGELOG / DANG_END_CHANGELOG Changelogs - very useful for bug fixing, and avvailable for use with DPR (or that's the theory)