@c ----------------------------------------------------------------------
@node go32.h, header
@heading @code{<go32.h>}

This header provides structure definitions and functions that access
functionality that is only available because of go32.

@c ----------------------------------------------------------------------
@node _go32_conventional_mem_selector, go32
@heading @code{_go32_conventional_mem_selector}
@subheading Syntax

@example
#include <go32.h>

u_short _go32_conventional_mem_selector();
@end example

@subheading Description

This function returns a selector which has a physical base address
corresponding to the beginning of conventional memory.  This selector
can be used as a parameter to @code{movedata} (@pxref{movedata}) to
manipulate memory in the conventional address space. 

@subheading Return Value

The selector.

@subheading Example

@example
short blank_row_buf[ScreenCols()];
/* scroll screen */
movedata(_go32_conventional_mem_selector(), 0xb8000 + ScreenCols()*2,
         _go32_conventional_mem_selector(), 0xb8000,
         ScreenCols() * (ScreenRows()-1) * 2);
/* fill last row */
movedata(_go32_my_ds, (int)blank_row_buf,
         _go32_conventional_mem_selector(),
            0xb8000 + ScreenCols()*(ScreenRows()-1)*2,
          ScreenCols() * 2);
@end example

@c ----------------------------------------------------------------------
@node Go32/DPMI Information, dpmi
@heading GO32/DPMI structures
@subheading Syntax

@example
#include <dpmi.h>
@end example

@subheading Description

DPMI is an interface to the program controlling the protected mode of
the PC.  For more information on DPMI, order Intel document number
240977-001.  If there is no DPMI server running on the PC, go32 itself
will provide a subset of the DPMI functions.  For maximum portability,
programs should confine themselves to the specifications listed in the
file @file{docs/djgpp/dpmi.doc} in the DJGPP distribution.  The
convenience functions listed in @file{include/dpmi.h} comply with these
restrictions and thus will always be usable on a given PC. 

The DPMI convenience functions provided by go32 use two structures to
pass information around in.  These structures are shown below.

@example
typedef union @{
  struct @{
    u_long edi;
    u_long esi;
    u_long ebp;
    u_long res;
    u_long ebx;
    u_long edx;
    u_long ecx;
    u_long eax;
  @} d;
  struct @{
    u_short di, di_hi;
    u_short si, si_hi;
    u_short bp, bp_hi;
    u_short res, res_hi;
    u_short bx, bx_hi;
    u_short dx, dx_hi;
    u_short cx, cx_hi;
    u_short ax, ax_hi;
    u_short flags;
    u_short es;
    u_short ds;
    u_short fs;
    u_short gs;
    u_short ip;
    u_short cs;
    u_short sp;
    u_short ss;
  @} x;
  struct @{
    u_char edi[4];
    u_char esi[4];
    u_char ebp[4];
    u_char res[4];
    u_char bl, bh, ebx_b2, ebx_b3;
    u_char dl, dh, edx_b2, edx_b3;
    u_char cl, ch, ecx_b2, ecx_b3;
    u_char al, ah, eax_b2, eax_b3;
  @} h;
@} _go32_dpmi_registers;
@end example

The @code{_go32_dpmi_registers} structure is used to pass a CPU state
image between protected and real mode. 

@example
typedef struct @{
  u_long  size;
  u_long  pm_offset;
  u_short pm_selector;
  u_short rm_offset;
  u_short rm_segment;
@} _go32_dpmi_seginfo;
@end example

The @code{_go32_dpmi_seginfo} structure is used to pass information
about protected mode and real mode pointers to the convenience
functions.  Unless stated otherwise, you should not modify any field in
this structure.  Many calls store important information in otherwise
unused fields that is used in cleanup-style functions.  For example,
@code{_go32_dpmi_allocate_dos_memory} stores a value in pm_selector that
is only used by @code{_go32_dpmi_free_dos_memory}. 

@c ----------------------------------------------------------------------
@node _go32_dpmi_allocate_dos_memory, dpmi
@heading @code{_go32_dpmi_allocate_dos_memory}
@subheading Syntax

@example
#include <dpmi.h>

int _go32_dpmi_allocate_dos_memory(_go32_dpmi_seginfo *info);
@end example

@subheading Description

@xref{Go32/DPMI Information}

Allocate a part of the conventional memory area (the first 640K).  Set
the @code{size} field of @var{info} to the number of paragraphs
requested (this is (size in bytes + 15)/16), then call.  The
@code{rm_segment} field of @var{info} contains the segment of the
allocated memory. 

The memory may be resized with @code{_go32_dpmi_resize_dos_memory} and
must be freed with @code{_go32_dpmi_free_dos_memory}. 

If there isn't enough memory in the system, the @code{size} field of
@var{info} has the largest available size, and an error is returned. 

@xref{dosmemput} @xref{dosmemget}

@subheading Return Value

Zero on success, nonzero on failure.

@subheading Example

@example
_go32_dpmi_seginfo info;
info.size = (want_size+15) / 16;
_go32_dpmi_allocate_dos_memory(&info);
dosmemput(buffer, want_size, info.rm_segment*16);
_go32_dpmi_free_dos_memory(&info);
@end example

@c ----------------------------------------------------------------------
@node _go32_dpmi_allocate_iret_wrapper, dpmi
@heading @code{_go32_dpmi_allocate_iret_wrapper}
@subheading Syntax

@example
#include <dpmi.h>

int _go32_dpmi_allocate_iret_wrapper(_go32_dpmi_seginfo *info);
@end example

@subheading Description

@xref{Go32/DPMI Information}

This function creates a small assembler function that handles the
overhead of servicing an interrupt.  To use, put the address of your
servicing function in the @code{pm_offset} field of @var{info} and call
this function.  The @code{pm_field} will get replaced with the address
of the wrapper function, which you pass to both
@code{_go32_dpmi_set_protected_mode_interrupt_vector} and
@code{_go32_dpmi_free_iret_wrapper}. 

@xref{_go32_dpmi_set_protected_mode_interrupt_vector}
@xref{_go32_dpmi_free_iret_wrapper}

@subheading Return Value

Zero on success, nonzero on failure.

@subheading Example

@example
_go32_dpmi_seginfo info;
info.pm_offset = my_handler;
_go32_dpmi_allocate_iret_wrapper(&info);
_go32_dpmi_set_protected_mode_interrupt_handler(0x75, &info);
@dots{}
_go32_dpmi_free_iret_wrapper(&info);
@end example

@c ----------------------------------------------------------------------
@node _go32_dpmi_allocate_real_mode_callback_iret, dpmi
@heading @code{_go32_dpmi_allocate_real_mode_callback_iret}
@subheading Syntax

@example
#include <dpmi.h>

int _go32_dpmi_allocate_real_mode_callback_iret(_go32_dpmi_seginfo *info, _go32_dpmi_registers *regs);
@end example

@subheading Description

@xref{Go32/DPMI Information}

This function allocates a "real-mode callback".  Fill in the
@code{pm_offset} field of @var{info} and call this function.  It will
fill in the @code{rm_segment} and @code{rm_offset} fields.  Any time a
real-mode program calls the real-mode address, your function gets
called.  The registers in affect will be stored in @var{regs}, which
should be a global, and will be passed to your function.  Any changes in
@var{regs} will be reflected back into real mode.  A wrapper will be
added to your function to simulate the effects of an @code{iret}
instruction, so this function is useful for trapping real-mode software
interrupts (like 0x1b - @kbd{Ctrl-Break} hit). 

@subheading Return Value

Zero on success, nonzero on failure.

@subheading Example

@example
_go32_dpmi_registers regs;

my_handler(_go32_dpmi_registers *r)
@{
  r.d.eax = 4;
@}

setup()
@{
  _go32_dpmi_seginfo info;
  _go32_dpmi_seginfo old_vector;
  _go32_dpmi_get_real_mode_interrupt_vector(0x84, &old_vector);
  info.pm_offset = my_handler;
  _go32_dpmi_allocate_real_mode_callback_iret(&info, &regs);
  _go32_dpmi_set_real_mode_interrupt_vector(0x84, &info);
  do_stuff();
  _go32_dpmi_set_real_mode_interrupt_vector(0x84, &old_vector);
  _go32_dpmi_free_real_mode_callback(&info);
@}
@end example

@c ----------------------------------------------------------------------
@node _go32_dpmi_allocate_real_mode_callback_retf, dpmi
@heading @code{_go32_dpmi_allocate_real_mode_callback_retf}
@subheading Syntax

@example
#include <dpmi.h>

int _go32_dpmi_allocate_real_mode_callback_retf(_go32_dpmi_seginfo *info, _go32_dpmi_registers *regs);
@end example

@subheading Description

@xref{Go32/DPMI Information}

This function allocates a "real-mode callback".  Fill in the
@code{pm_offset} field of @var{info} and call this function.  It will
fill in the @code{rm_segment} and @code{rm_offset} fields.  Any time a
real-mode program calls the real-mode address, your function gets
called.  The registers in affect will be stored in @var{regs}, which
should be a global, and will be passed to your function.  Any changes in
@var{regs} will be reflected back into real mode.  A wrapper will be
added to your function to simulate the effects of a far return, such
as the callback for the packet driver receiver.

@subheading Return Value

Zero on success, nonzero on failure.

@subheading Example

@xref{_go32_dpmi_allocate_real_mode_callback_iret}

@c ----------------------------------------------------------------------
@node _go32_dpmi_chain_protected_mode_interrupt_vector, dpmi
@heading @code{_go32_dpmi_chain_protected_mode_interrupt_vector}
@subheading Syntax

@example
#include <dpmi.h>

int _go32_dpmi_chain_protected_mode_interrupt_vector(int vector, _go32_dpmi_seginfo *info);
@end example

@subheading Description

@xref{Go32/DPMI Information}

This function is used to chain a protected mode interrupt.  It will
build a suitable wrapper that will call your function and then jump to
the next handler.  Your function need not perform any special handling. 

@strong{Warning!} Because of the way DPMI works, you may @emph{not}
@code{longjmp} out of an interrupt handler or perform any system calls
(such as @code{printf}) from within an interrupt handler. 

@subheading Return Value

Zero on success, nonzero on failure.

@subheading Example

@xref{_go32_dpmi_set_protected_mode_interrupt_vector}

@c ----------------------------------------------------------------------
@node _go32_dpmi_free_dos_memory, dpmi
@heading @code{_go32_dpmi_free_dos_memory}
@subheading Syntax

@example
#include <dpmi.h>

int _go32_dpmi_free_dos_memory(_go32_dpmi_seginfo *info);
@end example

@subheading Description

@xref{Go32/DPMI Information}

This function frees the conventional memory allocated by
@code{_go32_dpmi_allocate_real_mode_memory}.  You should pass it the
same structure as was used to allocate it. 

@subheading Return Value

Zero on success, nonzero on failure.

@subheading Example

@example
_go32_dpmi_seginfo info;
info.size = 100;
_go32_dpmi_allocate_dos_memory(&info);
_go32_dpmi_free_dos_memory(&info);
@end example

@c ----------------------------------------------------------------------
@node _go32_dpmi_free_iret_wrapper, dpmi
@heading @code{_go32_dpmi_free_iret_wrapper}
@subheading Syntax

@example
#include <dpmi.h>

int _go32_dpmi_free_iret_wrapper(_go32_dpmi_seginfo *info);
@end example

@subheading Description

@xref{Go32/DPMI Information}

This function frees the memory used by the wrapper created by
@code{_go32_dpmi_allocate_iret_wrapper}.  You should not free a wrapper
that is still in use. 

@subheading Return Value

Zero on success, nonzero on failure.

@subheading Example

@xref{_go32_dpmi_allocate_iret_wrapper}

@c ----------------------------------------------------------------------
@node _go32_dpmi_free_real_mode_callback, dpmi
@heading @code{_go32_dpmi_free_real_mode_callback}
@subheading Syntax

@example
#include <dpmi.h>

int _go32_dpmi_free_real_mode_callback(_go32_dpmi_seginfo *info);
@end example

@subheading Description

@xref{Go32/DPMI Information}

This function frees the real-mode callbacks and wrappers allocated by
@code{_go32_dpmi_allocate_real_mode_callback_iret} and
@code{_go32_dpmi_allocate_real_mode_callback_retf}. 

@subheading Return Value

Zero on success, nonzero on failure.

@subheading Example

@xref{_go32_dpmi_allocate_real_mode_callback_iret}

@c ----------------------------------------------------------------------
@node _go32_dpmi_get_free_memory_information, dpmi
@heading @code{_go32_dpmi_get_free_memory_information}
@subheading Syntax

@example
#include <dpmi.h

int _go32_dpmi_get_free_memory_information(_go32_dpmi_meminfo *info);
@end example

@subheading Description

This function fills in the following structure:

@example
typedef struct @{
  u_long available_memory;
  u_long available_pages;
  u_long available_lockable_pages;
  u_long linear_space;
  u_long unlocked_pages;
  u_long available_physical_pages;
  u_long total_physical_pages;
  u_long free_linear_space;
  u_long max_pages_in_paging_file;
  u_long reserved[3];
@} _go32_dpmi_meminfo;
@end example

The only field that is guaranteed to have useful data is
@code{available_memory}.  Any unavailable field has -1 in it. 

@subheading Return Value

Zero on success, nonzero on failure.

@subheading Example

@example
int phys_mem_left()
@{
  _go32_dpmi_meminfo info;
  _go32_dpmi_get_free_memory_information(&info);
  if (info.available_physical_pages != -1)
    return info.available_physical_pages * 4096;
  return info.available_memory;
@}
@end example

@c ----------------------------------------------------------------------
@node _go32_dpmi_get_protected_mode_interrupt_vector, dpmi
@heading @code{_go32_dpmi_get_protected_mode_interrupt_vector}
@subheading Syntax

@example
#include <dpmi.h>

int _go32_dpmi_get_protected_mode_interrupt_vector(int vector, _go32_dpmi_seginfo *info);
@end example

@subheading Description

@xref{Go32/DPMI Information}

This function puts the selector and offset of the specified interrupt
vector into the @code{pm_selector} and @code{pm_offset} fields of
@var{info}.  This structure can be saved and later passed to
@code{_go32_dpmi_get_protected_mode_interrupt_vector} to restore
a vector.

@subheading Return Value

Zero on success, nonzero on failure.

@subheading Example

@xref{_go32_dpmi_set_protected_mode_interrupt_vector}

@c ----------------------------------------------------------------------
@node _go32_dpmi_get_real_mode_interrupt_vector, dpmi
@heading @code{_go32_dpmi_get_real_mode_interrupt_vector}
@subheading Syntax

@example
#include <dpmi.h>

int _go32_dpmi_get_real_mode_interrupt_vector(int vector, _go32_dpmi_seginfo *info);
@end example

@subheading Description

@xref{Go32/DPMI Information}

This function fills in the @code{rm_segment} and @code{rm_offset} fields
of @var{info} with the address of the specified real-mode interrupt
vector. 

@subheading Return Value

Zero on success, nonzero on failure.

@subheading Example

@xref{_go32_dpmi_allocate_real_mode_callback_iret}

@c ----------------------------------------------------------------------
@node _go32_dpmi_remaining_physical_memory, dpmi
@heading @code{_go32_dpmi_remaining_physical_memory}
@subheading Syntax

@example
#include <dpmi.h>

u_long _go32_dpmi_remaining_physical_memory();
@end example

@subheading Description

Returns the amount of physical memory that is still available in the
system. 

@subheading Return Value

The amount in bytes.

@c ----------------------------------------------------------------------
@node _go32_dpmi_remaining_virtual_memory, dpmi
@heading @code{_go32_dpmi_remaining_virtual_memory}
@subheading Syntax

@example
#include <dpmi.h>

u_long _go32_dpmi_remaining_virtual_memory();
@end example

@subheading Description

Returns the amount of virtual memory that is still available in the
system. 

@subheading Return Value

The amount in bytes.

@c ----------------------------------------------------------------------
@node _go32_dpmi_resize_dos_memory, dpmi
@heading @code{_go32_dpmi_resize_dos_memory}
@subheading Syntax

@example
#include <dpmi.h>

int _go32_dpmi_resize_dos_memory(_go32_dpmi_seginfo *info);
@end example

@subheading Description

@xref{Go32/DPMI Information}

The @var{info} structure is the same one used to allocate the memory. 
Fill in a new value for @code{size} and call this function.  If there is
not enough memory to satisfy the request, the largest size is filled in
to the @code{size} field, the memory is not resized, and this function
fails. 

@subheading Return Value

Zero on success, nonzero on failure.

@subheading Example

@example
_go32_dpmi_seginfo info;
info.size = 10;
_go32_dpmi_allocate_dos_memory(&info);
info.size = 20;
_go32_dpmi_resize_dos_memory(&info);
_go32_dpmi_free_dos_memory(&info);
@end example

@c ----------------------------------------------------------------------
@node _go32_dpmi_set_protected_mode_interrupt_vector, dpmi
@heading @code{_go32_dpmi_set_protected_mode_interrupt_vector}
@subheading Syntax

@example
#include <dpmi.h>

int _go32_dpmi_set_protected_mode_interrupt_vector(int vector, _go32_dpmi_seginfo *info);
@end example

@subheading Description

@xref{Go32/DPMI Information}

This function sets the protected mode interrupt vector specified to
point to the given function.  The @code{pm_offset} and
@code{pm_selector} fields of @var{info} must be filled in
(@pxref{_go32_my_cs}).  The following should be noted:

@itemize @bullet

@item

You may not @code{longjmp} out of an interrupt handler.

@item

You may not make any function calls that require go32's assistance, such
as @code{printf}. 

@item

This function will not wrap the handler for you.  The
@code{_go32_dpmi_allocate_iret_wrapper} and
@code{_go32_dpmi_chain_protected_mode_interrupt_vector} functions can
wrap your function if you want.

@item

You must set the pm_selector field of @var{info}.  Use
@code{_go32_my_cs} to get a selector valid for your functions. 

@end itemize

@subheading Return Value

Zero on success, nonzero on failure.

@subheading Example

@example
volatile int tics = 0;

timer_handler()
@{
  tics++;
@}

int main()
@{
  _go32_dpmi_seginfo old_handler, new_handler;

  printf("grabbing timer interrupt\n");
  _go32_dpmi_get_protected_mode_interrupt_vector(8, &old_handler);
  
  new_handler.pm_offset = (int)tic_handler;
  new_handler.pm_selector = _go32_my_cs();
  _go32_dpmi_chain_protected_mode_interrupt_vector(8, &new_handler);

  getkey();

  printf("releasing timer interrupt\n");
  _go32_dpmi_set_protected_mode_interrupt_vector(8, &old_handler);

  return 0;
@}

@end example

@c ----------------------------------------------------------------------
@node _go32_dpmi_set_real_mode_interrupt_vector, dpmi
@heading @code{_go32_dpmi_set_real_mode_interrupt_vector}
@subheading Syntax

@example
#include <dpmi.h>

int _go32_dpmi_set_real_mode_interrupt_vector(int vector, _go32_dpmi_seginfo *info);
@end example

@subheading Description

@xref{Go32/DPMI Information}

This function sets the real-mode interrupt vector specified to point to
the address in the @code{rm_segment} and @code{rm_offset} fields in
@var{info}.

@subheading Return Value

Zero on success, nonzero on failure.

@subheading Example

@xref{_go32_dpmi_allocate_real_mode_callback_iret}

@c ----------------------------------------------------------------------
@node _go32_dpmi_simulate_fcall, dpmi
@heading @code{_go32_dpmi_simulate_fcall}
@subheading Syntax

@example
#include <dpmi.h>

int _go32_dpmi_simulate_fcall(_go32_dpmi_registers *regs);
@end example

@subheading Description

@xref{Go32/DPMI Information}

This function simulates a real-mode far call to a function that returns
with a far return.  The registers are set up from @var{regs}, including
@code{CS} and @code{IP}, which indicate the address of the call.  Any
registers the function modifies are reflected in @var{regs} on return.

If @code{SS} and @code{SP} are both zero, a small temporary stack is
used when in real mode.  If not, they are used AS IS.  It's a good
idea to use @code{memset} to initialize the register structure before
using it.

@subheading Return Value

Zero on success, nonzero on failure.

@subheading Example

@example
_go32_dpmi_registers r;
r.x.ax = 47;
r.x.cs = some_segment;
r.x.ip = some_offset;
r.x.ss = r.x.sp = 0;
_go32_dpmi_simulate_fcall(&r);
printf("returns %d\n", r.x.ax);
@end example

@c ----------------------------------------------------------------------
@node _go32_dpmi_simulate_fcall_iret, dpmi
@heading @code{_go32_dpmi_simulate_fcall_iret}
@subheading Syntax

@example
#include <dpmi.h>

int _go32_dpmi_simulate_fcall_iret(_go32_dpmi_registers *regs);
@end example

@subheading Description

@xref{Go32/DPMI Information}

This function simulates a real-mode far call to a function that returns
with an @code{iret} instruction.  The registers are set up from
@var{regs}, including @code{CS} and @code{IP}, which indicate the
address of the call.  Any registers the function modifies are reflected
in @var{regs} on return. 

If @code{SS} and @code{SP} are both zero, a small temporary stack is
used when in real mode.  If not, they are used AS IS.  It's a good
idea to use @code{memset} to initialize the register structure before
using it.

@subheading Return Value

Zero on success, nonzero on failure.

@subheading Example

@example
_go32_dpmi_registers r;
r.x.ax = 47;
r.x.cs = some_segment;
r.x.ip = some_offset;
r.x.ss = r.x.sp = 0;
_go32_dpmi_simulate_fcall_iret(&r);
printf("returns %d\n", r.x.ax);
@end example

@c ----------------------------------------------------------------------
@node _go32_dpmi_simulate_int, dpmi
@heading @code{_go32_dpmi_simulate_int}
@subheading Syntax

@example
#include <dpmi.h>

int _go32_dpmi_simulate_int(int vector, _go32_dpmi_registers *regs);
@end example

@subheading Description

@xref{Go32/DPMI Information}

This function simulates a real-mode interrup.  The registers are set up from
@var{regs}, including @code{CS} and @code{IP}, which indicate the
address of the call.  Any registers the function modifies are reflected
in @var{regs} on return. 

If @code{SS} and @code{SP} are both zero, a small temporary stack is
used when in real mode.  If not, they are used AS IS.  It's a good
idea to use @code{memset} to initialize the register structure before
using it.

@subheading Return Value

Zero on success, nonzero on failure.

@subheading Example

@example
_go32_dpmi_registers r;
r.h.ah = 0x08;
r.h.dl = 0x80; /* drive C: */
r.x.ss = r.x.sp = 0;
_go32_dpmi_simulate_int(0x13, &r);
printf("disk is %d cyl, %d head, %d sect\n",
       r.h.ch | ((r.x.cl<<2)&0x300),
       r.h.dh, r.h.cl & 0x3f));
@end example

@c ----------------------------------------------------------------------
@node _go32_info_block, dpmi
@heading @code{_go32_info_block}
@subheading Syntax

@example
#include <go32.h>

extern Go32_Info_Block _go32_info_block;
@end example

@subheading Description

The go32 information block is a mechanism for @file{go32} to pass
information to the application.  Some of this information is generally
useful, such as the pid or the transfer buffer, while some is used
internally to @file{libc.a} only. 

The structure has this format:

@example
typedef struct @{
  u_long size_of_this_structure_in_bytes;
  u_long linear_address_of_primary_screen;
  u_long linear_address_of_secondary_screen;
  u_long linear_address_of_transfer_buffer;
  u_long size_of_transfer_buffer;
  u_long pid;
  u_char master_interrupt_controller_base;
  u_char slave_interrupt_controller_base;
  u_short selector_for_linear_memory;
  u_long linear_address_of_stub_info_structure;
  u_long linear_address_of_original_psp;
  u_short run_mode;
  u_short run_mode_info;
@} Go32_Info_Block;
@end example

The linear address fields provide values that are suitable for
@code{dosmemget} and @code{dosmemput}.

The @code{run_mode} field indicates the mode that the program is running
in.  The following modes are defined:

@table @code

@item _GO32_RUN_MODE_UNDEF

This indicates that the extender did not (or could not) determine or
provide the mode information.  The most probable reason is that it's an
older extender that does not support this field.  The program should not
assume anything about the run mode if it is this value. 

@item _GO32_RUN_MODE_RAW

This indicates that no CPU manager is being used, and no XMS manager is
present.  The CPU is being managed directly from the extender, and
memory was allocated from the extended memory pool. 

@item _GO32_RUN_MODE_XMS

This indicates that the extender is managing the CPU, but an XMS driver
is managing the memory pool. 

@item _GO32_RUN_MODE_VCPI

This indicates that a VCPI server (like @code{emm386} or @code{qemm}) is
managing both the CPU and the memory. 

@item _GO32_RUN_MODE_DPMI

This indicates that a DPMI server (like @code{qdpmi} or Windows) is
managing both the CPU and memory.  Programs may rely on this value
to determine if it is safe to use DPMI 0.9 functions.

If this value is set, the @code{run_mode_info} field has the DPMI
specification version, in hex, shifted eight bits.  For example, DPMI
0.9 has 0x0090 in the @code{run_mode_info} field. 

@end table

Note that the program should not assume that the value will be one of
the listed values.  If the program is running with an extender that
provides some other mode (say, a newly released extender) then the
program should be able to handle that case gracefully. 

@subheading Example

@example
dosmemget(_go32_info_block.linear_address_of_primary_screen, 80*25*2, buf);
@end example

@c ----------------------------------------------------------------------
@node _go32_my_cs, go32
@heading @code{_go32_my_cs}
@subheading Syntax

@example
#include <go32.h>

u_short _go32_my_cs();
@end example

@subheading Description

Returns the current @code{CS}.  This is useful for setting up interrupt
vectors and such. 

@subheading Return Value

@code{CS}

@c ----------------------------------------------------------------------
@node _go32_my_ds, go32
@heading @code{_go32_my_ds}
@subheading Syntax

@example
#include <go32.h>

u_short _go32_my_ds();
@end example

@subheading Description

Returns the current @code{DS}.  This is useful for setting up interrupt
handlers and such. 

@subheading Return Value

@code{DS}

@c ----------------------------------------------------------------------
@node _go32_my_ss, go32
@heading @code{_go32_my_ss}
@subheading Syntax

@example
#include <go32.h>

u_short _go32_my_ss();
@end example

@subheading Description

Returns the current @code{SS}.  This is useful for setting up interrupt
handlers and such. 

@subheading Return Value

@code{SS}

@c ----------------------------------------------------------------------
@node _go32_want_ctrl_break, go32
@heading @code{_go32_want_ctrl_break}
@subheading Syntax

@example
#include <go32.h>

void   _go32_want_ctrl_break(int yes);
@end example

@subheading Description

This function tells go32 whether or not it wants @kbd{Ctrl-Break} to be
an exception or passed to the application.  If you pass a nonzero value
for @var{yes}, pressing @kbd{Ctrl-Break} will set a flag that can be
detected with @code{_go32_was_ctrl_break_hit}
(@pxref{_go32_was_ctrl_break_hit}).  If you pass zero for @var{yes}, When
you press @kbd{Ctrl-Break} the program will be terminated. 

Note that if you call @code{_go32_was_ctrl_break_hit}, this function
automatically gets called to ask for @kbd{Ctrl-Break} events. 

@subheading Return Value

None.

@subheading Example

@example
_g32_want_ctrl_break(1);
do_something_long();
_g32_want_ctrl_break(0);
@end example

@c ----------------------------------------------------------------------
@node _go32_was_ctrl_break_hit, go32
@heading @code{_go32_was_ctrl_break_hit}
@subheading Syntax

@example
#include <go32.h>

u_long _go32_was_ctrl_break_hit();
@end example

@subheading Description

This function returns the number of times that @kbd{Ctrl-Break} was hit
since the last call to this function or @code{_go32_want_ctrl_break}
(@pxref{_go32_want_ctrl_break}). 

@subheading Return Value

Zero if @kbd{Ctrl-Break} hasn't been hit, nonzero to indicate how many
times if it has been hit. 

Note that @code{_go32_want_ctrl_break} is automatically called to
request these events, so you don't have to set up for this call. 

@subheading Example

@example
while (!_go32_was_ctrl_break_hit())
  do_something();
@end example

