home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-387-Vol-3of3.iso
/
v
/
vcpispec.zip
/
VCPI.DOC
< prev
Wrap
Text File
|
1993-01-19
|
60KB
|
1,134 lines
.MT2
.MB0
.PO0
.PN0
Virtual Control Program Interface
Version 1.0
June 12, 1989
VCPI SPONSORS
A.I. Architects, Inc., Peabody, MA
Lotus Development Corp., Cambridge, MA
Phar Lap Software, Inc., Cambridge, MA
Quadram, Norcross, GA
Qualitas, Inc., Bethesda, MD
Quarterdeck Office Systems, Santa Monica, CA
Rational Systems, Inc., Natick, MA
VCPI Co-ordinators: Phar Lap Software, Inc.
(617) 661-1510
Robert Moote
Quarterdeck Office Systems
(310) 392-9851
Daniel Spear
Copyright Phar Lap Software, Inc., 1987-1989
Copyright Quarterdeck Office Systems, 1987-1989
This specification may be duplicated provided it is reproduced in its
entirety, including the above copyright notice.
Version 1.0 Specification Revision History
June 12, 1989 Final revision approved by attendees of the VCPI
Developer's Conference, held at the offices of Phar
Lap Software on April 25, 1989. Attendees included
the following VCPI sponsors: A.I. Architects,
Inc., Lotus Development Corporation, Phar Lap
Software, Inc., Qualitas, Inc., Quarterdeck Office
Systems, Rational Systems, Inc.; and the following
observers: Compaq Computer Corporation, Intel
Corporation.
May 8, 1989 Revision incorporating modifications agreed upon at
the VCPI Developer's Conference. This revision was
distributed for approval to all conference
attendees.
March 31, 1989 A more detailed and explicit revision of the
December 1987 specification, drafted for review at
the VCPI Developer's Conference.
December 21, 1987 First revision of the specification, written by
Phar Lap Software, Inc., and Quarterdeck Office
Systems.
1.0 Background
The Intel 80386 microprocessor has three fundamental operating modes. Real
mode is provided for backward compatibility with existing 8086 programs.
Protected mode allows programs written specifically for the 80386 to take
advantage of the larger address space available. Virtual 8086 (V86) mode,
like real mode, is used to run 8086 programs. However, V86 mode runs under
the control of a protected mode operating environment. This provides certain
advantages, chiefly the ability to enable the paging hardware of the 80386 and
thus run multiple 8086 programs simultaneously, and also the ability to make
arbitrary physical memory available within the V86 address space of an 8086
program. (The 80486 microprocessor provides the same architecture and
operating modes as the 80386, thus software written for the 80386 runs without
modification on an 80486).
The capabilities of the 8086 have spawned the creation of several new kinds of
control programs that can run under MS-DOS on a 386 machine. To date, these
programs fall into three basic categories: (1) protected mode run-time
environments, which allow an application program to execute in protected mode
under MS-DOS; (2) EMS emulators, which use V86 mode to make all the memory on
the machine available to 8086 programs which use EMS (Lotus/Intel/Microsoft
Expanded Memory Specification) memory, and, (3) multitasking environments
which use V86 mode to multitask 8086 MS-DOS programs, while still giving each
8086 program a full 640Kb of physical memory (or more, if they use EMS
memory). Such multitasking environments typically run in conjunction with a
separate EMS emulator, or implement the EMS interface as part of the
multitasker. For the remainder of this specification, the terms "DOS-
Extender," "EMS emulator," and "multitasker," respectively, will be used to
refer to these program categories.
Since these control programs run under MS-DOS, it is desirable to make them
compatible with each other, so that users don't have to turn off one control
program in order to run an application under another control program. The
purpose of this document is to specify an interface that allows these classes
of control programs to coexist successfully. This interface is called the
Virtual Control Program Interface, or VCPI.
2.0 Areas of Conflict
There are a variety of resource contention issues which must be solved to
allow multiple 386 control programs to coexist. The section below summarizes
each of these issues.
2.1 Extended Memory Allocation
Because DOS only knows about memory below one MB, there is no universally used
method in the DOS environment for allocating and freeing extended memory
(memory above one MB). The following existing techniques are available for
allocating extended memory on both 80286 and 80386 PCs:
1. Memory can be allocated "top down" by taking over the BIOS extended
memory size system call (INT 15h function 88h) and reporting less
extended memory available than is actually present on the machine.
This method allocates a contiguous block of memory starting at the top
of extended memory and growing downward. See Appendix A.1 for a
description of top down allocation.
2. Memory can be allocated "bottom-up" by taking over the PC reboot
interrupt (INT 19h) and installing a signature block and allocation
size marker in the interrupt handler, and boot block with an
______________________________________________________________________________
VCPI Version 1.0 June 12, 1989 Page 1
allocation size marker at one megabyte. This is commonly referred to
as the VDISK technique, since it is the method employed by the
original IBM VDISK driver. This method allocates a contiguous block
of memory starting at one megabyte and growing upward. See Appendix
A.2 for a description of bottom-up allocation.
3. If an XMS (Microsoft Extended Memory Specification) drive is
installed, extended memory can be allocated by making calls to the XMS
driver. The XMS driver reserves extended memory for an XMS memory
pool using top-down allocation, and the allocates memory out of the
XMS memory pool. Copies of the XMS specification may be obtained by
calling Microsoft at 1-800-426-9400.
A program that wishes to allocate extended memory must first determine what
extended memory is free (not in use by another program). It does this by
calling INT 15h function 88h to obtain the top of free extended memory, and by
checking the signature of INT 19h and the boot block at one megabyte for any
bottom-up memory allocation, thus obtaining the bottom of free extended
memory.
The program can then allocate its own chunk of extended memory, either top
down by taking over INT 15h, or bottom-up by taking over INT 19h. The top-down
allocation method is preferable because it is simpler and more robust. The
diagram below shows an example in which three programs which use extended
memory are installed. Program 1 (the first program installed) allocates some
extended memory bottom-up, program 2 allocates two chunks of memory, one
bottom-up and one top-down, and program 3 allocates memory top-down.
top of _______________________________
memory |XXXXXXXXXXXXXXXXXXXXXXXXXXX|<= allocated by program 2
|XXXXXXXXXXXXXXXXXXXXXXXXXXX|
|---------------------------|--
|***************************|<= allocated by program 3
|---------------------------|--
| |<= free extended memory
|---------------------------|--
|XXXXXXXXXXXXXXXXXXXXXXXXXXX|<= allocated by program 2
|XXXXXXXXXXXXXXXXXXXXXXXXXXX|
|---------------------------|--
|^^^^^^^^^^^^^^^^^^^^^^^^^^^|<= allocated by program 1
1 MB => |---------------------------|--
|///////////////////////////|<= BIOS ROM, screen, etc.
640 KB => |---------------------------|--
|\\\\\\\\\\\\\\\\\\\\\\\\\\\|<= DOS memory
|___________________________|__
Note that only the last installed program which allocates extended memory top-
down or bottom-up (the first program in the interrupt chain for INT 15h or INT
19h) can dynamically change its memory allocation. In the example above, only
program 2 can dynamically modify its bottom-up memory allocation, and only
program 3 can dynamically modify its top-down memory allocation.
______________________________________________________________________________
VCPI Version 1.0 June 12, 1989 Page 2
It is possible for VCPI memory, XMS memory and extended memory all to be
available on a single PC. (This can occur, for example, if a VCPI driver is
installed and is given a portion of extended memory, an XMS driver is
installed and even another chunk of extended memory, and the rest of extended
memory is left free.) Therefore, programs which can use extended memory may
wish to look for all three sources of memory. The recommended order of use of
the different memory allocation methods is: (1) VCPI memory, (2) XMS memory,
and, (3) extended memory.
2.2 Mode Switching
All 386 control programs need to do some processing in protected mode, but
also need to allow standard 8086 code (such as other applications, DOS, and
the BIOS) to execute. Therefore, they must switch between 80386 protected mode
and either real mode or V86 mode.
If two control programs both switch between protected mode and real mode, no
special problems are posed. If, however, a control program switches between
V86 mode and protected mode, it is impossible for a second control program to
switch into protected mode. This is because programs running in V86 mode are
executing at the least privileged level of the 80386 processor, so system-
level operations will cause processor exceptions, which result in the first
control program regaining control. Thus the first control program must
provide a method to allow subsequent control programs to switch to protected
mode and back to V86 mode again.
2.3 8259A Interrupt Controller
The standard interrupt vectors used on the 386 PC for hardware interrupts
IRQ0 - IRQ7 are vectors 08h - 0Fh. Unfortunately, those vectors are also used
by the 80386 processor for certain processor exceptions. For this reason,
some 386 control programs reprogram the 8259A interrupt controller chip to
relocate IRQ0 - IRQ7 to different interrupt vectors. Information about
reprogramming of the 8259A must be made available to all cooperating 386
control programs.
2.4 Privileged Instructions
When the 386 processor is executing in V86 mode, it is executing at privilege
level 3 (the least privileged level), and privileged instructions cause an
exception. These include instructions which load or store 386 system
registers, including the control registers, the debug registers, the test
registers, GDTR, LDTR, and TR. Access to some of these registers is needed in
V86 mode; others only need to be modified as part of a mode switch to
protected mode.
In addition, a number of instructions cause a general protection exception if
the I/O privilege level (IOPL) is not 3 when executing in V86 mode. These
instructions must be made available, either by setting IOPL to 3, or by
emulating the instructions.
3.0 Interface Summary
Many of the problems listed above occur only when one control program uses V86
mode. EMS emulators run in V86 mode and are widely used on 386 PCs, and an
EMS interface is typically used or provided by multitaskers. In addition, one
of the primary functions performed by EMS emulators is memory allocation.
______________________________________________________________________________
VCPI Version 1.0 June 12, 1989 Page 3
For these reasons, the VCPI interface is defined as a superset of the EMS
version 4.0 interface (an EMS 4.0 driver must be provided underneath the VCPI
interface; a copy of the EMS 4.0 interface specification may be obtained by
calling Intel literature sales at 1-800-548-4725 and requesting part #300275).
If an EMS emulator with the VCPI interface is installed, a multitasker and/or
an arbitrary number of DOS-Extender programs which use the VCPI interface can
be run. Control programs which utilize the VCPI interface provided by the EMS
emulator will be referred to as "clients" for the remainder of this document.
The control program providing the VCPI interface (and the EMS 4.0 interface)
will be referred to as the "server" for the remainder of this document.
A server is installed at boot time, and takes over a block of extended memory
which becomes the expanded memory pool from which it allocates EMS pages.
When the server is installed, it can be given all the extended memory on the
computer, or extended memory can be "partitioned" into expanded memory and
extended memory (i.e., some extended memory is taken by the server for the
expanded memory pool, and the rest is left free, available for use by other
programs).
Clients can obtain memory by making requests of the server. Memory allocated
though the VCPI interface comes out of the memory pool owned by the server
(i.e., expanded memory), and must be in the physical address space of the
computer (e.g., it must not be memory on a separate expanded memory board).
If any extended memory is left free by the server, clients can allocate that
extended memory in the usual way.
The VCPI interface is implemented with calls to functions provided by the
server. Calls need to be made both in V86 mode and in protected mode. The
V86 mode calls are implemented through the standard INT 67h EMS interface.
The protected mode calls are made with FAR procedure calls to an entry point
in the server. The protected mode entry point is obtained via an
initialization on call to the server.
Both the server and each client program maintain their own set of system
tables (GDT, LDT, IDT, page tables, etc.) Each client program must initialize
a memory space in its page tables which is identical to a portion of the
memory space used by the server, in order to provide a common ground for
communication with the server. When the client calls the server to switch to
protected mode, the client's system tables are set up as part of the mode
switch. Likewise, when the client calls the server to switch back to V86
mode, the server's system tables are set up.
The server must leave A20 (address line 20 on a PC) enabled at all times, in
both V86 mode and in protected mode.
The client must always use the services of the server to switch modes. It
should never, for example, implement its own switch back to V86 mode, because
the server's system tables must be set up when executing in V86 mode.
4.0 V86 Mode Program Interface
The V86 mode interface is provided through the EMS interrupt (INT 67h), with
an EMS function code in AH of DEh, and a VCPI function code in AL. (Note that
any EMS driver which does not provide VCPI should return either code 84h (bad
function code) for this EMS call, since it is not a defined function number
for the LIM 4.0 EMS specification.) If the function succeeds, AH is returned
as zero; otherwise, there is an error code in AH. Except as noted for each
call, all other registers are unchanged on output.
_______________________________________________________________________________
VCPI Version 1.0 June 12, 1989 Page 4
If an undefined VCPI subfunction code is passed in AL, the server returns an
either code in AH; the recommended value is 8Fh (bad subfunction code).
The IOPL-sensitive privileged instructions must be available in V86 mode.
This means the server must either set the IOPL to 3, or emulate these
instructions. Other privileged instructions need not be emulated as part of
the VCPI interface. Instead, access to certain system registers is provided
via system calls (see Section 4.4).
4.1 Presence Detection
The presence of a server which provides the VCPI interface is detected by
first using one of the standard detection checks to see if an EMS driver is
installed, and then making the EMS call below to check for the presence of
VCPI.
==============================================================================
INT 67h
AX = DE00h VCPI Presence Detection
==============================================================================
INPUTS: None
-------------------------------------------------------------------------------
OUTPUTS: If VCPI is present:
AH = 0
BL = 0 (VCPI minor version number, in binary)
BH = 1 (VCPI major version number, in binary)
If not present:
AH = nonzero (recommended value: 84h)
-------------------------------------------------------------------------------
If the server is installed but no EMS memory has been allocated, the server
may be executing in real mode rather than V86 mode. The detection call should
return success in real mode as well as V86 mode (so that it is possible to
detect a VCPI server that is currently turned off, and also for backward
compatibility with clients that make this call in real mode); however, for the
rest of the VCPI interface to be enabled, the processor must be executing in
V86 mode. Therefore, the following VCPI detection sequence is recommended:
1. Check to see if the processor is an 80386 or 80486.
2. Check to see if an EMS driver is installed.
3. Allocate one EMS page. This will turn on the EMS driver if it is
off, switching the processor to V86 mode.
4. Make the above VCPI detection call.
The EMS page allocated in step 3 must not be deallocated again until the
client is done using the VCPI interface; otherwise, the server could turn off
again, setting the processor back to real mode and disabling the VCPI
interface.
Appendix A.3 contains a code sequence demonstrating VCPI detection.
4.2 Interface Initialization
The interface initialization process involves creating a common ground between
the server and the client that allows them to communicate in protected mode,
and providing any other information that the client may need to complete its
______________________________________________________________________________
VCPI Version 1.0 June 12, 1989 Page 5
own initialization. Since the server and the client each have separate page
tables, GDT, LDT, and IDT, in order to communicate in protected mode the
client must set up a region in its page tables that maps memory used by the
server, and must initialize segment descriptors in its GDT to point to code
and data regions in the server.
The calls below are used to initialize the interface between the server and
the client.
==============================================================================
INT 67h
AX = DE01h Get Protected Mode Interface
==============================================================================
INPUTS: ES:DI = pointer to 4K page table buffer
DS:SI = pointer to three descriptor table entries in the
client's GDT, the first to be set up as the
protected mode code segment in the server, and the
additional two entries to be used as desired by
the server when it is called in protected mode
-------------------------------------------------------------------------------
OUTPUTS: AH = 0
DI = advanced to point to the first unused page table
entry in the buffer (could be advanced by 4K, if
server initializes entire page table)
EBX = offset in code segment of protected mode entry point
-------------------------------------------------------------------------------
The Get Protected Mode Interface call is used to set up a common frame of
reference which allows the client to make calls to the server in protected
mode. The call initializes a page table which the client must set up as its
0th page table. This page table must map at least one megabyte of memory
starting at linear address zero: the real mode address space provided in V86
mode. In addition, the server can map any additional memory above one
megabyte (up to a total of four megabytes, since there is just one page table)
which it requires to provide the protected mode interface. While the mappings
for the first megabyte must be identical for both the client and the server
(so the client will be able to set up segments to access its V86 memory from
protected mode), memory above one megabyte can be mapped as desired by the
server (e.g., if the server's code and data is mapped at a high address in its
own page tables, it would simply map the same code and data just above one
megabyte in the client's 0th page table).
For backward compatibility, both the server and the client must clear the
software-defined bits (bits 9 - 11) in the page table entries it copies into
the client's page table; all other bits should be preserved the client must
not copy its 0th page table to a different physical page after this call is
made. This is so the server can always access the client's 0th page table.
The client must never modify any bits other than the software-defined bits (9-
11) in the page table entries which are initialized by this call.
In addition to initializing the 0th page table, this call also fills in a GDT
entry in the client's GDT. This segment is used by the client when calling
the server in protected mode. The segment must be set up as a code segment,
and must reside in the linear address space set up in the 0th page table by
this call. The entry point of the interface routine (its offset within the
code segment) is returned in EBX. Two additional entries in the client's GDT,
immediately following the GDT entry for the code segment, are available to the
server for its own use. Typically at least one of these GDT segments is used
by the server as a data segment.
______________________________________________________________________________
VCPI Version 1.0 June 12, 1989 Page 6
When the client calls the server in protected mode, it makes a FAR call to a
USE32 segment, using the entry point provided by this call. Since the server
has initialized the code segment descriptor, it can, of course, set it up any
way it desires, but it is responsible for executing a USE32 FAR return when it
terminates, regardless of the actual use type of the code segment. Thus, when
the server is called in protected mode, it will have CS pointing to the code
segment which is set up by this call. It can obtain selectors for the two
additional GDT entries which it set up by adding 0008h and 0010h,
respectively, to the segment selector value in CS. The server must preserve
all segment registers across a protected mode VCPI call.
==============================================================================
INT 67h
AX = DE02h Get Maximum Physical Memory Address
==============================================================================
INPUTS: None
------------------------------------------------------------------------------
OUTPUTS: AH = 0
EDX = PHYSICAL address of the highest 4K memory page that
could ever be allocated.
------------------------------------------------------------------------------
The Get Maximum Physical Memory Address call is used by the client to
initialize its memory management data structures. To do this, it may need to
know the physical address of the highest 4K memory page that could ever be
allocated by the Allocate 4K Page call specified below. For backward
compatibility, both the server and the client must mask the 12 LSBs of the
physical page address (returned in EDX) to zero.
4.3 Memory Allocation Calls
The memory allocation calls are used to allocate and free 4K pages of memory.
The server allocates these pages out of its EMS memory pool. The client can
also do its own allocation of extended memory or XMS memory, if any is
available.
==============================================================================
INT 67h
AX = DE03h Get Number of Free 4K Pages
===============================================================================
INPUTS: None
-------------------------------------------------------------------------------
OUTPUTS: AH = 0
EDX = number of free 4K pages
-------------------------------------------------------------------------------
This call returns the total number of 4K pages available to be allocated out
of the server's expanded memory pool.
Note that this is the total amount of free memory available to all tasks on
the system. The client should allocate this memory only on an as needed
basis. In addition, in a multitasking environment, this number does not
reflect any memory restrictions placed on the client task by the multitasker.
The client should, during initialization, use the EMS call Get Number of Pages
(INT 67h function 3 (AH=42h)) to obtain the number of unallocated EMS pages
available, and then limit its usage of memory allocated through the server to
that amount. (Note that the size of an EMS page is 16K, and the size of a
page allocated through the VCPI interface is 4K.)
______________________________________________________________________________
VCPI Version 1.0 June 12, 1989 Page 7
==============================================================================
INT 67h
AX = DE04h Allocate a 4K Page
===============================================================================
INPUTS: None
-------------------------------------------------------------------------------
OUTPUTS: If success:
AH = 0
EDX = PHYSICAL address of allocated 4K page
If failure:
AH = nonzero (recommended value: 88h)
EDX = contents modified
-------------------------------------------------------------------------------
This call allocates a 4K page of memory. For backward compatibility, both the
server and client must make the 12 LSBs of the physical page address (returned
in EDX) to zero. The client is responsible for freeing all memory allocated
with this call before terminating execution.
==============================================================================
INT 67h
AX = DE05h Free a 4K Page
===============================================================================
INPUTS: EDX = PHYSICAL address of 4K page to free
-------------------------------------------------------------------------------
OUTPUTS: If success:
AH = 0
If failure:
AH = nonzero (recommended value: 8Ah)
-------------------------------------------------------------------------------
This call frees a page of memory previously allocated with subfunction 04h.
For backward compatibility, both the server and the client must mask the 12
LSBs of the physical page address (passed in EDX) to zero.
______________________________________________________________________________
VCPI Version 1.0 June 12, 1989 Page 8
==============================================================================
INT 67h
AX = DE06h Get Physical Address of 4K Page in First Megabyte
===============================================================================
INPUTS: CX = page number (linear address of page SHR 12)
-------------------------------------------------------------------------------
OUTPUTS: If success:
AH = 0
EDX = PHYSICAL address of 4K page
If invalid page number:
AH = nonzero (recommended value: 8Bh)
-------------------------------------------------------------------------------
This call returns the physical address of a 4K page in the first megabyte of
the V86 mode linear address space. For backward compatibility, both the
server and the client must mask the 12 LSBs of the physical page address
(returned in EDX) to zero.
This call is useful for obtaining the address of memory which is allocated and
mapped into the first megabyte with the standard EMS calls. While this
information can also be extracted from the page table obtained with the Get
Protected Mode Interface system call, that page table is a "snapshot" of the
server's page tables at the time the system call was made, and would not have
the correct addresses for any EMS memory mapped in after the Get Protected
Mode Interface call was made.
4.4 System Register Access Calls
When executing in V86 mode, any attempt to load or store system registers
causes a general protection exception. The system calls below provide access
to certain system registers in V86 mode.
===============================================================================
INT 67h
AX = DE07h Read CR0
===============================================================================
INPUTS: None
-------------------------------------------------------------------------------
OUTPUTS: AH = 0
EBX = CR0 value
-------------------------------------------------------------------------------
This call returns the current value of the CR0 register.
______________________________________________________________________________
VCPI Version 1.0 June 12, 1989 Page 9
===============================================================================
INT 67h
AX = DE08h Read Debug Registers
===============================================================================
INPUTS: ES:DI = pointer to array of 8 DWORDS, DR0 first in
array, DR4 and DR5 not used
-------------------------------------------------------------------------------
OUTPUTS: AH = 0
-------------------------------------------------------------------------------
This call stores the values of the debug registers into an array in memory.
===============================================================================
INT 67h
AX = DE09h Load Debug Registers
===============================================================================
INPUTS: ES:DI = pointer to array of 8 DWORDS, DR0 first in array,
DR4 and DR5 not used
-------------------------------------------------------------------------------
OUTPUTS: AH = 0
-------------------------------------------------------------------------------
This function loads the debug registers with the values in the array.
4.5 8259A Interrupt Vector Mapping Calls
The default PC interrupt vector assignments for hardware interrupts are
vectors 08h - 0Fh for interrupts IRQ0 - IRQ7, and vectors 70h - 77h for
interrupts IRQ8 - IRQ15. The 80386 processor uses interrupt vectors 08h - 0Fh
for processor exceptions, which are important to 386-specific software.
Therefore, some clients find it desirable to reprogram the 8259A interrupt
controller to map the hardware interrupt vectors elsewhere in the interrupt
space. The server, as the first control program in place, is the repository
of information on what the current vector mappings are. Client programs
should query the server during initialization to determine the current
mappings. If they have been changed from the PC default mappings, the client
is obligated not to change them again. If they are still set to the PC
defaults, the client can reprogram the interrupt controller and then inform
the server what the new mappings are.
______________________________________________________________________________
VCPI Version 1.0 June 12, 1989 Page 10
===============================================================================
INT 67h
AX = DE0Ah Get 8259A Interrupt Vector Mappings
===============================================================================
INPUTS: None
-------------------------------------------------------------------------------
OUTPUTS: AH = 0
BX = 1st vector mapping for master 8259A (IRQ0-IRQ7)
CX = 1st vector mapping for slave 8259A (IRQ8-IRQ15)
-------------------------------------------------------------------------------
This function returns the interrupt vectors generated by the 8259A interrupt
controller chips when a hardware interrupt occurs. If there is no slave 8259A
to generate IRQ8-IRQ15 (because the software is running on a 386 accelerator
card plugged into a PC or a PC/XT), then the value returned in CX is
unspecified.
Note that, for programs who wish to take over hardware interrupts in V86 mode,
other considerations may apply when executing in a multitasking environment.
===============================================================================
INT 67h
AX = DE0Bh Set 8259A Interrupt Vector Mappings
===============================================================================
INPUTS: BX = vector mapping for master 8259A (IRQ0-IRQ7)
CX = vector mapping for slave 8259A (IRQ8-IRQ15)
Interrupts disabled
-------------------------------------------------------------------------------
OUTPUTS: AH = 0
-------------------------------------------------------------------------------
This call is used by the client to inform the server if it remaps the 8259A
interrupt controllers. The client must leave interrupts disabled from the
time it begins to reprogram the interrupt controllers until after it makes
this function call to inform the server of the remapping.
Note that the server must leave interrupts disabled until after it has logged
the vector mappings provided by the call. In particular, it must not
"reflect" the interrupt back to V86 mode before recording the information, in
case there is another program in the INT 67h chain which enables interrupts.
If the client remaps the 8259A interrupt controller, it is responsible for
restoring the original interrupt controller mappings when it terminates.
______________________________________________________________________________
VCPI Version 1.0 June 12, 1989 Page 11
4.6 Switch to Protected Mode
===============================================================================
INT 67h
AX = DE0Ch Switch From V86 Mode to Protected Mode
===============================================================================
INPUTS: ESI = linear address of data structure in first megabyte,
containing values to load into system registers
Interrupts disabled
-------------------------------------------------------------------------------
OUTPUTS: GDTR, IDTR, LDTR, TR loaded
Interrupts disabled
Control transferred to specified FAR entry point
SS:ESP must have at least 16 BYTEs of space on it, and the
protected mode entry point is required to set up its
own stack before re-enabling interrupts
EAX = contents modified
ESI = contents modified
DS, ES, FS, GS = contents modified
All other registers unmodified
-------------------------------------------------------------------------------
This call switches to protected mode, sets up all the system tables for the
client, and transfers control to the specified entry point in the client.
Interrupts must remain disabled for the entire duration of the switch. The
ESI register contains a linear address of a data structure in the first
megabyte; because the page table mappings for the first megabyte are identical
in both the server's and the client's page tables, this address can be used by
the server both before and after reloading the CR3 register.
The data structure pointed to by ESI looks like:
10 (DWORD) CS:EIP too transfer control to
0E (WORD) selector value to load into TR
0C (WORD) selector value to load into LDTR
08 (DWORD) linear address in first megabyte of 6-byte value to
load into IDTR
04 (DWORD) linear address in first megabyte of 6-byte value to
load into GDTR
ESI->00 (DWORD) new value to load into CR3
Note that the server must load GDTR before loading the LDTR and TR (IDTR can
be loaded at any time, since interrupts are disabled). The GDTR and IDTR must
be loaded with the 32-bit forms of the LGDT and LIDT instructions, not the 24-
bit forms provided for backward compatibility with the 80286 processor. The
server must clear the task busy bit in the TSS descriptor table entry in the
client's GDT before loading TR (which must be loaded with an LTR instruction,
not a task switch). Note that, since the client's GDT could reside anywhere
in the 4 GB linear address space, the TSS descriptor table entry cannot be
modified (and the LDTR and TR registers cannot be loaded) until after CR3 is
loaded with the client's value, and the data segment used to modify the TSS
descriptor must have a base address of zero and a limit of 4 GB. The server
must not reload any segment registers after it loads the GDTR with the
client's GDT address; note that the ability to modify GDTR and LDTR without
reloading segment registers relies on the segment descriptor caching performed
by the processor.
______________________________________________________________________________
VCPI Version 1.0 June 12, 1989 Page 12
The server's code that implements the switch must reside in the linear region
that was initialized with the Get Protected Mode Interface call (function
DE01h), since that is the only linear region that is mapped identically in
both the server's and the client's page tables.
When the client gets control, the stack is still set to whatever stack the
server was using (because SS has not been reloaded, the descriptor cache
register for SS still points to the server's stack segment). The client must
reload all segment registers and set up its own stack before enabling
interrupts. This is a requirement since an interrupt handler will attempt to
save and restore segment registers, and the values left in the segment
registers after the switch are not necessarily valid segments for the client.
5.0 Protected Mode Interface
The protected mode interface is a FAR entry point in the server, which is
obtained during initialization with the Get Protected Mode Interface system
call (INT 67h function DE01h). The client makes a FAR call to a USE32 segment
when it calls the server entry point, and the server must execute a USE32 FAR
return when it terminates.
An EMS function code of DEh is passed in AH, and a VCPI function code is
passed in AL. If the function succeeds, AH is returned as zero; otherwise,
there is an error code in AH. Except as noted for each call, all other
registers are unchanged on output.
If an undefined VCPI subfunction code is passed in AL, the server returns an
error code in AH; the recommended value is 8Fh (bad subfunction code).
5.1 Memory Allocation Calls
The memory allocation calls are used to allocate and free 4K pages of memory
the server allocates these pages out of its expanded memory pool. The client
can also do its own allocation of extended memory or XMS memory, if any is
available.
===============================================================================
INT 67h
AX = DE03h Get Number of Free 4K Pages
===============================================================================
INPUTS: None
-------------------------------------------------------------------------------
OUTPUTS: AH = 0
EDX = number of free 4K pages
-------------------------------------------------------------------------------
This call returns the total number of 4K pages available to be allocated out
of the server's expanded memory pool.
Note that this is the total amount of free memory available to all tasks on
the system. The client should allocate this memory only on an as needed
basis. In addition, in a multitasking environment, this number does not
reflect any memory restrictions placed on the client task by the multitasker.
The client should, during initialization, use the EMS call Get Number of Pages
(INT 67h function 3 (AH = 42h)) to obtain the number of unallocated EMS pages
available, and then limit its usage of memory allocated through the server to
that amount. (Note that the size of an EMS page is 16K, and the size of a
page allocated through the VCPI interface is 4K.)
______________________________________________________________________________
VCPI Version 1.0 June 12, 1989 Page 13
===============================================================================
INT 67h
AX = DE04h Allocate a 4K page
===============================================================================
INPUTS: None
-------------------------------------------------------------------------------
OUTPUTS: If success:
AH = 0
EDX = PHYSICAL address of allocated 4K page
If failure:
AH = nonzero (recommended value: 88h)
EDX = contents modified
-------------------------------------------------------------------------------
This call allocates a 4K page of memory. For backward compatibility, both the
server and client must mask the 12 LSBs of the physical page address (returned
in EDX) to zero. The client is responsible for freeing all memory allocated
with this call before terminating execution.
===============================================================================
INT 67h
AX = DE05h Free a 4K Page
===============================================================================
INPUTS: EDX = PHYSICAL address of allocated 4K page
-------------------------------------------------------------------------------
OUTPUTS: If success:
AH = 0
If failure:
AH = nonzero (recommended value: 8Ah)
-------------------------------------------------------------------------------
This call frees a page of memory previously allocated with subfunction 04h.
For backward compatibility, both the server and the client must mask the 12
LSBs of the physical page address (passed in EDX) to zero.
______________________________________________________________________________
VCPI Version 1.0 June 12, 1989 Page 14
5.2 Switch to V86 Mode
===============================================================================
INT 67h
AX = DE0Ch Switch From Protected Mode to V86 Mode
===============================================================================
INPUTS: Top of stack looks as described below
Interrupts disabled
SS:ESP must be in the first megabyte of linear memory
DS = segment selector that maps the entire linear address space
that was obtained with subfunction 01h, Get Protected Mode
Interface (i.e., its base address is 0, and its limit is
the size of the address space obtained with the Get
Protected Mode Interface call)
-------------------------------------------------------------------------------
OUTPUTS: GDTR, IDTR, LDTR, TR loaded with server's values
Interrupts disabled
Control transferred to specified FAR entry point
SS:ESP and all segment registers loaded with values on stack
EAX = destroyed
All other registers unmodified
-------------------------------------------------------------------------------
This call switches from protected mode back to V86 mode, after setting up all
of the server's system tables. The top of stack looks as follows on input to
this function:
28 (DWORD) GS value
24 (DWORD) FS value
20 (DWORD) DS value
1C (DWORD) ES value
18 (DWORD) SS value
14 (DWORD) ESP value
10 (DWORD) reserved for EFLAGS value
0C (DWORD) CS value
08 (DWORD) EIP value
SS:ESP-> 00 (DWORD) return address from FAR call to USE32 segment
The first 8 bytes at SS:ESP are the return address pushed by the FAR CAlL
instruction; since this call never returns, the return address is irrelevant
and should be discarded. It is the responsibility of the server to fill in an
appropriate EFLAGS value (e.g., VM bit set, IOPL = 3, IF bit cleared) before
executing the IRETD to return to V86 mode. Interrupts must remain disabled
for the entire duration of the switch, and the interrupt enable bit must be
off in the EFLAGS value which is stored on the stack before executing the
IRETD which switches back to V86 mode. The server's code that implements the
switch must reside in the linear region that was initialized with the Get
Protected Mode Interface call (function DE01h), since that is the only linear
region that is mapped identically in both the server's and the client's page
tables.
If the client does any task switching, it should clear the TS bit in CR0
before making this call. Otherwise, the TS bit will still be set after the
switch to V86 mode, and a floating point coprocessor instruction in V86 mode
will cause an exception 7 trap to the server.
______________________________________________________________________________
VCPI Version 1.0 June 12, 1989 Page 15
Appendix A
Implementation Notes
A.1 Top-Down Extended Memory Allocation
The BIOS extended memory size system call is used to determine the upper limit
of extended memory which is not in use by other programs. The following code
fragment gets the physical address of one byte past the end of available
extended memory in the EAX register:
xor eax,eax ; clear MSBs in EAX
mov ah, 88h ; get size of extended memory in KB
int 15h
shl eax, 10 ; convert it address of top of memory
add eax, 100000h
To allocate extended memory top down, simply install an INT 15h handler which
passes all functions except 88h through to the previous INT 15h handler. If
an INT 15h function 88h call is made, return a value which reduces the size of
extended memory by the amount of memory you wish to allocate.
A.2 Bottom-Up Extended Memory Allocation
Bottom-up extended memory allocation is not recommended, as it is more
complicated and less versatile than top-down allocation. However, programs
that wish to allocate extended memory must first check to see if any other
programs have allocated extended memory using the bottom-up technique. Bottom-
up extended memory allocation is done by marking the amount of memory
allocated in two locations. If there is any extended memory on the system (if
the BIOS call documented in Appendix A.1 does not return zero), it is
necessary to check BOTH of these locations to see if any bottom-up extended
memory has been allocated. If the two locations show different amounts of
allocated memory, the safest thing to do is terminate with an error message.
Failing that, the larger of the two values found should be used. The values
may differ in the two locations because there are several programs available
which use bottom-up allocation but which do not correctly update both
locations, and also because the DOS PRINT command in DOS 3.3 or later wipes
out the allocation information in one of the two locations.
The first location is the segment pointed at by the INT 19h vector (the reboot
interrupt). If an appropriate signature is present at a specific offset in
this segment, then there is a 24-bit address of the first free byte of
extended memory at another specific offset in the segment. The following code
fragment obtains the physical address of the first free byte of extended
memory and loads it into EAX:
data segment
vdisk_sig db 'VDISK V' ; signature string
SIG _ LEN equ $ - vdisk_sig ; signature string length
SIG_VEC equ 19h ; interrupt vector for signature
SIG_OFFS equ 12h ; offset of signature string in segment
LO_OFFS equ 2Ch ; offset of low word of 24-bit value
HI_OFFS equ 2Eh ; offset of high byte of 24-bit value
data ends
______________________________________________________________________________
VCPI Version 1.0 June 12, 1989 Page 16
assume cs:code,ds:data
code segment use16
xor ax,ax ; get segment addr in ES
mov es,ax
mov ax,es:(SIG_VEC * 4) + 2
mov es,ax
mov di,SIG_OFFS ; branch of signature not present
lea si,vdisk_sig
mov ex,SIG_LEN
cld
repe cmpsb
jne short no_alloc
xor eax,eax ; get addr of bottom of extended memory
mov al,es:HI_OFFS ; into EAX
shl eax,16
mov ax,es:LO_OFFS
jmp short done ; all done
no_alloc:
mov eax,100000h ; no bottom-up memory allocated
done: ; bottom of extended memory is now in EAX
code ends
The second location to check is a boot block located at one megabyte. The
following C code fragment retrieves the allocation value from the boot block
and saves it in the variable "bot_ext" (note that this code should NOT be
executed if there is no extended memory on the system, since it attempts to
read memory at one megabyte):
long bot_ext; /* addr of 1st free byte of extended memory */
char buf [0x20]; /* buffers boot block */
#define SIGOFF 0x03 /* offset of signature in boot block */
#define SIZEOFF 0x1E /* offset of size word in boot block */
/*
* Read boot block at one megabyte by calling an assembly language
* routine (not shown) which either uses the BIOS block move call to
* read from extended memory, or does it in some other way.
*/
read_ext(0x100000, buf, sizeof(buf));
/*
* Now check for the correct signature in the boot block, and if
* present, extract the bottom of available extended memory.
*/
if (memcmp(&buf[SIGOFF], "VDISK", 5) != 0)
bot_ext = 0x100000;
else
{
bot_ext = 01;
memcpy(&bot_ext, &buf[SIZEOFF], 2]; /* get KB addr */
bot_ext = bot_ext << 10; /* convert to byte addr */
______________________________________________________________________________
VCPI Version 1.0 June 12, 1989 Page 17
A.3 Sample VCPI Detection Code
The following code sequence should be used to detect the presence of the VCPI
interface:
data segment
emm_name db 'EMMXXXX0',0 ; device name for EMM
data ends
assume cs:code,ds:data
code segment use16
;
; First check to make sure we are on an 80386 or 80486
;
pushf ; save flags
xor ax,ax ; try to put a zero word into flags and then
push ax ; get result back into AX
popf
pushf
pop ax
and ax,0F000h ; if high 4 bits of flags are all 1's, it's an
cmp ax,0F000h ; 8086/8088/80186/80188
jne short not_386
mov ax,0F000h ; Now try to set the high 4 bits of the flags
push ax ; and then get the result back in AX
popf
pushf
pop ax
and ax,0F000h ; if none of the high 4 bits are set, it's an
jz short not_386 ; 80286 -- otherwise, it's a 386 or 486
popf ; restore flags
jmp short ems_check ; go to next check
not_386:
popf ; restore flags
jmp no_vcpi ; not a 386 or 486 -- VCPI not present
ems_check:
;
; Check for EMS driver present
;
lea dx,emm_name ; open EMM device, read-only
mov ax,3D00h
int 21h
jc short no_vcpi ; branch if error
mov bx,ax ; get device information
mov ax,4400h
int 21h
jc short no_vcpi ; branch if error
test dx,80h ; branch if file (not device)
jz short no_vcpi
mov ax,4407h ; check output status
int 21h
push ax ; save return code from IOCTL call
mov ah,3Eh ; close file
int 21h
pop ax ; restore IOCTL return code
cmp al,0FFh ; branch if status not device ready
jne short no_vcpi
______________________________________________________________________________
VCPI Version 1.0 June 12, 1989 Page 18
; Now allocate an EMS page to make sure the EMS emulator is turned on.
; Note that we must save the handle for this allocated page and free it
; again eventually, although this is not shown in the code fragment.
;
mov bx,1 ; allocate 1 EMS page
mov ah,43h
int 67h
cmp ah,0 ; branch if error
jne short no_vcpi
; save handle returned in DX to be freed later
; Now make VCPI detection call
;
mov ax,0DE00h ; is VCPI there?
int 67h
cmp ah,0 ; branch if not there
jne short no_vcpi
; OK, the VCPI interface is present and the server is turned on.
no_vcpi: ; VCPI interface not present
code ends
______________________________________________________________________________
VCPI Version 1.0 June 12, 1989 Page 19
GLOSSARY
4K page A four-kilobyte page, the page size allocated by
calls to the VCPI interface. A 4K page is always
aligned on a four-kilobyte physical address boundary.
A20 Address line 20. On AT and MCA architectures, there
is hardware to truncate physical addresses to 20 bits
(one megabyte). This is known as "disabling A20," and
is for compatibility with 8086 programs which rely on
address wraparound at one megabyte. To use extended
memory, it is necessary to "enable A20."
bottom-up allocation Allocation of extended memory starting at one
megabyte and growing upward. This allocation method
is used by older VDISK device drivers.
client A program which uses the VCPI interface
expanded memory Memory allocated by an EMS emulator
extended memory Physical memory above one megabyte.
EMS page A 16-kilobyte page, the page size allocated by calls
to an EMS driver. An EMS page is always allocated on
a four-kilobyte physical address boundary.
real mode address space Linear addresses below one megabyte (note that this
does not necessarily correspond to physical addresses
below one megabyte)
server A program which provides the VCPI interface
top-down allocation Allocation of extended memory starting at the top of
memory and growing downward. This is the recommended
technique for allocating extended memory.
______________________________________________________________________________
VCPI Version 1.0 June 12, 1989 Page 20