  The DOSEMU Alterer Novices Guide
  Author: Alistair MacDonald, alistair\@slitesys.demon.co.uk
  version dosemu-0.99.8

  This Document is the DOSEMU Alterer Novices Guide. It is known as the
  DANG.
  ______________________________________________________________________

  Table of Contents

























































  1. Introduction

  2. The Main group of Modules

     2.1 dos.c Information
     2.2 Functions in dos.c
        2.2.1 dosemu
     2.3 emu.c Information
     2.4 Functions in emu.c
        2.4.1 jmp_emulate
        2.4.2 SIG_int
        2.4.3 emulate
     2.5 Remarks in emu.c
     2.6 include/emu.h Information
     2.7 Functions in include/emu.h
        2.7.1 NEWSETQSIG
     2.8 Remarks in include/emu.h

  3. The Init group of Modules

     3.1 base/init/init.c Information
     3.2 Functions in base/init/init.c
        3.2.1 dosemu_banner
        3.2.2 stdio_init
        3.2.3 time_setting_init
        3.2.4 timer_interrupt_init
        3.2.5 hardware_setup
        3.2.6 map_video_bios
        3.2.7 map_hardware_ram
        3.2.8 map_custom_bios
        3.2.9 bios_mem_setup
        3.2.10 memory_init
        3.2.11 device_init
        3.2.12 low_mem_init
        3.2.13 version_init
     3.3 Items for Fixing in base/init/init.c
     3.4 base/init/config.c Information
     3.5 Functions in base/init/config.c
        3.5.1 cpu_override
        3.5.2 config_defaults
        3.5.3 config_init
        3.5.4 parse_debugflags
     3.6 Remarks in base/init/config.c
     3.7 base/init/dev_list.c Information

  4. The DPMI group of Modules

     4.1 dosext/dpmi/dpmi.c Information
     4.2 Functions in dosext/dpmi/dpmi.c
        4.2.1 dpmi_control
        4.2.2 run_pm_int
        4.2.3 do_default_cpu_exception
        4.2.4 do_cpu_exception
        4.2.5 dpmi_fault
     4.3 Remarks in dosext/dpmi/dpmi.c
     4.4 Items for Fixing in dosext/dpmi/dpmi.c
     4.5 New Ideas for dosext/dpmi/dpmi.c
     4.6 dosext/dpmi/msdos.h Information
     4.7 Functions in dosext/dpmi/msdos.h
        4.7.1 msdos_pre_extender
        4.7.2 msdos_post_extender

  5. The Video group of Modules

     5.1 env/video/vc.c Information
     5.2 env/video/video.c Information
     5.3 Functions in env/video/video.c
        5.3.1 video_init
     5.4 Remarks in env/video/video.c
     5.5 env/video/X.c Information
     5.6 Functions in env/video/X.c
        5.6.1 X_close
        5.6.2 X_close
        5.6.3 X_shm_init
        5.6.4 X_shm_init
        5.6.5 X_handle_events
        5.6.6 graphics_cmap_init
        5.6.7 X_set_videomode
        5.6.8 X_setmode
        5.6.9 X_update_screen
        5.6.10 X_change_mouse_cursor
        5.6.11 set_mouse_position
     5.7 Remarks in env/video/X.c
     5.8 env/video/vgaemu.c Information
     5.9 Functions in env/video/vgaemu.c
        5.9.1 VGA_emulate_outb
        5.9.2 VGA_emulate_inb
        5.9.3 vga_emu_fault
        5.9.4 vga_emu_init
        5.9.5 vga_emu_update
        5.9.6 vgaemu_switch_plane
        5.9.7 vga_emu_switch_bank
        5.9.8 vga_emu_find_mode
        5.9.9 vga_emu_setmode
        5.9.10 vga_emu_set_textsize
        5.9.11 dirty_all_video_pages
        5.9.12 vga_emu_set_text_page
        5.9.13 dirty_all_vga_colors
        5.9.14 changed_vga_colors
        5.9.15 vgaemu_adj_cfg
     5.10 env/video/vesa.c Information
     5.11 Functions in env/video/vesa.c
        5.11.1 vbe_init
        5.11.2 do_vesa_int
     5.12 env/video/vesabios.S Information
     5.13 env/video/vesabios_pm.S Information
     5.14 env/video/attremu.c Information
     5.15 Functions in env/video/attremu.c
        5.15.1 Attr_init
        5.15.2 Attr_get_entry
        5.15.3 Attr_set_entry
        5.15.4 Attr_read_value
        5.15.5 Attr_write_value
        5.15.6 Attr_get_index
     5.16 env/video/dacemu.c Information
     5.17 Functions in env/video/dacemu.c
        5.17.1 DAC_init
        5.17.2 DAC_set_width
        5.17.3 DAC_get_entry
        5.17.4 DAC_set_entry
        5.17.5 DAC_rgb2gray
        5.17.6 DAC_set_read_index
        5.17.7 DAC_set_write_index
        5.17.8 DAC_read_value
        5.17.9 DAC_write_value
        5.17.10 DAC_get_pel_mask
        5.17.11 DAC_set_pel_mask
        5.17.12 DAC_get_state
     5.18 env/video/seqemu.c Information
     5.19 env/video/crtcemu.c Information
     5.20 Functions in env/video/crtcemu.c
        5.20.1 CRTC_init
     5.21 env/video/remap.c Information
     5.22 env/video/remap_asm.S Information
     5.23 env/video/console.c Information
     5.24 env/video/dualmon.c Information
     5.25 Functions in env/video/dualmon.c
        5.25.1 MDA_init
     5.26 Remarks in env/video/dualmon.c
     5.27 env/video/et4000.c Information
     5.28 env/video/hgc.c Information
     5.29 base/bios/int10.c Information
     5.30 env/video/s3.c Information
     5.31 env/video/terminal.c Information
     5.32 env/video/trident.c Information
     5.33 env/video/vga.c Information
     5.34 env/video/vgaemu.c Information
     5.35 Functions in env/video/vgaemu.c
        5.35.1 VGA_emulate_outb
        5.35.2 VGA_emulate_inb
        5.35.3 vga_emu_fault
        5.35.4 vga_emu_init
        5.35.5 vga_emu_update
        5.35.6 vgaemu_switch_plane
        5.35.7 vga_emu_switch_bank
        5.35.8 vga_emu_find_mode
        5.35.9 vga_emu_setmode
        5.35.10 vga_emu_set_textsize
        5.35.11 dirty_all_video_pages
        5.35.12 vga_emu_set_text_page
        5.35.13 dirty_all_vga_colors
        5.35.14 changed_vga_colors
        5.35.15 vgaemu_adj_cfg
     5.36 include/vgaemu.h Information

  6. The Keyboard group of Modules

     6.1 base/keyboard/keymaps.c Information
     6.2 Remarks in base/keyboard/keymaps.c
     6.3 base/keyboard/serv_xlat.c Information
     6.4 Functions in base/keyboard/serv_xlat.c
        6.4.1 putrawkey
        6.4.2 putkey
        6.4.3 set_shiftstate
     6.5 base/keyboard/serv_backend.c Information
     6.6 base/keyboard/serv_8042.c Information
     6.7 base/keyboard/keyb_raw.c Information
     6.8 Functions in base/keyboard/keyb_raw.c
        6.8.1 raw_keyboard_init
     6.9 base/keyboard/keyb_slang.c Information
     6.10 Functions in base/keyboard/keyb_slang.c
        6.10.1 slang_keyb_init()

  7. The Misc group of Modules

     7.1 dosext/misc/emm.c Information
     7.2 dosext/misc/xms.c Information
     7.3 base/async/int.c Information
     7.4 Functions in base/async/int.c
        7.4.1 DEFAULT_INTERRUPT
        7.4.2 ms_dos
        7.4.3 run_caller_func(i, from_int)
        7.4.4 DO_INT
        7.4.5 setup_interrupts
        7.4.6 int_vector_setup
     7.5 Remarks in base/async/int.c
     7.6 include/int.h Information
     7.7 arch/linux/async/sigsegv.c Information
     7.8 Functions in arch/linux/async/sigsegv.c
        7.8.1 dosemu_fault(int, struct sigcontext_struct);
        7.8.2 print_exception_info
     7.9 arch/linux/async/signal.c Information
     7.10 Functions in arch/linux/async/signal.c
        7.10.1 signal_init
        7.10.2 cli
        7.10.3 sti
        7.10.4 handle_signals
        7.10.5 SIGNAL_save
        7.10.6 SIGIO_call
     7.11 Remarks in arch/linux/async/signal.c
     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
        7.15.1 disk_init
     7.16 dev/misc/lpt.c Information
     7.17 base/dev/misc/timers.c Information
     7.18 Functions in base/dev/misc/timers.c
        7.18.1 initialize_timers
        7.18.2 timer_tick
        7.18.3 do_sound
        7.18.4 timer_int_engine
     7.19 base/speaker/speaker.c Information
     7.20 base/misc/shared.c Information
     7.21 Functions in base/misc/shared.c
        7.21.1 shared_qf_memory_init
     7.22 Remarks in base/misc/shared.c
     7.23 base/misc/dos2linux.c Information
     7.24 Functions in base/misc/dos2linux.c
        7.24.1 run_unix_command
     7.25 base/misc/ioctl.c Information
     7.26 Functions in base/misc/ioctl.c
        7.26.1 io_select_init
        7.26.2 add_to_io_select
        7.26.3 remove_from_io_select
     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
        7.29.1 printer_init
     7.30 base/dev/misc/pci.c Information
     7.31 Functions in base/dev/misc/pci.c
        7.31.1 pci_read_header
        7.31.2 pci_read_header
        7.31.3 pci_read_header
     7.32 include/doshelpers.h Information
     7.33 Remarks in include/doshelpers.h
     7.34 dosext/drivers/aspi.c Information

  8. The CPU_Intel group of Modules

     8.1 emu-i386/cpu.c Information
     8.2 Functions in emu-i386/cpu.c
        8.2.1 cpu_trap_0f
        8.2.2 cpu_setup
     8.3 emu-i386/ports.c Information
     8.4 Functions in emu-i386/ports.c
        8.4.1 port_inb(ioport_t port)
        8.4.2 port_outb(ioport_t port, Bit8u byte)
        8.4.3 port_inw(ioport_t port)
        8.4.4 port_outw(ioport_t port, Bit16u word)
        8.4.5 port_ind(ioport_t port)
        8.4.6 special_port_inb,special_port_outb
        8.4.7 port_init()
        8.4.8 extra_port_init()
        8.4.9 port_register_handler
        8.4.10 port_allow_io
        8.4.11 set_ioperm
     8.5 Remarks in emu-i386/ports.c
     8.6 Items for Fixing in emu-i386/ports.c
     8.7 emu-i386/do_vm86.c Information
     8.8 Functions in emu-i386/do_vm86.c
        8.8.1 vm86_GP_fault
        8.8.2 run_vm86
     8.9 Remarks in emu-i386/do_vm86.c
     8.10 emu-i386/fake_cpu.c Information
     8.11 emu-i386/n_ports.c Information
     8.12 emu-i386/cputime.c Information
     8.13 Functions in emu-i386/cputime.c
        8.13.1 GETcpuTIME
        8.13.2 GETusTIME(sc)
        8.13.3 GETtickTIME(sc)
        8.13.4 GETusSYSTIME()
     8.14 Remarks in emu-i386/cputime.c

  9. The Serial group of Modules

     9.1 base/serial/ser_defs.h Information
     9.2 Remarks in base/serial/ser_defs.h
     9.3 base/serial/ser_init.c Information
     9.4 Functions in base/serial/ser_init.c
        9.4.1 serial_init
     9.5 Items for Fixing in base/serial/ser_init.c
     9.6 base/serial/ser_ports.c Information
     9.7 Functions in base/serial/ser_ports.c
        9.7.1 do_serial_in
        9.7.2 do_serial_out
     9.8 Items for Fixing in base/serial/ser_ports.c
     9.9 base/serial/ser_irq.c Information
     9.10 Functions in base/serial/ser_irq.c
        9.10.1 serial_int_engine
        9.10.2 pic_serial_run
        9.10.3 serial_run
     9.11 Remarks in base/serial/ser_irq.c
     9.12 Items for Fixing in base/serial/ser_irq.c
     9.13 base/serial/int14.c Information
     9.14 Functions in base/serial/int14.c
        9.14.1 int14
     9.15 New Ideas for base/serial/int14.c
     9.16 base/serial/fossil.c Information
     9.17 Items for Fixing in base/serial/fossil.c
     9.18 include/serial.h Information
     9.19 Items for Fixing in include/serial.h

  10. The Mouse group of Modules

     10.1 base/mouse/mouse.c Information
     10.2 Functions in base/mouse/mouse.c
        10.2.1 mouse_init
     10.3 Remarks in base/mouse/mouse.c

  11. The Bios group of Modules

     11.1 base/bios/bios.S Information
     11.2 base/bios/hlt.c Information
     11.3 Functions in base/bios/hlt.c
        11.3.1 hlt_init(void)
        11.3.2 hlt_handle()

  12. The PIC group of Modules

     12.1 base/dev/pic/pic.c Information
     12.2 Functions in base/dev/pic/pic.c
        12.2.1 pic_print
        12.2.2 write_pic0,write_pic1
        12.2.3 read_pic0,read_pic1
        12.2.4 pic_mask,pic_unmask
        12.2.5 pic_seti
        12.2.6 run_irqs
        12.2.7 do_irq
        12.2.8 pic_request
        12.2.9 pic_iret
        12.2.10 pic_watch
        12.2.11 pic_pending
        12.2.12 pic_activate
        12.2.13 pic_sched
     12.3 Remarks in base/dev/pic/pic.c
     12.4 include/pic.h Information

  13. The Sound group of Modules

     13.1 dosext/sound/sound.c Information
     13.2 Functions in dosext/sound/sound.c
        13.2.1 sb_io_read
        13.2.2 adlib_io_read
        13.2.3 mpu401_io_read
        13.2.4 sb_io_write
        13.2.5 sb_dsp_write
     13.3 Remarks in dosext/sound/sound.c
     13.4 Items for Fixing in dosext/sound/sound.c
     13.5 arch/linux/dosext/sound/linux_sound.c Information
     13.6 base/dev/dma/dma.c Information
     13.7 Remarks in base/dev/dma/dma.c
     13.8 Items for Fixing in base/dev/dma/dma.c

  14. The FileAccess group of Modules

     14.1 dosext/mfs/mfs.c Information
     14.2 Remarks in dosext/mfs/mfs.c
     14.3 Items for Fixing in dosext/mfs/mfs.c

  15. The Threads group of Modules

     15.1 arch/linux/threads/lt-threads.c Information
     15.2 Functions in arch/linux/threads/lt-threads.c
        15.2.1 Making room on the stack
        15.2.2 Setting User Space Stack limits
        15.2.3 Queuing tools
        15.2.4 Avoiding Libc reentrancy Problems
        15.2.5 getting page aligned memory from the heap
        15.2.6 Name List Tools
        15.2.7 Exiting a thread
        15.2.8 Suspending / resuming a thread
        15.2.9 Locking Resources
        15.2.10 Sending and receiving messages
        15.2.11 Creating (starting) a thread
        15.2.12 Some debugging aids
     15.3 include/lt-threads.h Information
     15.4 Functions in include/lt-threads.h
        15.4.1 The thread itself
        15.4.2 A thread's exit function
        15.4.3 Accessing a thread's TCB
        15.4.4 Looping through all TCBs
        15.4.5 Atomic inline Functions
        15.4.6 Misc inline Functions
     15.5 Data Definitions in include/lt-threads.h
        15.5.1 TCB  (Thread Control Block)
  16. And Finally ...



  ______________________________________________________________________

  11..  IInnttrroodduuccttiioonn

  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"
  <corey@interaccess.com>. It has been completely revised. It is now
  generated automatically directly from the source code. Special thanks
  to "James B. MacLean" <macleajb@ednet.ns.ca> 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!





  22..  TThhee MMaaiinn ggrroouupp ooff MMoodduulleess

  These files are used to start DOSEMU as well as hold globally called
  functions and global vars.



  22..11..  ddooss..cc IInnffoorrmmaattiioonn

  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.


  22..22..  FFuunnccttiioonnss iinn ddooss..cc

  These are the functions defined in dos.c.


  22..22..11..  ddoosseemmuu



  Arguments are:

  +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.


  22..33..  eemmuu..cc IInnffoorrmmaattiioonn

  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.


  22..44..  FFuunnccttiioonnss iinn eemmuu..cc

  These are the functions defined in emu.c.


  22..44..11..  jjmmpp__eemmuullaattee


  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





  22..44..22..  SSIIGG__iinntt


  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





  22..44..33..  eemmuullaattee



  Arguments are:

  +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().







  22..55..  RReemmaarrkkss iinn eemmuu..cc

  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.


  22..66..  iinncclluuddee//eemmuu..hh IInnffoorrmmaattiioonn


  22..77..  FFuunnccttiioonnss iinn iinncclluuddee//eemmuu..hh

  These are the functions defined in include/emu.h.


  22..77..11..  NNEEWWSSEETTQQSSIIGG



  Arguments are:

  +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
     ADDSET_SIGNALS_THAT_QUEUE define and use SETQSIG(). To that end
     they will also need to be set up in an order such as SIGIO.





  22..88..  RReemmaarrkkss iinn iinncclluuddee//eemmuu..hh

  The `vm86_struct` is used to pass all the necessary status/registers
  to DOSEMU when running in vm86 mode.

  -----

  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

  -----

  DOSEMU keeps system wide configuration status in a structure called
  config.

  -----

  The var `fatalerr` can be given a true value at any time to have
  DOSEMU exit on the next return from vm86 mode.


  33..  TThhee IInniitt ggrroouupp ooff MMoodduulleess

  These files are used for initialization and runtime configuration of
  DOSEMU



  33..11..  bbaassee//iinniitt//iinniitt..cc IInnffoorrmmaattiioonn


  33..22..  FFuunnccttiioonnss iinn bbaassee//iinniitt//iinniitt..cc

  These are the functions defined in base/init/init.c.


  33..22..11..  ddoosseemmuu__bbaannnneerr


  Setup the call stack to draw the dosemu banner





  33..22..22..  ssttddiioo__iinniitt


  Initialize stdio, open debugging output file if user specified one





  33..22..33..  ttiimmee__sseettttiinngg__iinniitt


  Beats me





  33..22..44..  ttiimmeerr__iinntteerrrruupptt__iinniitt


  Tells the OS to send us periodic timer messages





  33..22..55..  hhaarrddwwaarree__sseettuupp


  Initialize any leftover hardware.





  33..22..66..  mmaapp__vviiddeeoo__bbiiooss


  Map the video bios into main memory





  33..22..77..  mmaapp__hhaarrddwwaarree__rraamm



  Initialize the hardware direct-mapped pages





  33..22..88..  mmaapp__ccuussttoomm__bbiiooss


  Setup the dosemu amazing custom BIOS, quietly overwriting anything was
  copied there before. Do not overwrite graphic fonts!





  33..22..99..  bbiiooss__mmeemm__sseettuupp


  Set up all memory areas as would be present on a typical i86 during
  the boot phase.





  33..22..1100..  mmeemmoorryy__iinniitt


  Set up all memory areas as would be present on a typical i86 during
  the boot phase.





  33..22..1111..  ddeevviiccee__iinniitt


  Calls all initialization routines for devices (keyboard, video,
  serial, disks, etc.)





  33..22..1122..  llooww__mmeemm__iinniitt


  Initializes the lower 1Meg via mmap & sets up the HMA region





  33..22..1133..  vveerrssiioonn__iinniitt


  Find version of OS running and set necessary global parms.







  33..33..  IItteemmss ffoorr FFiixxiinngg iinn bbaassee//iinniitt//iinniitt..cc

  config.timer is undocumented and probably obsolete


  33..44..  bbaassee//iinniitt//ccoonnffiigg..cc IInnffoorrmmaattiioonn


  33..55..  FFuunnccttiioonnss iinn bbaassee//iinniitt//ccoonnffiigg..cc

  These are the functions defined in base/init/config.c.


  33..55..11..  ccppuu__oovveerrrriiddee


  Process user CPU override from the config file ('cpu xxx') or from the
  command line. Returns the selected CPU identifier or -1 on error.
  'config.realcpu' should have already been defined.





  33..55..22..  ccoonnffiigg__ddeeffaauullttss


  Set all values in the `config` structure to their default value. These
  will be modified by the config parser.





  33..55..33..  ccoonnffiigg__iinniitt


  This is called to parse the command-line arguments and config files.





  33..55..44..  ppaarrssee__ddeebbuuggffllaaggss



  Arguments are:

  +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.


  33..66..  RReemmaarrkkss iinn bbaassee//iinniitt//ccoonnffiigg..cc

  For simpler support of X, DOSEMU can be started by a symbolic link
  called `xdos` which DOSEMU will use to switch into X-mode.

  33..77..  bbaassee//iinniitt//ddeevv__lliisstt..cc IInnffoorrmmaattiioonn

  Description: Manages a list of the available I/O devices.  It will
  automatically call their initialization and termination routines.  The
  current I/O device list includes:


       Fully emulated:      pit, pic, cmos, serial
       Partially emulated:  rtc, keyb, lpt
       Unemulated:          dma, hdisk, floppy, pos



  44..  TThhee DDPPMMII ggrroouupp ooff MMoodduulleess

  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 ...)



  44..11..  ddoosseexxtt//ddppmmii//ddppmmii..cc IInnffoorrmmaattiioonn

  DOS Protected Mode Interface allows DOS programs to run in the
  protected mode of [2345..]86 processors


  44..22..  FFuunnccttiioonnss iinn ddoosseexxtt//ddppmmii//ddppmmii..cc

  These are the functions defined in dosext/dpmi/dpmi.c.


  44..22..11..  ddppmmii__ccoonnttrrooll


  This function is similar to the vm86() syscall in the kernel and
  switches to dpmi code.





  44..22..22..  rruunn__ppmm__iinntt


  This routine is used for running protected mode hardware interrupts
  and software interrupts 0x1c, 0x23 and 0x24.  run_pm_int() switches to
  the locked protected mode stack and calls the handler. If no handler
  is installed the real mode interrupt routine is called.






  44..22..33..  ddoo__ddeeffaauulltt__ccppuu__eexxcceeppttiioonn


  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 :-)).





  44..22..44..  ddoo__ccppuu__eexxcceeppttiioonn


  This routine switches to the locked protected mode stack, disables
  interrupts and calls the DPMI client exception handler.  If no handler
  is installed the default handler is called.





  44..22..55..  ddppmmii__ffaauulltt


  This is the brain of DPMI. All CPU exceptions are first reflected
  (from the signal handlers) to this code.

  Exception from nonprivileged instructions INT XX, STI, CLI, HLT and
  from WINDOWS 3.1 are handled here.

  All here unhandled exceptions are reflected to do_cpu_exception()





  44..33..  RReemmaarrkkss iinn ddoosseexxtt//ddppmmii//ddppmmii..cc

  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...............

  NOTE: Using DIRECT_DPMI_CONTEXT_SWITCH we avoid these 4  taskswitches
  actually doing 0. We don't need a 'physical' taskswitch (not having
  different TSS for us and DPMI), we only need a complete register
  (context) replacement. For back-switching, however, we need the
  sigcontext technique, so we build a proper sigcontext structure even
  for 'hand made taskswitch'. (Hans Lermen, June 1996)

  dpmi_control is called only from dpmi_run when in_dpmi_dos_int==0


  -----

  Hopefully the below LAR can serve as a replacement for the KERNEL_LDT,
  which we are abandoning now. Especially the 'accessed-bit' will get
  updated in the ldt-cache with the code below.  Most DPMI-clients
  fortunately _are_ using LAR also to get this info, however, some do
  not. Some of those which do _not_, atleast use the DPMI-GetDescriptor
  function, so this may solve the problem.  (Hans Lermen, July 1996)

  -----

  Handling of the virtual interrupt flag is still not correct and there
  are many open questions since DPMI specifications are unclear in this
  point.  An example: If IF=1 in protected mode and real mode code is
  called which is disabling interrupts via cli and returning to
  protected mode, is IF then still one or zero?  I guess I have to think
  a lot about this and to write a small dpmi client running under a
  commercial dpmi server :-).

  -----

  Here we handle all prefixes prior switching to the appropriate
  routines The exception CS:EIP will point to the first prefix that
  effects the the faulting instruction, hence, 0x65 0x66 is same as 0x66
  0x65.  So we collect all prefixes and remember them.  - Hans Lermen


  44..44..  IItteemmss ffoorr FFiixxiinngg iinn ddoosseexxtt//ddppmmii//ddppmmii..cc

  Should we really care for the Memory info?

  -----

  We shouldn't return to dosemu code if IF=0, but it helps - WHY? */

  -----

  we should not change registers for hardware interrupts */


  44..55..  NNeeww IIddeeaass ffoorr ddoosseexxtt//ddppmmii//ddppmmii..cc

  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


  44..66..  ddoosseexxtt//ddppmmii//mmssddooss..hh IInnffoorrmmaattiioonn

  MS-DOS API translator allows DPMI programs to call DOS service
  directly in protected mode.


  44..77..  FFuunnccttiioonnss iinn ddoosseexxtt//ddppmmii//mmssddooss..hh

  These are the functions defined in dosext/dpmi/msdos.h.


  44..77..11..  mmssddooss__pprree__eexxtteennddeerr


  This function is called before a protected mode client goes to real
  mode for DOS service. All protected mode selector is changed to real
  mode segment register. And if client\'s data buffer is above 1MB,
  necessary buffer copying is performed. This function returns 1 if it
  does not need to go to real mode, otherwise returns 0.
  44..77..22..  mmssddooss__ppoosstt__eexxtteennddeerr


  This function is called after return from real mode DOS service All
  real mode segment registers are changed to protected mode selectors
  And if client\'s data buffer is above 1MB, necessary buffer copying is
  performed.





  55..  TThhee VViiddeeoo ggrroouupp ooff MMoodduulleess

  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.



  55..11..  eennvv//vviiddeeoo//vvcc..cc IInnffoorrmmaattiioonn

  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.

  55..22..  eennvv//vviiddeeoo//vviiddeeoo..cc IInnffoorrmmaattiioonn


  55..33..  FFuunnccttiioonnss iinn eennvv//vviiddeeoo//vviiddeeoo..cc

  These are the functions defined in env/video/video.c.


  55..33..11..  vviiddeeoo__iinniitt


  Set pointer to correct structure of functions to initialize, close,
  etc... video routines.





  55..44..  RReemmaarrkkss iinn eennvv//vviiddeeoo//vviiddeeoo..cc

  Here the sleeping lion will be awoken and eat much of CPU time !!!

  The result of setting VM86_SCREEN_BITMAP (at state of Linux 1.1.56):
  Each vm86 call will set 32 pages of video mem RD-only (there may be
  1000000 per second) Write access to RD-only page results in page-fault
  (mm/memory.c), which will set a bit in current->screen_bitmap and
  calls do_wp_page() which does __get_free_page(GFP_KERNEL) but frees it
  immediatly, because copy-on-write is not neccessary and sets RD/WR for
  the page.  (this could happen 32000000 per second, if the CPU were
  fast enough) It would be better to get the DIRTY-bit directly from the
  page table, isn't it?  A special syscall in emumodule could do this.
  -----

  reserve_video_memory()

  This procedure is trying to eke out all the UMB blocks possible to
  maximize your memory under DOSEMU.  If you know about dual monitor
  setups, you can contribute by putting in the correct graphics page
  address values.


  55..55..  eennvv//vviiddeeoo//XX..cc IInnffoorrmmaattiioonn

  This module contains the video interface for the X Window System. It
  has mouse and selection 'cut' support.


  55..66..  FFuunnccttiioonnss iinn eennvv//vviiddeeoo//XX..cc

  These are the functions defined in env/video/X.c.


  55..66..11..  XX__cclloossee


  Initialize everything X-related.





  55..66..22..  XX__cclloossee


  Destroy the window, unload font, pixmap and colormap.





  55..66..33..  XX__sshhmm__iinniitt


  Check availability of the MIT-SHM shared memory extension.





  55..66..44..  XX__sshhmm__iinniitt


  Turn off usage of the MIT-SHM shared memory extension.





  55..66..55..  XX__hhaannddllee__eevveennttss


  Handle pending X events (called from SIGALRM handler).





  55..66..66..  ggrraapphhiiccss__ccmmaapp__iinniitt


  Allocate a colormap for graphics modes and initialize it.  Do mostly
  nothing on true color displays.  Otherwise, do: - if colormaps have
  less than 256 entries (notably 16 or 2 colors), don't use a private
  colormap - if a shared map is requested and there are less than 36
  colors (3/4/3) available, use a private colormap

  Note: Text modes always use the screen's default colormap.





  55..66..77..  XX__sseett__vviiddeeoommooddee


  This is the interface function called by the video subsystem to set a
  video mode.

  NOTE: The actual mode is taken from the global variable "video_mode".





  55..66..88..  XX__sseettmmooddee


  Set the video mode.  If init_vga is zero, this will only reinitialize
  the current mode.  The other arguments are ignored in this case.





  55..66..99..  XX__uuppddaattee__ssccrreeeenn


  Update the part of the screen which has changed, in text mode and in
  graphics mode. Usually called from the SIGALRM handler.

  X_update_screen returns 0 if nothing was updated, 1 if the whole
  screen was updated, and 2 for a partial update.

  It is called in arch/linux/async/signal.c::SIGALRM_call() as part of a
  struct video_system (see top of X.c) every 50 ms or every 10 ms if 2
  was returned, depending somewhat on various config options as e.g.
  config.X_updatefreq and VIDEO_CHECK_DIRTY.  At least it is supposed to
  do that.





  55..66..1100..  XX__cchhaannggee__mmoouussee__ccuurrssoorr


  This function seems to be called each screen_update :( It is called in
  base/mouse/mouse.c:mouse_cursor(int) a lot for show and hide (changes
  the mouse cursor shape).




  55..66..1111..  sseett__mmoouussee__ppoossiittiioonn


  Place the mouse on the right position.





  55..77..  RReemmaarrkkss iinn eennvv//vviiddeeoo//XX..cc

  DO NOT REMOVE THIS TEST!!!  It is magic, without it EMS fails on my
  machine under X.  Perhaps someday when we don't use a buggy
  /proc/self/mem..  -- EB 18 May 1998 A slightly further look says it's
  not the test so much as suppressing noop resize events...  -- EB 1
  June 1998


  55..88..  eennvv//vviiddeeoo//vvggaaeemmuu..cc IInnffoorrmmaattiioonn

  The VGA emulator for DOSEmu.

  Emulated are the video memory and the VGA register set (CRTC, DAC,
  etc.).  Parts of the hardware emulation is done in separate files
  (attremu.c, crtcemu.c, dacemu.c and seqemu.c).

  VGAEmu uses the video BIOS code in base/bios/int10.c and
  env/video/vesa.c.

  For an excellent reference to programming SVGA cards see Finn
  Thgersen's VGADOC4, available at http://www.datashopper.dk/ finth


  55..99..  FFuunnccttiioonnss iinn eennvv//vviiddeeoo//vvggaaeemmuu..cc

  These are the functions defined in env/video/vgaemu.c.


  55..99..11..  VVGGAA__eemmuullaattee__oouuttbb


  Emulates writes to VGA ports.  This is a hardware emulation function.


  Arguments are:

  +o  port  - The port being written to.

  +o  value - The value written,



  55..99..22..  VVGGAA__eemmuullaattee__iinnbb


  Emulates reads from VGA ports.  This is a hardware emulation function.


  Arguments are:

  +o  port  - The port being read from.





  55..99..33..  vvggaa__eemmuu__ffaauulltt


  vga_emu_fault() is used to catch video access, and handle it.  This
  function is called from arch/linux/async/sigsegv.c::dosemu_fault1().
  The sigcontext_struct is defined in include/cpu.h.  Now it catches
  only changes in a 4K page, but maybe it is useful to catch each video
  access. The problem when you do that is, you have to simulate each
  instruction which could write to the video memory.  It is easy to get
  the place where the exception happens (scp->cr2), but what are those
  changes?  An other problem is, it could eat a lot of time, but it does
  now also.


  Arguments are:

  +o  scp - A pointer to a struct sigcontext_struct holding some relevant
     data.



  55..99..44..  vvggaa__eemmuu__iinniitt


  vga_emu_init() must be called before using the VGAEmu functions.  It
  is only called from env/video/X.c::X_init() at the moment.  This
  function basically initializes the global variable `vga' and allocates
  the VGA memory.

  It does in particular *not* map any memory into the range 0xa0000 -
  0xc0000, this is done as part of a VGA mode switch.

  There should be an accompanying vga_emu_done().


  Arguments are:

  +o  vedt - Pointer to struct describing the type of display we are
     actually

  +o  attached to.



  55..99..55..  vvggaa__eemmuu__uuppddaattee


  vga_emu_update() scans the VGA memory for dirty (= written to since
  last update) pages and returns the changed area in *veut. See the
  definition of vga_emu_update_type in env/video/vgaemu_inside.h for
  details.

  You will need to call this function repeatedly until it returns 0 to
  grab all changes. You can specify an upper limit for the size of the
  area that will be returned using `veut->max_max_len' and
  `veut->max_len'.  See the example in env/video/X.c how this works.

  If the return value of vga_emu_update() is >= 0, it is the number of
  changed pages, -1 means there are still changed pages but the maximum
  update chunk size (`veut->max_max_len') was exceeded.

  This function does in its current form not work for Hercules modes; it
  does, however work for text modes, although this feature is currently
  not used.


  Arguments are:

  +o  veut - A pointer to a vga_emu_update_type object holding all
     relevant info.



  55..99..66..  vvggaaeemmuu__sswwiittcchh__ppllaannee


  vgaemu_switch_plane() maps the specified plane.

  This function returns True on success and False on error, usually
  indicating an invalid bank number.


  Arguments are:

  +o  plane (0..3) - The plane to map.



  55..99..77..  vvggaa__eemmuu__sswwiittcchh__bbaannkk


  vga_emu_switch_bank() is used to emulate video-bankswitching.

  This function returns True on success and False on error, usually
  indicating an invalid bank number.


  Arguments are:

  +o  bank - The bank to switch to.



  55..99..88..  vvggaa__eemmuu__ffiinndd__mmooddee


  Searches a video mode with the requested mode number.

  The search starts with the mode *after* the mode `vmi' points to.  If
  `vmi' == NULL, starts at the beginning of the internal mode table.
  `mode' may be a standard VGA mode number (0 ... 0x7f) or a VESA mode
  number (>= 0x100). The mode number may have its don't-clear-bit (bit 7
  or bit 15) or its use-lfb-bit (bit 14) set.  The special mode number
  -1 will match any mode and may be used to scan through the whole
  table.

  Returns NULL if no mode was found and a pointer into the mode table
  otherwise. The returned pointer is a suitable argument for subsequent
  calls to this function.

  You should (and can) access the mode table only through this function.


  Arguments are:

  +o  mode   - video mode.

  +o  vmi    - pointer into internal mode list




  55..99..99..  vvggaa__eemmuu__sseettmmooddee


  Set a video mode.

  Switches to `mode' with text sizes `width' and `height' or (if no such
  mode was found) at least `width' and `height'.


  Arguments are:

  +o  mode   - The new video mode.

  +o  width  - Number of text columns.

  +o  height - Number of text rows.



  55..99..1100..  vvggaa__eemmuu__sseett__tteexxttssiizzee


  Sets the text mode resolution. Typically called after a font change.


  Arguments are:

  +o  width  - Number of text columns.

  +o  height - Number of text rows.



  55..99..1111..  ddiirrttyy__aallll__vviiddeeoo__ppaaggeess


  Marks the whole VGA memory as modified.





  55..99..1122..  vvggaa__eemmuu__sseett__tteexxtt__ppaaggee


  Set visible text page.

  `vga.display_start' is set to `page' * `page_size'.  This function
  works only in text modes.


  Arguments are:

  +o  page      - Number of the text page.

  +o  page_size - Size of one text page.



  55..99..1133..  ddiirrttyy__aallll__vvggaa__ccoolloorrss


  Marks all colors as changed.



  55..99..1144..  cchhaannggeedd__vvggaa__ccoolloorrss


  Checks DAC and Attribute Controller to find all colors with changed
  RGB-values.  Returns number of changed colors.  Note: the list _must_
  be large enough, that is, have at least min(256, (1 <<
  vga.pixel_size)) entries!


  Arguments are:

  +o  de - list of DAC entries to store changed colors in



  55..99..1155..  vvggaaeemmuu__aaddjj__ccffgg


  Adjust VGAEmu according to VGA register changes.





  55..1100..  eennvv//vviiddeeoo//vveessaa..cc IInnffoorrmmaattiioonn

  VESA BIOS Extensions for VGAEmu.

  Supported are VBE version 2.0, including a linear frame buffer and
  display power management support.


  55..1111..  FFuunnccttiioonnss iinn eennvv//vviiddeeoo//vveessaa..cc

  These are the functions defined in env/video/vesa.c.


  55..1111..11..  vvbbee__iinniitt


  Initializes the VGA/VBE BIOS and the VBE support.


  Arguments are:

  +o  vedt - Pointer to struct describing the type of display we are
     actually

  +o  attached to.



  55..1111..22..  ddoo__vveessaa__iinntt


  This is the VESA interrupt handler.

  It is called from base/bios/int10.c::int10(). The VESA interrupt is
  called with 0x4f in AH and the function number (0x00 ... 0x10) in AL.







  55..1122..  eennvv//vviiddeeoo//vveessaabbiiooss..SS IInnffoorrmmaattiioonn

  The VGA/VESA BIOS for VGAEmu.

  This is what DOS applications see as their video BIOS. It will be
  mapped at 0xc000:0x0000 and typically be less than one page in size.
  This video BIOS is write-protected, write accesses to this memory are
  emulated by vesa_emu_fault() in env/video/vesa.c.

  It doesn't have much functionality, just stores the VESA mode table
  and the protected mode interface necessary for VESA BIOS Extension
  (VBE) support.

  Note that some parts of the video BIOS are added by vbe_init() in
  env/video/vesa.c.


  55..1133..  eennvv//vviiddeeoo//vveessaabbiiooss__ppmm..SS IInnffoorrmmaattiioonn

  The protected mode code for the VESA BIOS Extensions.

  We define some functions here that are required to support the VBE 2.0
  protected mode interface.

  The whole code _must_ be fully relocatable. It will be copied into the
  video BIOS during VBE initialization (cf. vbe_init()).


  55..1144..  eennvv//vviiddeeoo//aattttrreemmuu..cc IInnffoorrmmaattiioonn

  The Attribute Controller emulator for VGAemu.

  55..1155..  FFuunnccttiioonnss iinn eennvv//vviiddeeoo//aattttrreemmuu..cc

  These are the functions defined in env/video/attremu.c.


  55..1155..11..  AAttttrr__iinniitt


  Initializes the attribute controller.  This is an interface function.





  55..1155..22..  AAttttrr__ggeett__eennttrryy


  Directly reads the Attribute Controller's registers.  This is an
  interface function.





  55..1155..33..  AAttttrr__sseett__eennttrryy


  Directly sets the Attribute Controller's registers.  This is an
  interface function.





  55..1155..44..  AAttttrr__rreeaadd__vvaalluuee


  Emulates reads from the attribute controller.  This is a hardware
  emulation function.





  55..1155..55..  AAttttrr__wwrriittee__vvaalluuee


  Emulates writes to attribute controller combined index and data
  register. Read VGADOC for details.  This is a hardware emulation
  function.





  55..1155..66..  AAttttrr__ggeett__iinnddeexx


  Returns the current index of the attribute controller.  This is a
  hardware emulation function, though in fact this function is undefined
  in a real attribute controller.  Well, it is exactly what my VGA board
  (S3) does. -- sw This is a hardware emulation function.





  55..1166..  eennvv//vviiddeeoo//ddaacceemmuu..cc IInnffoorrmmaattiioonn

  The DAC emulator for DOSEMU.

  55..1177..  FFuunnccttiioonnss iinn eennvv//vviiddeeoo//ddaacceemmuu..cc

  These are the functions defined in env/video/dacemu.c.


  55..1177..11..  DDAACC__iinniitt


  Initializes the DAC.  It depends on a correct value in vga.pixel_size.
  This function should be called during VGA mode initialization.  This
  is an interface function.





  55..1177..22..  DDAACC__sseett__wwiiddtthh


  Sets the DAC width. Typical values are 6 or 8 bits.  In theory, we
  support other values as well (untested).  This is an interface
  function.







  55..1177..33..  DDAACC__ggeett__eennttrryy


  Returns a complete DAC entry (r, g, b).  Don't forget to set
  DAC_entry.index first!  This is an interface function.





  55..1177..44..  DDAACC__sseett__eennttrryy


  Sets a complete DAC entry (r,g,b).  This is an interface function.





  55..1177..55..  DDAACC__rrggbb22ggrraayy


  Converts a DAC register's RGB values to gray scale.  This is an
  interface function.





  55..1177..66..  DDAACC__sseett__rreeaadd__iinnddeexx


  Specifies which palette entry is read.  This is a hardware emulation
  function.





  55..1177..77..  DDAACC__sseett__wwrriittee__iinnddeexx


  Specifies which palette entry is written.  This is a hardware
  emulation function.





  55..1177..88..  DDAACC__rreeaadd__vvaalluuee


  Read a value from the DAC. Each read will cycle through the registers
  for red, green and blue. After a ``blue read'' the read index will be
  incremented. Read VGADOC4 if you want to know more about the DAC.
  This is a hardware emulation function.





  55..1177..99..  DDAACC__wwrriittee__vvaalluuee


  Write a value to the DAC. Each write will cycle through the registers
  for red, green and blue. After a ``blue write'' the write index will
  be incremented.  This is a hardware emulation function.





  55..1177..1100..  DDAACC__ggeett__ppeell__mmaasskk


  Returns the current PEL mask. Note that changed_vga_colors() already
  applies the PEL mask; so applications should not worry too much about
  it.  This is a hardware emulation function.





  55..1177..1111..  DDAACC__sseett__ppeell__mmaasskk


  Sets the PEL mask and marks all DAC entries as dirty.  This is a
  hardware emulation function.





  55..1177..1122..  DDAACC__ggeett__ssttaattee


  Returns the current state of the DAC.  This is a hardware emulation
  function.





  55..1188..  eennvv//vviiddeeoo//sseeqqeemmuu..cc IInnffoorrmmaattiioonn

  The VGA Sequencer emulator for VGAEmu.

  55..1199..  eennvv//vviiddeeoo//ccrrttcceemmuu..cc IInnffoorrmmaattiioonn

  The VGA CRT Controller emulator for VGAEmu.

  55..2200..  FFuunnccttiioonnss iinn eennvv//vviiddeeoo//ccrrttcceemmuu..cc

  These are the functions defined in env/video/crtcemu.c.


  55..2200..11..  CCRRTTCC__iinniitt


  Initializes the CRT Controller.  This is an interface function.





  55..2211..  eennvv//vviiddeeoo//rreemmaapp..cc IInnffoorrmmaattiioonn

  Transform a 2D image (rescale and color space conversion).

  Here are functions to adapt the VGA graphics to various X displays.


  55..2222..  eennvv//vviiddeeoo//rreemmaapp__aassmm..SS IInnffoorrmmaattiioonn

  Low-level assembler functions for remapping 2D images.

  Note that these functions mostly call other functions that have been
  calculated in remap.c.


  55..2233..  eennvv//vviiddeeoo//ccoonnssoollee..cc IInnffoorrmmaattiioonn


  55..2244..  eennvv//vviiddeeoo//dduuaallmmoonn..cc IInnffoorrmmaattiioonn


  55..2255..  FFuunnccttiioonnss iinn eennvv//vviiddeeoo//dduuaallmmoonn..cc

  These are the functions defined in env/video/dualmon.c.


  55..2255..11..  MMDDAA__iinniitt


  Initializes the monochrome card. First detects which monochrome card
  is used, because the Hercules RamFont and the Hercules InColor need
  one more register to be initialized. If there is no monochrome card at
  all, we just think there is one and poke an peek in the void.  After
  the detection the card is initialized.

  returns: nothing


  Arguments are:

  +o  none



  55..2266..  RReemmaarrkkss iinn eennvv//vviiddeeoo//dduuaallmmoonn..cc

  After MDA_init() the VGA is configured, something in video.c or
  console.c "reprograms" the monochrome card again in such a way that I
  always have to run hgc.com before I can use any program that uses the
  monochrome card. I've spent a day trying to find it, but I can't
  figure out. Something is writing to one of the following ports: 0x3b4,
  0x3b5, 0x3b8, 0x3b9, 0x3ba, 0x3bb, 0x3bf.  The problem occurs at (at
  least) the following 2 systems:

  - AMD 386DX40, Trident 9000/512Kb ISA, Hercules Graphics Card Plus -
  Intel 486DX2/66, Cirrus Logic 5426/1Mb VLB, Hercules clone

  The problem doesn't occur when I start dosemu from a telnet connection
  or from a VT100 terminal. (Erik Mouw, jakmouw@et.tudelft.nl)



  55..2277..  eennvv//vviiddeeoo//eett44000000..cc IInnffoorrmmaattiioonn


  55..2288..  eennvv//vviiddeeoo//hhggcc..cc IInnffoorrmmaattiioonn


  55..2299..  bbaassee//bbiiooss//iinntt1100..cc IInnffoorrmmaattiioonn

  Video BIOS implementation.


  This module handles the int10 video functions.  Most functions here
  change only the video memory and status variables; the actual screen
  is then rendered asynchronously after these by Video->update_screen.


  55..3300..  eennvv//vviiddeeoo//ss33..cc IInnffoorrmmaattiioonn


  55..3311..  eennvv//vviiddeeoo//tteerrmmiinnaall..cc IInnffoorrmmaattiioonn


  55..3322..  eennvv//vviiddeeoo//ttrriiddeenntt..cc IInnffoorrmmaattiioonn


  55..3333..  eennvv//vviiddeeoo//vvggaa..cc IInnffoorrmmaattiioonn


  55..3344..  eennvv//vviiddeeoo//vvggaaeemmuu..cc IInnffoorrmmaattiioonn

  The VGA emulator for DOSEmu.

  Emulated are the video memory and the VGA register set (CRTC, DAC,
  etc.).  Parts of the hardware emulation is done in separate files
  (attremu.c, crtcemu.c, dacemu.c and seqemu.c).

  VGAEmu uses the video BIOS code in base/bios/int10.c and
  env/video/vesa.c.

  For an excellent reference to programming SVGA cards see Finn
  Thgersen's VGADOC4, available at http://www.datashopper.dk/ finth


  55..3355..  FFuunnccttiioonnss iinn eennvv//vviiddeeoo//vvggaaeemmuu..cc

  These are the functions defined in env/video/vgaemu.c.


  55..3355..11..  VVGGAA__eemmuullaattee__oouuttbb


  Emulates writes to VGA ports.  This is a hardware emulation function.


  Arguments are:

  +o  port  - The port being written to.

  +o  value - The value written,



  55..3355..22..  VVGGAA__eemmuullaattee__iinnbb


  Emulates reads from VGA ports.  This is a hardware emulation function.


  Arguments are:

  +o  port  - The port being read from.






  55..3355..33..  vvggaa__eemmuu__ffaauulltt


  vga_emu_fault() is used to catch video access, and handle it.  This
  function is called from arch/linux/async/sigsegv.c::dosemu_fault1().
  The sigcontext_struct is defined in include/cpu.h.  Now it catches
  only changes in a 4K page, but maybe it is useful to catch each video
  access. The problem when you do that is, you have to simulate each
  instruction which could write to the video memory.  It is easy to get
  the place where the exception happens (scp->cr2), but what are those
  changes?  An other problem is, it could eat a lot of time, but it does
  now also.


  Arguments are:

  +o  scp - A pointer to a struct sigcontext_struct holding some relevant
     data.



  55..3355..44..  vvggaa__eemmuu__iinniitt


  vga_emu_init() must be called before using the VGAEmu functions.  It
  is only called from env/video/X.c::X_init() at the moment.  This
  function basically initializes the global variable `vga' and allocates
  the VGA memory.

  It does in particular *not* map any memory into the range 0xa0000 -
  0xc0000, this is done as part of a VGA mode switch.

  There should be an accompanying vga_emu_done().


  Arguments are:

  +o  vedt - Pointer to struct describing the type of display we are
     actually

  +o  attached to.



  55..3355..55..  vvggaa__eemmuu__uuppddaattee


  vga_emu_update() scans the VGA memory for dirty (= written to since
  last update) pages and returns the changed area in *veut. See the
  definition of vga_emu_update_type in env/video/vgaemu_inside.h for
  details.

  You will need to call this function repeatedly until it returns 0 to
  grab all changes. You can specify an upper limit for the size of the
  area that will be returned using `veut->max_max_len' and
  `veut->max_len'.  See the example in env/video/X.c how this works.

  If the return value of vga_emu_update() is >= 0, it is the number of
  changed pages, -1 means there are still changed pages but the maximum
  update chunk size (`veut->max_max_len') was exceeded.

  This function does in its current form not work for Hercules modes; it
  does, however work for text modes, although this feature is currently
  not used.


  Arguments are:

  +o  veut - A pointer to a vga_emu_update_type object holding all
     relevant info.



  55..3355..66..  vvggaaeemmuu__sswwiittcchh__ppllaannee


  vgaemu_switch_plane() maps the specified plane.

  This function returns True on success and False on error, usually
  indicating an invalid bank number.


  Arguments are:

  +o  plane (0..3) - The plane to map.



  55..3355..77..  vvggaa__eemmuu__sswwiittcchh__bbaannkk


  vga_emu_switch_bank() is used to emulate video-bankswitching.

  This function returns True on success and False on error, usually
  indicating an invalid bank number.


  Arguments are:

  +o  bank - The bank to switch to.



  55..3355..88..  vvggaa__eemmuu__ffiinndd__mmooddee


  Searches a video mode with the requested mode number.

  The search starts with the mode *after* the mode `vmi' points to.  If
  `vmi' == NULL, starts at the beginning of the internal mode table.
  `mode' may be a standard VGA mode number (0 ... 0x7f) or a VESA mode
  number (>= 0x100). The mode number may have its don't-clear-bit (bit 7
  or bit 15) or its use-lfb-bit (bit 14) set.  The special mode number
  -1 will match any mode and may be used to scan through the whole
  table.

  Returns NULL if no mode was found and a pointer into the mode table
  otherwise. The returned pointer is a suitable argument for subsequent
  calls to this function.

  You should (and can) access the mode table only through this function.


  Arguments are:

  +o  mode   - video mode.

  +o  vmi    - pointer into internal mode list




  55..3355..99..  vvggaa__eemmuu__sseettmmooddee


  Set a video mode.

  Switches to `mode' with text sizes `width' and `height' or (if no such
  mode was found) at least `width' and `height'.


  Arguments are:

  +o  mode   - The new video mode.

  +o  width  - Number of text columns.

  +o  height - Number of text rows.



  55..3355..1100..  vvggaa__eemmuu__sseett__tteexxttssiizzee


  Sets the text mode resolution. Typically called after a font change.


  Arguments are:

  +o  width  - Number of text columns.

  +o  height - Number of text rows.



  55..3355..1111..  ddiirrttyy__aallll__vviiddeeoo__ppaaggeess


  Marks the whole VGA memory as modified.





  55..3355..1122..  vvggaa__eemmuu__sseett__tteexxtt__ppaaggee


  Set visible text page.

  `vga.display_start' is set to `page' * `page_size'.  This function
  works only in text modes.


  Arguments are:

  +o  page      - Number of the text page.

  +o  page_size - Size of one text page.



  55..3355..1133..  ddiirrttyy__aallll__vvggaa__ccoolloorrss


  Marks all colors as changed.



  55..3355..1144..  cchhaannggeedd__vvggaa__ccoolloorrss


  Checks DAC and Attribute Controller to find all colors with changed
  RGB-values.  Returns number of changed colors.  Note: the list _must_
  be large enough, that is, have at least min(256, (1 <<
  vga.pixel_size)) entries!


  Arguments are:

  +o  de - list of DAC entries to store changed colors in



  55..3355..1155..  vvggaaeemmuu__aaddjj__ccffgg


  Adjust VGAEmu according to VGA register changes.





  55..3366..  iinncclluuddee//vvggaaeemmuu..hh IInnffoorrmmaattiioonn

  Header file for the VGA emulator for DOSEmu.

  This file describes the interface to the VGA emulator.  Have a look at
  env/video/vgaemu.c and env/video/vesa.c for details.


  66..  TThhee KKeeyybbooaarrdd ggrroouupp ooff MMoodduulleess

  All of the Keyboard handling code is in the "keyboard" subdirectory.

  Latest addition is SLANG.



  66..11..  bbaassee//kkeeyybbooaarrdd//kkeeyymmaappss..cc IInnffoorrmmaattiioonn

  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.


  66..22..  RReemmaarrkkss iinn bbaassee//kkeeyybbooaarrdd//kkeeyymmaappss..cc

  The DEAD codes must refer to keys that don't exist on any language
  keyboard. I hope nobody has a smily face key :-) dead_key_table is a
  list of the dead keys supported. They must be placed on the correct
  key in the keymaps above. See key_map_es_latin1.


  -----

  dos850_dead_map consists of the triple, {deadkey, letter, result}.  It
  should be correct for all the code page 850 users (Western Europe).
  If you uses a different code page, please create a map!  Jon Tombs
  jon@gtex02.us.es



  66..33..  bbaassee//kkeeyybbooaarrdd//sseerrvv__xxllaatt..cc IInnffoorrmmaattiioonn

  This module contains the the translation part of the keyboard
  'server', which translates keysyms into the form in which they can be
  sent do DOS.

  The frontends will call one of the following functions to send
  keyboard events to DOS:



       putrawkey(t_rawkeycode code);
       putkey(Boolean make, t_keysym key)
       set_shiftstate(t_shiftstate s);



  Interface to serv_backend.c is through write_queue(bios_key, shift,
  raw).

  More information about this module is in doc/README.newkbd


  Maintainers:

  Rainer Zimmermann  <zimmerm@mathematik.uni-marburg.de>

  66..44..  FFuunnccttiioonnss iinn bbaassee//kkeeyybbooaarrdd//sseerrvv__xxllaatt..cc

  These are the functions defined in base/keyboard/serv_xlat.c.


  66..44..11..  ppuuttrraawwkkeeyy


  This function sends a raw keycode byte, e.g. read directly from the
  hardware, to DOS. It is both queued for the port60h emulation and
  processed for the BIOS keyboard buffer, using the national translation
  tables etc.

  For DOS applications using int16h we will therefore not have to load
  KEYB.EXE, others (e.g. games) need their own drivers anyway.

  This function is used if we are at the console and
  config.rawkeyboard=on.





  66..44..22..  ppuuttkkeeyy


  This does all the work of sending a key event to DOS.  scan  - the
  keycode, one of the KEY_ constants from new-kbd.h make  - TRUE for key
  press, FALSE for release ascii - the key's ascii value, or 0 for none.

  Applications using int16h will always see the ASCII code passed here
  independently of the scancode, so no character translation
  needs/should be done. As DOS expects characters in IBM Extended ASCII,
  the keyboard clients may have to do ISO->IBM character translation or
  similar!

  An emulated hardware scancode is also sent to port60h.


  Note that you have to send both MAKE (press) and BREAK (release)
  events.  If no BREAK codes are available (e.g. terminal mode), send
  them immediately after the MAKE codes.  Also, shift keys should be
  sent (with ascii = 0).





  66..44..33..  sseett__sshhiiffttssttaattee


  This simply sets the keyboard server's shift state.

  USE WITH CAUTION: this changes the keyboard flags without generating
  the appropriate shift key make/break codes that normally come along
  with such changes. This function is mostly intended for start-up
  shiftstate synchronisation.

  Note also that you can't simply write to the shiftstate variable
  instead of using this function.





  66..55..  bbaassee//kkeeyybbooaarrdd//sseerrvv__bbaacckkeenndd..cc IInnffoorrmmaattiioonn

  This module handles interfacing to the DOS side both on int9/port60h
  level (if keybint=on), or on the bios buffer level.  Keycodes are
  buffered in a queue, which, however, has limited depth, so it
  shouldn't be used for pasting.

  More information about this module is in doc/README.newkbd


  Maintainers:

  Rainer Zimmermann  <zimmerm@mathematik.uni-marburg.de>

  66..66..  bbaassee//kkeeyybbooaarrdd//sseerrvv__88004422..cc IInnffoorrmmaattiioonn

  This code provides truly rudimentary 8042 controller emulation.  Not
  having any documentation on the 8042 makes it hard to improve. :)


  66..77..  bbaassee//kkeeyybbooaarrdd//kkeeyybb__rraaww..cc IInnffoorrmmaattiioonn


  66..88..  FFuunnccttiioonnss iinn bbaassee//kkeeyybbooaarrdd//kkeeyybb__rraaww..cc

  These are the functions defined in base/keyboard/keyb_raw.c.


  66..88..11..  rraaww__kkeeyybbooaarrdd__iinniitt


  Initialize the keyboard for RAW mode.








  66..99..  bbaassee//kkeeyybbooaarrdd//kkeeyybb__ssllaanngg..cc IInnffoorrmmaattiioonn


  66..1100..  FFuunnccttiioonnss iinn bbaassee//kkeeyybbooaarrdd//kkeeyybb__ssllaanngg..cc

  These are the functions defined in base/keyboard/keyb_slang.c.


  66..1100..11..  ssllaanngg__kkeeyybb__iinniitt(())


  Code is called at start up to set up the terminal line for non-raw
  mode.





  77..  TThhee MMiisscc ggrroouupp ooff MMoodduulleess

  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.



  77..11..  ddoosseexxtt//mmiisscc//eemmmm..cc IInnffoorrmmaattiioonn

  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.


  77..22..  ddoosseexxtt//mmiisscc//xxmmss..cc IInnffoorrmmaattiioonn

  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.


  77..33..  bbaassee//aassyynncc//iinntt..cc IInnffoorrmmaattiioonn


  77..44..  FFuunnccttiioonnss iinn bbaassee//aassyynncc//iinntt..cc

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


  77..44..11..  DDEEFFAAUULLTT__IINNTTEERRRRUUPPTT



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





  77..44..22..  mmss__ddooss


  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.





  77..44..33..  rruunn__ccaalllleerr__ffuunncc((ii,, ffrroomm__iinntt))


  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





  77..44..44..  DDOO__IINNTT


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





  77..44..55..  sseettuupp__iinntteerrrruuppttss


  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.





  77..44..66..  iinntt__vveeccttoorr__sseettuupp


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





  77..55..  RReemmaarrkkss iinn bbaassee//aassyynncc//iinntt..cc

  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


  77..66..  iinncclluuddee//iinntt..hh IInnffoorrmmaattiioonn




  77..77..  aarrcchh//lliinnuuxx//aassyynncc//ssiiggsseeggvv..cc IInnffoorrmmaattiioonn


  77..88..  FFuunnccttiioonnss iinn aarrcchh//lliinnuuxx//aassyynncc//ssiiggsseeggvv..cc

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


  77..88..11..  ddoosseemmuu__ffaauulltt((iinntt,, ssttrruucctt ssiiggccoonntteexxtt__ssttrruucctt));;


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





  77..88..22..  pprriinntt__eexxcceeppttiioonn__iinnffoo


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





  77..99..  aarrcchh//lliinnuuxx//aassyynncc//ssiiggnnaall..cc IInnffoorrmmaattiioonn


  77..1100..  FFuunnccttiioonnss iinn aarrcchh//lliinnuuxx//aassyynncc//ssiiggnnaall..cc

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


  77..1100..11..  ssiiggnnaall__iinniitt


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





  77..1100..22..  ccllii


  Stop additional signals from interrupting DOSEMU.





  77..1100..33..  ssttii


  Allow all signals to interrupt DOSEMU.







  77..1100..44..  hhaannddllee__ssiiggnnaallss


  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.





  77..1100..55..  SSIIGGNNAALL__ssaavvee



  Arguments are:

  +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.





  77..1100..66..  SSIIGGIIOO__ccaallll


  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.





  77..1111..  RReemmaarrkkss iinn aarrcchh//lliinnuuxx//aassyynncc//ssiiggnnaall..cc

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


  77..1122..  iinncclluuddee//ppoorrttss..hh IInnffoorrmmaattiioonn


  77..1133..  bbaassee//mmiisscc//ddoossiioo..cc IInnffoorrmmaattiioonn


  77..1144..  bbaassee//mmiisscc//ddiisskkss..cc IInnffoorrmmaattiioonn


  77..1155..  FFuunnccttiioonnss iinn bbaassee//mmiisscc//ddiisskkss..cc

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




  77..1155..11..  ddiisskk__iinniitt


  Test by opening all floppies/hardrives configured.





  77..1166..  ddeevv//mmiisscc//llpptt..cc IInnffoorrmmaattiioonn


  77..1177..  bbaassee//ddeevv//mmiisscc//ttiimmeerrss..cc IInnffoorrmmaattiioonn

  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]


  77..1188..  FFuunnccttiioonnss iinn bbaassee//ddeevv//mmiisscc//ttiimmeerrss..cc

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


  77..1188..11..  iinniittiiaalliizzee__ttiimmeerrss


  ensure the 0x40 port timer is initially set correctly





  77..1188..22..  ttiimmeerr__ttiicckk


  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.





  77..1188..33..  ddoo__ssoouunndd


  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




  77..1188..44..  ttiimmeerr__iinntt__eennggiinnee


  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.





  77..1199..  bbaassee//ssppeeaakkeerr//ssppeeaakkeerr..cc IInnffoorrmmaattiioonn


  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 :)

  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

  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 to it's default
  speaker functions, which will always work.

  --EB 20 Sept 1997


  Maintainers:

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

  77..2200..  bbaassee//mmiisscc//sshhaarreedd..cc IInnffoorrmmaattiioonn

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

  77..2211..  FFuunnccttiioonnss iinn bbaassee//mmiisscc//sshhaarreedd..cc

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


  77..2211..11..  sshhaarreedd__qqff__mmeemmoorryy__iinniitt


  Setup all memory areas to be shared with clients.





  77..2222..  RReemmaarrkkss iinn bbaassee//mmiisscc//sshhaarreedd..cc

  Set to 0 all client request area

  -----

  Output info required for client activity


  77..2233..  bbaassee//mmiisscc//ddooss22lliinnuuxx..cc IInnffoorrmmaattiioonn


  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).


  77..2244..  FFuunnccttiioonnss iinn bbaassee//mmiisscc//ddooss22lliinnuuxx..cc

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


  77..2244..11..  rruunn__uunniixx__ccoommmmaanndd


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


  Return values mean:

  Arguments are:

  +o  buffer - string with command to execute



  77..2255..  bbaassee//mmiisscc//iiooccttll..cc IInnffoorrmmaattiioonn


  77..2266..  FFuunnccttiioonnss iinn bbaassee//mmiisscc//iiooccttll..cc

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


  77..2266..11..  iioo__sseelleecctt__iinniitt


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





  77..2266..22..  aadddd__ttoo__iioo__sseelleecctt



  Arguments are:

  +o  fd - File handle to add to select statment

  +o  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.





  77..2266..33..  rreemmoovvee__ffrroomm__iioo__sseelleecctt




  Arguments are:

  +o  fd - File handle to remove from select statment.

  +o  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.





  77..2277..  bbaassee//ddeevv//mmiisscc//ccmmooss..cc IInnffoorrmmaattiioonn


  77..2288..  bbaassee//ddeevv//mmiisscc//llpptt..cc IInnffoorrmmaattiioonn


  77..2299..  FFuunnccttiioonnss iinn bbaassee//ddeevv//mmiisscc//llpptt..cc

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


  77..2299..11..  pprriinntteerr__iinniitt


  Initialize printer control structures





  77..3300..  bbaassee//ddeevv//mmiisscc//ppccii..cc IInnffoorrmmaattiioonn


  77..3311..  FFuunnccttiioonnss iinn bbaassee//ddeevv//mmiisscc//ppccii..cc

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


  77..3311..11..  ppccii__rreeaadd__hheeaaddeerr


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





  77..3311..22..  ppccii__rreeaadd__hheeaaddeerr


  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().







  77..3311..33..  ppccii__rreeaadd__hheeaaddeerr


  Register standard PCI ports 0xcf8-0xcff





  77..3322..  iinncclluuddee//ddoosshheellppeerrss..hh IInnffoorrmmaattiioonn


  77..3333..  RReemmaarrkkss iinn iinncclluuddee//ddoosshheellppeerrss..hh

  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.


  77..3344..  ddoosseexxtt//ddrriivveerrss//aassppii..cc IInnffoorrmmaattiioonn



   drivers/aspi.c - emulate the DOS ASPI programming interface using
                      the Linux generic SCSI driver (/dev/sg?)
   basic aspi code shamelessly stolen from the wine
   project aspi.c written by  Bruce Milner <Bruce.Milner@genetics.utah.edu>

   hacked by         Karl Kiniger <ki@kretz.co.at>
   further hacked by Hans Lermen <lermen@dosemu.org>

   For now there are several limitations I am aware of:

   - Residual byte length reporting not handled
   - Only Linux supported so far
   - SG_BIG_BUFF may need to be adjusted and the sg driver therefore be recompiled
   - No posting routine possible - reentrancy needed for posting, since the
     posting routine may call ASPI services
   - Blocking read/write to/from /dev/sg? used
   - Too few sense bytes returned (16 instead of 18). This is a limitiation
       from the sg driver.
   - SCSI timeout may need to be increased - formatting a DAT tape may take some time
       set to 5 minutes for now.
   - 'Direction' table very incomplete (see below)
   - Debug output not well organized/formatted
   - no access control for now
   - Look at the various FIXME's
   - all hostadapters are mapped to _one_ single seen by DOS,
     but the targetID can be mapped differently.
   - LUNs have to be equal for real and DOS seen ones, because we
     don't translate the LUNs in the CDB.




  88..  TThhee CCPPUU__IInntteell ggrroouupp ooff MMoodduulleess

  These files all relate to Intel-x86 specific code.



  88..11..  eemmuu--ii338866//ccppuu..cc IInnffoorrmmaattiioonn

  CPU/V86 support for dosemu

  88..22..  FFuunnccttiioonnss iinn eemmuu--ii338866//ccppuu..cc

  These are the functions defined in emu-i386/cpu.c.


  88..22..11..  ccppuu__ttrraapp__00ff


  process opcodes 0F xx xx trapped by GP_fault returns 1 if handled, 0
  otherwise Main difference with previous version: bits in our pseudo-
  control regs can now be written. This should make CPU detection pgms
  happy.





  88..22..22..  ccppuu__sseettuupp


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





  88..33..  eemmuu--ii338866//ppoorrttss..cc IInnffoorrmmaattiioonn

  This is the code that allows and disallows port access within DOSEMU.
  The BOCHS port IO code was actually very cleverly done.  So the idea
  was stolen from there.

  This port I/O code (previously in portss.c, from Scott Bucholz) is
  based on a table access instead of a switch statement. This method is
  much more clean and easy to maintain, while not slower than a switch.

  Remains of the old code are emerging here and there, they will
  hopefully be moved back to where they belong, mainly video code.

  88..44..  FFuunnccttiioonnss iinn eemmuu--ii338866//ppoorrttss..cc

  These are the functions defined in emu-i386/ports.c.


  88..44..11..  ppoorrtt__iinnbb((iiooppoorrtt__tt ppoorrtt))


  Handles/simulates an inb() port IO read







  88..44..22..  ppoorrtt__oouuttbb((iiooppoorrtt__tt ppoorrtt,, BBiitt88uu bbyyttee))


  Handles/simulates an outb() port IO write





  88..44..33..  ppoorrtt__iinnww((iiooppoorrtt__tt ppoorrtt))


  Handles/simulates an inw() port IO read.  Usually this invokes
  port_inb() twice, but it may be necessary to do full word i/o for some
  video boards.





  88..44..44..  ppoorrtt__oouuttww((iiooppoorrtt__tt ppoorrtt,, BBiitt1166uu wwoorrdd))


  Handles/simulates an outw() port IO write





  88..44..55..  ppoorrtt__iinndd((iiooppoorrtt__tt ppoorrtt))


  Handles/simulates an ind()/outd() port IO read/write.





  88..44..66..  ssppeecciiaall__ppoorrtt__iinnbb,,ssppeecciiaall__ppoorrtt__oouuttbb


  I don't know what to do of this stuff... it was added incrementally to
  port.c and has mainly to do with video code. This is not the right
  place for it...  Anyway, this implements some HGC stuff for X and the
  emuretrace port access for 0x3c0/0x3da





  88..44..77..  ppoorrtt__iinniitt(())


  Resets all the port port_handler information.  This must be called
  before parsing the config file - This must NOT be called again when
  warm booting!  Can't use debug logging, it is called too early.





  88..44..88..  eexxttrraa__ppoorrtt__iinniitt(())


  Catch all the special cases previously defined in ports.c mainly video
  stuff that should be moved away from here This must be called at the
  end of initialization phase

  NOTE: the order in which these inits are done could be significant!  I
  tried to keep it the same it was in ports.c but this code surely can
  still have bugs





  88..44..99..  ppoorrtt__rreeggiisstteerr__hhaannddlleerr


  Assigns a handle in the port table to a range of ports with or without
  a device, and registers the ports





  88..44..1100..  ppoorrtt__aallllooww__iioo







  88..44..1111..  sseett__iiooppeerrmm


  wrapper for the ioperm() syscall, returns -1 if port>=0x400





  88..55..  RReemmaarrkkss iinn eemmuu--ii338866//ppoorrttss..cc



   PORT_DEBUG is to specify whether to record port writes to debug output.
     0 means disabled.
     1 means record all port accesses to 0x00 to 0xFF
     2 means record ANY port accesses!  (big fat debugfile!)
     3 means record all port accesses >= 0x100



  -----

  The following port_{in|out}{bwd} functions are the main entry points
  to the port code. They look into the port_handle_table and call the
  appropriate code, usually the std_port_ functions, but each device is
  free to register its own functions which in turn will call std_port or
  directly access I/O (like video code does), or emulate it - AV


  -----

  optimized versions for rep - basically we avoid changing privileges
  and iopl on and off lots of times. We are safe letting iopl=3 here
  since we don't exit from this code until finished.  This code is
  shared between VM86 and DPMI.


  -----

  This is the core of the new emuretrace algorithm: If a read of port
  0x3da is performed we just set it as pending and set ioperm OFF for
  port 0x3c0 When a write to port 0x3c0 is then trapped, we perform any
  pending read to 0x3da and reset the ioperm for 0x3c0 in the default ON
  state.  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.
  Futher accesses to port 0x3c0 are handled at full speed.


  -----

  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

  -----

  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.


  88..66..  IItteemmss ffoorr FFiixxiinngg iinn eemmuu--ii338866//ppoorrttss..cc

  This stuff should be moved to video code!!

  -----

  this code needs to be removed - it collides with vgaemu

  -----

  we should free the name but we are going to exit anyway


  88..77..  eemmuu--ii338866//ddoo__vvmm8866..cc IInnffoorrmmaattiioonn


  88..88..  FFuunnccttiioonnss iinn eemmuu--ii338866//ddoo__vvmm8866..cc

  These are the functions defined in emu-i386/do_vm86.c.


  88..88..11..  vvmm8866__GGPP__ffaauulltt


  All from the kernel unhandled general protection faults from V86 mode
  are handled here. This are mainly port IO and the HLT instruction.








  88..88..22..  rruunn__vvmm8866


  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 ...





  88..99..  RReemmaarrkkss iinn eemmuu--ii338866//ddoo__vvmm8866..cc

  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

  -----

  Here we handle all prefixes prior switching to the appropriate
  routines The exception CS:EIP will point to the first prefix that
  effects the faulting instruction, hence, 0x65 0x66 is same as 0x66
  0x65.  So we collect all prefixes and remember them.  - Hans Lermen


  88..1100..  eemmuu--ii338866//ffaakkee__ccppuu..cc IInnffoorrmmaattiioonn


  88..1111..  eemmuu--ii338866//nn__ppoorrttss..cc IInnffoorrmmaattiioonn


  88..1122..  eemmuu--ii338866//ccppuuttiimmee..cc IInnffoorrmmaattiioonn


  Maintainers:


  88..1133..  FFuunnccttiioonnss iinn eemmuu--ii338866//ccppuuttiimmee..cc

  These are the functions defined in emu-i386/cputime.c.


  88..1133..11..  GGEETTccppuuTTIIMMEE


  GETcpuTIME is a pointer to a function which returns the relative CPU
  time. Different methods of getting the time can then be implemented,
  currently there are two using gettimeofday() for 486 and TSC for
  pentium





  88..1133..22..  GGEETTuussTTIIMMEE((sscc))


  GETusTIME returns the DOS ('stretched') time with 1-usec resolution
  using GETcpuTIME to get the implementation-dependent CPU time.  The
  'sc' parameter controls the granularity of the stretching algorithm
  (not yet there, see the docs)





  88..1133..33..  GGEETTttiicckkTTIIMMEE((sscc))


  GETtickTIME returns the DOS (stretched) time with 838ns resolution
  using GETcpuTIME to get the implementation-dependent CPU time.  The
  'sc' parameter works like in GETusTIME.





  88..1133..44..  GGEETTuussSSYYSSTTIIMMEE(())


  GETusSYSTIME returns the real CPU time with 1-usec resolution





  88..1144..  RReemmaarrkkss iinn eemmuu--ii338866//ccppuuttiimmee..cc

  At the heart of the timing system in dosemu >= 0.67.11 is the
  availability of the system time as a 64-bit [type hitimer_t] monoton
  value.  (a 64-bit timer on a 200MHz CPU increments by 2^48 a day).

  Dosemu needs this time under two resolutions:


     - a MICROSECOND resolution for general timing purposes
     - a TICK(838ns) resolution for PIT


  On non-pentium machines, only the first one is available via the ker-
  nel call gettimeofday(). On the pentium and up, the situation is bet-
  ter since we have a cheap hi-res timer on-chip, and worse since this
  timer runs at a speed depending from the CPU clock (which we need to
  know/measure, and could be not 100% accurate esp. if the speed is a
  non-integer multiple of 33.3333).

  dosemu >= 0.67.11 can use both timing methods (call them 486 and
  pentium), and switch between them in a dynamic way when configuring.

  At the first level (local to the file cputime.c) there are the RAW
  timer functions, addressed by RAWcpuTIME(). These get the actual
  absolute CPU time in usecs.

  At the second level, GETcpuTIME() returns the relative, zero-based
  system time. This is where the 486/pentium switch happens.

  The third level is the actual timer interface for dosemu and is made
  of two functions:


    - GETusTIME(s)   gives the time in usecs
    - GETtickTIME(s) gives the time in ticks


  The 's' parameter can be used to control secondary time functions like
  'time stretching' (see the READMEs).  The function GETusSYSTIME()
  never activates this stretching, and is used only by the realtime
  thread-based 1-sec timer in rtc.c.

  All timing are RELATIVE to a base. The use of a based time allows us
  to play more freely with time, e.g. stop and restart it during
  debugging, stretch it, make it go at different speeds between real-
  time and CPU emulation, etc. The base has been chosen to be zero,
  because it will avoid overflows in calculations, produce more readable
  and more easily comparable debug log files, and also because only
  int0x1a and BIOS timer require knowledge of the actual time, PIT and
  PIC are not sensitive.



  99..  TThhee SSeerriiaall ggrroouupp ooff MMoodduulleess

  This is the code that works our serial emulation. This needs to be
  very fast if we are to convince DOS that we have a very fast serial
  port.



  99..11..  bbaassee//sseerriiaall//sseerr__ddeeffss..hh IInnffoorrmmaattiioonn

  ser_defs.h: Include file for all files in the 'serial' subdirectory.
  Please send bug reports and bugfixes to marky@magmacom.com Please read
  the files in this 'serial' subdirectory for more info.


  99..22..  RReemmaarrkkss iinn bbaassee//sseerriiaall//sseerr__ddeeffss..hh

  Extensions to serial debugging.

  SER_DEBUG_MAIN   (0 or 1) - extra debug output on the most critical
  information.

  SER_DEBUG_HEAVY   (0 or 1) - super-heavy extra debug output, including
  all ports reads and writes, and every character received and
  transmitted!

  SER_DEBUG_INTERRUPT   (0 or 1) - additional debug output related to
  serial interrupt code, including flagging serial interrupts, or PIC-
  driven code.

  SER_DEBUG_FOSSIL_RW   (0 or 1) - heavy FOSSIL debug output, including
  all reads and writes.

  SER_DEBUG_FOSSIL_STATUS   (0 or 1) - super-heavy FOSSIL debug output,
  including all status checks.

  You must recompile dosemu everytime one of these constants are
  modified.  Just type 'make' in the dosemu dir and it will recompile
  the changes only.

  -----

  IMPORTANT INFO about com[] variable array structure used in serial.c

  Most of the serial variables are stored in the com[] array.  The com[]
  array is a structure in itself.   Take a look at the about this.  Only
  the most commonly referenced global variables are listed here:

  config.num_ser         Number of serial ports active.
  com[x].base_port       The base port address of emulated serial port.
  com[x].real_comport    The COM port number.  com[x].interrupt
  The PIC interrupt level (based on IRQ number) com[x].mouse
  Flag  mouse (to enable extended features) com[x].fd              File
  descriptor for port device com[x].dev[]           Filename of port
  port device com[x].dev_locked      Flag whether device has been locked

  The arbritary example variable 'x' in com[x] can have a minimum value
  of 0 and a maximum value of (config.numser - 1).  There can be no gaps
  for the value 'x', even though gaps between actual COM ports are
  permitted.  It is strongly noted that the 'x' does not equal the COM
  port number.  This example code illustrates the fact, and how the
  com[] array works:

  for (i = 0; i < config.numser; i++) s_printf("COM port number %d has a
  base address of %x", com[i].real_comport, com[i].base_port);



  99..33..  bbaassee//sseerriiaall//sseerr__iinniitt..cc IInnffoorrmmaattiioonn

  ser_init.c: Serial ports initialization for DOSEMU Please read the
  README.serial file in this directory for more info!

  Lock file stuff was derived from Taylor UUCP with these copyrights:
  Copyright (C) 1991, 1992 Ian Lance Taylor Uri Blumenthal
  <uri@watson.ibm.com> (C) 1994 Paul Cadach, <paul@paul.east.alma-
  ata.su> (C) 1994

  Rest of serial code Copyright (C) 1995 by Mark Rejhon

  The code in this module 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 module is maintained by Mark Rejhon at these Email addresses:
  marky@magmacom.com ag115@freenet.carleton.ca

  Maintainers:

  Mark Rejhon  <marky@ottawa.com>

  99..44..  FFuunnccttiioonnss iinn bbaassee//sseerriiaall//sseerr__iinniitt..cc

  These are the functions defined in base/serial/ser_init.c.


  99..44..11..  sseerriiaall__iinniitt


  This is the master serial initialization function that is called upon
  startup of DOSEMU to initialize ALL the emulated UARTs for all
  configured serial ports.  The UART is initialized via the
  initialize_uart function, which opens the serial ports and defines
  variables for the specific UART.

  If the port is a mouse, the port is only initialized when i





  99..55..  IItteemmss ffoorr FFiixxiinngg iinn bbaassee//sseerriiaall//sseerr__iinniitt..cc

  This needs more work before it is implemented into /etc/dosemu.conf as
  an 'rtscts' option.


  99..66..  bbaassee//sseerriiaall//sseerr__ppoorrttss..cc IInnffoorrmmaattiioonn

  ser_ports.c: Serial ports for DOSEMU: Software emulated 16550 UART!
  Please read the README.serial file in this directory for more info!

  Copyright (C) 1995 by Mark Rejhon

  The code in this module 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 module is maintained by Mark Rejhon at these Email addresses:
  marky@magmacom.com ag115@freenet.carleton.ca


  99..77..  FFuunnccttiioonnss iinn bbaassee//sseerriiaall//sseerr__ppoorrttss..cc

  These are the functions defined in base/serial/ser_ports.c.


  99..77..11..  ddoo__sseerriiaall__iinn

  The following function returns a value from an I/O port.  The port is
  an I/O address such as 0x3F8 (the base port address of COM1).  There
  are 8 I/O addresses for each serial port which ranges from the base
  port (ie 0x3F8) to the base port plus seven (ie 0x3FF).  [num =
  abritary port number for serial line, address = I/O port address]




  99..77..22..  ddoo__sseerriiaall__oouutt

  The following function writes a value to an I/O port.  The port is an
  I/O address such as 0x3F8 (the base port address of COM1).  [num =
  abritary port number for serial line, address = I/O port address, val
  = value to write to I/O port address]




  99..88..  IItteemmss ffoorr FFiixxiinngg iinn bbaassee//sseerriiaall//sseerr__ppoorrttss..cc

  Should clearing UART cause THRE int if it's enabled? */

  -----

  Fix the calculation assumption

  -----

  Is this safe to put this here? */

  -----

  Is this safe to put this here? */


  99..99..  bbaassee//sseerriiaall//sseerr__iirrqq..cc IInnffoorrmmaattiioonn

  ser_irq.c: Serial interrupt services for DOSEMU Please read the
  README.serial file in this directory for more info!

  Copyright (C) 1995 by Mark Rejhon

  The code in this module 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.


  99..1100..  FFuunnccttiioonnss iinn bbaassee//sseerriiaall//sseerr__iirrqq..cc

  These are the functions defined in base/serial/ser_irq.c.


  99..1100..11..  sseerriiaall__iinntt__eennggiinnee


  This function is the serial interrupts scheduler.  Its purpose is to
  update interrupt status and/or invoke a requested serial interrupt.
  If interrupts are not enabled, the Interrupt Identification Register
  is still updated and the function returns.  See pic_serial_run() below
  it is executed right at the instant the interrupt is actually invoked.

  Since it is not possible to run the interrupt on the spot, it triggers
  the interrupt via the pic_request() function (which is in pic.c) and
  sets a flag that an interrupt is going to be occur soon.

  Please read pic_serial_run() for more information about interrupts.
  [num = port, int_requested = the requested serial interrupt]





  99..1100..22..  ppiicc__sseerriiaall__rruunn


  This function is called by the priority iunterrupt controller when a
  serial interrupt occurs.  It executes the highest priority serial
  interrupt for that port. (Priority order is: RLSI, RDI, THRI, MSI)

  Because it is theoretically possible for things to change between the
  interrupt trigger and the actual interrupt, some checks must be
  repeated.





  99..1100..33..  sseerriiaall__rruunn


  This is the main housekeeping function, which should be called about
  20 to 100 times per second.  The more frequent, the better, up to a
  certain point.   However, it should be self-compensating if it
  executes 10 times or even 1000 times per second.   Serial performance
  increases with frequency of execution of serial_run.

  Serial mouse performance becomes more smooth if the time between calls
  to serial_run are smaller.





  99..1111..  RReemmaarrkkss iinn bbaassee//sseerriiaall//sseerr__iirrqq..cc

  Linux code hackers: How do I detect a break signal without having to
  rely on Linux signals?  Can I peek a 'break state bit'?  Also, how do
  I 'turn on' and 'turn off' the break state, via an ioctl() or
  tcsetattr(), rather than using POSIX tcsendbrk()?


  99..1122..  IItteemmss ffoorr FFiixxiinngg iinn bbaassee//sseerriiaall//sseerr__iirrqq..cc

  how do we cancel a PIC interrupt, when we have come this far?

  -----

  Perhaps this can be modified to limit max chain length?


  99..1133..  bbaassee//sseerriiaall//iinntt1144..cc IInnffoorrmmaattiioonn

  int14.c: Serial BIOS services for DOSEMU.  Please read the
  README.serial file in this directory for more info!

  Copyright (C) 1995 by Mark Rejhon

  The code in this module 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 module is maintained by Mark Rejhon at these Email addresses:
  marky@magmacom.com ag115@freenet.carleton.ca


  99..1144..  FFuunnccttiioonnss iinn bbaassee//sseerriiaall//iinntt1144..cc

  These are the functions defined in base/serial/int14.c.


  99..1144..11..  iinntt1144

  The following function executes a BIOS interrupt 0x14 function.  This
  code by Mark Rejhon replaced some very buggy, old int14 interface a
  while back.  These routines are not flawless since it does not wait
  for a character during receive, and this may confuse some programs.




  99..1155..  NNeeww IIddeeaass ffoorr bbaassee//sseerriiaall//iinntt1144..cc

  If any of you coders are ambitious, try thinking of the following: -
  Converting this into inline assembler and use direct port access


  99..1166..  bbaassee//sseerriiaall//ffoossssiill..cc IInnffoorrmmaattiioonn

  fossil.c: FOSSIL serial driver emulator for dosemu.

  Copyright (C) 1995 by Pasi Eronen.  Portions Copyright (C) 1995 by
  Mark Rejhon

  The code in this module 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.





  99..1177..  IItteemmss ffoorr FFiixxiinngg iinn bbaassee//sseerriiaall//ffoossssiill..cc

  This really should be write-with-wait. */


  99..1188..  iinncclluuddee//sseerriiaall..hh IInnffoorrmmaattiioonn

  serial.h: Include file for port data array for DOSEMU serial.  Please
  send bug reports and bugfixes to marky@magmacom.com Please read the
  files in the 'serial' subdirectory for more info.

  99..1199..  IItteemmss ffoorr FFiixxiinngg iinn iinncclluuddee//sseerriiaall..hh

  Why does a RX_BUFFER_SIZE of 256 cause slower performance than a size
  of 128?


  1100..  TThhee MMoouussee ggrroouupp ooff MMoodduulleess

  All of the Mouse handling code is in the "mouse" subdirectory.

  There are only 2 main files, mouse.c and mouseint.c.



  1100..11..  bbaassee//mmoouussee//mmoouussee..cc IInnffoorrmmaattiioonn


  1100..22..  FFuunnccttiioonnss iinn bbaassee//mmoouussee//mmoouussee..cc

  These are the functions defined in base/mouse/mouse.c.


  1100..22..11..  mmoouussee__iinniitt


  Initialize internal mouse.





  1100..33..  RReemmaarrkkss iinn bbaassee//mmoouussee//mmoouussee..cc

  I have not properly tested this INT74 - JES 96/10/20 I have removed
  it.  INT74 is irq 12.  Which I suppose is the proper irq for a ps2
  mouse.  It appears initial support was planned to support irq 12 and
  at Mouse_ROUTINE_OFF is a routine that acknowledges an irq.  That
  routine is probably what should be acknowledging irq12, and what int
  0x74 should point to.  I have disabled int0x74 support for now. --EB
  29 Oct 1997

  -----

  Whoever wrote the dos mouse driver spec was brain dead...  For some
  video modes the mouse driver appears to randomly pick a shift factor,
  possibly to keep at least a 640x200 resolution.

  The general programming documentation doesn't make this clear.  And
  says that in text modes it is safe to divide the resolution by 8 to
  get the coordinates in characters.

  The only safe way to handle the mouse driver is to call function 0x26
  Get max x & max y coordinates and scale whatever the driver returns
  yourself.

  To handle programs written by programmers who weren't so cautious a
  doctrine of least suprise has been implemented.

  As much as possible do the same as a standard dos mouse driver in the
  original vga modes 0,1,2,3,4,5,6,7,13,14,15,16,17,18,19.

  For other text modes allow the divide by 8 technique to work.  For
  other graphics modes return x & y in screen coordinates.  Except when
  those modes are either 40x?? or 320x???  and then handle the x
  resolution as in 40x25 and 320x200 modes.

  320x200 modes are slightly controversial as I have indications that
  not all mouse drivers do the same thing. So I have taken the simplest,
  and most common route, which is also long standing dosemu practice of
  always shifting by 1.

  -- Eric Biederman 19 August 1998


  1111..  TThhee BBiiooss ggrroouupp ooff MMoodduulleess

  All of the Bios code is in the "bios" subdirectory.

  DOSEMU requires certain code to be coded in assembler and also code to
  be located in the F000 segment. This is where all such code should be
  put.



  1111..11..  bbaassee//bbiiooss//bbiiooss..SS IInnffoorrmmaattiioonn


  1111..22..  bbaassee//bbiiooss//hhlltt..cc IInnffoorrmmaattiioonn


  1111..33..  FFuunnccttiioonnss iinn bbaassee//bbiiooss//hhlltt..cc

  These are the functions defined in base/bios/hlt.c.


  1111..33..11..  hhlltt__iinniitt((vvooiidd))


  Resets all the HLT handlers





  1111..33..22..  hhlltt__hhaannddllee(())


  Handles a HLT instruction reached inside the dos emulator.





  1122..  TThhee PPIICC ggrroouupp ooff MMoodduulleess

  All of the PIC handling code is in the "PIC" subdirectory.





  1122..11..  bbaassee//ddeevv//ppiicc//ppiicc..cc IInnffoorrmmaattiioonn

  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

  Debug information:

  A debug flag of +r or 1r will generate debug messages concerning reads
  and writes to pic ports.  Many of these messages are not yet
  implemented.  A debug flag of 2r will generate messages concerning
  activation, nesting, and completion of interrupts.  A flag of -r or 0r
  will turn off debugging messages.  Flags may be combined: to get both
  1r and 2r, use a value of 3r.


  1122..22..  FFuunnccttiioonnss iinn bbaassee//ddeevv//ppiicc//ppiicc..cc

  These are the functions defined in base/dev/pic/pic.c.


  1122..22..11..  ppiicc__pprriinntt


  This is the pic debug message printer.  It writes out some basic
  information, followed by an informative message.  The basic
  information consists of: interrupt nesting counter change flag (+, -,
  or blank) interrupt nesting count (pic_icount) interrupt level change
  flag (+, -, or blank) current interrupt level interrupt in-service
  register interrupt mask register interrupt request register message
  part one decimal data value message part two

  If the message part 2 pointer is a null pointer, then only message
  part one (without the data value) is printed.

  The change flags are there to facilitate grepping for changes in
  pic_ilevel and pic_icount
  To avoid line wrap, the first seven values are printed without labels.
  Instead, a header line is printed every 15 messages.





  1122..22..22..  wwrriittee__ppiicc00,,wwrriittee__ppiicc11


  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

  Arguments are:



  1122..22..33..  rreeaadd__ppiicc00,,rreeaadd__ppiicc11


  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.





  1122..22..44..  ppiicc__mmaasskk,,ppiicc__uunnmmaasskk


  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()





  1122..22..55..  ppiicc__sseettii


  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.








  1122..22..66..  rruunn__iirrqqss


  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.





  1122..22..77..  ddoo__iirrqq


  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 To assure notification when the irq completes, we push flags,
  ip, and cs here and fake cs:ip to PIC_[SEG,OFF], where there is a hlt.
  This makes the irq generate a sigsegv, which calls pic_iret when it
  completes.  pic_iret then pops the real cs:ip from the stack.  This
  routine is RE-ENTRANT - it calls run_irqs, which may call an interrupt
  routine, which may call do_irq().  Be Careful!  !!!!!!!!!!!!!!!!!!  No
  single interrupt is ever re-entered.

  Callers: base/misc/ioctl.c base/keyboard/serv_8042.c
  base/keyboard/keyboard-server.c base/serial/ser_irq.c
  dosext/sound/sound.c dosext/net/net/pktnew.c





  1122..22..88..  ppiicc__rreeqquueesstt


  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 argument, 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.





  1122..22..99..  ppiicc__iirreett


  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.  Also, some programs fake an iret, so that it is
  possible for pic_iret to fail.  See pic_watch for the watchdog timer
  that catches and fixes this event.





  1122..22..1100..  ppiicc__wwaattcchh


  pic_watch is a watchdog timer for pending interrupts.  If pic_iret
  somehow fails to activate a pending interrupt request for 2
  consecutive timer ticks, pic_watch will activate them anyway.
  pic_watch is called ONLY by timer_tick, the interval timer signal
  handler, so the two functions will probably be merged.





  1122..22..1111..  ppiicc__ppeennddiinngg

  This function returns a non-zero value if the designated interrupt has
  been requested and is not masked.  In these circumstances, it is
  important for a hardware emulation to return a status which does *not*
  reflect the event(s) which caused the request, until the interrupt
  actually gets processed.  This, in turn, hides the interrupt latency
  of pic from the dos software.

  The single parameter ilevel is the interrupt level (see pic.h) of the
  interrupt of interest.

  If the requested interrupt level is currently active, the returned
  status will depend upon whether the interrupt code has re-requested
  itself.  If no re-request has occurred, a value of false (zero) will
  be returned.




  1122..22..1122..  ppiicc__aaccttiivvaattee


  pic_activate requests any interrupts whose scheduled time has arrived.
  anything after pic_dos_time and before pic_sys_time is activated.
  pic_dos_time is advanced to the earliest time scheduled.




  1122..22..1133..  ppiicc__sscchheedd

  pic_sched schedules an interrupt for activation after a designated
  time interval.  The time measurement is in unis of 1193047/second, (
  or if using MONOTON_MICRO_TIMING in units of PIT_TICK_RATE/second )
  the same rate as the pit counters.  This is convenient for timer
  emulation, but can also be used for pacing other functions, such as
  serial emulation, incoming keystrokes, or video updates.  Some sample
  intervals:

  rate/sec:       5       7.5     11      13.45   15      30      60
  interval:       238608  159072  108459  88702   79536   39768   19884

  rate/sec:       120     180     200     240     360     480     720
  interval:       9942    6628    5965    4971    3314    2485    1657

  rate/sec:       960     1440    1920    2880    3840    5760    11520
  interval:       1243    829     621     414     311     207     103

  pic_sched expects two parameters: an interrupt level and an interval.
  To assure proper repeat scheduling, pic_sched should be called from
  within the interrupt handler for the same interrupt.  The maximum
  interval is 15 minutes (0x3fffffff).




  1122..33..  RReemmaarrkkss iinn bbaassee//ddeevv//ppiicc//ppiicc..cc

  pic_push,pic_pop

  Pic maintains two stacks of the current interrupt level. an internal
  one is maintained by run_irqs, and is valid whenever the emulator code
  for an interrupt is active.  These functions maintain an external
  stack, which is valid from the time the dos interrupt code is called
  until the code has issued all necessary EOIs.  Because pic will not
  necessarily get control immediately after an EOI, another EOI (for
  another interrupt) could occur.  This external stack is kept strictly
  synchronized with the actions of the dos code to avoid any problems.
  pic_push and pic_pop maintain the external stack.


  1122..44..  iinncclluuddee//ppiicc..hh IInnffoorrmmaattiioonn


  1133..  TThhee SSoouunndd ggrroouupp ooff MMoodduulleess

  The sound code provides emulation of the SB. The actual emulation
  provided depends upon the support available from the kernel sound
  driver. Because this is very OS dependant the driver code itself is
  kept in architecture specifc files under
  src/arch/osname/dosext/sound/. Communication is via a set of interface
  functions and the device independant structures.




  1133..11..  ddoosseexxtt//ssoouunndd//ssoouunndd..cc IInnffoorrmmaattiioonn


  Maintainers:

  Alistair MacDonald  <alistair@slitesys.demon.co.uk>
  David Brauman  <crisk@netvision.net.il>
  Rutger Nijlunsing  <rutger@null.net>
  Michael Karcher  <Michael.Karcher@writeme.com>

  1133..22..  FFuunnccttiioonnss iinn ddoosseexxtt//ssoouunndd//ssoouunndd..cc

  These are the functions defined in dosext/sound/sound.c.




  1133..22..11..  ssbb__iioo__rreeaadd



  Arguments are:

  +o  port - The I/O port being read from.

     This handles all of the reads for the SB emulation. The value read
     is returned. The value of 0xFF indicates an invalid read. (assumes
     the ports float high when not pulled low by the hardware.)





  1133..22..22..  aaddlliibb__iioo__rreeaadd



  Arguments are:

  +o  port - The I/O port being read from.

     This handles all of the reads for the adlib (FM) emulation. The
     value read is returned. The value of 0xFF indicates an invalid
     read. (assumes the ports float high when not pulled low by the
     hardware.)  The FM emulation is not written yet. The current plan
     is to use the midi emulation where available as this is the most
     common use for the FM sound.





  1133..22..33..  mmppuu440011__iioo__rreeaadd



  Arguments are:

  +o  port - The I/O port being read from.

     The MPU-401 functionality is primarily provided by 'midid' - a
     standalone program. This makes most of the MPU-401 code simply a
     pass-through driver.





  1133..22..44..  ssbb__iioo__wwrriittee



  Arguments are:

  +o  port - The I/O port being written to.

  +o  value - The value being output.

     This handles the writes for the SB emulation. Very little of the
     processing is performed in this function as it basically consists
     of a very large switch() statement. The processing here is limited
     to trivial (1 line) items and distinguishing between the different
     actions and responses that the different revisions of the SB series
     give.





  1133..22..55..  ssbb__ddsspp__wwrriittee



  Arguments are:

  +o  value - The value being written to the DSP.

     The SB DSP is a complete I/O system in itself controlled via a
     number of data bytes. The number of bytes depends upon the
     function. The function to be executed is determined by the first
     byte.  If there is no existing command then the command is stored.
     This then used in the switch to identify the action to be taken.
     When the command has supplied all of its arguments, or failed, then
     the command storage is cleared. Each DSP function is responsible
     for clearing this itself.  Again, this function relies on other
     functions to do the real work, and apart from storing details of
     the command and parameters is basically a large switch statement.





  1133..33..  RReemmaarrkkss iinn ddoosseexxtt//ssoouunndd//ssoouunndd..cc

  Write silence could probably be implemented by setting up a "DMA"
  transfer from /dev/null - AM


  1133..44..  IItteemmss ffoorr FFiixxiinngg iinn ddoosseexxtt//ssoouunndd//ssoouunndd..cc

  The file header needs tidying up a _LOT_ ! */

  -----

  Adlib status reads are unimplemented */

  -----

  Advanced adlib reads are unimplemented */

  -----

  CMS Writes are unimplemented.

  -----

  DSP Status is unimplemented

  -----

  Adlib Waveform tests are unimplemented */

  -----

  Advanced Adlib register writes are unimplemented */

  -----


  Advanced Adlib data writes are unimplemented */

  -----

  SB Midi is Unimplemented

  -----

  Sine Generation is unimplemented

  -----

  AUX Status is Unimplemented

  -----

  Stero Input is no implemented

  -----

  ADC is Unimplemented

  -----

  Stopping Auto-Init DMA is not implemented


  1133..55..  aarrcchh//lliinnuuxx//ddoosseexxtt//ssoouunndd//lliinnuuxx__ssoouunndd..cc IInnffoorrmmaattiioonn


  Maintainers:

  Alistair MacDonald  <alistair@slitesys.demon.co.uk>
  David Brauman  <crisk@netvision.net.il>
  Michael Karcher  <Michael.Karcher@writeme.com>

  1133..66..  bbaassee//ddeevv//ddmmaa//ddmmaa..cc IInnffoorrmmaattiioonn


  Maintainers:

  Alistair MacDonald  <alistair@slitesys.demon.co.uk>
  David Brauman  <crisk@netvision.net.il>

  1133..77..  RReemmaarrkkss iinn bbaassee//ddeevv//ddmmaa//ddmmaa..cc

  **** WARNING **** This Code _HAS_ changed.

  -----

  The Emulated DMA channels are provided by using files and writes.
  This means that they are easy to track.  It might cause problems when
  attempting to interface to the REAL DMA controller. (Necessary to talk
  to hardware which uses DMA.)

  Note that DMA controller 2 uses word granular addressing and
  controller 1 uses byte granular address ... this simplifies the code !


  -----

  I think that DREQ should only be set on auto-init if we are the
  reading portion.



  1133..88..  IItteemmss ffoorr FFiixxiinngg iinn bbaassee//ddeevv//ddmmaa//ddmmaa..cc

  : Pipe Creation failed. Lets hope that it times out !

  -----

  : Cascade Mode Reads are not supported

  -----

  : The Verify Mode is not supported

  -----

  : The Invalid Mode is not supported (!)


  1144..  TThhee FFiilleeAAcccceessss ggrroouupp ooff MMoodduulleess

  This hold all kind of accessing files on a Unix filesysten from DOS.



  1144..11..  ddoosseexxtt//mmffss//mmffss..cc IInnffoorrmmaattiioonn

  This is the file redirector code for DOSEMU. It was built on the Mach
  DOS redirector and as such continues that copyright as well in
  addition the GNU copyright. This redirector uses the DOS int2f fnx 11
  calls to give running DOS programs access to any Unix mounted drives
  that permissions exist for.


  1144..22..  RReemmaarrkkss iinn ddoosseexxtt//mmffss//mmffss..cc

  The msdos_dir_ent structure has much more than 28 bytes.  Is this
  significant?

  -----

  Added compares to NUL so that newer versions of Foxpro which test
  directories using xx\yy\nul perform closer to whats DOS does.



  1144..33..  IItteemmss ffoorr FFiixxiinngg iinn ddoosseexxtt//mmffss//mmffss..cc

  We probably should use llseek here for file > 2 GBytes

  -----

  returned size of struct dir_ent seems wrong at 28 bytes. */


  1155..  TThhee TThhrreeaaddss ggrroouupp ooff MMoodduulleess

  This is the (non-POSIX) threads package, that uses the basic clone
  interface of the Linux-kernel.

  Now, what is the difference between threads and processes? A process
  runs totaly isolated from the other processes in the Unix system, it
  concurrently request resources and is controled by the operating
  system such that it does no harm to the other processes.  Interfaceing
  between processes is cost intensive performance wise.

  A thread, on the other hand, is scheduled within the context of _one_
  process, shares most (if not all) of its resources, and has to
  cooperate with the other threads in order to do no harm to whole
  thread group. Interfaceing between threads is very cheap performance
  wise, hence, using threads is what You should do when having _one_
  application that needs to do work in parallel.



  1155..11..  aarrcchh//lliinnuuxx//tthhrreeaaddss//lltt--tthhrreeaaddss..cc IInnffoorrmmaattiioonn

  This thread package does _NOT_  POSIX compatible threading.  As its
  name says: it is a tiny fast alternative using Linux cloning.  The aim
  was to avoid as much unnecessary sys_calls as possible.  Locking is
  _NOT_ done via IPC semaphores, instead we use a user level atomic
  technique, when the resource is free, there will be no sys_call atall.

  Each thread has its own 'Thread Control Block' (TCB) at the bottom of
  its stack. Hence to identify itself it doesn't need to go over
  getpid().

  However, there are restrictions given by the technique used:



     - The total maximum number of threads is 27.
     - The size of the stack must be at power of 2 and is equal
       for all threads. It is not a problem to make the stack area huge,
       because only those pages actually used will be allocated (paged in)
       by the system. Though you will be estonished what /proc/<pid>/status
       is telling you about stack consumption, ... just ignore it;-)
     - You have to lock/unlock resource_libc when using non-reentrant parts
       of libc (malloc _is_ no-reentrant).
     - You must not use atexit, exit, _exit atall. instead use the techniques
       and functions supplied by lt-threads.




  Maintainers:

  Hans Lermen  <lermen@fgan.de>

  1155..22..  FFuunnccttiioonnss iinn aarrcchh//lliinnuuxx//tthhrreeaaddss//lltt--tthhrreeaaddss..cc

  These are the functions defined in arch/linux/threads/lt-threads.c.


  1155..22..11..  MMaakkiinngg rroooomm oonn tthhee ssttaacckk



  static char *force_stack_expand(unsigned long address)


  The kernel has a feature, such that it doesn't allow grow down the
  stack below the current stack pointer.  This makes sense in single
  threaded applications, but is bad for threading purposes:


     1.   You are forced to put the stacks into the heap (below 1st giga)
          hence it is less protected against overwriting then normally.
     2.   The 1 giga stack address space isn't used any more, and
          you may have problems with address space, on huge programs
          that use huge arrays (data bases, matrices).



  We trick out the kernel by expanding the stack vma to a given value
  (setting ESP to the bottom and thouching it).  ( look at do_page_fault
  in arch/i386/mm/fault.c how it treats growing down of stack )




  1155..22..22..  SSeettttiinngg UUsseerr SSppaaccee SSttaacckk lliimmiittss



  int make_stack_unlimited(int drop_privs)


  When running as user, current Linux has a stacklimit of 8Mb.  ( no way
  to change that via bash ulimit ) This is enough for normal stacksizes,
  however, if you need more You need some way to set it to 'unlimited'.
  This only can be done as root, hence setting the suid bit is needed.
  The below function sets the limit high, and (in case drop_privs) will
  drop root priviledges before return.




  1155..22..33..  QQuueeuuiinngg ttoooollss

  These two functions have to be used when maintaining queues of various
  sorts. You may cast to your private queue entry structure as long as
  the top of this structure fits `struct queue_entry':


          struct queue_entry {
                  struct queue_entry *next;
                  struct queue_entry *last;
          };




  void append_to_queue(struct queue_entry *existing, struct queue_entry *new)




  void remove_from_queue(struct queue_entry *entry)


  Note: An existing entry _must_ have valid pointers in `next', `last'.
  We build the head of a queue with an empty queue_entry haveing `next',
  `last' poining to itself.





  1155..22..44..  AAvvooiiddiinngg LLiibbcc rreeeennttrraannccyy PPrroobblleemmss

  Because all threads share the same VM, libc needs to be reentrant.
  This isn't the case for a lot of functions ( malloc() is one on them).
  Though newer libc can be made reentrant (needs the -D_REENTRANT on
  compilation of _each_ object file), this feature has a performance
  lost due to the overhead that applies to evry libc call. As we exactly
  know _when_ we come into trouble with libc, the faster (and IMHO)
  better solution is to to take care of this at application level.


  For this to accomplish we have to put a
  (un)lock_resource(resource_libc) bracket around those involved libc
  functions. The most frequently used ones are offered by the threads
  package, including such locking.  Some of those are:


  void *locked_malloc(size_t size)




  void locked_free(void *p)


  The prototype is exactly as you expect it from the libc functions.




  1155..22..55..  ggeettttiinngg ppaaggee aalliiggnneedd mmeemmoorryy ffrroomm tthhee hheeaapp

  If you need a page aligned piece of memory, you usualy would use
  valloc().  However, you can't free that memory later. For this purpose
  you may use the below functions, which are put on top of
  malloc()/free().


  void *page_malloc(size_t size)




  void page_free(void *ptr)





  1155..22..66..  NNaammee LLiisstt TToooollss

  The below functions are used for handling small name lists (you may
  call it directories). All major resources in lt-threads are accessable
  also by their names, as they are defined on creation time. Especially
  when it comes to link between different processes (thread cores) and
  different maschines, we look up the resources (such as mailboxes,
  threads, services) via name lists.

  The global structures used for building namelists (as defined in lt-
  threads.h) are:

















  struct name_list_entry {
          char *name;
          union {
                  void *p;
                  struct tcb *tcb;
                  struct lock_struct *lock;
                  struct mbox *mbox;
                  int idata;
          } u;
  };

  struct name_list {
          int size;
          int count;
          struct name_list_entry list[0];
  };


  The follow functions are available:


  struct name_list *create_namelist(int numentries)




  int lookup_name_list(struct name_list *list, char *name)




  void * get_name_list_value(struct name_list *list, char *name)




  int set_name_list_value(struct name_list *list, char *name, void *value)




  int insert_name_list_entry(struct name_list *list, char *name, void *value)




  int delete_name_list_entry(struct name_list *list, char *name)





  1155..22..77..  EExxiittiinngg aa tthhrreeaadd

  Once the threading system is setup, you never should use exit() or
  _exit(). Instead use exit_thread(0) to exit the running thread,
  exit_thread(tcb) to kill an other thread and exit_all() to terminate
  all threads.


  void exit_thread(struct tcb *tcb)





  void exit_all(int exit_code)





  1155..22..88..  SSuussppeennddiinngg // rreessuummiinngg aa tthhrreeaadd

  When a thread has nothing valuable to do (e.g. it is waiting for some
  event to happen), it should go asleep. The following function supends
  the current running thread:


  void suspend_thread()


  With the follow function a thread can awake a sleeping thread.  This
  may (but need not) happen imediately such that the calling thread has
  been sleeping before retuning from resume_thread()


  void resume_thread(struct tcb *tcb)


  To suspend a thread for a given time interval (not resume_thread()
  needed to awaken it later) the function thread_usleep can be used.


   Note: we use our own usleep to avoid
    A) problems with signal stuff
    B) problems with libc




  void thread_usleep(int useconds)





  1155..22..99..  LLoocckkiinngg RReessoouurrcceess


  The below locking scheme implements userspace semaphores, that in the
  most frequent cases do _not_ enter the kernel.  ( doesn't use IPC or
  kernel semphores ) It depends on the atomic_reserv/free() algorithme
  defined above and won't work with other locking strategies, that
  cannot `reserve and queue' with _one_ atomic operation.

  The win of this algorithme is _much_ more speed, the disadvantage is
  that you can't have more then 27 threads.  (though, on 64-bit machines
  it could be 58 threads)

  All locking function rely on the following structure


  struct lock_struct {
          int used;
          int id;
          int owner_count;
          struct tcb *owner;
          int successor_id;
  };


  However, you should not manipulate them manually.


  struct lock_struct *create_resource(char *name)


  create_resource returns a pointer to a newly created resource.  This
  one also is then added to the resources namelist so you may look up
  for then `name'. If there are too many resources NULL will be
  returned.  The following two functions are used to lock and unlock a
  previosly created resource. A call to lock_resource() will put the
  thread into sleep state, when the resource is already locked by an
  other thread.  A call to unlock_resource() will awake a thread, that
  has been waiting on the resource.


  void lock_resource(struct lock_struct *lock)




  void unlock_resource(struct lock_struct *lock)


  The below function is a special one: The owner of a lock may dedicate
  the lock to a given other thread instead of just releasing it.  This
  will change the normal scheduling of locks.  (for example, this is
  used by the message routines)


  void transfer_resource(struct lock_struct *lock, int successor_id)





  1155..22..1100..  SSeennddiinngg aanndd rreecceeiivviinngg mmeessssaaggeess

  A threading system without message transfer would be worthless.  We
  have it ;-)

  All messages can be send to `mailboxes', that were created before.
  The size of the message queue within a mailbox can be defined at
  creation time. When a sending thread hits a queue overflow in the
  mailbox, the sending thread is put asleep and queued for later to be
  awaken.  When a receiving thread hits an empty mailbox, it also gets
  asleep.  A sending thread on an empty mailbox awakens a sleeping
  receiver, A receiving thread on a full mailbox awakens a sleeping
  sender.


  mbox_handle create_local_mailbox(char *name, int numentries)




  mbox_handle get_mailbox(char *name)




  mbox_handle get_mailbox_wait(char *name)




  void sendmessage(mbox_handle mbx, struct msg *msg)




  struct msg *receivemessage(mbox_handle mbx)




  int mailbox_is_empty(mbox_handle mbx)





  1155..22..1111..  CCrreeaattiinngg ((ssttaarrttiinngg)) aa tthhrreeaadd

  Any thread can create child threads. You must pass the address of the
  function, that contains the thread's code and (optionaly) pass the
  thread a private parameter pointer.


  struct tcb *create_thread(thread_function_type *thread_code, void *params)


  A little bit different is the creation of the `father of all threads',
  the original Unix process itself. In order to let it also use the
  threads related functions, it must be converted into a thread.

  `init_zero_thread()' makes the starting parent process behave as a
  normal thread and threfore this function call must come before any
  other thread related call. It initializes the thrreads system.


  struct tcb *init_zero_thread(int stacksize)


  To obtain the pid of any thread please use the threads_getpid()
  instead of the system call getpid(). It may be called any time and
  returns the pid of the current process, when no threading is active
  (before init_thread0()) If `tcb' is NULL, it returns the pid of the
  current thread, if -1 or THREAD0_TCB it returns the pid of `the father
  of all threads' (thread0).


  pid_t threads_getpid(struct tcb *tcb)





  1155..22..1122..  SSoommee ddeebbuuggggiinngg aaiiddss


  To make your life a bit easier (and because GDB has problems debugging
  a thread group), here some usefull functions



  int locked_printf( const char *fmt, ...)





  void print_tcb(struct tcb *tcb)




  void print_resource(struct lock_struct *lock)




  void print_mbox(mbox_handle mbx)





  1155..33..  iinncclluuddee//lltt--tthhrreeaaddss..hh IInnffoorrmmaattiioonn


  1155..44..  FFuunnccttiioonnss iinn iinncclluuddee//lltt--tthhrreeaaddss..hh

  These are the functions defined in include/lt-threads.h.


  1155..44..11..  TThhee tthhrreeaadd iittsseellff



  typedef void thread_function_type(void *params);


  All treads are functions of this type, when control reaches end of
  this function, the thread exits the same as with exit_threads(0).  The
  'params' pointer can be passed on create_tread().




  1155..44..22..  AA tthhrreeaadd''ss eexxiitt ffuunnccttiioonn



  typedef void thread_exit_function_type(void);


  A thread must _not_ use atexit() to register a exit-function (problems
  with non reentrancy of libc).  Instead, it may use the tcb->exit_func
  pointer point to a function of below type. However, the old value of
  tcb->exit_func must be saved on a _static_ place and restored within
  the exit function.  This way a a chain of exit functions will be
  called on a `last-in first-out' policy.




  1155..44..33..  AAcccceessssiinngg aa tthhrreeaadd''ss TTCCBB

  All thread private data is on the stack, there may be private data
  allocated on the heap, but the pointers to those areas should be
  itself on the stack. As long as access happens within scope of the
  thread function itself (or within local functions within function)
  this needs no extra handling. However, calling an other function that
  needs to access thread private data may be a problem. This problem can
  be solved by putting all this data into a private structure and
  starting the thread by passing it a pointer to this structure. Now,
  within scope of the thread one has access to this pointer via.
   OWN_TCB->params;


  The TCB itself always is on bottom of the stack, hence it is also
  available within a signal handler.




  1155..44..44..  LLooooppiinngg tthhrroouugghh aallll TTCCBBss

  It may be necessary to scan data of all running threads or doing
  something special like notifying e.t.c. To acomplish this you should
  use the macro FOR_ALL_TCB such as


   struct tcb *tcb;
   int id;
   FOR_ALL_TCB(id,tcb) {
      locked_printf("thread %d tcb is at address %p\n", id, tcb);
   }






  1155..44..55..  AAttoommiicc iinnlliinnee FFuunnccttiioonnss

  This set of functions is mainly used within the threads package
  itself, however, you may find them usefull for your stuff too.

  Below function atomically reserves 'resource' and queues ID.  When the
  reservation was successfull (i.e. if 'resource' was -1 before) the
  function returns -1, otherwise '0'.  Id must be a number in the range
  0..27.  In any case bit 'idnum' is set in resource. Due to the
  technique used for being atomic, only 27 of 32 bits in the integer can
  be used.


  static __inline__ int atomic_reserv(int *resource, int id)


  Below function frees a previously with atomic_reserv reserved resource
  If there are still IDs queued, the function returns with 0, otherwise
  -1.


  static __inline__ int atomic_free(int *resource, int id)


  Below function return the highest priority queued ID in the resource
  or -1, if none is queued.  Format of 'resource' is as in atomic_reserv
  and atomic_free.


  static __inline__ int get_lowest_waiting_id_from_resource(int resource)


  Below function increases `flag' atomically and returns -1 if increas-
  ing did result in transition from negativ to positive, else returns 0.


  static __inline__ int lt_atomic_inc(int *flag, int increment)


  Below function decreases `flag' atomically and returns -1 if decreas-
  ing did result in transition from positive to negative, else returns
  0.


  static __inline__ int lt_atomic_dec(int *flag, int decrement)


  Below function atomicaly tests and sets bit `bitnum' in the bitfield
  pointed to by `addr'. It returns 0 if the bit was 0 before, else -1.


  static __inline__ int atomic_bitset(void *addr, int bitnum)


  Below function atomicaly tests and clears bit `bitnum' in the bitfield
  pointed to by `addr'. It returns 0 if the bit was 0 before, else -1.


  static __inline__ int atomic_bitclear(void *addr, int bitnum)





  1155..44..66..  MMiisscc iinnlliinnee FFuunnccttiioonnss

  This set of functions is mainly used within the threads package
  itself, however, you may find them usefull for your stuff too.

  search_lowest_bit returns the index of lowest bit set or -1, if not
  found `fieldsize' must be multiple of 32


  static __inline__ int search_lowest_bit(void *addr, int fieldsize)


  As its name says: roundup_to_power_of_2


  static __inline__ int roundup_to_power_of_2(int val)





  1155..55..  DDaattaa DDeeffiinniittiioonnss iinn iinncclluuddee//lltt--tthhrreeaaddss..hh

  These are the structures and/or data defined in include/lt-threads.h.


  1155..55..11..  TTCCBB  ((TThhrreeaadd CCoonnttrrooll BBlloocckk))

  The TCB is the main data structure, that is unic to each thread.  It
  alway is at bottom of the thread's stack and can be accessed using the
  OWN_TCB macro. This also is valid while in signal handlers.

  Elements are:

  +o  struct queue_entry link;

  +o  pid_t pid;

  +o  int tcb_id;


  +o  int threadflags;

  +o  struct tcb *parent;

  +o  thread_function_type *thread_code;

  +o  void *params;

  +o  unsigned long stack_size;

  +o  int suspend_count;

  +o  char owning_locks[MAX_RESOURCES>>3];

  +o  jmp_buf exit_jmpbuf;

  +o  thread_exit_function_type *exit_func;

  +o  int exit_code;

  +o  uid_t uid, euid;

  +o  gid_t gid, egid;



  1166..  AAnndd FFiinnaallllyy ......

  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). Within this you may have the keyword
  'Maintainer:' followed by a list (one line each) of maintainers for
  this packet. These will be turned into URLs.

  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. Within this you may have
  the keywords: `arguments:', `return:' and `description:', which will
  sort out the information following it to build proper lists.

  DANG_BEGIN_STRUCT / DANG_END_STRUCT This brackets a description of
  structures and data definitions Not every structure needs to be
  described in this way - just the major ones. Within this you may have
  the keywords: `elements:', and `description:', which will sort out the
  information following it to build proper lists. Also, you may bracket
  the structur definition of real C-code, given you have one element per
  line. In this case comments (/*...*/) behind the element will be
  inserted properly into the formatted list while the C-code itself is
  still compilable.

  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)

  In addition there are some keywords, that are recognized within a
  bracket.

  VERB ... /VERB This formats the enclosed text verbatim. This is valid
  within *_MODULE, *_REMARK, *_STRUCT, *_FUNCTION

  REMARK ... /REMARK This is only valid within *_MODULE and also can
  contain VERB brakets. Its usefull to when you want to have a global
  modul description

  PROTO ... /PROTO This is only valid within *_FUNCTION and takes a C-
  function prototype as `verbatim' until either a `{' or a /PROTO is
  seen. After this all input is `skipped' until the next PROTO or a
  /SKIP.

  SKIP ... /SKIP This is only valid within *_FUNCTION and skips
  formatting until either PROTO or /SKIP is seen.














































