home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC97 Software
/
SOFTWARE_97.iso
/
QEMM.97
/
DISK3
/
TECHNOTE.QIP
/
QPI.TEC
< prev
next >
Wrap
Text File
|
1997-05-15
|
21KB
|
571 lines
The QEMM Programming Interface - QPI
Quarterdeck Technical Note #292 Filename: QPI.TEC
by Quarterdeck Development CompuServe: QPI.TEC
Last Revised: 04/05/95 Category: QEMM
Subject: A discussion on programming issues when interfacing
with QEMM.
QPI:The QEMM Programming Interface
The QEMM Programming Interface (QPI) lets programs request
information or services from QEMM. Programs can use the QPI to do
the following:
Determine QEMM's status, and change that status if the system
configuration allows;
Determine QEMM's version number;
Determine whether QEMM's Stealth ROM feature is active, and if so
what Stealth ROM mode is in use;
Determine the number of ROMs that QEMM is Stealthing and the
beginning segment address and length of each ROM;
Determine whether QEMM is supporting the system's Suspend/Resume
features, and if so what interrupt these features are using;
Determine whether QEMM is allowing or suppressing the BIOS calls
that make it possible to do work while waiting for disk activity
to complete, and tell QEMM to allow or suppress these calls if the
system configuration allows;
Copy all or part of the contents of a Stealthed ROM into a buffer;
Determine the physical memory mapped to any linear memory address,
and change the page table so that any page of physical memory is
mapped to any linear memory address;
Read or write I/O ports, even if QEMM is trapping access to those
ports;
Determine whether QEMM is trapping access to I/O ports, and tell
QEMM to trap access to ports on the calling program's behalf;
Install a software routine that performs whatever actions the
program requires when a given I/O port is accessed;
Simulate a hardware interrupt in such a way that it goes to the
correct DESQview or DESQview/X window.
You can find sample QPI code and programs on the Quarterdeck
bulletin board and other electronic support locations.
Getting the QPI Entry Point
The first step in using the QPI is getting the double-word address
of the QPI entry point.
The method of obtaining the entry point address that is described
here is available only in versions of QEMM higher than 6.00.
Programs that want to run with QEMM 5 must use a less
straightforward INT 2F interface to get the QPI entry point; for
more information, contact Quarterdeck via Compuserve (GO
QUARTERDECK), the Internet (support@qdeck.com) or our BBS and ask
for the QDMEM interface document.
QEMM defines a DOS device driver called QEMM386$. To obtain the
entry point for QPI, do an IOCTL Read Control String call (INT 21,
function 4402h) to read four bytes from this device driver. Here
is a code sequence that demonstrates the details:
QEMMDeviceName db 'QEMM386$',0
QPIEntryPoint dd ?
GetQPIEntryPoint proc
mov dx,offset QEMMDeviceName
mov ax,3d00h
int 21h ; Try to open QEMM386$
jc NoQEMM ; If CY, QEMM not present
mov bx,ax ; Save file handle in BX
mov dx,offset QPIEntryPoint ; Store the entry point here
mov cx,4 ; Set up to read 4 bytes
mov ax,4402h ; IOCTL Read Control String
int 21h
pushf ; Save the error code
mov ah,3eh ; Close the handle
int 21h
popf ; Restore the error code
jc NoQEMM ; If CY, QEMM is pre-6.00
ret
NoQEMM: stc
ret
GetQPIEntryPoint endp
QPI Functions
Once you have stored the address of the QPI entry point, you make
all calls to QPI by loading AH or AX with the function number of
the call, setting the other registers to values appropriate to the
function, and making a far call to the entry point. The carry flag
is set on return if there is an error, or if the function number
is not valid in that version of QEMM.
The QPI calls of interest to third-party programmers are listed
below. The version in which each of the calls was implemented is
noted.
The QPI_GetStatus Call
The QPI_GetStatus call tells you whether QEMM is on or off, and
whether it is in auto mode (see the AUTO/ON/OFF parameter in
Chapter 7 in the QEMM Reference Manual for more information). All
versions of QEMM support this call.
QPI_GetStatus EQU 0
; Takes AH = 0
; Returns AL = 0 if on
; AL = 1 if auto/on
; AL = 2 if off
; AL = 3 if auto/off
The QPI_SetStatus Call
The QPI_SetStatus call lets you set the status of QEMM. If QEMM is
forced on by a parameter (like the RAM parameter) or other
services that it provides, this call will have no effect. You
should therefore make the QPI_GetStatus call after the
QPI_SetStatus call to see if the first call was successful. All
versions of QEMM support this call.
QPI_SetStatus EQU 1
; Takes AH = 1
; AL = 0 if on
; AL = 1 if auto/on
; AL = 2 if off
; AL = 3 if auto/off
The QPI_GetVersion Call
The QPI_GetVersion call returns the QEMM version number in Binary
Coded Decimal form in AX and BX. For instance, the call will
return BX = 0750 (not BX = 0732) for QEMM version 7.5. All
versions of QEMM support this call.
QPI_GetVersion EQU 3
; Takes AH = 3
; Returns BH = major version (in Binary Coded Decimal)
; BL = minor version (in Binary Coded Decimal)
; AX = same as BX
The QPI_GetInfo Call
In QEMM version 6.00 and later, the QPI_GetInfo call returns an
ASCII letter in CL that tells QEMM's Stealth ROM mode (if any),
and a number in CH that tells which interrupt (not IRQ) QEMM is
monitoring (if any) to support Suspend/Resume features. In QEMM
version 7.00 and later, the call also returns the size of QEMM's
disk buffer in DL and a bit map of information about the disk
buffer in BH. Bit 1 of BH will be on if the disk buffer has
already been used; bit 0 will be on if QEMM is buffering only INT
13s into the page frame (DISKBUFFRAME) and off if all INT 13s into
nonlinear memory are being buffered (DISKBUF). Note that other
registers are not preserved by this call.
QPI_GetInfo EQU 1E00h
; Takes AX = 1E00
; Returns BH = xxxxxxAB
; where A = 1 if disk buffer has been used yet, 0 if not
; B = 1 if DISKBUFFRAME buffer, 0 if DISKBUF buffer
- not valid if DL = 0
; BL = reserved
; CL = Stealth ROM type (0 for no Stealth ROM, "M"
; or "F" otherwise, other Stealth ROM types possible
; in future)
; CH = Suspend/Resume INT number (0 = none)
; DL = size of QEMM disk buffer in K (if 0, disk buffer
; doesn't exist)
; DH, DI, SI = reserved
The QPI_GetStealthCount Call
The QPI_GetStealthCount tells how many ROMs QEMM is Stealthing.
QEMM versions 6.00 and later support this call.
QPI_GetStealthCount equ 1E01h
; Takes AX = 1E01
; Returns BX = number of ROMs that are Stealthed
The QPI_GetStealthList Call
The QPI_GetStealthList call gives the same information as the
QPI_GetStealthCount call, and also fills a buffer with information
on the location and size of each Stealthed ROM. QEMM versions 6.00
and later support this call.
QPI_GetStealthList equ 1E02h
; Takes AX = 1E02
; ES:DI = buffer to hold the list of Stealthed ROMs
; Returns BX = number of ROMs that are Stealthed
; Table at ES:DI will be filled in with:
; dw ROM start segment
; dw Length of ROM in paragraphs
; for each ROM that is Stealthed
The QPI_GetPTE Call
The QPI_GetPTE call returns the page table entry for any logical
page in the first 1088K of memory. In other words, if you pass
this call the address of any page in the first 1088K of memory,
the call will return (in an extended register) the doubleword page
table entry for that address, which includes, among other things,
information about which physical page of memory QEMM has mapped to
the logical address that you provided. QEMM versions 6.00 and
later support this call.
CX should contain the number of the logical page in memory that
you want to affect; the highest valid CX is 010F. (Page numbers
refer to consecutive 4K sections of memory, aligned on 4K
boundaries: that is, 0000 refers to paragraph 0000-00FF, 0001 to
0100-01FF, etc.) EDX (the extended DX register) should contain a
page table entry, in the following format:
Bit 0 is the Present bit. Any access to a page with this bit off
causes a page fault.
Bit 1 is the Read/Write bit. Any writing to a page with this bit
off causes a page fault.
Bit 2 is the User/Supervisor bit. Any access to this page when the
processor is at privilege level 3 causes a page fault.
Bits 3 and 4 must be 0.
Bit 5 is the Accessed bit. Any read or write of the page causes
the processor to turn on this bit.
Bit 6 is the Dirty bit. Any write to the page causes the processor
to turn on this bit.
Bits 7 and 8 must be 0.
Bits 9, 10, and 11 are available for systems programmer use.
Bits 12 through 31 are the page number.
For instance, a page table entry 000FF007 means physical page
number 000FF (paragraph FF00-FFFF), which is not yet accessed nor
dirty, but which is present, writable and user-accessible.
QPI_GetPTE equ 1F00h
; Takes AX = 1F00
; CX = page number
; Returns EDX = page table entry for that page number
The QPI_SetPTE Call
The QPI_SetPTE call lets you set the page table entry for any
logical page in the first 1088K of memory. In particular, this
means that you can tell QEMM to map any 4K of memory to any
4K-aligned address below the 1088K mark. QEMM versions 6.00 and
later support this call. See the section above on the QPI_GetPTE
call for more information.
QPI_SetPTE equ 1F01h
; Takes AX = 1F01
; CX = page number
; EDX = page table entry to set at that page number
The QPI_GetVHIInfo Call
The QPI_GetVHIInfo call, in conjunction with the QPI_SetVHIInfo
call, is primarily used by disk cache developers who wish to get
information on QEMM's safety precaution of suppressing the BIOS
INT 15 function 90 callout. This safety precaution, known as
VirtualHDIRQ or VHI (see the section on the VIRTUALHDIRQ:N
parameter in Chapter 7 in the QEMM Reference Manual for more
information), is normally in effect only when the disk interrupt
INT 13 is being Stealthed. If you have verified that the use of
INT 15 fn 90 in the disk cache you are developing is compatible
with QEMM's Stealth ROM feature, you will want to tell QEMM to
allow INT 15 function 90.
The call returns flags in BL that give the VHI state. Bit 7 will
be on whenever QEMM is Stealthing INT 13 (if INT 13 is not
Stealthed, QEMM never suppresses INT 15 function 90); bit 0 will
be on if QEMM is currently suppressing INT 15 function 90. Bits
1-6 of the VHI bit map are reserved. QEMM versions 6.00 and later
support this call.
QPI_GetVHIInfo equ 2000h
; Takes AX = 2000
; Returns BL = AxxxxxxB
; where A = 1 if VHI is being paid attention to
; B = 1 if VHI is currently enabled
; (i.e. INT 15 fn 90 is currently suppressed)
; x = reserved
The QPI_SetVHIInfo Call
The QPI_SetVHIInfo call lets you turn on or off QEMM's safety
precaution of suppressing INT 15 function 90 whenever the disk
interrupt INT 13 is being Stealthed. (See the section above on the
QPI_GetVHIInfo call for more information.) To request a VHI state,
set BL to 1 to suppress INT 15 function 90, or set BL to 0 to
allow INT 15 fn 90. QEMM will return the previous VHI flags in BL.
If bit 7 of the returned flags is off, then QEMM is not paying
attention to the VHI state, and your request did not have an
effect. QEMM versions 6.00 and later support this call.
QPI_SetVHIInfo equ 2001h
; Takes AX = 2001
; BL = xxxxxxxB that you want (bit 7 is ignored)
; Returns BL = AxxxxxxB of previous VHI state;
; if A of output = 0, B of input was ignored
The QPI_CopyStealthRoms Call
The QPI_CopyStealthRoms call tells QEMM to copy the contents of
part or all of a Stealthed ROM into a buffer in conventional
memory. This is the only reliable to access the contents of a
Stealthed ROM. QEMM versions 6.00 and later support this call.
QPI_CopyStealthRoms equ 2100h
; Takes AX = 2100
; DS:SI = Original address of ROM to copy
; ES:DI = Destination address in conventional memory
; ECX = # of bytes to copy
; Returns CY if no stealth or if DS:SI not within C000-FFFF
I/O Trapping
The following calls make up the Quarterdeck QEMM I/O Trapping
Programming Interface. This interface allows a real-mode program
to specify I/O ports that QEMM should trap access to, as well as
I/O callback routines that QEMM will call whenever one of these
I/O ports is accessed. Using this interface, you can emulate
hardware devices that are accessible via I/O ports.
When QEMM traps an I/O port, all accesses of that port, whether
input or output, are intercepted by QEMM. (QEMM traps certain I/O
ports itself, for proper management of virtual-8086 mode.)
Whenever an I/O port that a program has asked QEMM to trap is
accessed, QEMM calls a real-mode I/O callback routine. The same
callback routine is called for all trapped I/O ports.
A program that wishes to trap an I/O port should:
1) Use the QPI_GetVersion call to make sure that the version of
QEMM is 7.03 or later. Earlier versions do not support most of
the I/O Trapping Programming Interface. Alternatively, if the
version of QEMM does not support the call you have made, the
call will return with the carry flag set;
2) Issue a QPI_GetPortTrap call to determine that another program
is not already trapping the port. If another program is
trapping the port, it is generally advisable not to install
your port trap;
3) Get the address of the existing callback routine with the
QPI_GetIOCallback call. Because there is only one I/O callback
routine, and because multiple programs may request I/O
trapping, your callback routine must jump to the previous
callback routine whenever your routine is not interested in the
I/O port being accessed;
4) Install its own far routine as the new callback routine, using
the QPI_SetIOCallback call. Your callback routine will be
passed the following information:
AX = Data for output
CX = Type of I/O (see flag bits defined below)
DX = Port number
IF = 0 (interrupts are disabled)
When the callback routine has finished its work, it should return
far with all registers other than CX and DX preserved. If the
routine is called to get input from a port, AX should be modified.
The bit-mapped word in CX contains the following information:
IOT_Output equ 0000000000000100b
; bit 2 is 1 if output,
; 0 if input
IOT_Word equ 0000000000001000b
; bit 3 is 1 if word I/O,
; 0 if byte I/O
IOT_IF equ 0000001000000000b
; bit 9 is the same as the
; caller's interrupt flag
5) Specify which port to trap with the QPI_SetPortTrap call.
If your program does not stay resident forever, it should do
the following before exiting:
6) Use the QPI_GetIOCallback call to make sure that no one has
installed a callback routine after yours. If a handler is
installed after yours, you should remain resident;
7) Remove its trap with the QPI_ClearPortTrap call. This call will
clear all traps on a particular I/O port, unless QEMM is
trapping that port for itself, in which case QEMM's trapping
alone will remain in effect for that port;
8) Remove its callback by using the QPI_SetIOCallback call to set
the previously existing callback routine.
The following restrictions apply to this interface:
Only INs and OUTs of words or bytes are supported, not INs and
OUTs of doublewords. Also, string I/O (the INS and OUTS
instructions) are supported only as of QEMM version 7.5.
QEMM cannot trap the I/O of VCPI protected-mode programs.
Furthermore, because Quarterdeck's DPMI driver (QDPMI) is
implemented as a VCPI client, QEMM cannot trap the I/O of DPMI
clients either. Furthermore, these traps are no longer in effect
when Microsoft Windows 386 enhanced mode is running.
The following four calls allow you to bypass port trapping and
read and write I/O ports directly. QEMM 5.00 and later versions
support these four calls.
QPI_UntrappedIORead equ 1A00h
; Takes AX = 1A00
; DX = port to read
; Returns BL = value read
QPI_UntrappedIOWrite equ 1A01h
; Takes AX = 1A01
; DX = port to write
; BL = value to write
QPI_UntrappedIOReadIndexed equ 1A02h
; Takes AX = 1A02
; DX = base port to read
; BH = index into base port
; Returns BL = value read
QPI_UntrappedIOWriteIndexed equ 1A03h
; Takes AX = 1A03
; DX = base port to write
; BH = index into base port
; BL = value to write
The QPI_UntrappedIO Call
The QPI_UntrappedIO call performs the same functions as the
QPI_UntrappedIORead and the QPI_UntrappedIOWrite calls, but it
uses register values that are similar to the ones QEMM passes to
your I/O callback routine (including the flags in CX that give
information about the type and size of the I/O and the caller's
interrupt flag). This call may therefore be easier to use from
within an I/O callback routine. QEMM 7.03 and later support this
call.
QPI_UntrappedIO equ 1A04h
; Takes AX = 1A04
; BX = value to write
; DX = port to read or write
; CX = type of I/O (see description above
; of CX passed to callback routine)
; Returns BX = value read
The following five calls are described in the introduction above.
QEMM 7.03 and later versions support these calls.
QPI_GetIOCallback equ 1A06h
; Takes AX = 1A06
; Returns ES:DI = previous I/O callback function
QPI_SetIOCallback equ 1A07h
; Takes AX = 1A07
; ES:DI = new I/O callback function
QPI_GetPortTrap equ 1A08h
; Takes AX = 1A08
; DX = I/O port number
; Returns BL = 0 if port not trapped,
BL = 1 if port already trapped
QPI_SetPortTrap equ 1A09h
; Takes AX = 1A09
; DX = I/O port number
QPI_ClearPortTrap equ 1A0Ah
; Takes AX = 1A0A
; DX = I/O port number
The QPI_SimulateHWInt Call
The QPI_SimulateHWInt call can be used by callback routines that
wish to simulate a hardware interrupt. When DESQview or DESQview/X
is running, the interrupt handler that should receive the
interrupt may be in a different process from the current one. Use
QPI_SimulateHWInt to simulate an interrupt properly when DESQview
or DESQview/X is running. The DESQview API Reference Manual
describes how to determine when DESQview is running. QEMM 7.03 and
later versions support this call.
QPI_SimulateHWInt equ 1C04h
; Takes AX = 1C04
; BX = interrupt number to generate
The QPI Get Sub-Version String Call
QPI_Get_QEMM_SubVer equ 1E05h
; Takes AX = 1E05
; CX = Length of buffer
; ES:DI = buffer
; Returns CX = number of bytes which could not fit in buffer
; CY if function not supported
; Fills in the given buffer with a null terminated string. If
; the actual length of the string is greater than the length of
; the buffer (as passed in CX) then it clips the string to the
; buffer length - 1 and puts a null in the last byte of the buffer
; and returns the number of extra bytes in CX. If everything
; fits in the buffer, then the returned CX=0.
******************************************************************
* Trademarks are property of their respective owners. *
* This and other technical notes may be available in updated *
* forms through Quarterdeck's standard support channels. *
* Copyright (C) 1996 Quarterdeck Corporation *
******************** E N D O F F I L E ***********************