Copyright ã1995 by NeXT Computer, Inc.  All Rights Reserved.

IODisplay

Inherits From:	IODirectDevice : IODevice : Object

Conforms To:	IOScreenEvents

Declared In:	driverkit/IODisplay.h

Class Description

IODisplay is an abstract class for controlling video displays. To write a display driver, you need to create a subclass of one of NeXT's IODisplay subclassesÐIOFrameBufferDisplay and IOSVGADisplay. IOFrameBufferDisplay is the preferred basis for display drivers, but it can only be used for video cards that linearly map the entire frame buffer into memory. Other video cards require IOSVGADisplay subclasses.

Note:  All VGA cards work even without special drivers. However, they have a small display area (640´480) and are 2-bit grayscale.

Most of what you need to create a display driver is described in the IOFrameBufferDisplay and IOSVGADisplay class specifications. In addition, both kinds of display drivers need to specify certain display-specific configuration keys and provide IODisplayInfo structures. 

Display Configuration Keys

Your driver's configuration table must have values for the ªVGA Memory Mapsº and ªDisplay Modeº keys. ªVGA Memory Mapsº must be equal to ª0xa0000-0xbffff 0xc0000-0xcffffº; those addresses must also be specified for the ªMemory Mapsº key. 

An IOFrameBufferDisplay might specify the following in its default configuration table. 

"Memory Maps" = "0x7e00000-0x7ffffff 0xa0000-0xbffff 0xc0000-0xcffff";
"VGA Memory Maps" = "0xa0000-0xbffff 0xc0000-0xcffff";

An IOSVGADisplay would have the following:

"Memory Maps" = "0xa0000-0xbffff 0xc0000-0xcffff";
"VGA Memory Maps" = "0xa0000-0xbffff 0xc0000-0xcffff";

Note:  The first range for the ªMemory Mapsº key must be the range that the window server will use for access to the screen. For example, for IOFrameBufferDisplays, the first range must be that of the linear frame buffer.

A default display mode is usually specified with the ªDisplay Modeº key in the default configuration table. The mode can also be set by the user, with Configure's display inspector. You specify the modes your driver supports with the ªDisplay Modesº key in the Localizable.strings file in the Language.lproj directories of your driver's bundle. (Driver bundles are discussed in Chapter 4.) An example of specifying display modes is below.

"Display Modes" = "
    Height: 600 Width: 800 Refresh: 60Hz ColorSpace: RGB:555/16;
    Height: 768 Width:1024 Refresh: 60Hz ColorSpace: BW:8;
    Height: 768 Width:1024 Refresh: 70Hz ColorSpace: BW:8;
    Height: 768 Width:1024 Refresh: 72Hz ColorSpace: BW:8;
    Height: 768 Width:1024 Refresh: 60Hz ColorSpace: RGB:555/16;
    Height: 768 Width:1024 Refresh: 72Hz ColorSpace: RGB:555/16;
    Height:1024 Width:1280 Refresh: 60Hz ColorSpace: BW:8;
    Height:1024 Width:1280 Refresh: 60Hz ColorSpace: RGB:555/16;
    Height: 600 Width: 800 Refresh: 60Hz ColorSpace: RGB:888/32;
    Height: 768 Width:1024 Refresh: 60Hz ColorSpace: RGB:888/32;
    Height: 768 Width:1024 Refresh: 72Hz ColorSpace: RGB:888/32";

See the ªConfiguration Keysº section of this chapter for more information on configuration keys.

IODisplayInfo

Display drivers need to have an IODisplayInfo structure for each mode the driver supports. Drivers that support multiple modes use one of the selectMode:... methods (provided by IOFrameBufferDisplay and IOSVGADisplay) to find the IODisplayInfo that corresponds to the value of the ªDisplay Modeº key. Once the driver has determined which mode it will be in, it needs to set the value returned by displayInfo so that it points to the appropriate IODisplayInfo structure. The display subsystem, as well as the driver, uses the IODisplayInfo to get information about the driver's mode. 

The IODisplayInfo type is defined in the driverkit/displayDefs.h header file as the following:

typedef struct {
    int width;
    int height;
    int totalWidth;
    int rowBytes; 
    int refreshRate;
    void *frameBuffer; 
    IOBitsPerPixel bitsPerPixel;
    IOColorSpace colorSpace;
    IOPixelEncoding pixelEncoding;
    unsigned int flags;
    void *parameters;
} IODisplayInfo; 

The width and height fields hold the width and height in pixels of the display area. Generally, the width should be at least 640, and the height at least 480. The totalWidth is the width including any undisplayed pixels that might be included for efficiency reasons; often, it's equal to width. The value of rowBytes is equal to totalWidth multiplied by the number of bytes used to address each pixel, as shown in the following table.

Color Mode	Value of rowBytes

SVGA 2-bit grayscale	totalWidth/4
8-bit grayscale	totalWidth
8-bit color	totalWidth
16-bit RGB (either 12 or 15 bits per pixel)	totalWidth x 2
24-bit RGB (24 bits per pixel)	totalWidth x 4

The refreshRate field holds the monitor refresh rate, in Hz.

The frameBuffer field should contain the first virtual address that screen memory is mapped to. You get this address during initialization by invoking mapFrameBufferAtPhysicalAddress:length:, as documented in the IOFrameBufferDisplay and IOSVGADisplay specifications.

The next three fields specify how the display subsystem should interpret the screen memory. The value of bitsPerPixel should be IO_2BitsPerPixel, IO_8BitsPerPixel, IO_12BitsPerPixel, IO_15BitsPerPixel, or IO_24BitsPerPixel. You shouldn't specify IO_VGA, since it's used only by NeXT-supplied VGA support. For IOFrameBufferDisplays, the value of colorSpace is IO_OneIsWhiteColorSpace for black-and-white modes and IO_RGBColorSpace for RGB modes. For IOSVGADisplays, colorSpace is always IO_OneIsBlackColorSpace. The value of pixelEncoding is a string that specifies how each bit of a pixel should be interpreted. Some common values of pixelEncoding are shown below.

Value of pixelEncoding	Description

ª--------RRRRRRRRGGGGGGGGBBBBBBBBº	24-bit RGB, 8 bits per component; ignore the most significant byte

ª-RRRRRGGGGGBBBBBº	16-bit RGB, 5 bits per component; ignore the most significant bit

ªRRRRGGGGBBBB----º	16-bit RGB, 4 bits per component; ignore the 4 least significant bits 

ªWWWWWWWWº	8-bit grayscale

ªWWº	2-bit grayscale; used by IOSVGADisplays

The flags field contains caching instructions and optionally some flags, combined using the bitwise OR operator. The value you specify for caching depends on whether your hardware supports burst reads. If your hardware supports burst reads (as most '486 hardware does), you should specify IO_DISPLAY_CACHE_WRITETHROUGH to specify that screen memory be cached write-through. Write-through caching means that each writeÐeven to memory that is in the cacheÐis immediately written to the device. If your hardware doesn't support burst reads, you should use IO_DISPLAY_CACHE_OFF to turn the cache off for screen memory. The third caching option, IO_DISPLAY_CACHE_COPYBACK, isn't currently supported; it specifies that writes have to be explicitly flushed, instead of being passed through the cache immediately. If flags contains no caching instructions, write-through caching is used.

IO_DISPLAY_NEEDS_SOFTWARE_GAMMA_CORRECTION and IO_DISPLAY_HAS_TRANSFER_TABLE are the two optional flags. IO_DISPLAY_NEEDS_SOFTWARE_GAMMA_CORRECTION should be specified if the display is in a 16-bit RGB mode with 5 bits per component and the hardware does not support gamma correction in this mode. It tells the display subsystem to use a default gamma correction table when converting the 4 bits used internally into the 5 bits required by the hardware. 

IO_DISPLAY_HAS_TRANSFER_TABLE should be specified if the hardware supports gamma correction in this mode. Generally, drivers that support gamma correction should implement the setTransferTable:... method, which is described in IOFrameBufferDisplay.

The following example shows how a driver specifies flags when its hardware supports gamma correction only for 8-bit modes. 

/* displayMode points to the IODisplayInfo for this mode */
displayMode->flags = IO_DISPLAY_CACHE_WRITETHROUGH;
if (displayMode->bitsPerPixel == IO_15BitsPerPixel)
    displayMode->flags |=  IO_DISPLAY_NEEDS_SOFTWARE_GAMMA_CORRECTION;
else if (displayMode->bitsPerPixel == IO_8BitsPerPixel) 
    displayMode->flags |= IO_DISPLAY_HAS_TRANSFER_TABLE;

The parameters field is ignored by the display system. You can use it for whatever you want. 

The following code example shows some typical IODisplayInfo structures, taken from a driver based on IOFrameBufferDisplay. See the description of displayInfo for an example for an IOSVGADisplay.

/* The frameBuffer field is initialized to 0, since it's determined 
 * at runtime.  The flags field is also determined at runtime.  The 
 * parameters field in this driver points to a mode-specific 
 * structure that specifies values for the hardware registers.*/

const IODisplayInfo S3_928_ModeTable[] = {
    {   /* 800 x 600, 15bpp, 60Hz. */
        800, 600, 1024, 2048, 60, 0, IO_15BitsPerPixel, 
        IO_RGBColorSpace, "-RRRRRGGGGGBBBBB", 0, 
        (void *)&S3_928_800x600x15,
    },
    {   /* 800 x 600, 24bpp, 60Hz. */
        800, 600, 1024, 4096, 60, 0, IO_24BitsPerPixel, 
        IO_RGBColorSpace, "--------RRRRRRRRGGGGGGGGBBBBBBBB",
        0, (void *)&S3_928_800x600x24,
    },
    {   /* 1024 x 768, 8bpp, 60Hz. */
        1024, 768, 1024, 1024, 60, 0, IO_8BitsPerPixel,
        IO_OneIsWhiteColorSpace, "WWWWWWWW", 0, 
        (void *)&S3_928_1024x768x8,
    },
    {   /* 1024 x 768, 8bpp, 70Hz. */
        1024, 768, 1024, 1024, 70, 0, IO_8BitsPerPixel,
        IO_OneIsWhiteColorSpace, "WWWWWWWW", 0, 
        (void *)&S3_928_1024x768x8,
    },
    {   /* 1024 x 768, 8bpp, 72Hz. */
        1024, 768, 1024, 1024, 72, 0, IO_8BitsPerPixel,
        IO_OneIsWhiteColorSpace, "WWWWWWWW", 0, 
        (void *)&S3_928_1024x768x8,
    },
    {   /* 1024 x 768 x 15bpp, 60Hz. */
        1024, 768, 1024, 2048, 60, 0, IO_15BitsPerPixel,
        IO_RGBColorSpace, "-RRRRRGGGGGBBBBB", 0, 
        (void *)&S3_928_1024x768x15,
    },
    {   /* 1024 x 768 x 15bpp, 72Hz. */
        1024, 768, 1024, 2048, 72, 0, IO_15BitsPerPixel,
        IO_RGBColorSpace, "-RRRRRGGGGGBBBBB", 0, 
        (void *)&S3_928_1024x768x15,
    },
    {   /* 1024 x 768 x 24bpp, 60Hz. */
        1024, 768, 1024, 4096, 60, 0, IO_24BitsPerPixel,
        IO_RGBColorSpace, "--------RRRRRRRRGGGGGGGGBBBBBBBB",
        0, (void *)&S3_928_1024x768x24,
    },
    {   /* 1024 x 768 x 24bpp, 72Hz. */
        1024, 768, 1024, 4096, 72, 0, IO_24BitsPerPixel,
        IO_RGBColorSpace, "--------RRRRRRRRGGGGGGGGBBBBBBBB",
        0, (void *)&S3_928_1024x768x24,
    },
    {   /* 1280 x 1024, 8bpp, 60Hz. */
        1280, 1024, 1280, 1280, 60, 0, IO_8BitsPerPixel,
        IO_OneIsWhiteColorSpace, "WWWWWWWW", 0, 
        (void *)&S3_928_1280x1024x8,
    },
    {   /* 1280 x 1024, 15bpp, 60Hz. */
        1280, 1024, 2048, 4096, 60, 0, IO_15BitsPerPixel,
        IO_RGBColorSpace, "-RRRRRGGGGGBBBBB", 0, 
        (void *)&S3_928_1280x1024x15,
    },
};

Instance Variables

None declared in this class.

Adopted Protocols

IOScreenEvents	- devicePort
- hideCursor:
- moveCursor:frame:token:
- setBrightness:token:
- showCursor:frame:token:

Method Types

Getting information about this display
- displayInfo

Getting and setting the registration token for this display
- setToken:
- token

Getting parameters	- getIntValues:forParameter:count:

Getting the device port	- devicePort

Note:  The IOScreenEvents protocol method devicePort is reimplemented in this class.

Instance Methods

devicePort

- (port_t)devicePort

Returns the device port, which should be obtained from this instance's IODeviceDescription. This method in the IOScreenEvents protocol is reimplemented in this class.

displayInfo

- (IODisplayInfo *)displayInfo

Returns the IODisplayInfo that describes this display. Each display driver instance must use this method to obtain its IODisplayInfo structure. The driver must then set the fields in the structure so that they describe the display's configuration. For example, the following code initializes the IODisplayInfo associated with this instance. See the class description for information on IODisplayInfo structures.

static const IODisplayInfo modeTable[] = {
    {1024, 768, 1024, 256, 60, 0, IO_2BitsPerPixel,
     IO_OneIsBlackColorSpace, "WW", 0, 0,
    },
    /* Add more modes here. */
};
#define modeTableCount  (sizeof(modeTable) / sizeof(IODisplayInfo))
#define defaultMode 0

- initFromDeviceDescription:deviceDescription
{
    IODisplayInfo *displayInfo;
    const IORange *range;

    if ([super initFromDeviceDescription:deviceDescription] == nil)
        return [super free];

    /* selectedMode is a driver-defined instance variable */
    selectedMode = [self selectMode:modeTable count:modeTableCount
                    valid:NULL];
    if (selectedMode < 0) {
        IOLog("%s: Sorry, cannot use requested display mode.\n",
              [self name]);
        selectedMode = defaultMode;
    }

    displayInfo = [self displayInfo];
    *displayInfo = modeTable[selectedMode];

    displayInfo->frameBuffer = (void *)
            [self mapFrameBufferAtPhysicalAddress:0 length:0];             
    if (displayInfo->frameBuffer == 0)
        return [super free];

    IOLog("%s: Initialized @ %d Hz.\n", [self name],
          displayInfo->refreshRate);
    return self;
}

getIntValues:forParameter:count:

- (IOReturn)getIntValues:(unsigned int *)array forParameter:(IOParameterName)parameter
count:(unsigned int *)count

Handles NeXT-internal parameters specific to IODisplays; forwards the handling of all other parameters to super. 

setToken:

- (void)setToken:(int)token 

Sets the registration token for this display. 

See also:  - token

token

- (int)token

Gets the registration token for this display. 

See also:  - setToken