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

IOFrameBufferDisplay

Inherits From:	IODisplay : IODirectDevice : IODevice : Object

Conforms To:	IOScreenEvents

Declared In:	driverkit/IOFrameBufferDisplay.h

Class Description

IOFrameBufferDisplay is an abstract class for managing display cards that support linear-mode frame buffers. IOFrameBufferDisplay's close interaction with the window server and event system means that your driver needs to do very little.

Note:  If your display adapter doesn't allow you to linearly address the entire frame buffer at once, use the IOSVGADisplay class instead.

IOFrameBufferDisplay currently supports the following bit depths: 

·	2-bit grayscale
·	8-bit grayscale
·	8-bit color
·	16-bit RGB (5-5-5 or 4-4-4Ðboth with 4096 colors)
·	24-bit RGB (8-8-8)

Most of the work in writing a IOFrameBufferDisplay driver is determining how to put the hardware into an advanced mode in which the frame buffer is linearly addressable. Some drivers support several advanced modes, which the user chooses between using the Configure application. The IODisplayInfo specification describes how to specify the modes your driver supports.

When specifying your driver's memory ranges in its default configuration table, you must first specify the addresses of the linear frame buffer, and then the addresses 0xa0000-0xbffff and 0xc0000-0xcffff. 

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

See the IODisplayInfo specification for information on display-specific configuration keys.

Implementing a Subclass

In your subclass of IOFrameBufferDisplay, you must implement the following methods:

·	initFromDeviceDescription:
·	enterLinearMode
·	revertToVGAMode

You might also need to implement two more methods:

·	If the hardware supports setting brightness, you must implement setBrightness:. 

·	To support multiple gamma correction tables, implement setTransferTable:count:.

Instance Variables

None declared in this class.

Method Types

Creating and initializing IOFrameBufferDisplays	
+ probe:
- initFromDeviceDescription:

Getting and setting parameters	- getIntValues:forParameter:count:
- setCharValues:forParameter:count:
- setIntValues:forParameter:count:

Handling the cursor	- hideCursor:
- moveCursor:frame:token:
- showCursor:frame:token:

Setting screen brightness	- setBrightness:token:

Setting the gamma correction table	
- setTransferTable:count:

Mapping the frame buffer	- mapFrameBufferAtPhysicalAddress:length:

Choosing display modes	- enterLinearMode
- revertToVGAMode
- selectMode:count:
- selectMode:count:valid:

Class Methods

probe:

+ (BOOL)probe:deviceDescription 

Without checking for the presence of hardware, allocates and initializes an IOFrameBufferDisplay. You shouldn't reimplement this method.

If the initialization (done with initFromDeviceDescription:) is unsuccessful, this method returns NO. Otherwise, this method sets the device kind to ªLinear Framebufferº, invokes registerDevice, and returns YES.

See also:  - initFromDeviceDescription:

Instance Methods

enterLinearMode

- (void)enterLinearMode

Implemented by subclasses to put the display into linear frame buffer mode. This method is invoked by the system when appropriate, such as when the window server starts running.

See also:  - revertToVGAMode

getIntValues:forParameter:count:

- (IOReturn)getIntValues:(unsigned int *)parameterArray 
forParameter:(IOParameterName)parameterName 
count:(unsigned int *)count 

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

See also:  - getIntValues:forParameter:count: (IODevice)

hideCursor:

- hideCursor:(int)token 

Implements this method, as described in the IOScreenEvents protocol specification. You should never need to invoke or implement this method.

initFromDeviceDescription:

- initFromDeviceDescription:deviceDescription 

Invokes initFromDeviceDescription: on super. If successful, sets the unit number and the name (to ªDisplayº followed by the unit number). Frees itself if initialization was unsuccessful.

Subclasses must implement this method so that it performs all initialization necessary to set up the device and the driver. This includes setting the IODisplayInfo structure (as described in the IODisplay class description) and invoking mapFrameBufferAtPhysicalAddress:length:. If possible, this method should also check the hardware to see if it matches the IOConfigTable. If the hardware doesn't match, the driver should do what it can to ensure that the display is still usable.

See also:  + probe:

mapFrameBufferAtPhysicalAddress:length:

- (vm_address_t)mapFrameBufferAtPhysicalAddress:(unsigned int)address length:(int)numBytes 

Maps the physical memory for this instance into virtual memory for use by the device driver. If address is 0, this method maps the physical memory corresponding to local memory range 0, and numBytes is ignored. If address is not 0, the reserved resources are overriddenÐaddress is used as the physical memory address and numBytes is used as the length. The mapped memory range is cached as specified in the IODisplayInfo for this instance. 

Note:  When overriding reserved resources, you can't map memory outside of the memory range reserved for the device. However, you can map a subset of the memory range.

You should invoke this method during initialization.

Returns the virtual address that corresponds to address. If the memory mapping failed, this method logs an error message and returns NULL.

See also:   - initFromDeviceDescription:

moveCursor:frame:token:

- moveCursor:(Point *)cursorLoc 
frame:(int)frame 
token:(int)token 

Implements this method, as described in the IOScreenEvents protocol specification. You should never need to invoke or implement this method. 

revertToVGAMode

- (void)revertToVGAMode

Implemented by subclasses to remove the display from whatever advanced mode it's in and enter a mode in which it can be used as a standard VGA device. 

See also:  - enterLinearMode

selectMode:count:

- (int)selectMode:(const IODisplayInfo *)modeList count:(int)count 

Invokes selectMode:count:valid:, specifying 0 for the last argument.

selectMode:count:valid:

- (int)selectMode:(const IODisplayInfo *)modeList 
count:(int)count 
valid:(const BOOL *)isValid 

Determines which IODisplayInfo in the driver-supplied modeList matches the value of the ªDisplay Modeº key in the device's IOConfigTable. Drivers that support multiple advanced modes should invoke this method during initialization. When the driver receives a enterLinearMode message, it should enter the mode selected by this method. If this method doesn't find a valid mode, the driver should determine a mode that will work.

The ªDisplay Modeº key is a configuration key that can be used by drivers to support multiple modesÐfor example, both 8-bit gray and 16-bit RGB. IODisplayInfo is defined in the header file driverkit/displayDefs.h.

The modeList argument should contain a IODisplayInfo for each advanced mode the driver supports. The count argument should specify the number of IODisplayInfos in modeList. isValid should either be 0 (in which case it's ignored) or an array that corresponds to the modeList. If isValid[1] is NO, for example, then this method ignores the IODisplayInfo pointed to by modeList[1].

If this method finds a match, it returns the index of the matching IODisplayInfo in modeList. If the ªDisplay Modeº key is missing or its value is improperly formatted, or if a corresponding IODisplayInfo isn't found, this method returns -1.

See the IODisplay class description for information on display modes and the IODisplayInfo type.

setBrightness:token:

- setBrightness:(int)level token:(int)token 

Checks whether level is between EV_SCREEN_MIN_BRIGHTNESS and EV_SCREEN_MAX_BRIGHTNESS (inclusive). If not, this method logs an error message. Subclasses that support brightness changes should override this method and implement it as described in the IOScreenEvents protocol specification.

Returns self. 

setCharValues:forParameter:count:

- (IOReturn)setCharValues:(unsigned char *)parameterArray 
forParameter:(IOParameterName)parameterName 
count:(unsigned int)count 

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

See also:  - setCharValues:forParameter:count: (IODevice)

setIntValues:forParameter:count:

- (IOReturn)setIntValues:(unsigned int *)parameterArray 
forParameter:(IOParameterName)parameterName 
count:(unsigned int)count 

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

See also:  - setIntValues:forParameter:count: (IODevice)

setTransferTable:count:

- setTransferTable:(const unsigned int *)table count:(int)numEntries 

Specifies new gamma correction values to be used by the hardware. The default implement does nothing but return self. Subclasses that support multiple gamma correction transforms must override this method so that it sets the hardware to reflect the values in table.

Gamma correction is necessary because displays respond nonlinearly to linear ranges of voltage. For example, consider a pixel that can have red, green, and blue values between 0 and 15. This pixel's brightness when the values are (7, 0, 0) might be more than 7/15 its brightness when the values are (15, 0, 0). Gamma correction lets the hardware adjust the voltage of the beamÐfor example, using 6.5/15 of maximum voltage instead of 7/15, so that the pixel isn't too bright.

Each entry in table specifies the gamma correction (a value scaled to be between 0 and 255, inclusive) for the corresponding pixel component values. For example, for RGB color modes, table[7] specifies the gamma corrections for a red value of 7, a green value of 7, and a blue value of 7 (using one byte of the entry per component). If a pixel's value is (0, 5, 15), for example, the hardware should use the red gamma correction from table[0], the green gamma correction from table[5], and the blue gamma correction from table[15]. Which bytes you use from each table entry depends on whether the transfer table is for a color or black-and-white mode; you can determine the mode from the value of numEntries. 

When numEntries is IO_2BPP_TRANSFER_TABLE_SIZE or IO_8BPP_TRANSFER_TABLE_SIZE (as defined in the header file driverkit/displayDefs.h), the table is for a black-and-white display. In this case, each table entry has only one meaningful byte: the least significant byte.

When numEntries is IO_12BPP_TRANSFER_TABLE_SIZE, IO_15BPP_TRANSFER_TABLE_SIZE, or IO_24BPP_TRANSFER_TABLE_SIZE, the table is for an RGB display, and each entry has three meaningful bytes. The most significant byte holds the red gamma correction, the next most significant byte holds the green gamma correction, and the next holds the blue gamma correction. The least significant byte holds no information. 

The following example shows how to copy the correction information from the transfer table to a particular type of hardware. 

/* This driver implements setTransferTable: so that it copies the 
 * table values into a table that contains first all the red values,
 * then all the green values, and then all the blue values.  It
 * defines 3 instance variables -- redTransferTable, 
 * greenTransferTable, and blueTransferTable -- to point to where 
 * each component's values begin in the copied table. Finally,
 * it puts the values in the hardware gamma correction table. */
- setTransferTable:(unsigned int *)table count:(int)numEntries
{
    int k;

    /* redTransferTable, greenTransferTable, and blueTransferTable
     * are driver-defined instance variables
    if (redTransferTable != 0)
        IOFree(redTransferTable, 3 * transferTableCount);

    transferTableCount = numEntries;

    redTransferTable = IOMalloc(3 * numEntries);
    greenTransferTable = redTransferTable + numEntries;
    blueTransferTable = greenTransferTable + numEntries;

    switch ([self displayInfo]->bitsPerPixel) {
    case IO_2BitsPerPixel:
    case IO_8BitsPerPixel:
        for (k = 0; k < numEntries; k++) {
            redTransferTable[k] = greenTransferTable[k] =
            blueTransferTable[k] = table[k] & 0xFF;
        }
        break;

    case IO_12BitsPerPixel:
    case IO_15BitsPerPixel:
    case IO_24BitsPerPixel:
        for (k = 0; k < numEntries; k++) {
            redTransferTable[k] = (table[k] >> 24) & 0xFF;
            greenTransferTable[k] = (table[k] >> 16) & 0xFF;
            blueTransferTable[k] = (table[k] >> 8) & 0xFF;
        }
        break;

    default:
        IOFree(redTransferTable, 3 * numEntries);
        redTransferTable = 0;
        break;
    }
    [self setGammaTable]; /* subclass method */
    return self;
}

/* subclass function */
static void
SetGammaValue(unsigned int r, unsigned int g, unsigned int b, 
              int level)
{
    /* EV_SCALE_BRIGHTNESS is a macro defined in bsd/dev/ev_types.h 
     * that scales a pixel value to the specified brightness level. */
    outb(PALETTE_DATA, EV_SCALE_BRIGHTNESS(level, r));
    outb(PALETTE_DATA, EV_SCALE_BRIGHTNESS(level, g));
    outb(PALETTE_DATA, EV_SCALE_BRIGHTNESS(level, b));
}

/* subclass method */
- setGammaTable
{
    unsigned int i, j, g;
    const IODisplayInfo *displayInfo;

    displayInfo = [self displayInfo];

    outb(PALETTE_WRITE, 0x00);

    /* brightnessLevel is a subclass ivar initialized to 
     * EV_SCREEN_MAX_BRIGHTNESS; setBrightness: changes it */
    if (redTransferTable != 0) {
        for (i = 0; i < transferTableCount; i++) {
            for (j = 0; j < 256/transferTableCount; j++) {
                SetGammaValue(redTransferTable[i],              
                              greenTransferTable[i],
                              blueTransferTable[i], brightnessLevel);
            }
        }
    } 
    return self;
}

Gamma correction transforms are set using the setframebuffertransfer PostScript operator. The Window Server uses the functions specified in setframebuffertransfer to fill the values used in table. It then passes the values down the display system so that eventually the setTransferTable:count: message is invoked. 

Note:  The default transfer table cannot be specified using NetInfo, despite the claims of the setframebuffertransfer documentation.

See also:  setframebuffertransfer PostScript Operator (NEXTSTEP General Reference)

showCursor:frame:token:

- showCursor:(Point *)cursorLoc 
frame:(int)frame 
token:(int)token 

Implements this method, as described in the IOScreenEvents protocol specification. You should never need to invoke or implement this method.