DDDR/2 - VIDEO Protect-Mode Interface

From EDM2
Revision as of 11:21, 13 January 2017 by Ak120 (Talk | contribs)

Jump to: navigation, search
Display Device Driver Reference
Chapters
  1. 16-Bit VGA Display Driver
  2. 8514/A Display Driver
  3. 32-Bit VGA Display Driver
  4. 32-Bit Super VGA Display Driver
  5. SVGA Base Video Subsystem
  6. Physical Video Device Drivers
  7. Virtual Video Device Drivers
  8. Seamless Windows Support
  9. PM Palette Management Support
  10. Distributed Console Access Facility (DCAF)
  11. DBCS Video Driver Support
  12. Installing and Configuring Display Device Drivers
  13. Graphics Test Suites
  14. Display Test Tool
  15. VIDEOCFG.DLL Exported Functions
  16. VIDEOPMI.DLL Exported Functions
  17. VIDEO Protect-Mode Interface
Appendixes
  1. Data Types
  2. S3 Display Driver

Reprint Courtesy of International Business Machines Corporation, © International Business Machines Corporation

Contents

VIDEO Protect-Mode Interface

This chapter describes the VIDEO Protect-Mode-Interface (VIDEOPMI) in OS/2 Warp. This interface is an extension of the standard.

The VIDEOPMI interface also provides parameters for the adapter virtualization in multiple DOS sessions and a number of support functions. The adapter description is provided as a flat file with an extension of .PMI. The main goal of the VIDEOPMI interface is to centralize all of the SetMode-related services and provide a consistent interface that is not dependent on availability of BIOS service or OEM utilities.

The following list includes the topics covered in this chapter:

Overview

The VIDEOPMI interface is procedurally represented by the exported functions of its main handler - VIDEOPMI.DLL. This handler provides both 32- bit and 16-bit entry points for setting a video mode, loading fonts, and saving and restoring the video state. The handler provides a mode query function and a software interrupt function, which allows for execution of real-mode software interrupts, such as VIDEO BIOS, from the protect mode.

VIDEOPMI.DLL imports the device-specific function from the underlying vendor- or IBM-provided PMI subsystem. This subsystem is comprised of any of the following:

1.Flat .PMI file with no code imports.

Although VIDEOPMI does not mandate the .PMI file name, at the moment SVGA Install and Configuration mandates \OS2\SVGADATA.PMI. Example: Any OS/2 2.x .PMI file.

2.Flat .PMI file with imported code sections from a dynamic link library (DLL).

This is called a HYBRID.PMI file. Imported functions are private to the PMI subsystem and conform to the IMPORTPMI prototype as described in the SVGADEFS.H header file. Example: Any OS/2 3.x .PMI file.

3.Flat .PMI file with imported code sections from a DLL that chains into VIDEOPMI.

This is called a META-HYBRID.PMI file. The shared library exports a "LoadAdapter" function, which signals to VIDEOPMI that the handler wishes to engage in chaining VIDEOPMI's calls. The handler is passed the VIDEOPMI's calling function table and can modify the table by replacing entries with its own entry points. When these entry points are invoked, the handler can implement the call or pass it back to VIDEOPMI. Example: A .PMI file generated by SVGAOEM.EXE in the DDK.

4.META handler alone, without a flat file.

When VIDEOPMI's PMIREQUEST_LOADPMIFILE is passed a .DLL name and the specified shared library exports and successfully handles the "LoadAdapter" call, the PMI subsystem requires no flat file. This method of customizing the PMI subsystem is not in use because SVGA install, video configuration, and the virtual driver still make assumptions and use the flat .PMI file. Example: OEMPMI.DLL in the DDK.

For a full description of VIDEOPMI's procedural interface, see VIDEOPMI.DLL Exported Functions.

SVGADATA PMI file

The VIDEOPMI interface is driven by the sections of the There are two main types of sections:

Query sections that describe adapter capabilities
Set sections that service hardware programming requests

Query sections provide information on hardware description, list of ports, list of supported modes, and the range or set of supported timing values. The Set sections provide the capability to identify adapters; unlock registers; cleanup, size, and position the active display; set a mode; save and restore a mode, and the VRAM used by the mode.

The VIDEOPMI language defines a video adapter as a hardware controller in terms of its I/O and memory addresses that are programmable by the CPU. The video controller can be a dumb frame VGA/SVGA, an accelerator, or a general-purpose coprocessor. The must contain all of the informational sections and a minimal set of Set sections (see PMI Sections). An adapter description starts with its Hardware section, followed by IdentifyAdapter, a number of support sections, and a list of all available modes with the corresponding SetMode sections. PMI language or as a call to an externally defined function. The two implementations are discussed in detail under Code vs. PMI in this chapter.

The PMI facilitates dynamic hardware configuration, which includes port remapping as well as adding or removing an adapter and its PMI definition. It also includes changing the attached display and multiple instances of the same video hardware driven by the same The interface defines monitor timing variables needed to drive a CRT monitor. These variables provide extensive monitor support and a consistent user configuration interface. The PMI language also facilitates programming of the support chips that can be mapped into the I/O and memory space addressable by the CPU, such as external clock-synchronizing chips or smart Digital-to-Analog Converters (DACs).

files are to be provided by the video chip or adapter manufacturers or by the providers of the display drivers. The file should be part of the video adapter installation kit, either as a pre-manufactured flat file or one created by the OEM's installation utility.

Limitations of the PMI

The following limitations exist in the PMI:

.PMI does not provide a graphical interface.
.PMI does not provide a means of accessing addresses that are internal to the video controller and are not mappable into the CPU space.
Save and Restore Hardware State Services have certain limitations (see " Save and Restore State" in this chapter).
.PMI does not provide the means to manipulate certain video parameters outside the context of the SetMode section.
.PMI does allow, and it requires, indirect management of all of the parameters within the Mode Set sections. For example, there are no services for the manipulation of the hardware cursor or RAMDAC outside the context of a mode set. These services are an integral part of the SetMode.
Programming of the monitor timing is considered a special case. It is an integral part of the SetMode, but it also can be independently invoked, if the .PMI file defines a SetMonitorTimings section. The same is true for manipulation of the active display size. If the PMI file contains a TuneDisplay section, this manipulation is offered independently.
Port descriptions have some limitations, as follows:
-Ports that require double or triple indirection cannot be adequately described in the PMI language.
-I/O addresses that serve as latches, or flip-flops, cannot be successfully described.
-There are no provisions for describing port addresses that define different registers depending on the read or write access.
These limitations have an influence on the level and success of the adapter virtualization using the system-provided virtual driver. See [TrapRegs] in PMI Sections.

Code vs. PMI

The Set type of sections can be implemented as pure PMI language constructs , as pure imported functions from an external binary object or as a mixture of the two. Each implementation has its benefits and its drawbacks. The vendor creating the PMI file should carefully evaluate which method is the most appropriate and beneficial.

.PMI Language Constructs only

Full use of the PMI language hides the implementation of the I/O and MMIO access on a particular hardware and operating system platform from the vendor creating the PMI file. This method provides good portability and code reuse. The initial cost in creating the SVGADATA.PMI file is mainly in rewriting the existing source into the PMI sequences.

Another benefit of this implementation is tighter execution control. Since the VIDEOPMI would be totally data-driven, the chances for memory violations and other execution hazards are minimized.

This implementation should not be used for timing-sensitive hardware, since the interpretation of PMI sequences creates an execution overhead that cannot be fine-tuned at the current time.

Note: SVGADATA.PMI files created internally by IBM are written either in full PMI language or in a mixture of PMI language and imported functions to cover as many chip sets as possible.

Imported Functions only

This implementation provides the greatest code reuse of the source objects already created and used elsewhere by the vendors. It also provides the performance needed in programming the timing-sensitive chip sets. Importing code also allows the vendor to call VIDEO BIOS as as means of implementing the exported function. This can be achieved only from a shared library. A flat .PMI file will not call VIDEOPMI's entry point. Provided that the shared library exports the "Load Adapter" API and conforms to the META-PMI definition, this method also allows for modifying VIDEOPMI's function by chaining into its calling table.

The drawback to this method is that the imported objects' source code is developed for a specific hardware and operating system platform and has to be ported to a new platform. Another drawback is that the imported binary object may introduce execution violations unless it is thoroughly tested.

.PMI Language Constructs + Imported Functions

This method represents a compromise between the two implementations discussed previously.

The method is applicable for vendors who require code reuse with small maintenance effort, but have performance-sensitive chip sets on board. Another example would be chip vendors who are handling a number of different adapter implementations with a single PMI file. Such PMI files could have common PMI sequence-based SetMode, UnLock and Cleanup functions, but adapter-specific functions, such as DAC and clock-chip programming, could be imported from an external binary object. Porting mixed PMI files to another operating system platform requires porting of the source code only.

External binary objects are 32-bit dynamic libraries, which have to provide instance initialization and export all of the functions that are referenced in the .PMI file. See Include Files in PMI Language Elements and PMI Sections for more detail.

Note: The imported library (OEMPMI.DLL) that is shipped with the IBM Developer Connection Device Driver Kit for OS/2 illustrates the importing functions.

Sample .PMI File Using Imported PMI Binary Object

This section diagrams a sample .PMI file. The sample file is shipped by a chip-set vendor and supports a number of adapter implementations of the vendor's chip set. All of the adapter-specific functions are handled by the imported PMI functions from the VENDOR.DLL dynamic link library. The adapter-specific [Hardware] section, which provides the description for the specific implementation identified on the user's machine, is provided in the VENDOR.PMI Include file.

Thus, by copying different Include files, together with the master SVGADATA .PMI and VENDOR.DLL files, specific adapter installation is covered with minimum investment in a utility for formatting the .PMI file.

The generic PMI file lists all of the modes possible, with the maximum memory configuration for the chip. It also lists reasonable timing limits per mode that should be supported by all adapters. This information provides the filtering service to the configuration utility, which presents the timing choices to the user. Should a particular adapter's capabilities be lower than the timing values set, the SetMonitorTimings function should perform verification of the input parameters in order to protect the hardware. If the adapter's capabilities vary greatly, the PMI file should be formatted to reflect the correct MonitorModeInfo for the adapter.

/*
** Vendor include PMI file VENDOR.PMI
*/
BusType             = ADAPTER_BUS_TYPE
OEMString           = "CHIPSET_NAME ADAPTER_NAME, ADAPTER_MANUFACTURER_NAME"
DACString           = "DAC_MANUFACTURER_NAME, DAC_NAME"
Version             = "3.2"
TotalMemory         = ACTUAL_VRAM_MEMORY_SIZE
MemoryIOAddress     = MMIO_ADDRESS
PortIOAddress       = PIO_ADDRESS
Endian              = LITTLE

/*
** Generic PMI file
*/
[PMIVersion]        2.2
#includecode        "vendor.DLL"   //exports all fnPMI entry points used
in this PMI file
#include            "vendor.PMI"

/*
 *        List of declared ports. Required if adapter is dynamically
 *        configurable
*/
[Declarations]
MRegisterA =MMIO{0x00180298}
...
/*
 *    List of I/O and MMIO ports to be trapped
*/

[TrapRegs]
DWORD_MMIOPORT RW ACCEL MRegisterA;
...

[EnableController]
call fnPMIEnableController;

[DisableController]
call fnPMIDisableController;

[UnLock]
call fnPMIUnlock;

[Cleanup]
call fnPMICleanup;

[GetBank]
call fnPMIGetBank;

[SetBank]
call fnPMISetBank;

[SetMonitorTimings]
call fnPMIProgramTimings;

[TuneDisplay]
call fnPMITuneDisplay;

[comment]
Graphics Mode: 640 x 480 x 16 colors.
[ModeInfo]
ModeAttributes      = 0x18
BytesPerScanLine    = 640
XResolution         = 640
YResolution         = 480
TextRows            = 30
BitsPerPixel        = 4
NumberOfPlanes      = 4
PageLength          = 38400
SaveSize            = 153600
Int10ModeSet        = 0x012
BufferAddress       = 0x000a0000
ApertureSize        = 0x00010000
[MonitorModeInfo]
VerticalRefresh     = 72
HorizontalRefresh   = 38
ScreenLeftEdge      = 0x00000021
ScreenRightEdge     = 0x000000C1
ScreenTopEdge       = 0x00000019
ScreenBottomEdge    = 0x000001F9

[comment]
Graphics Mode: 640 x 480 x 256 colors.
[ModeInfo]
ModeAttributes      = 0x18
BytesPerScanLine    = 640
XResolution         = 640
YResolution         = 480
TextRows            = 30
BitsPerPixel        = 8
NumberOfPlanes      = 1
PageLength          = 307200
SaveSize            = 307200
BufferAddress       = LinearWindowAddress
ApertureSize        = 0x00200000
[MonitorModeInfo]
VerticalRefresh     = 72
HorizontalRefresh   = 38
ScreenLeftEdge      = 0x00000021
ScreenRightEdge     = 0x000000C1
ScreenTopEdge       = 0x00000019
ScreenBottomEdge    = 0x000001F9

[comment] 
Graphics Mode: 640 x 480 x 64K colors.
[ModeInfo]
ModeAttributes      = 0x18
BytesPerScanLine    = 1280
XResolution         = 640
YResolution         = 480
TextRows            = 30
BitsPerPixel        = 16
NumberOfPlanes      = 1
PageLength          = 614400
SaveSize            = 614400
ColorFormat         = "RGB"
ColorWeight         = "5:6:5"
BufferAddress       = LinearWindowAddress
ApertureSize        = 0x00200000
[MonitorModeInfo]
VerticalRefresh     = 72
HorizontalRefresh   = 38
ScreenLeftEdge      = 0x00000021
ScreenRightEdge     = 0x000000C1
ScreenTopEdge       = 0x00000019
ScreenBottomEdge    = 0x000001F9

[comment]
Graphics Mode: 800 x 600 x 256 colors.
[ModeInfo]
ModeAttributes      = 0x18
BytesPerScanLine    = 800
XResolution         = 800
YResolution         = 600
TextRows            = 37
BitsPerPixel        = 8
NumberOfPlanes      = 1
PageLength          = 480000
SaveSize            = 480000
BufferAddress       = LinearWindowAddress
ApertureSize        = 0x00200000
[MonitorModeInfo]
VerticalRefresh     = 72
HorizontalRefresh   = 48
ScreenLeftEdge      = 0x0000002B
ScreenRightEdge     = 0x000000F3
ScreenTopEdge       = 0x0000001D
ScreenBottomEdge    = 0x00000275

[comment]
Graphics Mode: 1024 x 768 x 256 colors.
[ModeInfo]
ModeAttributes      = 0x18
BytesPerScanLine    = 1024
XResolution         = 1024
YResolution         = 768
TextRows            = 48
BitsPerPixel        = 8
NumberOfPlanes      = 1
PageLength          = 786432
SaveSize            = 786432
BufferAddress       = LinearWindowAddress
ApertureSize        = 0x00200000
[MonitorModeInfo]
VerticalRefresh     = 72
HorizontalRefresh   = 58
ScreenLeftEdge      = 0x00000041
ScreenRightEdge     = 0x00000141
ScreenTopEdge       = 0x00000021
ScreenBottomEdge    = 0x00000321

[SetMode]
call fnPMISetMode;
[comment]
Text Mode: 80 cols, 25 rows.
[ModeInfo]
ModeAttributes      = 0x08
BytesPerScanLine    = 80
XResolution         = 720
YResolution         = 400
XCharSize           = 9
YCharSize           = 16
TextRows            = 25
BitsPerPixel        = 4
NumberOfPlanes      = 1
PageLength          = 4000
SaveSize            = 4000
Int10ModeSet        = 0x003
VerticalRefresh     = 60
BufferAddress       = 0x000b8000
ApertureSize        = 0x00008000

[SetMode]
call fnPMISetTextMode;

How to Customize the PMI Subsystem for Your Device

The VIDEO PMI subsystem consists of VIDEOPMI-the main PMI handler, a flat PMI file, and optional imported library modules. The imported library modules may optionally chain into VIDEOPMI and provide a filter or replacement for VIDEOPMI's entry points. Such a library is called a META-PMI handler. Although the VIDEO PMI subsystem places no requirements on the existence of a flat PMI file (it is possible to provide all functions with a META-PMI handler alone), the SVGA installation, SVGA virtual video driver, BVHSVGA, and VIDEOCFG all make assumptions that the PMI subsystem is represented by SVGADATA.PMI.

The VIDEOPMI handler is maintained by IBM; it is shipped in the IBM Developer Connection Device Driver Kit for OS/2 as a binary file. See Video Subsystem Binary Files. The SVGADATA.PMI file is either provided or can be created at install time by running a utility. The SVGA installation action routine DLL (SVGA.DLL) assumes that a DOS utility called SVGA.EXE is used to generate the SVGADATA.PMI. A vendor wishing to modify the SVGADATA.PMI can provide its own action routine DLL or create the SVGA.EXE DOS utility. DDK sources include two different sources of a utility that generates the SVGADATA.PMI file, as follows:

src\svdh\svgautil\svga.exe

src\svdh\svgautil sources are those of the SVGA.EXE as shipped by IBM. It is a very large and complex source that generates a .PMI file for all of the devices supported by the IBM BBS display driver packages at the time the IBM Developer Connection Device Driver Kit for OS/2 was shipped.

Vendors should not modify this source; it is shipped so that vendors can create sample .PMI files for legacy hardware. PMI files created by this utility use IBMGPMI.DLL as an imported PMI library. The source for IBMGPMI.DLL is not available for vendor modification, but a binary file can be extracted from the most current IBM BBS video driver package. An older version of IBMGPMI can be found in previous DDKs.

For purposes of documenting an imported PMI library, an alternate library source in src\oempmi for OEMPMI.DLL is provided. This PMI library exemplifies both internal PMI calls and the META-PMI interface (chaining into VIDEOPMI). It also provides an example of using the VIDEOPMI's software interrupt API to call the VIDEO BIOS directly.

src\oempmi\svgautil\svgaoem.exe

src\oempmi\svgautil sources are the recommended sources for vendor modification. The makefile will generate an SVGAOEM.EXE, which should be renamed to SVGA.EXE if the SVGA.DLL action routine DLL is to be used. The utility will create a generic SVGADATA.PMI file based solely on VESA mode support without any vendor modifications. This generic .PMI file depends on the OEMPMI.DLL META-PMI handler, referred to in the previous bullet, for successful VESA BIOS calls. If there is no VESA support for the adapter, or vendors wish to add refresh support or customize the generic sections, the SetupChipInfo function in SVGAOEM.C needs to be modified. The header of the SVGAOEM.C source file includes the "ROADMAP to CHANGES" instructions.

src\oempmi sources are open to vendor modification, and its headers also include extensive instructions on the recommended changes. However, for a vendor with VESA mode set support and a display driver that can run on top of the hardware state as left by the VESA mode set, the quickest results are obtained by doing the following:

  • Install all of the Base Video Subsystem files.
  • Create a .PMI file by running the unmodified SVGAOEM.EXE with command line argument "ON".

Supported Modes

This section lists the OS/2 Warp requirements for the modes included in file. Each supported mode is represented by a set of sections, as follows:

Comment (optional)
ModeInfo (required)
MonitorModeInfo (optional)
SetMode (optional)

The ModeInfo section is a list of the common mode elements (PMI keyvariables) that define the resolution, window, and size elements of the mode. The mode definition is then complemented by all of the MonitorModeInfo sections following the ModeInfo section. There could be zero or more MonitorModeInfo sections, depending on the capabilities of the hardware to program timings. An adapter may not support a CRT in a particular mode; a single MonitorModeInfo section with zero values is used to indicate such a case. If the adapter can support only a distinct set of values, rather than a range of horizontal and vertical refresh values, multiple MonitorModeInfo sections per horizontal/vertical refresh pair are used to indicate this fact. An adapter with flexibility in programming a range of dotclock (which translates into horizontal and vertical refreshes) should list only one MonitorModeInfo entry with the end of range values for the vertical/horizontal refresh.

VGA modes

The VGA modes are the VGA compatible resolution modes that the adapter in question (or on its VGA daughter card) can support. If the modes are not included, they are set by first invoking the Cleanup function and then letting the base video handler set the standard VGA mode. If the Cleanup function is not successful, the mode set may fail to set the adapter to a stable state. Therefore, It is suggested that VGA modes be handled by the same PMI file.

Suggested modes include the following:

640x480x16 graphics
40x25 and 80x25 text

Extended modes

Extended modes include the following:

At least one of the 132-column text modes (if applicable).
At best, all of the supported 256-color modes with respective refresh rates (see Monitor Timings Support in this chapter).
At the minimum, modes that are supported by the respective Presentation Manager display driver.
If the adapter in question has both accelerated and nonaccelerated modes, only the accelerated modes should be provided.
At best, all of the supported hi-color and true-color modes with respective refresh rates (see Monitor Timings Support in this chapter).
At the minimum, modes which are supported by the respective Presentation Manager display driver.
If the adapter in question has both accelerated and nonaccelerated modes, only the accelerated modes should be provided.

Custom modes

Custom modes are those modes that use non-RGB color formats, as well as modes that target a special monitor.

Monitor Timings Support

The PMI defines eight display-timing-related variables as mode keyvariables. These variables facilitate selection of the mode, depending on the current monitor specification and sizing of the active display for the current mode. The MonitorModeInfo section contains all of the timing-related PMI key variables.

The display-timing-related variables are:

VerticalRefresh Vertical refresh in Hz (rounded to the nearest integer)
HorizontalRefresh Horizontal refresh in KHz (rounded to the nearest integer)
HPolarityPositive Contains the Horizontal polarity (0,1) for the current mode selection
VPolarityPositive Contains the Vertical polarity (0,1) for the current mode selection
ScreenLeftEdge Represents the end of the horizontal blanking (HBP) in pixel count along the horizontal sweep (HSP)
ScreenRightEdge Represents the start of the horizontal blanking (HFP) in pixel count along the horizontal sweep (HSP)
ScreenTopEdge Represents the end of the vertical blanking (VBP) in line count along the vertical sweep (VSP)
ScreenBottomEdge Represents the start of the vertical blanking (VFP)

The last four timing elements, defining the start and end of the horizontal active display and start and end of the vertical active display, are suggested as mode elements in order to enhance visual quality. Their values are never directly communicated to the end user configuring the adapter, only the net results. The values are manipulated through a TuneDisplay function as part of the SetMode or upon the end user's configuration request. See [TuneDisplay] section in PMI Sections.

There is no interface for specification and manipulation of the widths of the Horizontal Sweep (HSP) and Vertical Sweep (VSP) signals.

If an adapter is capable of supporting both non-CRT- and CRT-style displays , modes of both types should be listed. Non-CRT Mode sections are those that have 0 for both horizontal and vertical refresh rate.

If the adapter has monitor sensing, identification, and auto-adjusting capability built in so that software manipulation of the timing-related registers is not required, none of the timing-related mode elements have to be specified. No MonitorModeInfo sections should be included and monitor sizing parameters and the TuneDisplay function should not be listed.

The vendor providing the .PMI file can supply either a single MonitorModeInfo, which denotes the upper limit for horizontal and vertical refresh, or a number of MonitorModeInfo sections with distinct sets of horizontal and vertical refresh values. In the first case, the OS/2 Warp configuration utility offers refresh values that are part of the current monitor definition for the desired resolution, as long as the monitor specification is within the range specified by the adapter. If more than one MonitorModeInfo section exists per mode, all of those within the monitor's specification are offered as a selection to the user by the OS/2 Warp Video Configuration Manager. Polarity PMI keyvariables are not required, unless an exact match with the monitor's capabilities is desired by the adapter vendor.

For a full description of Video Configuration, see VIDEOCFG.DLL Exported Functions

Save and Restore State

VIDEOPMI does not have dedicated SaveState or RestoreState sections. The VIDEOPMI engine does offer those services. PMIREQUEST_SAVESTATE in VIDEOCFG.DLL Exported Functions.

SaveRestore VRAM

VIDEOPMI offers saving and restoring of the video buffer of SaveSize for each mode and is internally aware of the type of VRAM access it has to perform. The parameters taken into consideration when addressing the VRAM are BufferAddress, ApertureSize, and SaveSize. See [ModeInfo] section in PMI Sections.

If ApertureSize is equal to or greater than SaveSize, direct linear access to the BufferAddress is assumed. If this is not the case, the SetBank function is necessary in order to save and restore the entire on-screen VRAM. Granularity of a bank is assumed to be the ApertureSize. SaveSize should be set to reflect the logical line length programmed by the current mode, rather than just horizontal resolution.

SaveRestore Hardware

This service is available for .PMI files that use the PMI language to define SetMode sections. function calls become a no-op.

The virtual video driver and desktop driver do perform their own Save and Restore of the state and are not dependent on the service. The PMI-enabled base video handler uses the Save and Restore State service and, in case of a partial restore, reissues the mode set and restores the important video attributes.

The SaveRestore Hardware service is based on the PMI sequence for the SetMode; all of the ports that are programmed by the SetMode section for the current mode will be saved and restored. When saving a mode, the VIDEOPMI interpreter parses the command list of the SetMode section.

BOUTB commands are converted into BINB commands. The VIDEOPMI executes the newly constructed section in order to capture register values and converts all of the commands back into their original SetMode format. The command list is then ready for a subsequent RestoreState call and is returned to the user.

This approach has some limitations, mainly for adapters that employ double and higher indirection levels in register addressing; for example, the WDc24.

Adapter Configuration

This portion of the chapter specifies the requirements placed on the .PMI file by the video subsystem. It does not address the physical installation steps for an adapter, or the bus management, device enumeration, and conflict management employed by the operating system.

An adapter is defined by its Hardware section, which lists the type of bus, the default start address of the I/O and memory space, and alternative addresses for the I/O and memory space, as addressable by the CPU. The adapter is uniquely defined by its OEMString and Version strings.

There are two basic types of adapters:

those that support Plug and Play (PCI, PnP-ISA) and allow the device to define the resources and to be programmed dynamically to use the resources
those called Legacy hardware (MC-A, ISA, EISA), which use predefined system resources

There also are adapters that are configurable in terms of the memory range and that coexist with a Legacy VGA controller; these will be referred to as Configurable Legacy adapters. Another type of Configurable Legacy adapter can co-reside with properly configured instances of the same adapter, such as MC-A XGA*.

Three PMI sections, IdentifyAdapter, EnableController and DisableController , are used to identify, configure and enable video adapters in conjunction with any PnP configuration BIOS services available to the operating system' s configuration manager. The identification function verifies if hardware matching the OEMString description is present on the system. It does not verify if the configuration is set to the default Hardware values specified in the PMI file.

The primary functions of EnableController and DisableController are to control the sync generation for controllers sharing the sync generation function with a VGA chip. The secondary function of the EnableController is to provide configuration for the Configurable Legacy adapters and to verify if the configuration matches the passed hardware values for Static Legacy and PnP hardware.

For a static Legacy adapter, where the configuration is hard-wired, there is no need to declare its I/O and Memory base addresses, nor is there a need to declare its registers. The EnableController and DisableController should only ensure that the device acquires and relinquishes control over the sync generation. For coprocessors that co-reside with VGA chips, EnableController should disable VGA and enable the coprocessor. DisableController enables the VGA chips.

For a Configurable Legacy adapter, in which a configurable memory-mapped coprocessor co-resides with a hard-wired VGA controller, the MemoryIOAddress and memory-mapped registers of the coprocessor should be declared, not hardcoded. DisableController enables the VGA chip and EnableController configures and enables the coprocessor at the current MemoryIOAddress, if this can be done through software. If it cannot be done, the EnableController function should verify whether the hardware is configured for the passed MemoryIOAddress. If it is not so configured, the return code is set to reflect that situation.

In the case of Configurable Legacy adapters that can co-reside, the PortIO and MemoryIO addresses are used to provide addressability to different instances. The EnableController function verifies if the configuration for a particular instance is complete and, if not, completes it. For example, a user may have run the Reference diskette to configure 3 XGAs, so the instances are already configured in terms of their I/O space. However, the user may not have configured the Memory-mapped portion, which is required for the desktop driver. The PMI file's EnableController should complete the configuration.

For PnP adapters, the configuration is performed through the PnP BIOS, if such BIOS is available. If it is not available, the EnableController can be used to configure the controller as well as enable its sync generation. Consequently, DisableController disables the coprocessor and enables the sync generation by a co-residing VGA chip (if one exists). See [ EnableController] and [DisableController] in PMI Sections.

PMI Language Elements

The VIDEOPMI language consists of the following elements:

Sections
User-defined functions
Expressions
.PMI commands, identifiers, constants, variables, string-literals, and comments

The language is not case-sensitive, so BOUTB and boutb represent the same identifier. Throughout this section, Backus-Naur Form (BNF) grammar is used to describe the syntax. Some examples are given in the text. Where such examples are omitted, sample .PMI files accompanying the document should be used as a reference.

Comments and Delimiters

Comments can be either in-line comments (//) or ANSI C style comments (/.* */). White space is used as the token delimiter and a semicolon (;) is used as the expression delimiter.

The Comment section defines a mode-info related comment that describes the mode to the user. See [Comment] in PMI Sections.

Include Files

.PMI allows for inclusion of other all of which must conform to the PMI language. The include files should be in the same directory as There can be more than one #include statement in a .PMI file. The include .PMI files can have #include statements to include other .PMI files. An Include file facility is provided in order to offer flexibility in supporting multiple adapter configurations with a single .PMI file. Failure to locate the include .PMI file does not cause the unloading of the SVGADATA.PMI file.

The external binary objects are included using a #includecode directive, and flat PMI sub-files are included using a #include directive. The include statement can be found anywhere in the .PMI file as long as it does not violate the integrity of the section before and the section after, and as long as the references to the objects belonging to the include file are made after the inclusion.

External binary objects are considered "binary include" files. The VIDEOPMI parser attempts to load the module as a 32-bit DLL and attempts to resolve the procedural addresses for every external code reference made using all of the loaded module. If the loading or address resolution fails, the loading of the .PMI file fails.

#include "filename" //.PMI extension assumed
#includecode "filename" //DLL extension assumed

Constants, String-Literals, Identifiers, and Keywords

.PMI constants are 32-bit integer constants, either in decimal or hexadecimal format.

<digit>  ::= '0'..'9'
<hexdigit> ::= <digit>  |  'a'..'f'
<character> ::= 'a'..'z' |  'A'..  'Z'|  '_' |  '.'
<decimal number>  ::= <digit>  |  <decimal number> <digit>
<hexadecimal number>  ::= '0x' <hexdigit>  |
                         <hexadecimal number>  <hexdigit>
<constant>  ::= <decimal number>  |  <hexadecimal number>

Any combination of printable ASCII characters in quotes is considered a string-literal. String-literals are not parsed in any way. They are stored in their uppercase format and are passed on query-style calls, converting both source and target to uppercase. String-literals are limited to 128 characters in length, including 0 at the end. Binary strings are also limited to 128 bits (4 doublewords).

<string>  ::= "<ASCII character> [<string>.]"
<binary-string>  ::= " <'0'|'1'> | <'0'|1'> [<binary-string>.]"

An Identifier, or a name, is a sequence of letters and digits. The first character must be a letter. The underscore (_) and point (.) count as a letter, but point (.) cannot be used in the first position. Maximum length of an identifier is 32 characters.

<name>  ::= <character>  <token>
<token>  ::= {<character>  |  [<digit> <token>.]}

Reserved identifiers are called keywords. Keywords are divided into three groups:

.PMI keyvariables, which are keywords representing configuration and mode parameters
.PMI constants, backed by system-wide definitions
All other reserved identifiers

All of the PMI keyvariables are available through the VIDEOPMI programming interface as fields of the video instance structure. They are also available to all of the PMI sections and functions and can be used in conditional statements or expressions. At run time, during a SetMode, some of the ModeInfo PMI keyvariables could differ from the values assigned by the .PMI file. These PMI keyvariables can be modified at the user or system level and are therefore regarded as Dynamic. Others are called Static. At the procedural level, static PMI keyvariables are fixed to the values specified in the .PMI file and cannot be changed for a given mode. Some dynamic variables have a limited set of possible values; others are valid in a range that should be verified by dedicated sections. See [ModeInfo], [Hardware] and [TuneDisplay] in PMI Sections for more information on dynamic vs. static keyvariables.

Not all of the PMI keyvariables have to be defined. See [ModeInfo] and [Hardware] in PMI Sections for further explanations.

.PMI Keyvariables

The following table lists all of the keyvariables for the Protect Mode Interface (PMI).

Name Section
ApertureSize ModeInfo
BitsPerPixel ModeInfo
BufferAddress ModeInfo
BusType Hardware
BytesPerScanLine ModeInfo
ColorFormat ModeInfo
ColorWeight ModeInfo
DACString Hardware
Endian Hardware
HorizontalRefresh MonitorModeInfo
HPolarityPositive MonitorModeInfo
Int10ModeSet ModeInfo
MemoryIOAddress Hardware
ModeAttributes ModeInfo
NumberOfPlanes ModeInfo
OEMString Hardware
PageLength ModeInfo
PortIOAddress Hardware
SaveSize ModeInfo
ScreenLeftEdge MonitorModeInfo
ScreenRightEdge MonitorModeInfo
ScreenBottomEdge MonitorModeInfo
ScreenTopEdge MonitorModeInfo
SlotID EnableController
TextRows ModeInfo
TotalMemory Hardware
VerticalRefresh MonitorModeInfo
VPolarityPositive MonitorModeInfo
XCharSize ModeInfo
XResolution ModeInfo
YCharSize ModeInfo
YResolution ModeInfo

.PMI Constants

The following table lists the constants used by the Protect Mode Interface (PMI).

Name Section
BIG Hardware
EISA Hardware
ISA Hardware
LITTLE Hardware
MCA Hardware
MMIO Declarations
PCI Hardware
PCMCIA** Hardware
PIO Declarations
VLB Hardware

.PMI Keywords

The following table lists the reserved identifiers, called Keywords, used by the Protect Mode Interface (PMI).

Name Section
[Cleanup] .PMI sections
[Comment] .PMI sections
[Declarations] .PMI sections
[GetBank] .PMI sections
[Hardware] .PMI sections
[IdentifyAdapter] .PMI sections
[ModeInfo] .PMI sections
[MonitorModeInfo] .PMI sections
[PMIVersion] .PMI sections
[SetBank] .PMI sections
[SetMode] .PMI sections
[SetMemoryIOAddress] .PMI sections
[TrapRegs] .PMI sections
[TuneDisplay] .PMI sections
[UnLock] .PMI sections
ABOUTDW .PMI commands
ABOUTW .PMI commands
BINB .PMI commands
BOUTB .PMI commands
CALL .PMI commands
ENDWHILE .PMI constructs
GOTO .PMI constructs
IF .PMI constructs
INB .PMI commands
INDW .PMI commands
INW .PMI commands
MEMCMP .PMI constructs
OUTB .PMI commands
OUTDW .PMI commands
OUTW .PMI commands
READB .PMI commands
READDW .PMI commands
READW .PMI commands
RMWB .PMI commands
RMWBI .PMI commands
RMWW .PMI commands
STRCMP .PMI constructs
WHILE .PMI constructs
WRITEB .PMI commands
WRITEDW .PMI commands
WRITEW .PMI commands

Variables are user-defined identifiers that symbolically represent a hardware register in terms of its offset, in either the CPU's I/O space or memory space. Use of variables is required for system architectures in which dynamic configuration and multiple instances of the same hardware are possible. A variable must be declared prior to being used. See [Declarations] section in PMI Sections.

<memory-mapped variable>  ::= <mmio variable>  =  'MMIO{'<number>'}'
<port-variable declaration>  ::= <pio variable>  = 'PIO{'<number>'}'
<mmio variable>  ::= <name>
<pio variable>  ::= <name>

For example:

seq_address = PIO{0x3c4};
interrupt_en = MMIO{0x00000080}

Labels are user-defined identifiers that refer to code locations. The scope of a label is its containing function (or section). A label name within an adapter definition should be unique. The label must be declared prior to its reference.

<label>  ::= <name>':'

Registers

Registers are internal local variables that are used to hold interim results and return or pass information.

There are 256 32-bit noninitialized registers that are private to every VIDEOPMI caller. Registers should be assigned their values prior to being used. They can be used as a source in port OUT commands and memory WRITE commands or as a destination in the port IN commands and memory READ commands. Size of these operations is determined by the size of the PMI command. A set of 32-bit operations on registers is also defined in the syntax. When used in block I/O commands, the register index should be the same as that of the port index to which it corresponds. Register r0 is used as the return value register from functions that have a return value. Register r0 is also used to provide the bank number to the SetBank function .

Care should be taken in assigning registers in sections that contain function calls. Because all of the internal and imported PMI functions have addressability to the same set of registers, they will overwrite values set before function calls.

<register>  = <'0'..'255'>

Operators, Assignment Expressions, and Conditional Expressions

The following operators are valid in the PMI syntax:

<postfix unary additive op>  ::= '++'  |  '--'
<additive op>  ::= '+'  |  '-'
<shift op> ::= '<<'  |  '>>'
<bitwise op> ::= '&'  |  '|'  |  '^'
<relational op> ::= '<'  |  '>'  |  '==' | '<=' |  '>=' |  '!='
<binary assignment op> ::= '&=' | '|= ' | '<<=' |  '>>=' | '+=' | '-=' | '^='
<unary negation op>  ::= '~'
<assignment op>  ::= '='

Both assignment and conditional expressions in the PMI syntax are limited to a single expression term. The value of a conditional expression is either TRUE (nonzero) or FALSE (zero).

An assignment expression and example are shown below.

<assignment>  ::=
<register><postfix unary additive op>  |

<register><binary assignment op> [<constant>|<register>.]  |

<register><assignment op>  { <.PMI Keyvariable>  |
                             <register operand>|<constant>  } |

<register><assignment op>  {<register operand>  |  <.PMI keyvariable>}
                           {<additive op>|<shift op>  |  <bitwiseop>}
                           {<constant>  |  <register>

<register operand>  ::= [<unary negation op>.]<register>

Examples:

r0 = VerticalRefresh;
r0 <<= 0x10;
r1++; r2--;
r1 = ~r2 ^ 0x04;
r2 = XResolution <<  r1;
r1 = r2 + 0xffff;

A conditional expression and example are shown below.

<condition>  ::=
          '(' { <.PMI Keyvariable>  |  <register>} {<relational op> | <bitwise op>}

          { <.PMI Keyvariable>  |  <register>  |  <constant>  } ')'

Examples:

(XResolution == 1024)
(r1 & 0x0fe0)
(r2 == VerticalRefresh)

.PMI Functions

There are two types of functions, internal PMI functions and imported PMI functions. The Internal function is defined as a PMI Section with a user- defined name other than one of the predefined Section names. Imported PMI functions are not declared, but are assumed, to be of the IMPORTPMI prototype. They are imported from external binary objects that have been included using the #includecode directive.

Internal PMI functions
-Argument passing is performed using registers.
-Functions can be of either the VOID type (no return value) or of the APIRET type (return 0 for success and nonzero for failure).
-Function prototypes are not explicitly declared; the calling section has to understand how many and which registers need to be set and set them before calling the function.
-Functions are invoked by specifying the function name in a section.
-Functions must be declared prior to their use.
-A function may be called from within a function.
-Recursions are not allowed.
-There is no explicit exit or return command from functions.
-The last command or assignment in the function's section is considered its exit point.
Imported PMI functions
The IMPORTPMI function entry point is defined as follows:
(APIRET APIENTRY
*fnImportPMI)(VIDEO_ADAPTER
*pVideoInstance,
               PULONG (pRegisters)
APIRET returns 0 for success and nonzero (DOS errors) for failure.
APIENTRY refers to the _Syscall (C) calling convention.
-Functions are invoked using the PMI CALL command; for example, call fnFunctionName;.
-Current VIDEO_ADAPTER address and the start address of the registers are passed on the stack.
-A return value of 0 indicates success (r0 should also be set if subsequent PMI command sequences will need to evaluate the return code).
-Registers should be used to pass values from the PMI command sequences preceding the function call, if that is necessary.
-Full programming and development specifications for the imported binary objects will be available with the device driver development kit.

.PMI functions should be used extensively to create commonality and to encapsulate related operations. This use will reduce development costs, support more adapter-specific variations, reduce the size of the .PMI file, and improve performance.

The VIDEO_ADAPTERstructure is passed by PMI procedural callers at every PMI entry point and is available to all of the PMI functions other than IdentifyAdapter. All PMI functions have addressability to the current state of the PMI registers and care should be taken in using the registers.

.PMI Commands

PMI commands are divided into several categories, as follows:

Simple I/O commands
Block I/O commands
Read/Modify/Write commands
Simple memory access commands
WAIT command

INx Commands

INx commands perform an I/O input from the source and place the result into the destination. Width can be byte, word, or doubleword. The syntax is as follows:

INB( destination, source);
INW( destination, source);
INDW( destination, source);

<destination>  ::= <register>
<source> ::= <constant>  |  <pio variable>

OUTx Commands

OUTx commands perform an I/O output from the source into the destination. Width can be byte, word, or doubleword. The syntax is as follows:

OUTB( destination, source);
OUTW( destination, source);
OUTDW( destination, source);

<destination>  ::= <pio variable>  |  <constant>
<source>  ::= {<constant>  |  <register>}

For example:

outb(seq_address,r1);              //seq_address must have been declared.
outw(0x3c4,0x5520);

Block I/O Commands

Block I/O commands are designed for indexed ports. Byte-indexed access requires both index and data port values. Word and Dword block I/O is implemented as autoincrement block I/O, which causes no explicit modification to the index register. Word and Dword block I/O assumes that the hardware either implements autoincrementing or that the values being written specify both index and data. The startindex field is used as the index of the first PMI register in the set and as the first indexed port value. If the hardware's autoincrementing feature needs to be programmed explicitly, it should be done prior to calling the block I/O and should be left enabled upon completion of the mode set. See "Save and Restore State" , and [TrapRegs] in PMI Sections.

BINB( count, startindex, indexport, dataport );
BOUTB( count,startindex, indexport, dataport );

<startindex>  ::= <constant>
<count>  ::= <constant>
<indexport>  ::= <pio variable>  |  <constant>
<dataport>  ::= <pio variable>  |  <constant>
<port>  ::= <pio variable>  |  <constant>

For example:

r0 = 0x11; r1 = 0x12; r2 = 0x13;
boutb(0x03, 0x00, seq_address, seq_data);   //seq_address and seq_data
                                           //already declared.

RMWx Commands

RMWx (Read/Modify/Write) commands are available in byte format (indexed or nonindexed) and in word format (nonindexed). A nonindexed port RMWx can be used for ports that have different read and write access I/O addresses. The syntax is as follows:

RMWBI( indexport, dataport, index, andmask, ormask );
RMWB( bytereadport, bytewriteport, andmask, ormask );
RMWW( wordreadport, wordwriteport, andmask, ormask );

<indexport>  ::= <pio variable>  |  <constant>
<dataport>  ::= <pio variable>  |  <constant>
<bytereadport>  ::= <pio variable>  |  <constant>
<bytewriteport>  ::= <pio variable>  |  <constant>
<wordreadport>  ::= <pio variable>  |  <constant>
<wordwriteport>  ::= <pio variable>  |  <constant>
<index>  ::= <constant>
<andmask>  ::= <constant>
<ormask>  ::= <constant>

For example:

rmww(0x4ae8, 0x4ae8, 0x01, 0x00);

Note: Old PMI syntax (PMIVersion prior to 2.2) had ambiguous definitions for RMWW and RMWB. RMWB was used for indexed, RMWW for nonindexed, both byte and word access. The old definitions are no longer supported.

Memory I/O Commands

Memory I/O commands have only simple, single-port access format. Block I/O or indexing is not facilitated. Supported widths are Byte, Word, or Dword. Both destination and source represent either physical addresses or a register. The syntax is as follows:

READB( destination, source );      //read from source address, store
                                             //in destination variable
READW(destination, source );
READDW( destination, source);

<destination>  ::= <register>
<source>  ::= <constant>  |  <mmio variable>

WRITEB( destination, source );          //read from source variable, store
                                        //in destination address
WRITEW( destination, source );
WRITEDW( destination, source );
<destination>  ::= <mmio variable>  |  <constant>
<source>  ::= <constant>|<register>

For example:

writedw(interrupt_en, r1);      //interrupt_en already declared.
writeb(0xa0000080,0x88);      //write 0x88 into phys.  add 0xa00000080
readw(r1, 0xa0000080);        //read a word from 0xa0000080 into r1.

WAIT Command

The WAIT command should be used to wait on vertical retrace or to wait on a desired status. The command allows for a time-out in milliseconds. The condition for wait has been met if port value ANDed with andmask has the waitonvalue. Register r0 is set to convey the status:

TRUE (1) means that the waiting condition has been met.
FALSE means that a time-out has occurred.

The wait is interruptable. This command should not be used in Cleanup sections.

The port can be an immediate value, which presumes that the port is an I/O port or a declared port. In these cases, the port's declaration type is used in interpreting this command.

WAIT( port, andmask, timeout, waitonvalue );
<andmask>  ::= <number>
<timeout>  ::= <number>
<waitonvalue> ::= <number>

<port>  ::= <  constant>  |  <pio variable>  |  <mmio variable>

CALL Command

The CALL command performs a call to an imported PMI function entry point. Function entry point addresses are resolved at parsing (loading) time, by querying the procedural entry points of the dynamic libraries that were imported by the #includecode directive. Failing to resolve the addresses fails the loading of the PMI file. The calling convention is _Syscall (C). A return value of 0 denotes success; otherwise, an error applicable to the operating system should be returned.

Internal PMI functions are called implicitly by specifying the function's name. See PMI Sections for more information.

CALL function;
<function>  ::= identifier

For example:

[SetMode]        //set mode section
call fnPMISetMode;                      //call imported fnPMISetMode function

.PMI Constructs and Library Functions

.PMI constructs are keywords that are used for program flow control in PMI command sections. There are three flow control constructs: WHILE loop, unconditional jump GOTO, and conditional IF GOTO label jump. The constructs can be nested. Label reference can only be forward; in other words, a label must have been encountered before its referring construct.

WHILE <condition>       ;while loop condition is true, proceed
...                             ;else continue after ENDWHILE statement
...
...
ENDWHILE

GOTO <label>            ;jump to label

IF <condition>  GOTO <label>     ;if condition true, jump to label

For example:

if (r1 != 0x88) goto done

Two library functions facilitate string and binary compares: STRCMP and MEMCMP. These functions are especially useful in searching for signature sequences when identifying the adapter or comparing other string-literal names. STRCMP is used to compare a zero-ended character string (must be in double quotes) source with a destination specified as its physical address. MEMCMP is used to compare binary fields. The source string-literal for MEMCMP is assumed to be a string of 1s and 0s. If there is a need to search for a hexadecimal or another string, these must be converted to their binary form first. Byte alignment of both the source and target in the physical memory is assumed. Both functions return the result in r0: zero if the match was completely successful or nonzero otherwise. The length of the search is determined by the length of the source string.

String compares are performed after both source and target are converted to uppercase.

STRCMP(<destination>, <source>};
<destination>  ::= <address>        ;physical address
<source>  ::= <string>)
MEMCMP(<destination>, <source>};
<source>  ::= <binary-string>
<address> ::= <.PMI keyvariable> | <constant>

For example:

MEMCMP (0xc0154,"1001001111010001"); //compare 2 bytes at 0xc0154 with 0x93d1

PMI Sections

Proceed to the following information for a description of the types of sections that appear in a .PMI file.

Sections and Their Order of Appearance

The service sections listed in the following table are commented on and illustrated using the PMI language. functions or by using a mix of the two. See "Code vs. PMI" for an illustration of the PMI sections using imported functions.

The sections in the table are listed in the order they appear in a .PMI file.

Name Required Type Comments
[PMIVersion] Yes Informational
[Hardware] Yes Informational
[Declarations] No Informational Provides multiple instances, dynamic configuration support
[TrapRegs] Yes Informational Provides limited virtualization support
[IdentifyAdapter] Yes Service
[SetMemoryIOAddress] No Service Sets the linear aperture
[UnLock] Yes Service
[Cleanup] Yes Service Provides reset, disable, and bail-out support
[SetBank] Yes Service If applicable
[GetBank] Yes Service If applicable
[TuneDisplay] No Service Provides display centering and sizing
[Comment] No Informational One per ModeInfo, if desired
[ModeInfo] Yes Informational Multiple entries with unique values
[MonitorModeInfo] No Informational Provides multiple-monitor timing support
[SetMode] Yes Service At least one per file or, at most, one per MonitorModeInfo section

Predefined PMI Sections

Proceed to the following information for a description of the PMI Sections listed in the table that appears under Sections and Their Order of Appearance.

[PMIVersion]

This section is used to describe the PMI language revision level used. PMI files with older revisions (or no PMIVersion level) will not be supported by the VIDEOPMI interpreter.

[Hardware]

BusType = { ISA | VLB | PCI | EISA | PCMCIA | MCA }

The hardware description is available through a system query function. Any other definition is regarded as a user definition.

OEMString = "CHIPNAME ADAPTERNAME, ADAPTER MANUFACTURER NAME"

OEMString has an internal length of 128 chars, 0 ended. This string should be sufficient to uniquely describe the video adapter. The string will be presented to the user at configuration and installation and is the key element of the system's description of the adapter. It is regarded as a user definition, meaning that no translation of this information to any other format is performed. Any trademark information should be provided as a comment in the PMI file.

If the PMI file is not specifically written for an adapter, the ADAPTERNAME GENERIC is suggested (such files may be shipped by the chip manufacturers or software vendors). CHIPNAME is a required token and is used as a key in the display driver installation process to find a corresponding display driver for a given PMI file (and vice versa).

DACString = "MANUFACTURER NAME [, DACNAME]"

DACNAME, such as Bt485 or AT&T 491 is optional. Regarded as a user definition. Any trademark information should be provided as a comment.

Version = <string>

User-defined. Should represent the version of the manufacturer's .PMI file , rather than the revision level of the hardware. If multiple versions of the .PMI file exist for the same OEMString description, and all respective IdentifyAdapter function calls were successful, the file with the greater Version string is assumed to be the more appropriate one and is offered at the top of the PMI list during the video configuration.

The user, however, does have a choice of selecting a different PMI file. Note that the PMIVersion section is used to describe the PMI language revision level used, not the version of the PMI file.

TotalMemory = <constant>

This represents the total size of the currently installed VRAM memory in bytes.

MemoryIOAddress = <constant> [`{.' <mmio list> `}.'] <mmio list> : := <constant> | <constant> [`,' <mmio list>.]

Specifies the default base memory address for memory mapped I/O and a list of possible base addresses. The default value should match the value set by the configuration performed at the time of the adapter's installation. It is possible to reconfigure the adapter's address at a later time without modifying the .PMI file.

If this address is specified and is not zero, the BufferAddress fields in the [ModeInfo] sections of all graphics modes with more than 256 colors will be replaced by this address and the usFlag in the #VIDEOMODEINFO structure will have MODE_FALG_LINEAR_BUFFER flag set to on, indicating that this mode can be set to linear aperture mode. [SetMemoryIOAddress] should also be provided to handle the address setting.

PortIOAddress = <constant> [`{.' <pio list> `}.'] <pio list> ::= < constant> | <constant> [`,' <pio list>.]

Specifies default base port address for port I/O and a list of possible I/O addresses. For example, this variable for an MCA XGA adapter would reflect its instance that needs to be added to all of the register addresses. See the preceding discussion on MemoryIOAddress.

Endian = {BIG | LITTLE}

This represents the endian control capability of the device. The PMI constants are always represented with the most significant byte at the leftmost position. There are three possible cases of endian control:

-The device can conform to the endian type of the platform, such as WEITEK or XGA.
-The device cannot conform to the endian type but is of the same endian type as the platform.
-The device is of a different endian type than the platform on which it is installed.

The first two cases require no endian conversion on the part of the VIDEOPMI interpreter. In the third case, the VIDEOPMI interpreter native to a platform will perform the byte swapping to the platform's endian type. The programming of the endian control on devices that are capable of address swapping, such as XGA or WEITEK, is the responsibility of the .PMI file. In the case of WEITEK, this is done indirectly by generating correct addresses. It is preferable to configure the adapter in the endian control of the platform for which it is intended, if such capability is present.

Here is a sample file for a Viper VLB card:

BusType = VLB
OEMString = "P9000 VIPER, Diamond Computer Systems Inc."
DACString = "Brooktree Corporation"
Version = "3.2"
TotalMemory = 2097152
MemoryIOAddress = 0x80000000
PortIOAddress = 0x00000000
Endian = LITTLE

[Declarations]

This section is a list of port mnemonics defined by their offsets. Use MMIO for those whose offset is relative to MemoryIOAddress and PIO for those whose offset is relative to the PortIOAddress field in the Hardware section. Addresses for the ports that are referenced by their mnemonics are resolved at the time of the mode sets, using the MemoryIOAddress and/or PortIOAddress hardware values. These values can be changed at run time to allow for dynamic reconfiguration.

Here is a sample file for a Viper VLB card:

sysconfig   = MMIO{0x00100004}
interrupt_en= MMIO{0x0010000c}
x0y0        = MMIO{0x00181018}
x1y1        = MMIO{0x00181028}
x2y2        = MMIO{0x00181048}
x3y3        = MMIO{0x00181068}
cindex      = MMIO{0x0018018c}
w_off.xy    = MMIO{0x00180190}
fground     = MMIO{0x00180200}
bground     = MMIO{0x00180204}
pmask       = MMIO{0x00180208}
draw_mode   = MMIO{0x0018020c}
pat_originx = MMIO{0x00180210}
pat_originy = MMIO{0x00180214}
raster      = MMIO{0x00180218}
pixel8_reg  = MMIO{0x0018021c}
w_min       = MMIO{0x00180220}
w_max       = MMIO{0x00180224}
pattern0    = MMIO{0x00180280}
pattern2    = MMIO{0x00180284}
pattern4    = MMIO{0x00180288}
pattern6    = MMIO{0x0018028c}
pattern8    = MMIO{0x00180290}
patternA    = MMIO{0x00180294}
patternC    = MMIO{0x00180298}
patternE    = MMIO{0x0018029c}

[TrapRegs]

Currently, the [TrapRegs] section is only parsed and used by virtual video driver (vsvga.sys). videopmi.dll does not interpret the contents.

[IdentifyAdapter]

This is a required section and should perform the adapter identification. Recommended identification steps depend on the bus architecture and hardware support for the identification. For example, on a PCI adapter, a positive check of the PCI device ID, revision ID, and vendor ID would be sufficient. On an ISA card, a physical memory location can be read and compared against a string or a binary key, using MEMCMP and STRCMP PMI commands. Or, an identification port could be read in order to confirm the adapter type and revision level. The dependency on familiar port response should be minimal and resorted to only if more reliable checks do not exist . For vendors writing .PMI files for generic adapter support, however, this may be the only option, and it should be implemented with great care.

Register r0 is used to hold the function result. The register should contain zero if the adapter matches its Hardware description (OEMString and DACString in its entirety) or nonzero otherwise.

The purpose of the IdentifyAdapter function is to verify that an instance of the adapter is found that matches the OEMString and Version string from the .PMI file's Hardware section. Whether multiple instances exist, or if the instance found is not configured to the passed MemoryIOAddress and PortIOAddress, is of no consequence.

An adapter is considered available if its IdentifyAdapter section returns success. Consequently, if the .PMI file contains the minimum VIDEOPMI content, its .PMI file will be loaded.

Attention:

It is essential that any I/O or MMIO registers modified in this section be saved and restored! This is of great importance, as IdentifyAdapter sections from a .PMI file will be executed on nonrelated hardware in an attempt to find the corresponding .PMI file.

[SetMemoryIOAddress]

This section provides a way to set the linear apertures after the mode set. It can be executed through PMIREQUEST_SETMEMORYIOADDRESS. The passed address in that function will replace r0 in the PMI commands. Please see MemoryIOAddress under the [Hardware] section and PMIREQUEST_SETMODE for details.

[UnLock]

This section contains the list of commands required to make the hardware available for the execution of the SetMode section, as well as for saving and restoring of the controller and video buffer. The list of commands should be inclusive of saving and restoring the registers modified in the process, with the exclusion of the unlock key register. The function can be made mode-sensitive by using the conditional statements that evaluate key mode PMI keyvariables. However, the function could be a superset of all required unlock commands, for as long as such a sequence is not counter- productive in any mode sets.

Here is a sample file for a 9GXE S3 card:

inb(r0, 0x3d4);               //save index
outb(0x3d4, 0x38);
outb(0x3d5, 0x48);
outb(0x3d4, 0x39);
outb(0x3d5, 0xa0);
outb(0x3d4, r0);              //restore index

[Cleanup]

Cleanup is used on session switches or when SetMode control is being relinquished to a driver that may not be VIDEOPMI-driven. This function is also used if and when a mode targeting the VGA chip is to be issued from a resource other than the .PMI file. The virtual video driver depends on this function during session switches when the engine is found busy and a reset engine mechanism is needed as part of the recovery. The function will also be used at shutdown, after the shutdown message is displayed. It ensures that extended functionality is disabled and reset to the extent that pure VGA compatibility and/or subsequent use of the accelerator is allowed. For SVGA and accelerator/coprocessors that coexist with a VGA chip, this function is used to disable the controller and enable the VGA chip. Recommended order of disabling is:

Reset DAC to VGA mode.
Reset engine.
Disable extended functionality.
Enable VGA.
Set clock to 25 MHz.

Here is a sample file for a Viper VLB card:

[Cleanup]
          //reset DAC
r0   = 0x00000000;
r1   = 0x00000000;
ProgramDAC;
          //reset clock to 60Hz, 32 KHz
r0  = 0x0045A8BC;
ProgramClock;
          //enable VGA
DisableController;

[SetBank]

Specifies the commands necessary in order to switch banks on a frame buffer device. The function is called as part of the saving and restoring of the frame buffer for any mode with an aperture smaller than the PageLength. The bank number is assumed to be in r0. If the aperture is large enough to accommodate direct access to VRAM needed in any mode, the section may be omitted.

Here is a sample file for a 9GXE S3 card:

[SetBank]
                         //r0 contains the bank number
inb(r1, 0x3d4);          //save index
outb(0x3d4, 0x35);
r2   = r0   &  0x0000000f;
outb(0x3d4, 0x51);
inb(r2, 0x3d5);
r2   & = 0x00000030;
r0   >>= 0x00000002;
r2   & = 0x000000f3;
r0   |= r2  ;
outb(0x3d5, r0);         //set bank
outb(0x3d4, r1);         //restore index

[GetBank]

Specifies the name of the function to be called in order to get the current write bank. This assumes a device with an aperture smaller than the PageLength. The bank number is assumed to be returned in r0. It should be sensitive to the mode.

Here is a sample file for a 9GXE S3 card:

[GetBank]
inb(r1, 0x3d4);          //save index
outb(0x3d4, 0x35);
inb(r0, 0x3d5);
r0   & = 0x0000000f;
outb(0x3d4, 0x51);
inb(r2, 0x3d5);
r2   & = 0x00000004;
r2   <<= 0x00000002;
r0   |= r2  ;            //r0 contains the value
outb(0x3d4, r1);         //restore index

[TuneDisplay]

This section lists the execution steps required to set the start and end of the vertical active display in terms of the line count along the vertical sweep. It also lists the start and end of the horizontal active display in terms of the dot count along the horizontal sweep. The input values are the ScreenLeftEdge, ScreenRightEdge, ScreenTopEdge, and ScreenBottomEdge PMI keyvariables. The function should implement verification of the values , to keep them in the valid range for the current mode.

This section is not required but, if supplied, it provides a monitor centering and sizing capability. If provided, TuneDisplay should be invoked by the respective SetMode section in order to ensure that user- selected values are being reflected in the mode set. This applies to all MonitorModeInfo sections that list the four PMI keyvariables. If the current mode does not contain the PMI keyvariables, TuneDisplay will be a no-op, because default mode values do not correspond to how the real hardware is programmed and, therefore, the tuning cannot be performed.

The PMI keyvariable values represent the pixel count (dot count* bytesperpixel) and line count. They are incremented according to the end- user's configuration requests, which are processed one unit at a time. For example, if the user is trying to center a display in 640x480x64K, the start values of the current active display are obtained from the mode table for the current mode. For every mouse or pointer drag-increment on the centering area to the left, the current ScreenLeftEdge and ScreenRightEdge fields are incremented and a call into TuneDisplay is made with the current values. TuneDisplay translates the values into the dot count or any other internal representation and validates the range. VIDEOCFG.DLL Exported Functions for information on video configuration.

Here is a sample file for a Viper VLB card:

[TuneDisplay]
r0 = 1;             //set return code to failure, if validation fails
if (BitsPerPixel < 8) goto exittune
                    // all horizontal values are set in terms of DDOTCLK
                    //multiply by the number of bytes.
r9 = BitsPerPixel >> 4;
r5 = ScreenLeftEdge << r9;         //r5 = hrzbr
r6 = ScreenRightEdge << r9;        //r6 = hrzbf
r7 = ScreenTopEdge;                //r7 = vrtbr
r8 = ScreenBottomEdge;             //r8 = vrtbf
readdw(r1, hrzsr);                 //validate parameters
if (r5 <= r1) goto exittune        //validate left edge > hrzsr
readdw(r2, vrtsr);
if (r7 <= r2) goto exittune        //validate top edge > vrtsr
readdw(r3, hrzt);
if (r6 >= r3) goto exittune        //validate right edge < hrzt
readdw(r4, vrtt);
if (r8 >= r4) goto exittune        //validate bottom edge < vrtt
writedw(hrzbr, r5);
writedw(hrzbf, r6);
writedw(vrtbr, r7);
writedw(vrtbf, r8);
r0 = 0;                            //indicate success exittune:

[ModeInfo]

ModeInfo, together with the MonitorModeInfo section, defines mode capabilities of the PMI adapter. The complete list of all ModeInfo and MonitorModeInfo headers is available through a system-mode query function. The ModeInfo header specifies attributes that are not dependent on the type of display attached. Some of the fields are optional and, if not provided, are internally set to 0. Most fields are static; that is, they will not be modified at run-time and changed from their .PMI file values. However, Aperture address is a dynamic PMI keyvariable and is set by the caller to reflect the current value. All of the mode PMI keyvariables are field members of the VIDEOMODEINFO structure, a substructure of the VIDEO_ADAPTER .

ModeAttributes = <constant>
-Static PMI keyvariable. Required.
-0x18 for color graphic modes, 0x08 for color text modes.
-See VESA SVPMI Standard for full description.
BytesPerScanLine = <constant>
-Static PMI keyvariable. Required.

-Length of logical scan line in bytes.

-See VESA SVPMI Standard for full description.
XResolution = <constant>
-Static PMI keyvariable. Required.
-Horizontal resolution in pixels or characters in graphics and text modes, respectively.
YResolution = <constant>
-Static PMI keyvariable. Required.
-Vertical resolution in pixels or characters in graphics and text modes, respectively.
XCharSize = <constant>
-Static PMI keyvariable. Required in text modes.
-Character cell width in pixels.
YCharSize = <constant>
-Static PMI keyvariable. Required in text modes.
-Character cell height in pixels.
TextRows = <constant>
-Static PMI keyvariable. Required in both graphics and text modes.
-Number of text rows.
BitsPerPixel = <constant>
-Static PMI keyvariable. Required.
-Color depth.
NumberOfPlanes = <constant>
-Static PMI keyvariable. Required.
-[4|1] planar vs. linear memory organization.
PageLength = <constant>
-Static PMI keyvariable. Required.
-Size of memory required to save a page of the on-screen VRAM.
SaveSize = <constant>
-Static PMI keyvariable. Required.
-Size of memory required to save all of the on-screen VRAM. It should be set to include at least the logical scanline width (BytesPerScanLine* Yresolution).
Int10ModeSet = <constant>
-Static PMI keyvariable. Required if the same mode can be set though BIOS.
ColorFormat = <string>
-Static PMI keyvariable. Optional.
-User defined.
-Zero-ended string. Required for hi-color and true-color modes.
Suggested definitions:
[ RGB | BGR | GBR | YUI ]
-Not used internally; available to drivers through a mode query.
-If not specified, zeros are returned.
ColorWeight = <constant> ':' <constant> ':' <constant>
-Static PMI keyvariable. Optional.
-User defined.
-Required for hi-color and true-color modes.
-Not used internally; available to drivers through a mode query.
-If not specified, zeros are returned.
BufferAddress = <constant>
-Dynamic PMI keyvariable. Required if direct VRAM access is possible.
-Represents the physical address of the video buffer. If direct buffer access is possible, VIDEOPMI interpreter will copy VRAM in chunks of ApertureSize or SaveSize, whichever is smaller. If 0, no direct buffer access is possible.
This PMI keyvariable is dynamic on all systems in which remapping of the aperture is possible. In such cases, it should be assigned the LinearWindowAddress value from the Hardware description. The SetMode section should ensure that it programs hardware to reflect the hardware's dynamic value.
ApertureSize = <constant>
-Static PMI keyvariable. Required if direct VRAM access is possible.
-Size of the aperture. If ApertureSize < SaveSize and BufferAddress is not 0, SetBank and GetBank sections are required.
-Aperture size will not be modified, even if hardware does allow for different sizes.
Colors.
-Number of colors for this mode.

Here is a sample file for a 9GXE S3 card:

[comment]
   Graphics Mode: 1280 x 1024 x 256 colors.

[ModeInfo]
    ModeAttributes   = 0x18
    BytesPerScanLine = 1280
    XResolution      = 1280
    YResolution      = 1024
    TextRows         = 64
    BitsPerPixel     = 8
    NumberOfPlanes   = 1
    PageLength       = 1310720
    SaveSize         = 1310720
    Int10ModeSet     = 0x107
    BufferAddress    = 0x000a0000
    ApertureSize     = 0x00010000

[MonitorModeInfo]

This section provides information on the capabilities of the adapter in terms of the synchronization signal range. This section is optional if an adapter does not require software intervention in order to detect the monitor type and program the optimal HSYNC, VSYNC, HBLNK, and VBLNK signals . Because the industry lacks a standard for monitor detection, most adapters require user intervention in order to detect the monitor and additional software to handle selection of the horizontal and vertical frequencies for the configured monitor. In the OS/2 environment, the configuration and recording of the user selection is done by the DSPCONF utility. The information is then available to all video drivers.

Depending on the type of clock generator, the specified frequencies could be definable only in distinct (discrete) sets of values, or they could be generated within the maximum range of the clock chip. Therefore, one or more MonitorModeInfo sections are used to provide a vehicle for user configuration of the refresh setup and for the subsequent mode setting.

If clock generation is contiguous within a range, a single MonitorModeInfo with the end of the range should be listed per each mode. Otherwise, a list of MonitorModeInfo sections should list all of the discrete refresh pairs. In this case, an exact match between the monitor refresh specification and the adapter's refresh capability has to happen (this includes the polarity information). If the vendor providing the .PMI file does not wish to discriminate based on the polarity, the polarity can be omitted or set to a predefined value of 2.

Note that all of the PMI keyvariables are marked as dynamic. This means that their run-time values could differ from their values specified in the flat file, depending on the user configuration. This also means that sections programming the hardware should verify that the values passed are in the valid range.

VerticalRefresh = <constant>
-Dynamic PMI keyvariable. Required.
-Vertical refresh in Hz, rounded to the nearest integer.
-Should be set to 0 for flat panel and other non-CRT display modes. Otherwise, set to either a discrete value or end-of-range value.
HorizontalRefresh = <constant>
-Dynamic PMI keyvariable. Required.
-Horizontal refresh in KHz, rounded to the nearest integer.
-Should be set to 0 for flat panel and other non-CRT display modes. Otherwise, set to either a discrete value or end-of-range value.
VPolarityPositive = <'0' | '1' | '2'>
-Vertical polarity.
-Dynamic PMI keyvariable. Not required.
-0 indicates negative; 1 indicates positive; 2 indicates that either one can be set and should not be used when matching the monitor specification. A value of 2 is logically the same as omitting the keyvariable.
HPolarityPositive = <'0' | '1' | '2'>
-Horizontal polarity.
-Dynamic PMI keyvariable. Not required.
-0 indicates negative; 1 indicates positive; 2 indicates that either one can be set and should not be used when matching the monitor specification. A value of 2 is logically the same as omitting the keyvariable.
ScreenLeftEdge = <constant>
-Dynamic PMI keyvariable. Required if TuneDisplay section exists.
-Defines the start of the active horizontal display in terms of the pixel count. Internally, it represents the offset in terms of the dot count along the horizontal sweep.
-If the TuneDisplay section is provided, the user has the option of fine- tuning this value. Consequently, the SetMode call will set the hardware according to the dynamic value of this PMI keyvariable (see [TuneDisplay] and [SetMode] in this chapter).
ScreenRightEdge = <constant>
-Dynamic PMI keyvariable. Required if TuneDisplay section exists.
-Defines the end of the horizontal active display in terms of the pixel count. Internally, it represents the offset in terms of the dot count along the horizontal sweep for the current mode.
-If the TuneDisplay section is provided, the user has the option of fine- tuning this value. Consequently, the mode will set the hardware according to the dynamic value of this PMI keyvariable (see [TuneDisplay] and [ SetMode] in this chapter).
ScreenBottomEdge = <constant>
-Dynamic PMI keyvariable. Required if TuneDisplay section exists.
-Defines the end of the active vertical display in terms of the line count along the vertical sweep in the current mode.
-If the TuneDisplay section is provided, the user has the option of fine- tuning this value. Consequently, the mode will set the hardware according to the dynamic value of this PMI keyvariable (see [TuneDisplay] and [SetMode] in this chapter).
ScreenTopEdge = <constant>
-Dynamic PMI keyvariable. Required if TuneDisplay section exists.
-Defines the start of the vertical sync in the current mode.
-If the TuneDisplay section is provided, the user has the option of fine- tuning this value. Consequently, the mode will set the hardware according to the dynamic value of this PMI keyvariable (see [TuneDisplay] and [ SetMode] in this chapter).

Here is a sample file for a Viper VLB card:

[MonitorModeInfo]             //1024 x 768 resolution

VerticalRefresh         = 80
HorizontalRefresh       = 64
VPolarityPositive       = 1
HPolarityPositive       = 1
ScreenLeftEdge          = 0x00000047
ScreenRightEdge         = 0x00000147
ScreenTopEdge           = 0x00000023
ScreenBottomEdge        = 0x00000323

[SetMode]

This section lists the required execution steps for a successful mode set. There could be one SetMode section per MonitorModeInfo, or one per ModeInfo , or one that services multiple modes. The Interpreter tags all ModeInfo and MonitorModeInfo sections found between two SetMode sections and, later on, associates the last SetMode with all of them. Thus, SetMode services for all of the modes could be provided by a number of different functions (if desired, a single function that serves as a router can be used). The SetMode section is also executed when Saving and Restoring the mode (see [SaveRestore] in this chapter).

Any number of can be called from within the mode section. The SetMode section has to ensure that the adapter is programmed to reflect the run- time settings of the ModeInfo/MonitorModeInfo structure. These settings are passed in the VIDEO_ADAPTER.VIDEOMODEINFO structure at the The settings are also available as PMI keyvariables to the PMI language On dynamic Legacy and PnP hardware, or when a coprocessor co-resides with a VGA chip, the SetMode has to ensure that the setup is configured appropriately for the mode to be set. This should be facilitated by an embedded EnableController call, which is sensitive to the current Hardware PMI keyvariable values.

Vendors who provide the TuneDisplay section for sizing of the active display and the SetMonitorTimings section for manipulation of the timing PMI keyvariables should ensure that the SetMode section has the ability to set the run-time values for the timing PMI keyvariables. The easiest way to ensure this is by making the SetMode section use the SetMonitorTimings and TuneDisplay sections.

See Supported Modes and [EnableController] in this chapter for more information. VIDEOCFG.DLL Exported Functions for information on video configuration.

Here is a sample file for a Viper VLB card:

[SetMode]
SetP9000AccelMode;

/*
** Set accelerated mode on P9000
*/
[SetP9000AccelMode]
EnableController;             //configure controller
r0   = 0x00000000;            //set DAC
r1   = 0x00000040;            //256 color 6:6:6
if (BitsPerPixel != 16) goto DAC
r1   = 0x00000030;            // 64K colors
DAC:
ProgramDAC;
InitializeP9000;              //initialize P9000 registers
                              //set sysconfig and clipping
if (Xresolution != 640) goto not640
r1  = 0x028001e0;             //640x480x8
r0  = 0x00563000;
if (BitsPerPixel == 8) goto domodeset
r0  = 0x00683000;             //640x480x16 bits
goto domodeset
not640:
if (Yresolution != 800) goto not800     //800x600x8
r0  =  0x00587000;
r1  =  0x03200258;
goto domodeset
not800:                       //must be 1024x760x8
r0  =  0x00603000;
r1  =  0x04000300;
domodeset:
writedw(sysconfig,r0);
writedw(w_min,0x00000000);
writedw(w_max,r1);            //program clipping
SetMonitorTimings;            //program clock and timings. Calls TuneDisplay.
writedw(srtctl,0x000001e5);   //enable

User-Defined Function Sections

Any section denoted by [NAME] not listed in the preceding table is regarded as a user-defined section. The function can be called internally by the predefined PMI sections or other user-defined functions (see "PMI Functions " in PMI Language Elements).