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:
 * .PMI file
 * Limitations of the PMI
 * Code vs. PMI
 * How to Customize the PMI Subsystem for Your Device
 * Supported Modes
 * Monitor Timings Support
 * Save and Restore State
 * Adapter Configuration
 * PMI Language Elements
 * PMI Sections

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.

.PMI file
The VIDEOPMI interface is driven by the sections of the .PMI file. There are two main types of sections: 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.
 * Query sections that describe adapter capabilities
 * Set sections that service hardware programming requests

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

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

.PMI 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 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.
 * 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.
 * 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 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. /* 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
 * Vendor include PMI file VENDOR.PMI

/* [PMIVersion]       2.2 in this PMI file
 * Generic PMI file
 * 1) includecode       "vendor.DLL"   //exports all fnPMI entry points used
 * 1) 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 a .PMI file. Each supported mode is represented by a set of sections, as follows: 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.
 * Comment (optional)
 * ModeInfo (required)
 * MonitorModeInfo (optional)
 * SetMode (optional)

At the minimum, modes which are supported by the respective Presentation Manager display driver.
 * Suggested modes include the following:
 * 40x25 and 80x25 text
 * 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).

If the adapter in question has both accelerated and nonaccelerated modes, only the accelerated modes should be provided.

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

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 Installing Video Configuration Manager for OS/2.

Save and Restore State
VIDEOPMI does not have dedicated SaveState or RestoreState sections. The VIDEOPMI engine does offer those services.

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.

The PM driver performs its own Save and Restore of the state and is not dependent on the service. The bvhsvga.dll uses the Save and Restore State service to save and restore OS/2 full screen sessions; in case of a partial restore, bvhsvga.dll 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.

PMI Language Elements
The VIDEOPMI language consists of the following elements: 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.
 * Sections
 * User-defined functions
 * Expressions
 * PMI commands, identifiers, constants, variables, string-literals, and comments

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 .PMI files, all of which must conform to the PMI language. The include files should be in the same directory as the current .PMI file. 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.
 * 1) include "filename" //PMI extension assumed
 * 2) includecode "filename" //DLL extension assumed

Constants, String-Literals, Identifiers, and Keywords
PMI constants are 32-bit integer constants, either in decimal or hexadecimal format. ::= '0'..'9' ::= |  'a'..'f' ::= 'a'..'z' |  'A'.. 'Z'| '_' |  '.' ::= |     ::= '0x'  | ::= |  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). ::= " [ ]"  ::= " <'0'|'1'> | <'0'|1'> []" 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. ::=   ::= {  |  [  ]} Reserved identifiers are called keywords. Keywords are divided into three groups: 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.
 * PMI keyvariables, which are keywords representing configuration and mode parameters
 * PMI constants, backed by system-wide definitions
 * All other reserved identifiers

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

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

PMI Keywords
The following table lists the reserved identifiers, called Keywords, used by the Protect Mode Interface (PMI). 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.  ::=  =  'MMIO{' '}'  ::=  = 'PIO{' '}' ::=  ::= 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. ::= ':'

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. = r<'0'..'255'>

Operators, Assignment Expressions, and Conditional Expressions
The following operators are valid in the PMI syntax: ::= '++' |  '--'  ::= '+'  |  '-' ::= '<<'  |  '>>' ::= '&'  |  '|'  |  '^' ::= '<'  |  '>'  |  '==' | '<=' |  '>=' |  '!=' ::= '&=' | '|= ' | '<<=' |  '>>=' | '+=' | '-=' | '^='  ::= '~'  ::= '=' 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. ::=  |

[ | ] |

{  | | } |

{ |  } { | |  }                           {  |

r0 = VerticalRefresh; r0 <<= 0x10; r1++; r2--; r1 = ~r2 ^ 0x04; r2 = XResolution << r1; r1 = r2 + 0xffff; A conditional expression and example are shown below. ::=         '(' {   |  } { | }

{  |   |   } ')' Examples:

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

PMI Functions
A PMI function is defined as a PMI Section with a user-defined name other than one of the predefined Section names.

PMI functions have the following characteristics:
 * 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.

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 structure 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);



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

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 startindexfield 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. BINB( count, startindex, indexport, dataport ); BOUTB( count,startindex, indexport, dataport );

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

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

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



WRITEB( destination, source );         //read from source variable, store //in destination address WRITEW( destination, source ); WRITEDW( destination, source ); ::= |    ::= | 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 and mask has the waitonvalue. Register r0 is set to convey the status: The wait is interruptable. This command should not be used in Cleanup sections.
 * TRUE (1) means that the waiting condition has been met.
 * FALSE means that a time-out has occurred.

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



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    ;while loop condition is true, proceed ...                          ;else continue after ENDWHILE statement ... ... ENDWHILE

GOTO           ;jump to label

IF GOTO   ;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(, }; ::=        ;physical address  ::= ) MEMCMP(, }; ::=  ::=  | 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.

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

Predefined PMI Sections
Proceed to the following information for a description of the PMI Sections listed in the table that appears under.

[PMIVersion]
This section describes the PMI language revision level used.

[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 =

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 =

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


 * MemoryIOAddress = ['{' '}'] ::= | [',' ]

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 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 = ['{' '}'] ::= | [',' ]

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 .PMI 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 .PMI 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. The passed address in that function will replace r0 in the PMI commands. Please see MemoryIOAddress under the [Hardware] section and 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 .PMI 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 .PMI 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 .PMI 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 .PMI 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.

Here is a sample .PMI 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 =
 * Static PMI keyvariable. Required.
 * 0x18 for color graphic modes, 0x08 for color text modes.
 * See VESA SVPMI Standard for full description.
 * BytesPerScanLine =
 * Static PMI keyvariable. Required.
 * Length of logical scan line in bytes.
 * See VESA SVPMI Standard for full description.
 * XResolution =
 * Static PMI keyvariable. Required.
 * Horizontal resolution in pixels or characters in graphics and text modes, respectively.
 * YResolution =
 * Static PMI keyvariable. Required.
 * Vertical resolution in pixels or characters in graphics and text modes, respectively.
 * XCharSize =
 * Static PMI keyvariable. Required in text modes.
 * Character cell width in pixels.
 * YCharSize =
 * Static PMI keyvariable. Required in text modes.
 * Character cell height in pixels.
 * TextRows =
 * Static PMI keyvariable. Required in both graphics and text modes.
 * Number of text rows.
 * BitsPerPixel =
 * Static PMI keyvariable. Required.
 * Color depth.
 * NumberOfPlanes =
 * Static PMI keyvariable. Required.
 * [4|1] planar vs. linear memory organization.
 * PageLength =
 * Static PMI keyvariable. Required.
 * Size of memory required to save a page of the on-screen VRAM.
 * SaveSize =
 * 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 =
 * Static PMI keyvariable. Required if the same mode can be set though BIOS.
 * ColorFormat =
 * 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 = ':' ':'
 * 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 =
 * 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 =
 * 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 .PMI 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 =
 * 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 =
 * 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 =
 * 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 =
 * 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 =
 * 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 =
 * 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 .PMI 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 PMI functions 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 procedural level. The settings are also available as PMI keyvariables to the PMI language command sequences. 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 and [EnableController] in this chapter for more information.

Here is a sample .PMI file for a Viper VLB card: [SetMode] SetP9000AccelMode;

/* [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
 * Set accelerated mode on P9000

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