diff options
Diffstat (limited to 'hw/xfree86/doc/sgml/DESIGN.sgml')
-rw-r--r-- | hw/xfree86/doc/sgml/DESIGN.sgml | 7415 |
1 files changed, 7415 insertions, 0 deletions
diff --git a/hw/xfree86/doc/sgml/DESIGN.sgml b/hw/xfree86/doc/sgml/DESIGN.sgml new file mode 100644 index 000000000..322ab00e0 --- /dev/null +++ b/hw/xfree86/doc/sgml/DESIGN.sgml @@ -0,0 +1,7415 @@ +<!DOCTYPE linuxdoc PUBLIC "-//XFree86//DTD linuxdoc//EN" [ + <!-- config file keyword markup --> + <!ENTITY s.key STARTTAG "bf"> + <!ENTITY e.key ENDTAG "bf"> + <!-- specific config file keywords --> + <!ENTITY k.device "&s.key;Device&e.key;"> + <!ENTITY k.monitor "&s.key;Monitor&e.key;"> + <!ENTITY k.display "&s.key;Display&e.key;"> + <!ENTITY k.inputdevice "&s.key;InputDevice&e.key;"> + <!ENTITY k.screen "&s.key;Screen&e.key;"> + <!ENTITY k.serverlayout "&s.key;ServerLayout&e.key;"> + <!ENTITY k.driver "&s.key;Driver&e.key;"> + <!ENTITY k.module "&s.key;Module&e.key;"> + <!ENTITY k.identifier "&s.key;Identifier&e.key;"> + <!ENTITY k.serverflags "&s.key;ServerFlags&e.key;"> + <!-- command line markup --> + <!ENTITY s.cmd STARTTAG "tt"> + <!ENTITY e.cmd ENDTAG "tt"> + <!-- inline code markup --> + <!ENTITY s.code STARTTAG "tt"> + <!ENTITY e.code ENDTAG "tt"> + <!-- function indent --> + <!ENTITY f.indent "&nl          "> +] > + +<article> + +<title>XFree86 X server ``New Design'' (DRAFT) +<author>The XFree86 Project, Inc +<date>Last modified 2003 January 22 + + + + + + + +<ident> +$XFree86: xc/programs/Xserver/hw/xfree86/doc/sgml/DESIGN.sgml,v 1.52 2003/02/25 19:31:00 dawes Exp $ +</ident> + + +<p> +<bf>NOTE</bf>: This is a DRAFT document, and the interfaces described here +are subject to change without notice. + + +<sect>Preface +<p> + +The broad design principles are: +<itemize> + <item>keep it reasonable + <itemize> + <item>We cannot rewrite the complete server + <item>We don't want to re-invent the wheel + </itemize> + <item>keep it modular + <itemize> + <item>As many things as possible should go into modules + <item>The basic loader binary should be minimal + <item>A clean design with well defined layering is important + <item>DDX specific global variables are a nono + <item>The structure should be flexible enough to allow + future extensions + <item> The structure should minimize duplication of common code + </itemize> + <item>keep important features in mind + <itemize> + <item>multiple screens, including multiple instances of drivers + <item>mixing different color depths and visuals on different + and ideally even on the same screen + <item>better control of the PCI device used + <item>better config file parser + <item>get rid of all VGA compatibility assumptions + </itemize> +</itemize> + +Unless we find major deficiencies in the DIX layer, we should avoid +making changes there. + +<sect>The XF86Config File +<p> + +The XF86Config file format is similar to the old format, with the following +changes: + +<sect1>&k.device; section +<p> + + The &k.device; sections are similar to what they used to be, and + describe hardware-specific information for a single video card. + &k.device; + Some new keywords are added: + + + <descrip> + <tag>Driver "drivername"</tag> + Specifies the name of the driver to be used for the card. This + is mandatory. + <tag>BusID "busslot"</tag> + Specifies uniquely the location of the card on the bus. The + purpose is to identify particular cards in a multi-headed + configuration. The format of the argument is intentionally + vague, and may be architecture dependent. For a PCI bus, it + is something like "bus:slot:func". + </descrip> + + A &k.device; section is considered ``active'' if there is a reference + to it in an active &k.screen; section. + +<sect1>&k.screen; section +<p> + + The &k.screen; sections are similar to what they used to be. They + no longer have a &k.driver; keyword, but an &k.identifier; keyword + is added. (The &k.driver; keyword may be accepted in place of the + &k.identifier; keyword for compatibility purposes.) The identifier + can be used to identify which screen is to be active when multiple + &k.screen sections are present. It is possible to specify the active + screen from the command line. A default is chosen in the absence + of one being specified. A &k.screen; section is considered ``active'' + if there is a reference to it either from the command line, or from + an active &k.serverlayout; section. + +<sect1>&k.inputdevice; section +<p> + + The &k.inputdevice; section is a new section that describes + configuration information for input devices. It replaces the old + &s.key;Keyboard&e.key;, &s.key;Pointer&e.key; and &s.key;XInput&e.key; + sections. Like the &k.device; section, it has two mandatory keywords: + &k.identifier; and &k.driver;. For compatibility purposes the old + &s.key;Keyboard&e.key; and &s.key;Pointer&e.key; sections are + converted by the parser into &k.inputdevice; sections as follows: + + <descrip> + <tag>&s.key;Keyboard&e.key;</tag> + &k.identifier; "Implicit Core Keyboard"<newline> + &k.driver; "keyboard" + <tag>&s.key;Pointer&e.key;</tag> + &k.identifier; "Implicit Core Pointer"<newline> + &k.driver; "mouse" + </descrip> + + An &k.inputdevice; section is considered active if there is a + reference to it in an active &k.serverlayout; section. An + &k.inputdevice; section may also be referenced implicitly if there + is no &k.serverlayout; section, if the &s.cmd;-screen&e.cmd; command + line options is used, or if the &k.serverlayout; section doesn't + reference any &k.inputdevice; sections. In this case, the first + sections with drivers "keyboard" and "mouse" are used as the core + keyboard and pointer respectively. + +<sect1>&k.serverlayout; section +<p> + + The &k.serverlayout; section is a new section that is used to identify + which &k.screen; sections are to be used in a multi-headed configuration, + and the relative layout of those screens. It also identifies which + &k.inputdevice; sections are to be used. Each &k.serverlayout section + has an identifier, a list of &k.screen; section identifiers, and a list of + &k.inputdevice; section identifiers. &k.serverflags; options may also be + included in a &k.serverlayout; section, making it possible to override + the global values in the &k.serverflags; section. + + A &k.serverlayout; section can be made active by being referenced on + the command line. In the absence of this, a default will be chosen + (the first one found). The screen names may optionally be followed + by a number specifying the preferred screen number, and optionally + by information specifying the physical positioning of the screen, + either in absolute terms or relative to another screen (or screens). + When no screen number is specified, they are numbered according to + the order in which they are listed. The old (now obsolete) method + of providing the positioning information is to give the names of + the four adjacent screens. The order of these is top, bottom, left, + right. Here is an example of a &k.serverlayout; section for two + screens using the old method, with the second located to the right + of the first: + + <code> + Section "ServerLayout" + Identifier "Main Layout" + Screen 0 "Screen 1" "" "" "" "Screen 2" + Screen 1 "Screen 2" + Screen "Screen 3" + EndSection + </code> + + The preferred way of specifying the layout is to explicitly specify + the screen's location in absolute terms or relative to another + screen. + + In the absolute case, the upper left corner's coordinates are given + after the &s.key;Absolute&e.key; keyword. If the coordinates are + omitted, a value of &s.code;(0,0)&e.code; is assumed. An example + of absolute positioning follows: + + <code> + Section "ServerLayout" + Identifier "Main Layout" + Screen 0 "Screen 1" Absolute 0 0 + Screen 1 "Screen 2" Absolute 1024 0 + Screen "Screen 3" Absolute 2048 0 + EndSection + </code> + + In the relative case, the position is specified by either using one of + the following keywords followed by the name of the reference screen: + + <quote> + &s.key;RightOf&nl; + LeftOf&nl; + Above&nl; + Below&nl; + Relative&e.key; + </quote> + + When the &s.key;Relative&e.key; keyword is used, the reference screen + name is followed by the coordinates of the new screen's origin + relative to reference screen. The following example shows how to use + some of the relative positioning options. + + <code> + Section "ServerLayout" + Identifier "Main Layout" + Screen 0 "Screen 1" + Screen 1 "Screen 2" RightOf "Screen 1" + Screen "Screen 3" Relative "Screen 1" 2048 0 + EndSection + </code> + +<sect1>Options +<p> + + Options are used more extensively. They may appear in most sections + now. Options related to drivers can be present in the &k.screen;, + &k.device; and &k.monitor; sections and the &k.display; subsections. + The order of precedence is &k.display;, &k.screen;, &k.monitor;, + &k.device;. Options have been extended to allow an optional value + to be specified in addition to the option name. For more details + about options, see the <ref id="options" name="Options"> section + for details. + +<sect>Driver Interface +<p> + +The driver interface consists of a minimal set of entry points that are +required based on the external events that the driver must react to. +No non-essential structure is imposed on the way they are used beyond +that. This is a significant difference compared with the old design. + +The entry points for drawing operations are already taken care of by +the framebuffer code (including, XAA). Extensions and enhancements to +framebuffer code are outside the scope of this document. + +This approach to the driver interface provides good flexibility, but does +increase the complexity of drivers. To help address this, the XFree86 +common layer provides a set of ``helper'' functions to take care of things +that most drivers need. These helpers help minimise the amount of code +duplication between drivers. The use of helper functions by drivers is +however optional, though encouraged. The basic philosophy behind the +helper functions is that they should be useful to many drivers, that +they should balance this against the complexity of their interface. It +is inevitable that some drivers may find some helpers unsuitable and +need to provide their own code. + +Events that a driver needs to react to are: + + <descrip> + <tag>ScreenInit</tag> + + An initialisation function is called from the DIX layer for each + screen at the start of each server generation. + + <tag>Enter VT</tag> + + The server takes control of the console. + + <tag>Leave VT</tag> + + The server releases control of the console. + + <tag>Mode Switch</tag> + + Change video mode. + + <tag>ViewPort change</tag> + + Change the origin of the physical view port. + + <tag>ScreenSaver state change</tag> + + Screen saver activation/deactivation. + + <tag>CloseScreen</tag> + + A close screen function is called from the DIX layer for each screen + at the end of each server generation. + </descrip> + + +In addition to these events, the following functions are required by +the XFree86 common layer: + + <descrip> + <tag>Identify</tag> + + Print a driver identifying message. + + <tag>Probe</tag> + + This is how a driver identifies if there is any hardware present that + it knows how to drive. + + <tag>PreInit</tag> + + Process information from the XF86Config file, determine the + full characteristics of the hardware, and determine if a valid + configuration is present. + </descrip> + +The VidMode extension also requires: + + <descrip> + <tag>ValidMode</tag> + + Identify if a new mode is usable with the current configuration. + The PreInit function (and/or helpers it calls) may also make use + of the ValidMode function or something similar. + </descrip> + + +Other extensions may require other entry points. The drivers will +inform the common layer of these in such cases. + +<sect>Resource Access Control Introduction +<p> + +Graphics devices are accessed through ranges in I/O or memory space. +While most modern graphics devices allow relocation of such ranges many +of them still require the use of well established interfaces such as +VGA memory and IO ranges or 8514/A IO ranges. With modern buses (like +PCI) it is possible for multiple video devices to share access to these +resources. The RAC (Resource Access Control) subsystem provides a +mechanism for this. + +<sect1>Terms and Definitions +<p> + +<sect2>Bus +<p> + + ``Bus'' is ambiguous as it is used for different things: it may refer + to physical incompatible extension connectors in a computer system. + The RAC system knows two such systems: The ISA bus and the PCI bus. + (On the software level EISA, MCA and VL buses are currently treated + like ISA buses). ``Bus'' may also refer to logically different + entities on a single bus system which are connected via bridges. A + PCI system may have several distinct PCI buses connecting each other + by PCI-PCI bridges or to the host CPU by HOST-PCI bridges. + + Systems that host more than one bus system link these together using + bridges. Bridges are a concern to RAC as they might block or pass + specific resources. PCI-PCI bridges may be set up to pass VGA + resources to the secondary bus. PCI-ISA buses pass any resources not + decoded on the primary PCI bus to the ISA bus. This way VGA resources + (although exclusive on the ISA bus) can be shared by ISA and PCI + cards. Currently HOST-PCI bridges are not yet handled by RAC as they + require specific drivers. + +<sect2>Entity +<p> + + The smallest independently addressable unit on a system bus is + referred to as an entity. So far we know ISA and PCI entities. PCI + entities can be located on the PCI bus by an unique ID consisting of + the bus, card and function number. + +<sect2>Resource +<p> + + ``Resource'' refers to a range of memory or I/O addresses an entity + can decode. + + If a device is capable of disabling this decoding the resource is + called sharable. For PCI devices a generic method is provided to + control resource decoding. Other devices will have to provide a + device specific function to control decoding. + + If the entity is capable of decoding this range at a different + location this resource is considered relocatable. + + Resources which start at a specific address and occupy a single + continuous range are called block resources. + + Alternatively resource addresses can be decoded in a way that they + satisfy the conditions: + <quote><verb> + address & mask == base + </verb></quote> + and + <quote><verb> + base & mask == base + </verb></quote> + Resources addressed in such a way are called sparse resources. + +<sect2>Server States +<p> + + The resource access control system knows two server states: the + SETUP and the OPERATING state. The SETUP state is entered whenever + a mode change takes place or the server exits or does VT switching. + During this state all entity resources are under resource access + control. During OPERATING state only those entities are controlled + which actually have shared resources that conflict with others. + +<sect>Control Flow in the Server and Mandatory Driver Functions +<p> + +At the start of each server generation, &s.code;main()&e.code; +(&s.code;dix/main.c&e.code;) calls the DDX function +&s.code;InitOutput()&e.code;. This is the first place that the DDX gets +control. &s.code;InitOutput()&e.code; is expected to fill in the global +&s.code;screenInfo&e.code; struct, and one +&s.code;screenInfo.screen[]&e.code; entry for each screen present. Here +is what &s.code;InitOutput()&e.code; does: + +<sect1>Parse the XF86Config file +<p> + + This is done at the start of the first server generation only. + + The XF86Config file is read in full, and the resulting information + stored in data structures. None of the parsed information is + processed at this point. The parser data structures are opaque to + the video drivers and to most of the common layer code. + + The entire file is parsed first to remove any section ordering + requirements. + + +<sect1>Initial processing of parsed information and command line options +<p> + + This is done at the start of the first server generation only. + + The initial processing is to determine paths like the + &s.key;ModulePath&e.key;, etc, and to determine which &k.serverlayout;, + &k.screen; and &k.device; sections are active. + + +<sect1>Enable port I/O access +<p> + + Port I/O access is controlled from the XFree86 common layer, and is + ``all or nothing''. It is enabled prior to calling driver probes, at + the start of subsequent server generations, and when VT switching + back to the Xserver. It is disabled at the end of server generations, + and when VT switching away from the Xserver. + + The implementation details of this may vary on different platforms. + + +<sect1>General bus probe +<p> + + This is done at the start of the first server generation only. + + In the case of ix86 machines, this will be a general PCI probe. + The full information obtained here will be available to the drivers. + This information persists for the life of the Xserver. In the PCI + case, the PCI information for all video cards found is available by + calling &s.code;xf86GetPciVideoInfo()&e.code;. + + <quote> + &s.code;pciVideoPtr *xf86GetPciVideoInfo(void)&e.code; + <quote><p> + returns a pointer to a list of pointers to + &s.code;pciVideoRec&e.code; entries, of which there is one for + each detected PCI video card. The list is terminated with a + &s.code;NULL&e.code; pointer. If no PCI video cards were + detected, the return value is &s.code;NULL&e.code;. + + </quote> + </quote> + + After the bus probe, the resource broker is initialised. + + +<sect1>Load initial set of modules +<p> + + This is done at the start of the first server generation only. + + The core server contains a list of mandatory modules. These are loaded + first. Currently the only module on this list is the bitmap font module. + + The next set of modules loaded are those specified explicitly in the + &k.module; section of the config file. + + The final set of initial modules are the driver modules referenced + by the active &k.device; and &k.inputdevice; sections in the config + file. Each of these modules is loaded exactly once. + + +<sect1>Register Video and Input Drivers +<p> + + This is done at the start of the first server generation only. + + When a driver module is loaded, the loader calls its + &s.code;Setup&e.code; function. For video drivers, this function + calls &s.code;xf86AddDriver()&e.code; to register the driver's + &s.code;DriverRec&e.code;, which contains a small set of essential + details and driver entry points required during the early phase of + &s.code;InitOutput()&e.code;. &s.code;xf86AddDriver()&e.code; adds + it to the global &s.code;xf86DriverList[]&e.code; array. + + The &s.code;DriverRec&e.code; contains the driver canonical name, + the &s.code;Identify()&e.code;, + &s.code;Probe()&e.code; and &s.code;AvailableOptions()&e.code; + function entry points as well as a pointer + to the driver's module (as returned from the loader when the driver + was loaded) and a reference count which keeps track of how many + screens are using the driver. The entry driver entry points are + those required prior to the driver allocating and filling in its + &s.code;ScrnInfoRec&e.code;. + + For a static server, the &s.code;xf86DriverList[]&e.code; array is + initialised at build time, and the loading of modules is not done. + + A similar procedure is used for input drivers. The input driver's + &s.code;Setup&e.code; function calls + &s.code;xf86AddInputDriver()&e.code; to register the driver's + &s.code;InputDriverRec&e.code;, which contains a small set of + essential details and driver entry points required during the early + phase of &s.code;InitInput()&e.code;. + &s.code;xf86AddInputDriver()&e.code; adds it to the global + &s.code;xf86InputDriverList[]&e.code; array. For a static server, + the &s.code;xf86InputDriverList[]&e.code; array is initialised at + build time. + + Both the &s.code;xf86DriverList[]&e.code; and + &s.code;xf86InputDriverList[]&e.code; arrays have been initialised + by the end of this stage. + + Once all the drivers are registered, their + &s.code;ChipIdentify()&e.code; functions are called. + + <quote> + &s.code;void ChipIdentify(int flags)&e.code; + <quote> + This is expected to print a message indicating the driver name, + a short summary of what it supports, and a list of the chipset + names that it supports. It may use the xf86PrintChipsets() helper + to do this. + </quote> + </quote> + + <quote> + &s.code;void xf86PrintChipsets(const char *drvname, const char *drvmsg, + &f.indent;SymTabPtr chips)&e.code; + <quote> + This function provides an easy way for a driver's ChipIdentify + function to format the identification message. + </quote> + </quote> + +<sect1>Initialise Access Control +<p> + + This is done at the start of the first server generation only. + + The Resource Access Control (RAC) subsystem is initialised before + calling any driver functions that may access hardware. All generic + bus information is probed and saved (for restoration later). All + (shared resource) video devices are disabled at the generic bus + level, and a probe is done to find the ``primary'' video device. These + devices remain disabled for the next step. + + +<sect1>Video Driver Probe<label id="probe"> +<p> + This is done at the start of the first server generation only. The + &s.code;ChipProbe()&e.code; function of each registered video driver + is called. + + <quote><p> + &s.code;Bool ChipProbe(DriverPtr drv, int flags)&e.code; + <quote><p> + The purpose of this is to identify all instances of hardware + supported by the driver. The flags value is currently either 0, + &s.code;PROBE_DEFAULT&e.code; or &s.code;PROBE_DETECT&e.code;. + &s.code;PROBE_DETECT&e.code; is used if "-configure" or "-probe" + command line arguments are given and indicates to the + &s.code;Probe()&e.code; function that it should not configure the + bus entities and that no XF86Config information is available. + + The probe must find the active device sections that match the + driver by calling &s.code;xf86MatchDevice()&e.code;. The number + of matches found limits the maximum number of instances for this + driver. If no matches are found, the function should return + &s.code;FALSE&e.code; immediately. + + Devices that cannot be identified by using device-independent + methods should be probed at this stage (keeping in mind that access + to all resources that can be disabled in a device-independent way + are disabled during this phase). The probe must be a minimal + probe. It should just determine if there is a card present that + the driver can drive. It should use the least intrusive probe + methods possible. It must not do anything that is not essential, + like probing for other details such as the amount of memory + installed, etc. It is recommended that the + &s.code;xf86MatchPciInstances()&e.code; helper function be used + for identifying matching PCI devices, and similarly the + &s.code;xf86MatchIsaInstances()&e.code; for ISA (non-PCI) devices + (see the <ref id="rac" name="RAC"> section). These helpers also + checks and claims the appropriate entity. When not using the + helper, that should be done with &s.code;xf86CheckPciSlot()&e.code; + and &s.code;xf86ClaimPciSlot()&e.code; for PCI devices and + &s.code;xf86ClaimIsaSlot()&e.code; for ISA devices (see the + <ref id="rac" name="RAC"> section). + + The probe must register all non-relocatable resources at this + stage. If a resource conflict is found between exclusive resources + the driver will fail immediately. This is usually best done with + the &s.code;xf86ConfigPciEntity()&e.code; helper function + for PCI and &s.code;xf86ConfigIsaEntity()&e.code; for ISA + (see the <ref id="rac" name="RAC"> section). It is possible to + register some entity specific functions with those helpers. When + not using the helpers, the &s.code;xf86AddEntityToScreen()&e.code; + &s.code;xf86ClaimFixedResources()&e.code; and + &s.code;xf86SetEntityFuncs()&e.code; should be used instead (see + the <ref id="rac" name="RAC"> section). + + If a chipset is specified in an active device section which the + driver considers relevant (ie it has no driver specified, or the + driver specified matches the driver doing the probe), the Probe + must return &s.code;FALSE&e.code; if the chipset doesn't match + one supported by the driver. + + If there are no active device sections that the driver considers + relevant, it must return &s.code;FALSE&e.code;. + + Allocate a &s.code;ScrnInfoRec&e.code; for each active instance of the + hardware found, and fill in the basic information, including the + other driver entry points. This is best done with the + &s.code;xf86ConfigIsaEntity()&e.code; helper function for ISA + instances or &s.code;xf86ConfigPciEntity()&e.code; for PCI instances. + These functions allocate a &s.code;ScrnInfoRec&e.code; for active + entities. Optionally &s.code;xf86AllocateScreen()&e.code; + function may also be used to allocate the &s.code;ScrnInfoRec&e.code;. + Any of these functions take care of initialising fields to defined + ``unused'' values. + + Claim the entities for each instance of the hardware found. This + prevents other drivers from claiming the same hardware. + + Must leave hardware in the same state it found it in, and must not + do any hardware initialisation. + + All detection can be overridden via the config file, and that + parsed information is available to the driver at this stage. + + Returns &s.code;TRUE&e.code; if one or more instances are found, + and &s.code;FALSE&e.code; otherwise. + + </quote> + + &s.code;int xf86MatchDevice(const char *drivername, + &f.indent;GDevPtr **driversectlist)&e.code; + <quote><p> + + This function takes the name of the driver and returns via + &s.code;driversectlist&e.code; a list of device sections that + match the driver name. The function return value is the number + of matches found. If a fatal error is encountered the return + value is &s.code;-1&e.code;. + + The caller should use &s.code;xfree()&e.code; to free + &s.code;*driversectlist&e.code; when it is no longer needed. + + </quote> + + &s.code;ScrnInfoPtr xf86AllocateScreen(DriverPtr drv, int flags)&e.code; + <quote><p> + This function allocates a new &s.code;ScrnInfoRec&e.code; in the + &s.code;xf86Screens[]&e.code; array. This function is normally + called by the video driver &s.code;ChipProbe()&e.code; functions. + The return value is a pointer to the newly allocated + &s.code;ScrnInfoRec&e.code;. The &s.code;scrnIndex&e.code;, + &s.code;origIndex&e.code;, &s.code;module&e.code; and + &s.code;drv&e.code; fields are initialised. The reference count + in &s.code;drv&e.code; is incremented. The storage for any + currently allocated ``privates'' pointers is also allocated and + the &s.code;privates&e.code; field initialised (the privates data + is of course not allocated or initialised). This function never + returns on failure. If the allocation fails, the server exits + with a fatal error. The flags value is not currently used, and + should be set to zero. + </quote> + </quote> + + At the completion of this, a list of &s.code;ScrnInfoRecs&e.code; + have been allocated in the &s.code;xf86Screens[]&e.code; array, and + the associated entities and fixed resources have been claimed. The + following &s.code;ScrnInfoRec&e.code; fields must be initialised at + this point: + + <quote><verb> + driverVersion + driverName + scrnIndex(*) + origIndex(*) + drv(*) + module(*) + name + Probe + PreInit + ScreenInit + EnterVT + LeaveVT + numEntities + entityList + access + </verb></quote> + + <tt>(*)</tt> These are initialised when the &s.code;ScrnInfoRec&e.code; + is allocated, and not explicitly by the driver. + + The following &s.code;ScrnInfoRec&e.code; fields must be initialised + if the driver is going to use them: + + <quote><verb> + SwitchMode + AdjustFrame + FreeScreen + ValidMode + </verb></quote> + +<sect1>Matching Screens +<p> + + This is done at the start of the first server generation only. + + After the Probe phase is finished, there will be some number of + &s.code;ScrnInfoRecs&e.code;. These are then matched with the active + &k.screen; sections in the XF86Config, and those not having an active + &k.screen; section are deleted. If the number of remaining screens + is 0, &s.code;InitOutput()&e.code; sets + &s.code;screenInfo.numScreens&e.code; to &s.code;0&e.code; and + returns. + + At this point the following fields of the &s.code;ScrnInfoRecs&e.code; + must be initialised: + + <quote><verb> + confScreen + </verb></quote> + + +<sect1>Allocate non-conflicting resources +<p> + + This is done at the start of the first server generation only. + + Before calling the drivers again, the resource information collected + from the Probe phase is processed. This includes checking the extent + of PCI resources for the probed devices, and resolving any conflicts + in the relocatable PCI resources. It also reports conflicts, checks + bus routing issues, and anything else that is needed to enable the + entities for the next phase. + + If any drivers registered an &s.code;EntityInit()&e.code; function + during the Probe phase, then they are called here. + + +<sect1>Sort the Screens and pre-check Monitor Information +<p> + + This is done at the start of the first server generation only. + + The list of screens is sorted to match the ordering requested in the + config file. + + The list of modes for each active monitor is checked against the + monitor's parameters. Invalid modes are pruned. + + +<sect1>PreInit +<p> + + This is done at the start of the first server generation only. + + For each &s.code;ScrnInfoRec&e.code;, enable access to the screens entities and call + the &s.code;ChipPreInit()&e.code; function. + + <quote><p> + &s.code;Bool ChipPreInit(ScrnInfoRec screen, int flags)&e.code; + <quote><p> + The purpose of this function is to find out all the information + required to determine if the configuration is usable, and to + initialise those parts of the &s.code;ScrnInfoRec&e.code; that + can be set once at the beginning of the first server generation. + + The number of entities registered for the screen should be checked + against the expected number (most drivers expect only one). The + entity information for each of them should be retrieved (with + &s.code;xf86GetEntityInfo()&e.code;) and checked for the correct + bus type and that none of the sharable resources registered during + the Probe phase was rejected. + + Access to resources for the entities that can be controlled in a + device-independent way are enabled before this function is called. + If the driver needs to access any resources that it has disabled + in an &s.code;EntityInit()&e.code; function that it registered, + then it may enable them here providing that it disables them before + this function returns. + + This includes probing for video memory, clocks, ramdac, and all + other HW info that is needed. It includes determining the + depth/bpp/visual and related info. It includes validating and + determining the set of video modes that will be used (and anything + that is required to determine that). + + This information should be determined in the least intrusive way + possible. The state of the HW must remain unchanged by this + function. Although video memory (including MMIO) may be mapped + within this function, it must be unmapped before returning. Driver + specific information should be stored in a structure hooked into + the &s.code;ScrnInfoRec&e.code;'s &s.code;driverPrivate&e.code; + field. Any other modules which require persistent data (ie data + that persists across server generations) should be initialised in + this function, and they should allocate a ``privates'' index to + hook their data into by calling + &s.code;xf86AllocateScrnInfoPrivateIndex().&e.code; The ``privates'' + data is persistent. + + Helper functions for some of these things are provided at the + XFree86 common level, and the driver can choose to make use of + them. + + All additional resources that the screen needs must be registered + here. This should be done with + &s.code;xf86RegisterResources()&e.code;. If some of the fixed + resources registered in the Probe phase are not needed or not + decoded by the hardware when in the OPERATING server state, their + status should be updated with + &s.code;xf86SetOperatingState()&e.code;. + + Modules may be loaded at any point in this function, and all + modules that the driver will need must be loaded before the end + of this function. Either the &s.code;xf86LoadSubModule()&e.code; + or the &s.code;xf86LoadDrvSubModule()&e.code; function should be + used to load modules depending on whether a + &s.code;ScrnInfoRec&e.code; has been set up. A driver may unload + a module within this function if it was only needed temporarily, + and the &s.code;xf86UnloadSubModule()&e.code; function should be used + to do that. Otherwise there is no need to explicitly unload modules + because the loader takes care of module dependencies and will + unload submodules automatically if/when the driver module is + unloaded. + + The bulk of the &s.code;ScrnInfoRec&e.code; fields should be filled + out in this function. + + &s.code;ChipPreInit()&e.code; returns &s.code;FALSE&e.code; when + the configuration is unusable in some way (unsupported depth, no + valid modes, not enough video memory, etc), and &s.code;TRUE&e.code; + if it is usable. + + It is expected that if the &s.code;ChipPreInit()&e.code; function + returns &s.code;TRUE&e.code;, then the only reasons that subsequent + stages in the driver might fail are lack or resources (like xalloc + failures). All other possible reasons for failure should be + determined by the &s.code;ChipPreInit()&e.code; function. + + </quote> + </quote> + + The &s.code;ScrnInfoRecs&e.code; for screens where the &s.code;ChipPreInit()&e.code; fails are removed. + If none remain, &s.code;InitOutput()&e.code; sets &s.code;screenInfo.numScreens&e.code; to &s.code;0&e.code; and returns. + + At this point, further fields of the &s.code;ScrnInfoRecs&e.code; would normally be + filled in. Most are not strictly mandatory, but many are required + by other layers and/or helper functions that the driver may choose + to use. The documentation for those layers and helper functions + indicates which they require. + + The following fields of the &s.code;ScrnInfoRecs&e.code; should be filled in if the + driver is going to use them: + + <quote><verb> + monitor + display + depth + pixmapBPP + bitsPerPixel + weight (>8bpp only) + mask (>8bpp only) + offset (>8bpp only) + rgbBits (8bpp only) + gamma + defaultVisual + maxHValue + maxVValue + virtualX + virtualY + displayWidth + frameX0 + frameY0 + frameX1 + frameY1 + zoomLocked + modePool + modes + currentMode + progClock (TRUE if clock is programmable) + chipset + ramdac + clockchip + numClocks (if not programmable) + clock[] (if not programmable) + videoRam + biosBase + memBase + memClk + driverPrivate + chipID + chipRev + </verb></quote> + + <quote><p> + &s.code;pointer xf86LoadSubModule(ScrnInfoPtr pScrn, const char *name)&e.code: + and + &s.code;pointer xf86LoadDrvSubModule(DriverPtr drv, const char *name)&e.code: + <quote><p> + Load a module that a driver depends on. This function loads the + module &s.code;name&e.code; as a sub module of the driver. The + return value is a handle identifying the new module. If the load + fails, the return value will be &s.code;NULL&e.code;. If a driver + needs to explicitly unload a module it has loaded in this way, + the return value must be saved and passed to + &s.code;xf86UnloadSubModule()&e.code; when unloading. + + </quote> + + &s.code;void xf86UnloadSubModule(pointer module)&e.code; + <quote><p> + Unloads the module referenced by &s.code;module&e.code;. + &s.code;module&e.code; should be a pointer returned previously + by &s.code;xf86LoadSubModule()&e.code; or + &s.code;xf86LoadDrvSubModule()&e.code; . + + </quote> + </quote> + +<sect1>Cleaning up Unused Drivers +<p> + + At this point it is known which screens will be in use, and which + drivers are being used. Unreferenced drivers (and modules they + may have loaded) are unloaded here. + + +<sect1>Consistency Checks +<p> + + The parameters that must be global to the server, like pixmap formats, + bitmap bit order, bitmap scanline unit and image byte order are + compared for each of the screens. If a mismatch is found, the server + exits with an appropriate message. + + +<sect1>Check if Resource Control is Needed +<p> + + Determine if resource access control is needed. This is the case + if more than one screen is used. If necessary the RAC wrapper module + is loaded. + +<sect1>AddScreen (ScreenInit) +<p> + + At this point, the valid screens are known. + &s.code;AddScreen()&e.code; is called for each of them, passing + &s.code;ChipScreenInit()&e.code; as the argument. + &s.code;AddScreen()&e.code; is a DIX function that allocates a new + &s.code;screenInfo.screen[]&e.code; entry (aka + &s.code;pScreen&e.code;), and does some basic initialisation of it. + It then calls the &s.code;ChipScreenInit()&e.code; function, with + &s.code;pScreen&e.code; as one of its arguments. If + &s.code;ChipScreenInit()&e.code; returns &s.code;FALSE&e.code;, + &s.code;AddScreen()&e.code; returns &s.code;-1&e.code;. Otherwise + it returns the index of the screen. &s.code;AddScreen()&e.code; + should only fail because of programming errors or failure to allocate + resources (like memory). All configuration problems should be + detected BEFORE this point. + + <quote><p> + &s.code;Bool ChipScreenInit(int index, ScreenPtr pScreen, + &f.indent;int argc, char **argv)&e.code; + <quote><p> + This is called at the start of each server generation. + + Fill in all of &s.code;pScreen&e.code;, possibly doing some of + this by calling ScreenInit functions from other layers like mi, + framebuffers (cfb, etc), and extensions. + + Decide which operations need to be placed under resource access + control. The classes of operations are the frame buffer operations + (&s.code;RAC_FB&e.code;), the pointer operations + (&s.code;RAC_CURSOR&e.code;), the viewport change operations + (&s.code;RAC_VIEWPORT&e.code;) and the colormap operations + (&s.code;RAC_COLORMAP&e.code;). Any operation that requires + resources which might be disabled during OPERATING state should + be set to use RAC. This can be specified separately for memory + and IO resources (the &s.code;racMemFlags&e.code; and + &s.code;racIoFlags&e.code; fields of the &s.code;ScrnInfoRec&e.code; + respectively). + + Map any video memory or other memory regions. + + Save the video card state. Enough state must be saved so that + the original state can later be restored. + + Initialise the initial video mode. The &s.code;ScrnInfoRec&e.code;'s + &s.code;vtSema&e.code; field should be set to &s.code;TRUE&e.code; + just prior to changing the video hardware's state. + + </quote> + </quote> + + + The &s.code;ChipScreenInit()&e.code; function (or functions from other + layers that it calls) should allocate entries in the + &s.code;ScreenRec&e.code;'s &s.code;devPrivates&e.code; area by + calling &s.code;AllocateScreenPrivateIndex()&e.code; if it needs + per-generation storage. Since the &s.code;ScreenRec&e.code;'s + &s.code;devPrivates&e.code; information is cleared for each server + generation, this is the correct place to initialise it. + + After &s.code;AddScreen()&e.code; has successfully returned, the + following &s.code;ScrnInfoRec&e.code; fields are initialised: + + <quote><verb> + pScreen + racMemFlags + racIoFlags + </verb></quote> + + The &s.code;ChipScreenInit()&e.code; function should initialise the + &s.code;CloseScreen&e.code; and &s.code;SaveScreen&e.code; fields + of &s.code;pScreen&e.code;. The old value of + &s.code;pScreen->CloseScreen&e.code; should be saved as part of + the driver's per-screen private data, allowing it to be called from + &s.code;ChipCloseScreen()&e.code;. This means that the existing + &s.code;CloseScreen()&e.code; function is wrapped. + +<sect1>Finalising RAC Initialisation +<p> + + After all the &s.code;ChipScreenInit()&e.code; functions have been + called, each screen has registered its RAC requirements. This + information is used to determine which shared resources are requested + by more than one driver and set the access functions accordingly. + This is done following these rules: + + <enum> + <item>The sharable resources registered by each entity are compared. + If a resource is registered by more than one entity the entity + will be marked to indicate that it needs to share this resources + type (IO or MEM). + + <item>A resource marked ``disabled'' during OPERATING state will be + ignored entirely. + + <item>A resource marked ``unused'' will only conflict with an overlapping + resource of an other entity if the second is actually in use + during OPERATING state. + + <item>If an ``unused'' resource was found to conflict but the entity + does not use any other resource of this type the entire resource + type will be disabled for that entity. + </enum> + + +<sect1>Finishing InitOutput() +<p> + + At this point &s.code;InitOutput()&e.code; is finished, and all the + screens have been setup in their initial video mode. + + +<sect1>Mode Switching +<p> + + When a SwitchMode event is received, &s.code;ChipSwitchMode()&e.code; + is called (when it exists): + + <quote><p> + &s.code;Bool ChipSwitchMode(int index, DisplayModePtr mode, int flags)&e.code; + <quote><p> + Initialises the new mode for the screen identified by + &s.code;index;&e.code;. The viewport may need to be adjusted + also. + + </quote> + </quote> + + +<sect1>Changing Viewport +<p> + + When a Change Viewport event is received, + &s.code;ChipAdjustFrame()&e.code; is called (when it exists): + + <quote><p> + &s.code;void ChipAdjustFrame(int index, int x, int y, int flags)&e.code; + <quote><p> + Changes the viewport for the screen identified by + &s.code;index;&e.code;. + + It should be noted that many chipsets impose restrictions on where the + viewport may be placed in the virtual resolution, either for alignment + reasons, or to prevent the start of the viewport from being positioned + within a pixel (as can happen in a 24bpp mode). After calculating the + value the chipset's panning registers need to be set to for non-DGA + modes, this function should recalculate the ScrnInfoRec's + &s.code;frameX0&e.code;, &s.code;frameY0&e.code, &s.code;frameX1&e.code; + and &s.code;frameY1&e.code; fields to correspond to that value. If + this is not done, switching to another mode might cause the position + of a hardware cursor to change. + + </quote> + </quote> + + +<sect1>VT Switching +<p> + + When a VT switch event is received, &s.code;xf86VTSwitch()&e.code; + is called. &s.code;xf86VTSwitch()&e.code; does the following: + + <descrip> + <tag>On ENTER:</tag> + <itemize> + <item>enable port I/O access + + <item>save and initialise the bus/resource state + + <item>enter the SETUP server state + + <item>calls &s.code;ChipEnterVT()&e.code; for each screen + + <item>enter the OPERATING server state + + <item>validate GCs + + <item>Restore fb from saved pixmap for each screen + + <item>Enable all input devices + </itemize> + <tag>On LEAVE:</tag> + <itemize> + <item>Save fb to pixmap for each screen + + <item>validate GCs + + <item>enter the SETUP server state + + <item>calls &s.code;ChipLeaveVT()&e.code; for each screen + + <item>disable all input devices + + <item>restore bus/resource state + + <item>disables port I/O access + </itemize> + </descrip> + + <quote><p> + &s.code;Bool ChipEnterVT(int index, int flags)&e.code; + <quote><p> + This function should initialise the current video mode and + initialise the viewport, turn on the HW cursor if appropriate, + etc. + + Should it re-save the video state before initialising the video + mode? + + </quote> + + &s.code;void ChipLeaveVT(int index, int flags)&e.code; + <quote><p> + This function should restore the saved video state. If + appropriate it should also turn off the HW cursor, and invalidate + any pixmap/font caches. + + </quote> + + Optionally, &s.code;ChipLeaveVT()&e.code; may also unmap memory + regions. If so, &s.code;ChipEnterVT()&e.code; will need to remap + them. Additionally, if an aperture used to access video memory is + unmapped and remapped in this fashion, &s.code;ChipEnterVT()&e.code; + will also need to notify the framebuffer layers of the aperture's new + location in virtual memory. This is done with a call to the screen's + &s.code;ModifyPixmapHeader()&e.code; function, as follows + + <quote><p> + &s.code;(*pScreen->ModifyPixmapHeader)(pScrn->ppix, + &f.indent;-1, -1, -1, -1, -1, <it>NewApertureAddress</it>);&e.code; + <quote><p> + where the &s.code``ppix''&e.code; field in a ScrnInfoRec + points to the pixmap used by the screen's + &s.code;SaveRestoreImage()&e.code; function to hold the screen's + contents while switched out. + + </quote> + </quote> + + Currently, aperture remapping, as described here, should not be + attempted if the driver uses the &s.code;xf8_16bpp&e.code; or + &s.code;xf8_32bpp&e.code; framebuffer layers. A pending + restructuring of VT switching will address this restriction in + the near future. + + </quote> + + Other layers may wrap the &s.code;ChipEnterVT()&e.code; and + &s.code;ChipLeaveVT()&e.code; functions if they need to take some + action when these events are received. + +<sect1>End of server generation +<p> + + At the end of each server generation, the DIX layer calls + &s.code;ChipCloseScreen()&e.code; for each screen: + + <quote><p> + &s.code;Bool ChipCloseScreen(int index, ScreenPtr pScreen)&e.code; + <quote><p> + This function should restore the saved video state and unmap the + memory regions. + + It should also free per-screen data structures allocated by the + driver. Note that the persistent data held in the + &s.code;ScrnInfoRec&e.code;'s &s.code;driverPrivate&e.code; field + should not be freed here because it is needed by subsequent server + generations. + + The &s.code;ScrnInfoRec&e.code;'s &s.code;vtSema&e.code; field + should be set to &s.code;FALSE&e.code; once the video HW state + has been restored. + + Before freeing the per-screen driver data the saved + &s.code;CloseScreen&e.code; value should be restored to + &s.code;pScreen->CloseScreen&e.code;, and that function should + be called after freeing the data. + + </quote> + </quote> + +<sect>Optional Driver Functions +<p> + +The functions outlined here can be called from the XFree86 common layer, +but their presence is optional. + +<sect1>Mode Validation +<p> + + When a mode validation helper supplied by the XFree86-common layer is + being used, it can be useful to provide a function to check for hw + specific mode constraints: + + <quote><p> + &s.code;ModeStatus ChipValidMode(int index, DisplayModePtr mode, + &f.indent;Bool verbose, int flags)&e.code; + <quote><p> + Check the passed mode for hw-specific constraints, and return the + appropriate status value. + + </quote> + </quote> + +<p> +This function may also modify the effective timings and clock of the passed +mode. These have been stored in the mode's &s.code;Crtc*&e.code; and +&s.code;SynthClock&e.code; elements, and have already been adjusted for +interlacing, doublescanning, multiscanning and clock multipliers and dividers. +The function should not modify any other mode field, unless it wants to modify +the mode timings reported to the user by &s.code;xf86PrintModes()&e.code;. + +<p> +The function is called once for every mode in the XF86Config Monitor section +assigned to the screen, with &s.code;flags&e.code; set to +&s.code;MODECHECK_INITIAL&e.code;. It is subsequently called for every mode +in the XF86Config Display subsection assigned to the screen, with +&s.code;flags&e.code; set to &s.code;MODECHECK_FINAL&e.code;. In the second +case, the mode will have successfully passed all other tests. In addition, +the &s.code;ScrnInfoRec&e.code;'s &s.code;virtualX&e.code;, +&s.code;virtualY&e.code; and &s.code;displayWidth&e.code; fields will have been +set as if the mode to be validated were to be the last mode accepted. + +<p> +In effect, calls with MODECHECK_INITIAL are intended for checks that do not +depend on any mode other than the one being validated, while calls with +MODECHECK_FINAL are intended for checks that may involve more than one mode. + +<sect1>Free screen data +<p> + + When a screen is deleted prior to the completion of the ScreenInit + phase the &s.code;ChipFreeScreen()&e.code; function is called when defined. + + <quote><p> + &s.code;void ChipFreeScreen(int scrnindex, int flags)&e.code; + <quote><p> + Free any driver-allocated data that may have been allocated up to + and including an unsuccessful &s.code;ChipScreenInit()&e.code; + call. This would predominantly be data allocated by + &s.code;ChipPreInit()&e.code; that persists across server + generations. It would include the &s.code;driverPrivate&e.code;, + and any ``privates'' entries that modules may have allocated. + + </quote> + </quote> + + +<sect>Recommended driver functions +<p> + +The functions outlined here are for internal use by the driver only. +They are entirely optional, and are never accessed directly from higher +layers. The sample function declarations shown here are just examples. +The interface (if any) used is up to the driver. + +<sect1>Save +<p> + + Save the video state. This could be called from &s.code;ChipScreenInit()&e.code; and + (possibly) &s.code;ChipEnterVT()&e.code;. + + <quote><p> + &s.code;void ChipSave(ScrnInfoPtr pScrn)&e.code; + <quote><p> + Saves the current state. This will only be saving pre-server + states or states before returning to the server. There is only + one current saved state per screen and it is stored in private + storage in the screen. + + </quote> + </quote> + +<sect1>Restore +<p> + + Restore the original video state. This could be called from the + &s.code;ChipLeaveVT()&e.code; and &s.code;ChipCloseScreen()&e.code; + functions. + + <quote><p> + &s.code;void ChipRestore(ScrnInfoPtr pScrn)&e.code; + <quote><p> + Restores the saved state from the private storage. Usually only + used for restoring text modes. + + </quote> + </quote> + + +<sect1>Initialise Mode +<p> + + Initialise a video mode. This could be called from the + &s.code;ChipScreenInit()&e.code;, &s.code;ChipSwitchMode()&e.code; + and &s.code;ChipEnterVT()&e.code; functions. + + <quote><p> + &s.code;Bool ChipModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)&e.code; + <quote><p> + Programs the hardware for the given video mode. + + </quote> + </quote> + + +<sect>Data and Data Structures +<p> + +<sect1>Command line data +<p> + +Command line options are typically global, and are stored in global +variables. These variables are read-only and are available to drivers +via a function call interface. Most of these command line values are +processed via helper functions to ensure that they are treated consistently +by all drivers. The other means of access is provided for cases where +the supplied helper functions might not be appropriate. + +Some of them are: + +<quote><verb> + xf86Verbose verbosity level + xf86Bpp -bpp from the command line + xf86Depth -depth from the command line + xf86Weight -weight from the command line + xf86Gamma -{r,g,b,}gamma from the command line + xf86FlipPixels -flippixels from the command line + xf86ProbeOnly -probeonly from the command line + defaultColorVisualClass -cc from the command line +</verb></quote> + +If we ever do allow for screen-specific command line options, we may +need to rethink this. + +These can be accessed in a read-only manner by drivers with the following +functions: + + <quote><p> + &s.code;int xf86GetVerbosity()&e.code; + <quote><p> + Returns the value of &s.code;xf86Verbose&e.code;. + + </quote> + + &s.code;int xf86GetDepth()&e.code; + <quote><p> + Returns the &s.cmd;-depth&e.cmd; command line setting. If not + set on the command line, &s.code;-1&e.code; is returned. + + </quote> + + &s.code;rgb xf86GetWeight()&e.code; + <quote><p> + Returns the &s.cmd;-weight&e.cmd; command line setting. If not + set on the command line, &s.code;{0, 0, 0}&e.code; is returned. + + </quote> + + &s.code;Gamma xf86GetGamma()&e.code; + <quote><p> + Returns the &s.cmd;-gamma&e.cmd; or &s.cmd;-rgamma&e.cmd;, + &s.cmd;-ggamma&e.cmd;, &s.cmd;-bgamma&e.cmd; command line settings. + If not set on the command line, &s.code;{0.0, 0.0, 0.0}&e.code; + is returned. + + </quote> + + &s.code;Bool xf86GetFlipPixels()&e.code; + <quote><p> + Returns &s.code;TRUE&e.code; if &s.cmd;-flippixels&e.cmd; is + present on the command line, and &s.code;FALSE&e.code; otherwise. + + </quote> + + &s.code;const char *xf86GetServerName()&e.code; + <quote><p> + Returns the name of the X server from the command line. + + </quote> + </quote> + +<sect1>Data handling +<p> + +Config file data contains parts that are global, and parts that are +Screen specific. All of it is parsed into data structures that neither +the drivers or most other parts of the server need to know about. + +The global data is typically not required by drivers, and as such, most +of it is stored in the private &s.code;xf86InfoRec&e.code;. + +The screen-specific data collected from the config file is stored in +screen, device, display, monitor-specific data structures that are separate +from the &s.code;ScrnInfoRecs&e.code;, with the appropriate elements/fields +hooked into the &s.code;ScrnInfoRecs&e.code; as required. The screen +config data is held in &s.code;confScreenRec&e.code;, device data in +the &s.code;GDevRec&e.code;, monitor data in the &s.code;MonRec&e.code;, +and display data in the &s.code;DispRec&e.code;. + +The XFree86 common layer's screen specific data (the actual data in use +for each screen) is held in the &s.code;ScrnInfoRecs&e.code;. As has +been outlined above, the &s.code;ScrnInfoRecs&e.code; are allocated at probe +time, and it is the responsibility of the Drivers' &s.code;Probe()&e.code; +and &s.code;PreInit()&e.code; functions to finish filling them in based +on both data provided on the command line and data provided from the +Config file. The precedence for this is: + + <quote> + command line -> config file -> probed/default data + </quote> + +For most things in this category there are helper functions that the +drivers can use to ensure that the above precedence is consistently +used. + +As well as containing screen-specific data that the XFree86 common layer +(including essential parts of the server infrastructure as well as helper +functions) needs to access, it also contains some data that drivers use +internally. When considering whether to add a new field to the +&s.code;ScrnInfoRec&e.code;, consider the balance between the convenience +of things that lots of drivers need and the size/obscurity of the +&s.code;ScrnInfoRec&e.code;. + +Per-screen driver specific data that cannot be accommodated with the +static &s.code;ScrnInfoRec&e.code; fields is held in a driver-defined +data structure, a pointer to which is assigned to the +&s.code;ScrnInfoRec&e.code;'s &s.code;driverPrivate&e.code; field. This +is per-screen data that persists across server generations (as does the +bulk of the static &s.code;ScrnInfoRec&e.code; data). It would typically +also include the video card's saved state. + +Per-screen data for other modules that the driver uses (for example, +the XAA module) that is reset for each server generation is hooked into +the &s.code;ScrnInfoRec&e.code; through it's &s.code;privates&e.code; +field. + +Once it has stabilised, the data structures and variables accessible to +video drivers will be documented here. In the meantime, those things +defined in the &s.code;xf86.h&e.code; and &s.code;xf86str.h&e.code; +files are visible to video drivers. Things defined in +&s.code;xf86Priv.h&e.code; and &s.code;xf86Privstr.h&e.code; are NOT +intended to be visible to video drivers, and it is an error for a driver +to include those files. + + +<sect1>Accessing global data +<p> + +Some other global state information that the drivers may access via +functions is as follows: + + <quote><p> + &s.code;Bool xf86ServerIsExiting()&e.code; + <quote><p> + Returns &s.code;TRUE&e.code; if the server is at the end of a + generation and is in the process of exiting, and + &s.code;FALSE&e.code; otherwise. + + </quote> + + &s.code;Bool xf86ServerIsResetting()&e.code; + <quote><p> + Returns &s.code;TRUE&e.code; if the server is at the end of a + generation and is in the process of resetting, and + &s.code;FALSE&e.code; otherwise. + + </quote> + + &s.code;Bool xf86ServerIsInitialising()&e.code; + <quote><p> + Returns &s.code;TRUE&e.code; if the server is at the beginning of + a generation and is in the process of initialising, and + &s.code;FALSE&e.code; otherwise. + + </quote> + + &s.code;Bool xf86ServerIsOnlyProbing()&e.code; + <quote><p> + Returns &s.code;TRUE&e.code; if the -probeonly command line flag + was specified, and &s.code;FALSE&e.code; otherwise. + + </quote> + + &s.code;Bool xf86CaughtSignal()&e.code; + <quote><p> + Returns &s.code;TRUE&e.code; if the server has caught a signal, + and &s.code;FALSE&e.code; otherwise. + + </quote> + </quote> + +<sect1>Allocating private data +<p> + +A driver and any module it uses may allocate per-screen private storage +in either the &s.code;ScreenRec&e.code; (DIX level) or +&s.code;ScrnInfoRec&e.code; (XFree86 common layer level). +&s.code;ScreenRec&e.code; storage persists only for a single server +generation, and &s.code;ScrnInfoRec&e.code; storage persists across +generations for the lifetime of the server. + +The &s.code;ScreenRec&e.code; &s.code;devPrivates&e.code; data must be +reallocated/initialised at the start of each new generation. This is +normally done from the &s.code;ChipScreenInit()&e.code; function, and +Init functions for other modules that it calls. Data allocated in this +way should be freed by the driver's &s.code;ChipCloseScreen()&e.code; +functions, and Close functions for other modules that it calls. A new +&s.code;devPrivates&e.code; entry is allocated by calling the +&s.code;AllocateScreenPrivateIndex()&e.code; function. + + <quote><p> + &s.code;int AllocateScreenPrivateIndex()&e.code; + <quote><p> + This function allocates a new element in the + &s.code;devPrivates&e.code; field of all currently existing + &s.code;ScreenRecs&e.code;. The return value is the index of this + new element in the &s.code;devPrivates&e.code; array. The + &s.code;devPrivates&e.code; field is of type + &s.code;DevUnion&e.code;: + + <verb> + typedef union _DevUnion { + pointer ptr; + long val; + unsigned long uval; + pointer (*fptr)(void); + } DevUnion; + </verb> + + which allows the element to be used for any of the above types. + It is commonly used as a pointer to data that the caller allocates + after the new index has been allocated. + + This function will return &s.code;-1&e.code; when there is an + error allocating the new index. + + </quote> + </quote> + +The &s.code;ScrnInfoRec&e.code; &s.code;privates&e.code; data persists +for the life of the server, so only needs to be allocated once. This +should be done from the &s.code;ChipPreInit()&e.code; function, and Init +functions for other modules that it calls. Data allocated in this way +should be freed by the driver's &s.code;ChipFreeScreen()&e.code; functions, +and Free functions for other modules that it calls. A new +&s.code;privates&e.code; entry is allocated by calling the +&s.code;xf86AllocateScrnInfoPrivateIndex()&e.code; function. + + + <quote><p> + &s.code;int xf86AllocateScrnInfoPrivateIndex()&e.code; + <quote><p> + This function allocates a new element in the &s.code;privates&e.code; + field of all currently existing &s.code;ScrnInfoRecs&e.code;. + The return value is the index of this new element in the + &s.code;privates&e.code; array. The &s.code;privates&e.code; + field is of type &s.code;DevUnion&e.code;: + + <verb> + typedef union _DevUnion { + pointer ptr; + long val; + unsigned long uval; + pointer (*fptr)(void); + } DevUnion; + </verb> + + which allows the element to be used for any of the above types. + It is commonly used as a pointer to data that the caller allocates + after the new index has been allocated. + + This function will not return when there is an error allocating + the new index. When there is an error it will cause the server + to exit with a fatal error. The similar function for allocation + privates in the &s.code;ScreenRec&e.code; + (&s.code;AllocateScreenPrivateIndex()&e.code;) differs in this + respect by returning &s.code;-1&e.code; when the allocation fails. + + </quote> + </quote> + +<sect>Keeping Track of Bus Resources<label id="rac"> +<p> + +<sect1>Theory of Operation +<p> + +The XFree86 common layer has knowledge of generic access control mechanisms +for devices on certain bus systems (currently the PCI bus) as well as +of methods to enable or disable access to the buses itself. Furthermore +it can access information on resources decoded by these devices and if +necessary modify it. + +When first starting the Xserver collects all this information, saves it +for restoration, checks it for consistency, and if necessary, corrects +it. Finally it disables all resources on a generic level prior to +calling any driver function. + +When the &s.code;Probe()&e.code; function of each driver is called the +device sections are matched against the devices found in the system. +The driver may probe devices at this stage that cannot be identified by +using device independent methods. Access to all resources that can be +controlled in a device independent way is disabled. The +&s.code;Probe()&e.code; function should register all non-relocatable +resources at this stage. If a resource conflict is found between +exclusive resources the driver will fail immediately. Optionally the +driver might specify an &s.code;EntityInit()&e.code;, +&s.code;EntityLeave()&e.code; and &s.code;EntityEnter()&e.code; function. + +&s.code;EntityInit()&e.code; can be used to disable any shared resources +that are not controlled by the generic access control functions. It is +called prior to the PreInit phase regardless if an entity is active or +not. When calling the &s.code;EntityInit()&e.code;, +&s.code;EntityEnter()&e.code; and &s.code;EntityLeave()&e.code; functions +the common level will disable access to all other entities on a generic +level. Since the common level has no knowledge of device specific +methods to disable access to resources it cannot be guaranteed that +certain resources are not decoded by any other entity until the +&s.code;EntityInit()&e.code; or &s.code;EntityEnter()&e.code; phase is +finished. Device drivers should therefore register all those resources +which they are going to disable. If these resources are never to be +used by any driver function they may be flagged &s.code;ResInit&e.code; +so that they can be removed from the resource list after processing all +&s.code;EntityInit()&e.code; functions. &s.code;EntityEnter()&e.code; +should disable decoding of all resources which are not registered as +exclusive and which are not handled by the generic access control in +the common level. The difference to &s.code;EntityInit()&e.code; is +that the latter one is only called once during lifetime of the server. +It can therefore be used to set up variables prior to disabling resources. +&s.code;EntityLeave()&e.code; should restore the original state when +exiting the server or switching to a different VT. It also needs to +disable device specific access functions if they need to be disabled on +server exit or VT switch. The default state is to enable them before +giving up the VT. + +In &s.code;PreInit()&e.code; phase each driver should check if any +sharable resources it has registered during &s.code;Probe()&e.code; has +been denied and take appropriate action which could simply be to fail. +If it needs to access resources it has disabled during +&s.code;EntitySetup()&e.code; it can do so provided it has registered +these and will disable them before returning from +&s.code;PreInit()&e.code;. This also applies to all other driver +functions. Several functions are provided to request resource ranges, +register these, correct PCI config space and add replacements for the +generic access functions. Resources may be marked ``disabled'' or +``unused'' during OPERATING stage. Although these steps could also be +performed in &s.code;ScreenInit()&e.code;, this is not desirable. + +Following &s.code;PreInit()&e.code; phase the common level determines +if resource access control is needed. This is the case if more than +one screen is used. If necessary the RAC wrapper module is loaded. In +&s.code;ScreenInit()&e.code; the drivers can decide which operations +need to be placed under RAC. Available are the frame buffer operations, +the pointer operations and the colormap operations. Any operation that +requires resources which might be disabled during OPERATING state should +be set to use RAC. This can be specified separately for memory and IO +resources. + +When &s.code;ScreenInit()&e.code; phase is done the common level will +determine which shared resources are requested by more than one driver +and set the access functions accordingly. This is done following these +rules: + +<enum> +<item>The sharable resources registered by each entity are compared. If + a resource is registered by more than one entity the entity will be + marked to need to share this resources type (&s.code;IO&e.code; or + &s.code;MEM&e.code;). + +<item>A resource marked ``disabled'' during OPERATING state will be ignored + entirely. + +<item>A resource marked ``unused'' will only conflicts with an overlapping + resource of an other entity if the second is actually in use during + OPERATING state. + +<item>If an ``unused'' resource was found to conflict however the entity + does not use any other resource of this type the entire resource type + will be disabled for that entity. +</enum> + +The driver has the choice among different ways to control access to +certain resources: + +<enum> +<item>It can rely on the generic access functions. This is probably the + most common case. Here the driver only needs to register any resource + it is going to use. + +<item>It can replace the generic access functions by driver specific + ones. This will mostly be used in cases where no generic access + functions are available. In this case the driver has to make sure + these resources are disabled when entering the &s.code;PreInit()&e.code; + stage. Since the replacement functions are registered in + &s.code;PreInit()&e.code; the driver will have to enable these + resources itself if it needs to access them during this state. The + driver can specify if the replacement functions can control memory + and/or I/O resources separately. + +<item>The driver can enable resources itself when it needs them. Each + driver function enabling them needs to disable them before it will + return. This should be used if a resource which can be controlled + in a device dependent way is only required during SETUP state. This + way it can be marked ``unused'' during OPERATING state. +</enum> + +A resource which is decoded during OPERATING state however never accessed +by the driver should be marked unused. + +Since access switching latencies are an issue during Xserver operation, +the common level attempts to minimize the number of entities that need +to be placed under RAC control. When a wrapped operation is called, +the &s.code;EnableAccess()&e.code; function is called before control is +passed on. &s.code;EnableAccess()&e.code; checks if a screen is under +access control. If not it just establishes bus routing and returns. +If the screen needs to be under access control, +&s.code;EnableAccess()&e.code; determines which resource types +(&s.code;MEM&e.code;, &s.code;IO&e.code;) are required. Then it tests +if this access is already established. If so it simply returns. If +not it disables the currently established access, fixes bus routing and +enables access to all entities registered for this screen. + +Whenever a mode switch or a VT-switch is performed the common level will +return to SETUP state. + +<sect1>Resource Types +<p> + +Resource have certain properties. When registering resources each range +is accompanied by a flag consisting of the ORed flags of the different +properties the resource has. Each resource range may be classified +according to + +<itemize> + <item>its physical properties i.e., if it addresses + memory (&s.code;ResMem&e.code;) or + I/O space (&s.code;ResIo&e.code;), + <item>if it addresses a + block (&s.code;ResBlock&e.code;) or + sparse (&s.code;ResSparse&e.code;) + range, + <item>its access properties. +</itemize> + +There are two known access properties: + +<itemize> + <item>&s.code;ResExclusive&e.code; + for resources which may not be shared with any other device and + <item>&s.code;ResShared&e.code; + for resources which can be disabled and therefore can be shared. +</itemize> + +If it is necessary to test a resource against any type a generic access +type &s.code;ResAny&e.code; is provided. If this is set the resource +will conflict with any resource of a different entity intersecting its +range. Further it can be specified that a resource is decoded however +never used during any stage (&s.code;ResUnused&e.code;) or during +OPERATING state (&s.code;ResUnusedOpr&e.code;). A resource only visible +during the init functions (ie. &s.code;EntityInit()&e.code;, +&s.code;EntityEnter()&e.code; and &s.code;EntityLeave()&e.code; should +be registered with the flag &s.code;ResInit&e.code;. A resource that +might conflict with background resource ranges may be flagged with +&s.code;ResBios&e.code;. This might be useful when registering resources +ranges that were assigned by the system Bios. + +Several predefined resource lists are available for VGA and 8514/A +resources in &s.code;common/xf86Resources.h&e.code;. + +<sect1>Available Functions<label id="avail"> +<p> + +The functions provided for resource management are listed in their order +of use in the driver. + + +<sect2>Probe Phase +<p> + +In this phase each driver detects those resources it is able to drive, +creates an entity record for each of them, registers non-relocatable +resources and allocates screens and adds the resources to screens. + +Two helper functions are provided for matching device sections in the +XF86Config file to the devices: + + <quote><p> + &s.code;int xf86MatchPciInstances(const char *driverName, int vendorID, + &f.indent;SymTabPtr chipsets, PciChipsets *PCIchipsets, + &f.indent;GDevPtr *devList, int numDevs, DriverPtr drvp, + &f.indent;int **foundEntities)&e.code; + <quote><p> + This function finds matches between PCI cards that a driver supports + and config file device sections. It is intended for use in the + &s.code;ChipProbe()&e.code; function of drivers for PCI cards. + Only probed PCI devices with a vendor ID matching + &s.code;vendorID&e.code; are considered. &s.code;devList&e.code; + and &s.code;numDevs&e.code; are typically those found from + calling &s.code;xf86MatchDevice()&e.code;, and represent the active + config file device sections relevant to the driver. + &s.code;PCIchipsets&e.code; is a table that provides a mapping + between the PCI device IDs, the driver's internal chipset tokens + and a list of fixed resources. + + When a device section doesn't have a &s.key;BusID&e.key; entry it + can only match the primary video device. Secondary devices are + only matched with device sections that have a matching + &s.key;BusID&e.key; entry. + + Once the preliminary matches have been found, a final match is + confirmed by checking if the chipset override, ChipID override or + probed PCI chipset type match one of those given in the + &s.code;chipsets&e.code; and &s.code;PCIchipsets&e.code; lists. + The &s.code;PCIchipsets&e.code; list includes a list of the PCI + device IDs supported by the driver. The list should be terminated + with an entry with PCI ID &s.code;-1&e.code;". The + &s.code;chipsets&e.code; list is a table mapping the driver's + internal chipset tokens to names, and should be terminated with + a &s.code;NULL&e.code; entry. Only those entries with a + corresponding entry in the &s.code;PCIchipsets&e.code; list are + considered. The order of precedence is: config file chipset, + config file ChipID, probed PCI device ID. + + In cases where a driver handles PCI chipsets with more than one + vendor ID, it may set &s.code;vendorID&e.code; to + &s.code;0&e.code;, and OR each devID in the list with (the + vendor ID << 16). + + Entity index numbers for confirmed matches are returned as an + array via &s.code;foundEntities&e.code;. The PCI information, + chipset token and device section for each match are found in the + &s.code;EntityInfoRec&e.code; referenced by the indices. + + The function return value is the number of confirmed matches. A + return value of &s.code;-1&e.code; indicates an internal error. + The returned &s.code;foundEntities&e.code; array should be freed + by the driver with &s.code;xfree()&e.code; when it is no longer + needed in cases where the return value is greater than zero. + + </quote> + + &s.code;int xf86MatchIsaInstances(const char *driverName, + &f.indent;SymTabPtr chipsets, IsaChipsets *ISAchipsets, + &f.indent;DriverPtr drvp, FindIsaDevProc FindIsaDevice, + &f.indent;GDevPtr *devList, int numDevs, + int **foundEntities)&e.code; + <quote><p> + This function finds matches between ISA cards that a driver supports + and config file device sections. It is intended for use in the + &s.code;ChipProbe()&e.code; function of drivers for ISA cards. + &s.code;devList&e.code; and &s.code;numDevs&e.code; are + typically those found from calling &s.code;xf86MatchDevice()&e.code;, + and represent the active config file device sections relevant to + the driver. &s.code;ISAchipsets&e.code; is a table that provides + a mapping between the driver's internal chipset tokens and the + resource classes. &s.code;FindIsaDevice&e.code; is a + driver-provided function that probes the hardware and returns the + chipset token corresponding to what was detected, and + &s.code;-1&e.code; if nothing was detected. + + If the config file device section contains a chipset entry, then + it is checked against the &s.code;chipsets&e.code; list. When + no chipset entry is present, the &s.code;FindIsaDevice&e.code; + function is called instead. + + Entity index numbers for confirmed matches are returned as an + array via &s.code;foundEntities&e.code;. The chipset token and + device section for each match are found in the + &s.code;EntityInfoRec&e.code; referenced by the indices. + + The function return value is the number of confirmed matches. A + return value of &s.code;-1&e.code; indicates an internal error. + The returned &s.code;foundEntities&e.code; array should be freed + by the driver with &s.code;xfree()&e.code; when it is no longer + needed in cases where the return value is greater than zero. + + </quote> + </quote> + +These two helper functions make use of several core functions that are +available at the driver level: + + <quote><p> + &s.code;Bool xf86ParsePciBusString(const char *busID, int *bus, + &f.indent;int *device, int *func)&e.code; + <quote><p> + Takes a &s.code;BusID&e.code; string, and if it is in the correct + format, returns the PCI &s.code;bus&e.code;, &s.code;device&e.code;, + &s.code;func&e.code; values that it indicates. The format of the + string is expected to be "PCI:bus:device:func" where each of `bus', + `device' and `func' are decimal integers. The ":func" part may + be omitted, and the func value assumed to be zero, but this isn't + encouraged. The "PCI" prefix may also be omitted. The prefix + "AGP" is currently equivalent to the "PCI" prefix. If the string + isn't a valid PCI BusID, the return value is &s.code;FALSE&e.code;. + + </quote> + + + &s.code;Bool xf86ComparePciBusString(const char *busID, int bus, + &f.indent;int device, int func)&e.code; + <quote><p> + Compares a &s.code;BusID&e.code; string with PCI &s.code;bus&e.code;, + &s.code;device&e.code;, &s.code;func&e.code; values. If they + match &s.code;TRUE&e.code; is returned, and &s.code;FALSE&e.code; + if they don't. + + </quote> + + &s.code;Bool xf86ParseIsaBusString(const char *busID)&e.code; + <quote><p> + Compares a &s.code;BusID&e.code; string with the ISA bus ID string + ("ISA" or "ISA:"). If they match &s.code;TRUE&e.code; is returned, + and &s.code;FALSE&e.code; if they don't. + + </quote> + + &s.code;Bool xf86CheckPciSlot(int bus, int device, int func)&e.code; + <quote><p> + Checks if the PCI slot &s.code;bus:device:func&e.code; has been + claimed. If so, it returns &s.code;FALSE&e.code;, and otherwise + &s.code;TRUE&e.code;. + + </quote> + + &s.code;int xf86ClaimPciSlot(int bus, int device, int func, DriverPtr drvp, + &f.indent;int chipset, GDevPtr dev, Bool active)&e.code; + <quote><p> + This function is used to claim a PCI slot, allocate the associated + entity record and initialise their data structures. The return + value is the index of the newly allocated entity record, or + &s.code;-1&e.code; if the claim fails. This function should always + succeed if &s.code;xf86CheckPciSlot()&e.code; returned + &s.code;TRUE&e.code; for the same PCI slot. + + </quote> + + &s.code;Bool xf86IsPrimaryPci(void)&e.code; + <quote><p> + This function returns &s.code;TRUE&e.code; if the primary card is + a PCI device, and &s.code;FALSE&e.code; otherwise. + + </quote> + + &s.code;int xf86ClaimIsaSlot(DriverPtr drvp, int chipset, + &f.indent;GDevPtr dev, Bool active)&e.code; + <quote><p> + This allocates an entity record entity and initialise the data + structures. The return value is the index of the newly allocated + entity record. + + </quote> + + &s.code;Bool xf86IsPrimaryIsa(void)&e.code; + <quote><p> + This function returns &s.code;TRUE&e.code; if the primary card is + an ISA (non-PCI) device, and &s.code;FALSE&e.code; otherwise. + + </quote> + </quote> + +Two helper functions are provided to aid configuring entities: + <quote><p> + &s.code;ScrnInfoPtr xf86ConfigPciEntity(ScrnInfoPtr pScrn, + &f.indent;int scrnFlag, int entityIndex, + &f.indent;PciChipsets *p_chip, + &f.indent;resList res, EntityProc init, + &f.indent;EntityProc enter, EntityProc leave, + &f.indent;pointer private)&e.code; + <p> + &s.code;ScrnInfoPtr xf86ConfigIsaEntity(ScrnInfoPtr pScrn, + &f.indent;int scrnFlag, int entityIndex, + &f.indent;IsaChipsets *i_chip, + &f.indent;resList res, EntityProc init, + &f.indent;EntityProc enter, EntityProc leave, + &f.indent;pointer private)&e.code; + <quote><p> + These functions are used to register the non-relocatable resources + for an entity, and the optional entity-specific &s.code;Init&e.code;, &s.code;Enter&e.code; and + &s.code;Leave&e.code; functions. Usually the list of fixed resources is obtained + from the Isa/PciChipsets lists. However an additional list of + resources may be passed. Generally this is not required. + For active entities a &s.code;ScrnInfoRec&e.code; is allocated + if the &s.code;pScrn&e.code; argument is &s.code;NULL&e.code;. +The + return value is &s.code;TRUE&e.code; when successful. The init, enter, leave + functions are defined as follows: + + <quote> + &s.code;typedef void (*EntityProc)(int entityIndex, + &f.indent;pointer private)&e.code; + </quote> + + They are passed the entity index and a pointer to a private scratch + area. This can be set up during &s.code;Probe()&e.code; and + its address can be passed to + &s.code;xf86ConfigIsaEntity()&e.code; and + &s.code;xf86ConfigPciEntity()&e.code; as the last argument. + + </quote> + </quote> + +These two helper functions make use of several core functions that are +available at the driver level: + <quote><p> + &s.code;void xf86ClaimFixedResources(resList list, int entityIndex)&e.code; + <quote><p> + This function registers the non-relocatable resources which cannot + be disabled and which therefore would cause the server to fail + immediately if they were found to conflict. It also records + non-relocatable but sharable resources for processing after the + &s.code;Probe()&e.code; phase. + + </quote> + + &s.code;Bool xf86SetEntityFuncs(int entityIndex, EntityProc init, + &f.indent;EntityProc enter, EntityProc leave, pointer)&e.code; + <quote><p> + This function registers with an entity the &s.code;init&e.code;, + &s.code;enter&e.code;, &s.code;leave&e.code; functions along + with the pointer to their private area. + + </quote> + + &s.code;void xf86AddEntityToScreen(ScrnInfoPtr pScrn, int entityIndex)&e.code; + <quote><p> + This function associates the entity referenced by + &s.code;entityIndex&e.code; with the screen. + + </quote> + </quote> + +<sect2>PreInit Phase +<p> + +During this phase the remaining resources should be registered. +&s.code;PreInit()&e.code; should call &s.code;xf86GetEntityInfo()&e.code; +to obtain a pointer to an &s.code;EntityInfoRec&e.code; for each entity +it is able to drive and check if any resource are listed in its +&s.code;resources&e.code; field. If resources registered in the Probe +phase have been rejected in the post-Probe phase +(&s.code;resources&e.code; is non-&s.code;NULL&e.code;), then the driver should +decide if it can continue without using these or if it should fail. + + <quote><p> + &s.code;EntityInfoPtr xf86GetEntityInfo(int entityIndex)&e.code; + <quote><p> + This function returns a pointer to the &s.code;EntityInfoRec&e.code; + referenced by &s.code;entityIndex&e.code;. The returned + &s.code;EntityInfoRec&e.code; should be freed with + &s.code;xfree()&e.code; when no longer needed. + + </quote> + </quote> +Several functions are provided to simplify resource registration: + <quote><p> + &s.code;Bool xf86IsEntityPrimary(int entityIndex)&e.code; + <quote><p> + This function returns &s.code;TRUE&e.code; if the entity referenced + by &s.code;entityIndex&e.code; is the primary display device (i.e., + the one initialised at boot time and used in text mode). + + </quote> + + &s.code;Bool xf86IsScreenPrimary(int scrnIndex)&e.code; + <quote><p> + This function returns &s.code;TRUE&e.code; if the primary entity + is registered with the screen referenced by + &s.code;scrnIndex&e.code;. + + </quote> + + &s.code;pciVideoPtr xf86GetPciInfoForEntity(int entityIndex)&e.code; + <quote><p> + This function returns a pointer to the &s.code;pciVideoRec&e.code; + for the specified entity. If the entity is not a PCI device, + &s.code;NULL&e.code; is returned. + + </quote> + </quote> + +The primary function for registration of resources is: + <quote><p> + &s.code;resPtr xf86RegisterResources(int entityIndex, resList list, + &f.indent;int access)&e.code; + <quote><p> + This function tries to register the resources in + &s.code;list&e.code;. If list is &s.code;NULL&e.code; it tries + to determine the resources automatically. This only works for + entities that provide a generic way to read out the resource ranges + they decode. So far this is only the case for PCI devices. By + default the PCI resources are registered as shared + (&s.code;ResShared&e.code;) if the driver wants to set a different + access type it can do so by specifying the access flags in the + third argument. A value of &s.code;0&e.code; means to use the + default settings. If for any reason the resource broker is not + able to register some of the requested resources the function will + return a pointer to a list of the failed ones. In this case the + driver may be able to move the resource to different locations. + In case of PCI bus entities this is done by passing the list of + failed resources to &s.code;xf86ReallocatePciResources()&e.code;. + When the registration succeeds, the return value is + &s.code;NULL&e.code;. + + </quote> + + &s.code;resPtr xf86ReallocatePciResources(int entityIndex, resPtr pRes)&e.code; + <quote><p> + This function takes a list of PCI resources that need to be + reallocated and returns &s.code;NULL&e.code when all relocations are + successful. + &s.code;xf86RegisterResources()&e.code; should be called again to + register the relocated resources with the broker. + If the reallocation fails, a list of the resources that could not be + relocated is returned. + + </quote> + </quote> + +Two functions are provided to obtain a resource range of a given type: + <quote><p> + &s.code;resRange xf86GetBlock(long type, memType size, + &f.indent;memType window_start, memType window_end, + &f.indent;memType align_mask, resPtr avoid)&e.code; + <quote><p> + This function tries to find a block range of size + &s.code;size&e.code; and type &s.code;type&e.code; in a window + bound by &s.code;window_start&e.code; and &s.code;window_end&e.code; + with the alignment specified in &s.code;align_mask&e.code;. + Optionally a list of resource ranges which should be avoided within + the window can be supplied. On failure a zero-length range of + type &s.code;ResEnd&e.code; will be returned. + + </quote> + &s.code;resRange xf86GetSparse(long type, memType fixed_bits, + &f.indent;memType decode_mask, memType address_mask, + &f.indent;resPtr avoid)&e.code; + <quote><p> + This function is like the previous one, but attempts to find a + sparse range instead of a block range. Here three values have to + be specified: the &s.code;address_mask&e.code; which marks all + bits of the mask part of the address, the &s.code;decode_mask&e.code; + which masks out the bits which are hardcoded and are therefore + not available for relocation and the values of the fixed bits. + The function tries to find a base that satisfies the given condition. + If the function fails it will return a zero range of type + &s.code;ResEnd&e.code;. Optionally it might be passed a list of + resource ranges to avoid. + + </quote> + </quote> + +Some PCI devices are broken in the sense that they return invalid size +information for a certain resource. In this case the driver can supply +the correct size and make sure that the resource range allocated for +the card is large enough to hold the address range decoded by the card. +The function &s.code;xf86FixPciResource()&e.code; can be used to do this: + <quote><p> + &s.code;Bool xf86FixPciResource(int entityIndex, unsigned int prt, + &f.indent;CARD32 alignment, long type)&e.code; + <quote><p> + This function fixes a PCI resource allocation. The + &s.code;prt&e.code; parameter contains the number of the PCI base + register that needs to be fixed (&s.code;0-5&e.code;, and + &s.code;6&e.code; for the BIOS base register). The size is + specified by the alignment. Since PCI resources need to span an + integral range of size &s.code;2^n&e.code;, the alignment also + specifies the number of addresses that will be decoded. If the + driver specifies a type mask it can override the default type for + PCI resources which is &s.code;ResShared&e.code;. The resource + broker needs to know that to find a matching resource range. This + function should be called before calling + &s.code;xf86RegisterResources()&e.code;. The return value is + &s.code;TRUE&e.code; when the function succeeds. + + </quote> + + &s.code;Bool xf86CheckPciMemBase(pciVideoPtr pPci, memType base)&e.code; + <quote><p> + This function checks that the memory base address specified matches + one of the PCI base address register values for the given PCI + device. This is mostly used to check that an externally provided + base address (e.g., from a config file) matches an actual value + allocated to a device. + + </quote> + </quote> + +The driver may replace the generic access control functions for an entity. +This is done with the &s.code;xf86SetAccessFuncs()&e.code;: + <quote><p> + &s.code;void xf86SetAccessFuncs(EntityInfoPtr pEnt, + &f.indent;xf86SetAccessFuncPtr funcs, + &f.indent;xf86SetAccessFuncPtr oldFuncs)&e.code; + <quote><p> + with: + </quote> + + <verb> + typedef struct { + xf86AccessPtr mem; + xf86AccessPtr io; + xf86AccessPtr io_mem; + } xf86SetAccessFuncRec, *xf86SetAccessFuncPtr; + </verb> + + <quote><p> + The driver can pass three functions: one for I/O access, one for + memory access and one for combined memory and I/O access. If the + memory access and combined access functions are identical the + common level assumes that the memory access cannot be controlled + independently of I/O access, if the I/O access function and the + combined access functions are the same it is assumed that I/O can + not be controlled independently. If memory and I/O have to be + controlled together all three values should be the same. If a + non &s.code;NULL&e.code; value is passed as third argument it is + interpreted as an address where to store the old access record. + If the third argument is &s.code;NULL&e.code; it will be assumed + that the generic access should be enabled before replacing the + access functions. Otherwise it will be disabled. The driver may + enable them itself using the returned values. It should do this + from its replacement access functions as the generic access may + be disabled by the common level on certain occasions. If replacement + functions are specified they must control all resources of the + specific type registered for the entity. + + </quote> + </quote> + +To find out if a specific resource range conflicts with another +resource the &s.code;xf86ChkConflict()&e.code; function may be used: + <quote><p> + &s.code;memType xf86ChkConflict(resRange *rgp, int entityIndex)&e.code; + <quote><p> + This function checks if the resource range &s.code;rgp&e.code; of + for the specified entity conflicts with with another resource. + If a conflict is found, the address of the start of the conflict + is returned. The return value is zero when there is no conflict. + + </quote> + </quote> + +The OPERATING state properties of previously registered fixed resources +can be set with the &s.code;xf86SetOperatingState()&e.code; function: + <quote><p> + &s.code;resPtr xf86SetOperatingState(resList list, int entityIndex, + &f.indent;int mask)&e.code; + <quote><p> + This function is used to set the status of a resource during + OPERATING state. &s.code;list&e.code; holds a list to which + &s.code;mask&e.code; is to be applied. The parameter + &s.code;mask&e.code; may have the value &s.code;ResUnusedOpr&e.code; + and &s.code;ResDisableOpr&e.code;. The first one should be used + if a resource isn't used by the driver during OPERATING state + although it is decoded by the device, while the latter one indicates + that the resource is not decoded during OPERATING state. Note + that the resource ranges have to match those specified during + registration. If a range has been specified starting at + &s.code;A&e.code; and ending at &s.code;B&e.code; and suppose + &s.code;C&e.code; us a value satisfying + &s.code;A < C < B&e.code; one may not + specify the resource range &s.code;(A,B)&e.code; by splitting it + into two ranges &s.code;(A,C)&e.code; and &s.code;(C,B)&e.code;. + + </quote> + </quote> + +The following two functions are provided for special cases: + <quote><p> + &s.code;void xf86RemoveEntityFromScreen(ScrnInfoPtr pScrn, int entityIndex)&e.code; + <quote><p> + This function may be used to remove an entity from a screen. This + only makes sense if a screen has more than one entity assigned or + the screen is to be deleted. No test is made if the screen has + any entities left. + + </quote> + + &s.code;void xf86DeallocateResourcesForEntity(int entityIndex, long type)&e.code; + <quote><p> + This function deallocates all resources of a given type registered + for a certain entity from the resource broker list. + + </quote> + </quote> + +<sect2>ScreenInit Phase +<p> + +All that is required in this phase is to setup the RAC flags. Note that +it is also permissible to set these flags up in the PreInit phase. The +RAC flags are held in the &s.code;racIoFlags&e.code; and &s.code;racMemFlags&e.code; fields of the +&s.code;ScrnInfoRec&e.code; for each screen. They specify which graphics operations +might require the use of shared resources. This can be specified +separately for memory and I/O resources. The available flags are defined +in &s.code;rac/xf86RAC.h&e.code;. They are: + + &s.code;RAC_FB&e.code; + <quote> + for framebuffer operations (including hw acceleration) + </quote> + &s.code;RAC_CURSOR&e.code; + <quote> + for Cursor operations + (??? I'm not sure if we need this for SW cursor it depends + on which level the sw cursor is drawn) + </quote> + &s.code;RAC_COLORMAP&e.code; + <quote> + for colormap operations + </quote> + &s.code;RAC_VIEWPORT&e.code; + <quote> + for the call to &s.code;ChipAdjustFrame()&e.code; </quote> + + +The flags are ORed together. + +<sect>Config file ``Option'' entries<label id="options"> +<p> + +Option entries are permitted in most sections and subsections of the +config file. There are two forms of option entries: + +<descrip> +<tag>Option "option-name"</tag> + A boolean option. +<tag>Option "option-name" "option-value"</tag> + An option with an arbitrary value. +</descrip> + +The option entries are handled by the parser, and a list of the parsed +options is included with each of the appropriate data structures that +the drivers have access to. The data structures used to hold the option +information are opaque to the driver, and a driver must not access the +option data directly. Instead, the common layer provides a set of +functions that may be used to access, check and manipulate the option +data. + +First, the low level option handling functions. In most cases drivers +would not need to use these directly. + + <quote><p> + &s.code;pointer xf86FindOption(pointer options, const char *name)&e.code; + <quote><p> + Takes a list of options and an option name, and returns a handle + for the first option entry in the list matching the name. Returns + &s.code;NULL&e.code; if no match is found. + + </quote> + + &s.code;char *xf86FindOptionValue(pointer options, const char *name)&e.code; + <quote><p> + Takes a list of options and an option name, and returns the value + associated with the first option entry in the list matching the + name. If the matching option has no value, an empty string + (&s.code;""&e.code;) is returned. Returns &s.code;NULL&e.code; + if no match is found. + + </quote> + + &s.code;void xf86MarkOptionUsed(pointer option)&e.code; + <quote><p> + Takes a handle for an option, and marks that option as used. + + </quote> + + &s.code;void xf86MarkOptionUsedByName(pointer options, const char *name)&e.code; + <quote><p> + Takes a list of options and an option name and marks the first + option entry in the list matching the name as used. + + </quote> + </quote> + + +Next, the higher level functions that most drivers would use. + <quote><p> + &s.code;void xf86CollectOptions(ScrnInfoPtr pScrn, pointer extraOpts)&e.code; + <quote><p> + Collect the options from each of the config file sections used by + the screen (&s.code;pScrn&e.code;) and return the merged list as + &s.code;pScrn->options&e.code;. This function requires that + &s.code;pScrn->confScreen&e.code;, &s.code;pScrn->display&e.code;, + &s.code;pScrn->monitor&e.code;, + &s.code;pScrn->numEntities&e.code;, and + &s.code;pScrn->entityList&e.code; are initialised. + &s.code;extraOpts&e.code; may optionally be set to an additional + list of options to be combined with the others. The order of + precedence for options is &s.code;extraOpts&e.code;, display, + confScreen, monitor, device. + + </quote> + + &s.code;void xf86ProcessOptions(int scrnIndex, pointer options, + &f.indent;OptionInfoPtr optinfo)&e.code; + <quote><p> + Processes a list of options according to the information in the + array of &s.code;OptionInfoRecs&e.code; (&s.code;optinfo&e.code;). + The resulting information is stored in the &s.code;value&e.code; + fields of the appropriate &s.code;optinfo&e.code; entries. The + &s.code;found&e.code; fields are set to &s.code;TRUE&e.code; + when an option with a value of the correct type if found, and + &s.code;FALSE&e.code; otherwise. The &s.code;type&e.code; field + is used to determine the expected value type for each option. + Each option in the list of options for which there is a name match + (but not necessarily a value type match) is marked as used. + Warning messages are printed when option values don't match the + types specified in the optinfo data. + + NOTE: If this function is called before a driver's screen number + is known (e.g., from the &s.code;ChipProbe()&e.code; function) a + &s.code;scrnIndex&e.code; value of &s.code;-1&e.code; should be + used. + + NOTE 2: Given that this function stores into the + &s.code;OptionInfoRecs&e.code; pointed to by &s.code;optinfo&e.code, + the caller should ensure the &s.code;OptionInfoRecs&e.code; are + (re-)initialised before the call, especially if the caller expects + to use the predefined option values as defaults. + + The &s.code;OptionInfoRec&e.code; is defined as follows: + + <verb> + typedef struct { + double freq; + int units; + } OptFrequency; + + typedef union { + unsigned long num; + char * str; + double realnum; + Bool bool; + OptFrequency freq; + } ValueUnion; + + typedef enum { + OPTV_NONE = 0, + OPTV_INTEGER, + OPTV_STRING, /* a non-empty string */ + OPTV_ANYSTR, /* Any string, including an empty one */ + OPTV_REAL, + OPTV_BOOLEAN, + OPTV_FREQ + } OptionValueType; + + typedef enum { + OPTUNITS_HZ = 1, + OPTUNITS_KHZ, + OPTUNITS_MHZ + } OptFreqUnits; + + typedef struct { + int token; + const char* name; + OptionValueType type; + ValueUnion value; + Bool found; + } OptionInfoRec, *OptionInfoPtr; + </verb> + + &s.code;OPTV_FREQ&e.code; can be used for options values that are + frequencies. These values are a floating point number with an + optional unit name appended. The unit name can be one of "Hz", + "kHz", "k", "MHz", "M". The multiplier associated with the unit + is stored in &s.code;freq.units&e.code;, and the scaled frequency + is stored in &s.code;freq.freq&e.code;. When no unit is specified, + &s.code;freq.units&e.code; is set to &s.code;0&e.code;, and + &s.code;freq.freq&e.code; is unscaled. + + Typical usage is to setup an array of + &s.code;OptionInfoRecs&e.code; with all fields initialised. + The &s.code;value&e.code; and &s.code;found&e.code; fields get + set by &s.code;xf86ProcessOptions()&e.code;. For cases where the + value parsing is more complex, the driver should specify + &s.code;OPTV_STRING&e.code;, and parse the string itself. An + example of using this option handling is included in the + <ref id="sample" name="Sample Driver"> section. + + </quote> + + &s.code;void xf86ShowUnusedOptions(int scrnIndex, pointer options)&e.code; + <quote><p> + Prints out warning messages for each option in the list of options + that isn't marked as used. This is intended to show options that + the driver hasn't recognised. It would normally be called near + the end of the &s.code;ChipScreenInit()&e.code; function, but only + when &s.code;serverGeneration == 1&e.code;. + + </quote> + + &s.code;OptionInfoPtr xf86TokenToOptinfo(const OptionInfoRec *table, + &f.indent;int token)&e.code; + + <quote><p> + Returns a pointer to the &s.code;OptionInfoRec&e.code; in + &s.code;table&e.code; with a token field matching + &s.code;token&e.code;. Returns &s.code;NULL&e.code; if no match + is found. + + </quote> + + &s.code;Bool xf86IsOptionSet(const OptionInfoRec *table, int token)&e.code; + <quote><p> + Returns the &s.code;found&e.code; field of the + &s.code;OptionInfoRec&e.code; in &s.code;table&e.code; with a + &s.code;token&e.code; field matching &s.code;token&e.code;. This + can be used for options of all types. Note that for options of + type &s.code;OPTV_BOOLEAN&e.code;, it isn't sufficient to check + this to determine the value of the option. Returns + &s.code;FALSE&e.code; if no match is found. + + </quote> + + &s.code;char *xf86GetOptValString(const OptionInfoRec *table, int token)&e.code; + <quote><p> + Returns the &s.code;value.str&e.code; field of the + &s.code;OptionInfoRec&e.code; in &s.code;table&e.code; with a + token field matching &s.code;token&e.code;. Returns + &s.code;NULL&e.code; if no match is found. + + </quote> + + &s.code;Bool xf86GetOptValInteger(const OptionInfoRec *table, int token, + &f.indent;int *value)&e.code; + <quote><p> + Returns via &s.code;*value&e.code; the &s.code;value.num&e.code; + field of the &s.code;OptionInfoRec&e.code; in &s.code;table&e.code; + with a &s.code;token&e.code; field matching &s.code;token&e.code;. + &s.code;*value&e.code; is only changed when a match is found so + it can be safely initialised with a default prior to calling this + function. The function return value is as for + &s.code;xf86IsOptionSet()&e.code;. + + </quote> + + &s.code;Bool xf86GetOptValULong(const OptionInfoRec *table, int token, + &f.indent;unsigned long *value)&e.code; + <quote><p> + Like &s.code;xf86GetOptValInteger()&e.code;, except the value is + treated as an &s.code;unsigned long&e.code;. + + </quote> + + &s.code;Bool xf86GetOptValReal(const OptionInfoRec *table, int token, + &f.indent;double *value)&e.code; + <quote><p> + Like &s.code;xf86GetOptValInteger()&e.code;, except that + &s.code;value.realnum&e.code; is used. + + </quote> + + &s.code;Bool xf86GetOptValFreq(const OptionInfoRec *table, int token, + &f.indent;OptFreqUnits expectedUnits, double *value)&e.code; + <quote><p> + Like &s.code;xf86GetOptValInteger()&e.code;, except that the + &s.code;value.freq&e.code; data is returned. The frequency value + is scaled to the units indicated by &s.code;expectedUnits&e.code;. + The scaling is exact when the units were specified explicitly in + the option's value. Otherwise, the &s.code;expectedUnits&e.code; + field is used as a hint when doing the scaling. In this case, + values larger than &s.code;1000&e.code; are assumed to have be + specified in the next smallest units. For example, if the Option + value is "10000" and expectedUnits is &s.code;OPTUNITS_MHZ&e.code;, + the value returned is &s.code;10&e.code;. + + </quote> + + &s.code;Bool xf86GetOptValBool(const OptionInfoRec *table, int token, Bool *value)&e.code; + <quote><p> + This function is used to check boolean options + (&s.code;OPTV_BOOLEAN&e.code;). If the function return value is + &s.code;FALSE&e.code;, it means the option wasn't set. Otherwise + &s.code;*value&e.code; is set to the boolean value indicated by + the option's value. No option &s.code;value&e.code; is interpreted + as &s.code;TRUE&e.code;. Option values meaning &s.code;TRUE&e.code; + are "1", "yes", "on", "true", and option values meaning + &s.code;FALSE&e.code; are "0", "no", "off", "false". Option names + both with the "no" prefix in their names, and with that prefix + removed are also checked and handled in the obvious way. + &s.code;*value&e.code; is not changed when the option isn't present. + It should normally be set to a default value before calling this + function. + + </quote> + + &s.code;Bool xf86ReturnOptValBool(const OptionInfoRec *table, int token, Bool def)&e.code; + <quote><p> + This function is used to check boolean options + (&s.code;OPTV_BOOLEAN&e.code;). If the option is set, its value + is returned. If the options is not set, the default value specified + by &s.code;def&e.code; is returned. The option interpretation is + the same as for &s.code;xf86GetOptValBool()&e.code;. + + </quote> + + &s.code;int xf86NameCmp(const char *s1, const char *s2)&e.code; + <quote><p> + This function should be used when comparing strings from the config + file with expected values. It works like &s.code;strcmp()&e.code;, + but is not case sensitive and space, tab, and `<tt>_</tt>' characters + are ignored in the comparison. The use of this function isn't + restricted to parsing option values. It may be used anywhere + where this functionality required. + + </quote> + </quote> + +<sect>Modules, Drivers, Include Files and Interface Issues +<p> + +NOTE: this section is incomplete. + + +<sect1>Include files +<p> + +The following include files are typically required by video drivers: + + <quote><p> + All drivers should include these: + <quote> + &s.code;"xf86.h"&nl; + "xf86_OSproc.h"&nl; + "xf86_ansic.h"&nl; + "xf86Resources.h"&e.code; + </quote> + Wherever inb/outb (and related things) are used the following should be + included: + <quote> + &s.code;"compiler.h"&e.code; + </quote> + Note: in drivers, this must be included after &s.code;"xf86_ansic.h"&e.code;. + + Drivers that need to access PCI vendor/device definitions need this: + <quote> + &s.code;"xf86PciInfo.h"&e.code; + </quote> + + Drivers that need to access the PCI config space need this: + <quote> + &s.code;"xf86Pci.h"&e.code; + </quote> + + Drivers that initialise a SW cursor need this: + <quote> + &s.code;"mipointer.h"&e.code; + </quote> + + All drivers implementing backing store need this: + <quote> + &s.code;"mibstore.h"&e.code; + </quote> + + All drivers using the mi colourmap code need this: + <quote> + &s.code;"micmap.h"&e.code; + </quote> + + If a driver uses the vgahw module, it needs this: + <quote> + &s.code;"vgaHW.h"&e.code; + </quote> + + Drivers supporting VGA or Hercules monochrome screens need: + <quote> + &s.code;"xf1bpp.h"&e.code; + </quote> + + Drivers supporting VGA or EGC 16-colour screens need: + <quote> + &s.code;"xf4bpp.h"&e.code; + </quote> + + Drivers using cfb need: + <quote> + &s.code;#define PSZ 8&nl; + #include "cfb.h"&nl; + #undef PSZ&e.code; + </quote> + + Drivers supporting bpp 16, 24 or 32 with cfb need one or more of: + <quote> + &s.code;"cfb16.h"&nl; + "cfb24.h"&nl; + "cfb32.h"&e.code; + </quote> + + If a driver uses XAA, it needs these: + <quote> + &s.code;"xaa.h"&nl; + "xaalocal.h"&e.code; + </quote> + + If a driver uses the fb manager, it needs this: + <quote> + &s.code;"xf86fbman.h"&e.code; + </quote> + </quote> + +Non-driver modules should include &s.code;"xf86_ansic.h"&e.code; to get the correct +wrapping of ANSI C/libc functions. + +All modules must NOT include any system include files, or the following: + + <quote> + &s.code;"xf86Priv.h"&nl; + "xf86Privstr.h"&nl; + "xf86_OSlib.h"&nl; + "Xos.h"&e.code; + </quote> + +In addition, "xf86_libc.h" must not be included explicitly. It is +included implicitly by "xf86_ansic.h". + + +<sect>Offscreen Memory Manager +<p> + +Management of offscreen video memory may be handled by the XFree86 +framebuffer manager. Once the offscreen memory manager is running, +drivers or extensions may allocate, free or resize areas of offscreen +video memory using the following functions (definitions taken from +&s.code;xf86fbman.h&e.code;): + +<code> + typedef struct _FBArea { + ScreenPtr pScreen; + BoxRec box; + int granularity; + void (*MoveAreaCallback)(struct _FBArea*, struct _FBArea*) + void (*RemoveAreaCallback)(struct _FBArea*) + DevUnion devPrivate; + } FBArea, *FBAreaPtr; + + typedef void (*MoveAreaCallbackProcPtr)(FBAreaPtr from, FBAreaPtr to) + typedef void (*RemoveAreaCallbackProcPtr)(FBAreaPtr) + + FBAreaPtr xf86AllocateOffscreenArea ( + ScreenPtr pScreen, + int width, int height, + int granularity, + MoveAreaCallbackProcPtr MoveAreaCallback, + RemoveAreaCallbackProcPtr RemoveAreaCallback, + pointer privData + ) + + void xf86FreeOffscreenArea (FBAreaPtr area) + + Bool xf86ResizeOffscreenArea ( + FBAreaPtr area + int w, int h + ) +</code> + +The function: +<quote> + &s.code;Bool xf86FBManagerRunning(ScreenPtr pScreen)&e.code; +</quote> + +can be used by an extension to check if the driver has initialized +the memory manager. The manager is not available if this returns +&s.code;FALSE&e.code; and the functions above will all fail. + + +&s.code;xf86AllocateOffscreenArea()&e.code; can be used to request a +rectangle of dimensions &s.code;width&e.code; x &s.code;height&e.code; +(in pixels) from unused offscreen memory. &s.code;granularity&e.code; +specifies that the leftmost edge of the rectangle must lie on some +multiple of &s.code;granularity&e.code; pixels. A granularity of zero +means the same thing as a granularity of one - no alignment preference. +A &s.code;MoveAreaCallback&e.code; can be provided to notify the requester +when the offscreen area is moved. If no &s.code;MoveAreaCallback&e.code; +is supplied then the area is considered to be immovable. The +&s.code;privData&e.code; field will be stored in the manager's internal +structure for that allocated area and will be returned to the requester +in the &s.code;FBArea&e.code; passed via the +&s.code;MoveAreaCallback&e.code;. An optional +&s.code;RemoveAreaCallback&e.code; is provided. If the driver provides +this it indicates that the area should be allocated with a lower priority. +Such an area may be removed when a higher priority request (one that +doesn't have a &s.code;RemoveAreaCallback&e.code;) is made. When this +function is called, the driver will have an opportunity to do whatever +cleanup it needs to do to deal with the loss of the area, but it must +finish its cleanup before the function exits since the offscreen memory +manager will free the area immediately after. + +&s.code;xf86AllocateOffscreenArea()&e.code; returns &s.code;NULL&e.code; +if it was unable to allocate the requested area. When no longer needed, +areas should be freed with &s.code;xf86FreeOffscreenArea()&e.code;. + +&s.code;xf86ResizeOffscreenArea()&e.code; resizes an existing +&s.code;FBArea&e.code;. &s.code;xf86ResizeOffscreenArea()&e.code; +returns &s.code;TRUE&e.code; if the resize was successful. If +&s.code;xf86ResizeOffscreenArea()&e.code; returns &s.code;FALSE&e.code;, +the original &s.code;FBArea&e.code; is left unmodified. Resizing an +area maintains the area's original &s.code;granularity&e.code;, +&s.code;devPrivate&e.code;, and &s.code;MoveAreaCallback&e.code;. +&s.code;xf86ResizeOffscreenArea()&e.code; has considerably less overhead +than freeing the old area then reallocating the new size, so it should +be used whenever possible. + +The function: + <quote> + &s.code;Bool xf86QueryLargestOffscreenArea( + &f.indent;ScreenPtr pScreen, + &f.indent;int *width, int *height, + &f.indent;int granularity, + &f.indent;int preferences, + &f.indent;int priority + &nl)&e.code; + </quote> + +is provided to query the width and height of the largest single +&s.code;FBArea&e.code; allocatable given a particular priority. +&s.code;preferences&e.code; can be one of the following to indicate +whether width, height or area should be considered when determining +which is the largest single &s.code;FBArea&e.code; available. + + <quote> + &s.code;FAVOR_AREA_THEN_WIDTH&nl; + FAVOR_AREA_THEN_HEIGHT&nl; + FAVOR_WIDTH_THEN_AREA&nl; + FAVOR_HEIGHT_THEN_AREA&e.code; + </quote> + +&s.code;priority&e.code; is one of the following: + + <quote><p> + &s.code;PRIORITY_LOW&e.code; + <quote><p> + Return the largest block available without stealing anyone else's + space. This corresponds to the priority of allocating a + &s.code;FBArea&e.code; when a &s.code;RemoveAreaCallback&e.code; + is provided. + + </quote> + &s.code;PRIORITY_NORMAL&e.code; + <quote><p> + Return the largest block available if it is acceptable to steal a + lower priority area from someone. This corresponds to the priority + of allocating a &s.code;FBArea&e.code; without providing a + &s.code;RemoveAreaCallback&e.code;. + + </quote> + &s.code;PRIORITY_EXTREME&e.code; + <quote><p> + Return the largest block available if all &s.code;FBAreas&e.code; + that aren't locked down were expunged from memory first. This + corresponds to any allocation made directly after a call to + &s.code;xf86PurgeUnlockedOffscreenAreas()&e.code;. + + </quote> + </quote> + + +The function: + + <quote> + &s.code;Bool xf86PurgeUnlockedOffscreenAreas(ScreenPtr pScreen)&e.code; + </quote> + +is provided as an extreme method to free up offscreen memory. This +will remove all removable &s.code;FBArea&e.code; allocations. + + +Initialization of the XFree86 framebuffer manager is done via + + <quote> + &s.code;Bool xf86InitFBManager(ScreenPtr pScreen, BoxPtr FullBox)&e.code; + </quote> + +&s.code;FullBox&e.code; represents the area of the framebuffer that the +manager is allowed to manage. This is typically a box with a width of +&s.code;pScrn->displayWidth&e.code; and a height of as many lines as +can be fit within the total video memory, however, the driver can reserve +areas at the extremities by passing a smaller area to the manager. + +&s.code;xf86InitFBManager()&e.code; must be called before XAA is +initialized since XAA uses the manager for it's pixmap cache. + +An alternative function is provided to allow the driver to initialize +the framebuffer manager with a Region rather than a box. + + <quote> + &s.code;Bool xf86InitFBManagerRegion(ScreenPtr pScreen, + &f.indent;RegionPtr FullRegion)&e.code; + </quote> + +&s.code;xf86InitFBManagerRegion()&e.code;, unlike +&s.code;xf86InitFBManager()&e.code;, does not remove the area used for +the visible screen so that area should not be included in the region +passed to the function. &s.code;xf86InitFBManagerRegion()&e.code; is +useful when non-contiguous areas are available to be managed, and is +required when multiple framebuffers are stored in video memory (as in +the case where an overlay of a different depth is stored as a second +framebuffer in offscreen memory). + + +<sect>Colormap Handling<label id="cmap"> +<p> + +A generic colormap handling layer is provided within the XFree86 common +layer. This layer takes care of most of the details, and only requires +a function from the driver that loads the hardware palette when required. +To use the colormap layer, a driver calls the +&s.code;xf86HandleColormaps()&e.code; function. + + <quote><p> + &s.code;Bool xf86HandleColormaps(ScreenPtr pScreen, int maxColors, + &f.indent;int sigRGBbits, LoadPaletteFuncPtr loadPalette, + &f.indent;SetOverscanFuncPtr setOverscan, + unsigned int flags)&e.code; + <quote><p> + This function must be called after the default colormap has been + initialised. The &s.code;pScrn->gamma&e.code; field must also + be initialised, preferably by calling &s.code;xf86SetGamma()&e.code;. + &s.code;maxColors&e.code; is the number of entries in the palette. + &s.code;sigRGBbits&e.code; is the size in bits of each color + component in the DAC's palette. &s.code;loadPalette&e.code; + is a driver-provided function for loading a colormap into the + hardware, and is described below. &s.code;setOverscan&e.code; is + an optional function that may be provided when the overscan color + is an index from the standard LUT and when it needs to be adjusted + to keep it as close to black as possible. The + &s.code;setOverscan&e.code; function programs the overscan index. + It shouldn't normally be used for depths other than 8. + &s.code;setOverscan&e.code; should be set to &s.code;NULL&e.code; + when it isn't needed. &s.code;flags&e.code; may be set to the + following (which may be ORed together): + + &s.code;CMAP_PALETTED_TRUECOLOR&e.code; + <quote><p> + the TrueColor visual is paletted and is + just a special case of DirectColor. + This flag is only valid for + &s.code;bpp > 8&e.code;. + + </quote> + + &s.code;CMAP_RELOAD_ON_MODE_SWITCH&e.code; + <quote><p> + reload the colormap automatically + after mode switches. This is useful + for when the driver is resetting the + hardware during mode switches and + corrupting or erasing the hardware + palette. + + </quote> + + &s.code;CMAP_LOAD_EVEN_IF_OFFSCREEN&e.code; + <quote><p> + reload the colormap even if the screen + is switched out of the server's VC. + The palette is <it>not</it> reloaded when + the screen is switched back in, nor after + mode switches. This is useful when the + driver needs to keep track of palette + changes. + + </quote> + + The colormap layer normally reloads the palette after VT enters so it + is not necessary for the driver to save and restore the palette + when switching VTs. The driver must, however, still save the + initial palette during server start up and restore it during + server exit. + + </quote> + + &s.code;void LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, + &f.indent;LOCO *colors, VisualPtr pVisual)&e.code; + <quote><p> + &s.code;LoadPalette()&e.code; is a driver-provided function for + loading a colormap into hardware. &s.code;colors&e.code; is the + array of RGB values that represent the full colormap. + &s.code;indices&e.code; is a list of index values into the colors + array. These indices indicate the entries that need to be updated. + &s.code;numColors&e.code; is the number of the indices to be + updated. + + </quote> + + &s.code;void SetOverscan(ScrnInfoPtr pScrn, int overscan)&e.code; + <quote><p> + &s.code;SetOverscan()&e.code; is a driver-provided function for + programming the &s.code;overscan&e.code; index. As described + above, it is normally only appropriate for LUT modes where all + colormap entries are available for the display, but where one of + them is also used for the overscan (typically 8bpp for VGA compatible + LUTs). It isn't required in cases where the overscan area is + never visible. + + </quote> + </quote> + + +<sect>DPMS Extension +<p> + +Support code for the DPMS extension is included in the XFree86 common layer. +This code provides an interface between the main extension code, and a means +for drivers to initialise DPMS when they support it. One function is +available to drivers to do this initialisation, and it is always available, +even when the DPMS extension is not supported by the core server (in +which case it returns a failure result). + + + <quote><p> + &s.code;Bool xf86DPMSInit(ScreenPtr pScreen, DPMSSetProcPtr set, int flags)&e.code; + <quote><p> + This function registers a driver's DPMS level programming function + &s.code;set&e.code;. It also checks + &s.code;pScrn->options&e.code; for the "dpms" option, and when + present marks DPMS as being enabled for that screen. The + &s.code;set&e.code; function is called whenever the DPMS level + changes, and is used to program the requested level. + &s.code;flags&e.code; is currently not used, and should be + &s.code;0&e.code;. If the initialisation fails for any reason, + including when there is no DPMS support in the core server, the + function returns &s.code;FALSE&e.code;. + + </quote> + </quote> + + +Drivers that implement DPMS support must provide the following function, +that gets called when the DPMS level is changed: + + + <quote><p> + &s.code;void ChipDPMSSet(ScrnInfoPtr pScrn, int level, int flags)&e.code; + <quote><p> + Program the DPMS level specified by &s.code;level&e.code;. Valid + values of &s.code;level&e.code; are &s.code;DPMSModeOn&e.code;, + &s.code;DPMSModeStandby&e.code;, &s.code;DPMSModeSuspend&e.code;, + &s.code;DPMSModeOff&e.code;. These values are defined in + &s.code;"extensions/dpms.h"&e.code;. + + </quote> + </quote> + + +<sect>DGA Extension +<p> + +Drivers can support the XFree86 Direct Graphics Architecture (DGA) by +filling out a structure of function pointers and a list of modes and +passing them to DGAInit. + + <quote><p> + &s.code;Bool DGAInit(ScreenPtr pScreen, DGAFunctionPtr funcs, + &f.indent;DGAModePtr modes, int num)&e.code; + <quote><p> + <verb> +/** The DGAModeRec **/ + +typedef struct { + int num; + DisplayModePtr mode; + int flags; + int imageWidth; + int imageHeight; + int pixmapWidth; + int pixmapHeight; + int bytesPerScanline; + int byteOrder; + int depth; + int bitsPerPixel; + unsigned long red_mask; + unsigned long green_mask; + unsigned long blue_mask; + int viewportWidth; + int viewportHeight; + int xViewportStep; + int yViewportStep; + int maxViewportX; + int maxViewportY; + int viewportFlags; + int offset; + unsigned char *address; + int reserved1; + int reserved2; +} DGAModeRec, *DGAModePtr; +</verb> + + &s.code;num&e.code; + <quote> + Can be ignored. The DGA DDX will assign these numbers. + </quote> + + &s.code;mode&e.code; + <quote> + A pointer to the &s.code;DisplayModeRec&e.code; for this mode. + </quote> + + &s.code;flags&e.code; + <quote><p> + The following flags are defined and may be OR'd together: + + &s.code;DGA_CONCURRENT_ACCESS&e.code; + <quote><p> + Indicates that the driver supports concurrent graphics + accelerator and linear framebuffer access. + + </quote> + + &s.code;DGA_FILL_RECT&nl; + DGA_BLIT_RECT&nl; + DGA_BLIT_RECT_TRANS&e.code; + <quote><p> + Indicates that the driver supports the FillRect, BlitRect + or BlitTransRect functions in this mode. + + </quote> + + &s.code;DGA_PIXMAP_AVAILABLE&e.code; + <quote><p> + Indicates that Xlib may be used on the framebuffer. + This flag will usually be set unless the driver wishes + to prohibit this for some reason. + + </quote> + + &s.code;DGA_INTERLACED&nl; + DGA_DOUBLESCAN&e.code; + <quote><p> + Indicates that these are interlaced or double scan modes. + + </quote> + </quote> + + &s.code;imageWidth&nl; + imageHeight&e.code; + <quote><p> + These are the dimensions of the linear framebuffer + accessible by the client. + + </quote> + + &s.code;pixmapWidth&nl; + pixmapHeight&e.code; + <quote><p> + These are the dimensions of the area of the + framebuffer accessible by the graphics accelerator. + + </quote> + + &s.code;bytesPerScanline&e.code; + <quote><p> + Pitch of the framebuffer in bytes. + + </quote> + + &s.code;byteOrder&e.code; + <quote><p> + Usually the same as + &s.code;pScrn->imageByteOrder&e.code;. + + </quote> + + &s.code;depth&e.code; + <quote><p> + The depth of the framebuffer in this mode. + + </quote> + + &s.code;bitsPerPixel&e.code; + <quote><p> + The number of bits per pixel in this mode. + + </quote> + + &s.code;red_mask&nl; + green_mask&nl; + blue_mask&e.code; + <quote><p> + The RGB masks for this mode, if applicable. + + </quote> + + &s.code;viewportWidth&nl; + viewportHeight&e.code; + <quote><p> + Dimensions of the visible part of the framebuffer. + Usually &s.code;mode->HDisplay&e.code; and + &s.code;mode->VDisplay&e.code;. + + </quote> + + &s.code;xViewportStep&nl; + yViewportStep&e.code; + <quote><p> + The granularity of x and y viewport positions that + the driver supports in this mode. + + </quote> + + &s.code;maxViewportX&nl; + maxViewportY&e.code; + <quote><p> + The maximum viewport position supported by the + driver in this mode. + + </quote> + + &s.code;viewportFlags&e.code; + <quote><p> + The following may be OR'd together: + + &s.code;DGA_FLIP_IMMEDIATE&e.code; + <quote><p> + The driver supports immediate viewport changes. + + </quote> + &s.code;DGA_FLIP_RETRACE&e.code; + <quote<p> + The driver supports viewport changes at retrace. + + </quote> + </quote> + + &s.code;offset&e.code; + <quote><p> + The offset into the linear framebuffer that corresponds to + pixel (0,0) for this mode. + + </quote> + + &s.code;address&e.code; + <quote><p> + The virtual address of the framebuffer as mapped by the driver. + This is needed when DGA_PIXMAP_AVAILABLE is set. + + </quote> + + <verb> +/** The DGAFunctionRec **/ + +typedef struct { + Bool (*OpenFramebuffer)( + ScrnInfoPtr pScrn, + char **name, + unsigned char **mem, + int *size, + int *offset, + int *extra + ); + void (*CloseFramebuffer)(ScrnInfoPtr pScrn); + Bool (*SetMode)(ScrnInfoPtr pScrn, DGAModePtr pMode); + void (*SetViewport)(ScrnInfoPtr pScrn, int x, int y, int flags); + int (*GetViewport)(ScrnInfoPtr pScrn); + void (*Sync)(ScrnInfoPtr); + void (*FillRect)( + ScrnInfoPtr pScrn, + int x, int y, int w, int h, + unsigned long color + ); + void (*BlitRect)( + ScrnInfoPtr pScrn, + int srcx, int srcy, + int w, int h, + int dstx, int dsty + ); + void (*BlitTransRect)( + ScrnInfoPtr pScrn, + int srcx, int srcy, + int w, int h, + int dstx, int dsty, + unsigned long color + ); +} DGAFunctionRec, *DGAFunctionPtr; +</verb> + + </quote> + + &s.code;Bool OpenFramebuffer (pScrn, name, mem, size, offset, extra)&e.code; + <quote><p> + &s.code;OpenFramebuffer()&e.code; should pass the client everything + it needs to know to be able to open the framebuffer. These + parameters are OS specific and their meanings are to be interpreted + by an OS specific client library. + + &s.code;name&e.code; + <quote><p> + The name of the device to open or &s.code;NULL&e.code; if + there is no special device to open. A &s.code;NULL&e.code; + name tells the client that it should open whatever device + one would usually open to access physical memory. + + </quote> + &s.code;mem&e.code; + <quote><p> + The physical address of the start of the framebuffer. + + </quote> + &s.code;size&e.code; + <quote><p> + The size of the framebuffer in bytes. + + </quote> + &s.code;offset&e.code; + <quote><p> + Any offset into the device, if applicable. + + </quote> + &s.code;flags&e.code; + <quote><p> + Any additional information that the client may need. + Currently, only the &s.code;DGA_NEED_ROOT&e.code; flag is + defined. + + </quote> + </quote> + + &s.code;void CloseFramebuffer (pScrn)&e.code; + <quote><p> + &s.code;CloseFramebuffer()&e.code; merely informs the driver (if it + even cares) that client no longer needs to access the framebuffer + directly. This function is optional. + + </quote> + + &s.code;Bool SetMode (pScrn, pMode)&e.code; + <quote><p> + &s.code;SetMode()&e.code; tells the driver to initialize the mode + passed to it. If &s.code;pMode&e.code; is &s.code;NULL&e.code;, + then the driver should restore the original pre-DGA mode. + + </quote> + + &s.code;void SetViewport (pScrn, x, y, flags)&e.code; + <quote><p> + &s.code;SetViewport()&e.code; tells the driver to make the upper + left-hand corner of the visible screen correspond to coordinate + &s.code;(x,y)&e.code; on the framebuffer. &s.code;Flags&e.code; + currently defined are: + + &s.code;DGA_FLIP_IMMEDIATE&e.code; + <quote><p> + The viewport change should occur immediately. + + </quote> + &s.code;DGA_FLIP_RETRACE&e.code; + <quote><p> + The viewport change should occur at the + vertical retrace, but this function should + return sooner if possible. + + </quote> + The &s.code;(x,y)&e.code; locations will be passed as the client + specified them, however, the driver is expected to round these + locations down to the next supported location as specified by the + &s.code;xViewportStep&e.code; and &s.code;yViewportStep&e.code; + for the current mode. + + </quote> + + &s.code;int GetViewport (pScrn)&e.code; + <quote><p> + &s.code;GetViewport()&e.code; gets the current page flip status. + Set bits in the returned int correspond to viewport change requests + still pending. For instance, set bit zero if the last SetViewport + request is still pending, bit one if the one before that is still + pending, etc. + + </quote> + + &s.code;void Sync (pScrn)&e.code; + <quote><p> + This function should ensure that any graphics accelerator operations + have finished. This function should not return until the graphics + accelerator is idle. + + </quote> + + &s.code;void FillRect (pScrn, x, y, w, h, color)&e.code; + <quote><p> + This optional function should fill a rectangle + &s.code;w × h&e.code; located at + &s.code;(x,y)&e.code; in the given color. + + </quote> + + &s.code;void BlitRect (pScrn, srcx, srcy, w, h, dstx, dsty)&e.code; + <quote><p> + This optional function should copy an area + &s.code;w × h&e.code; located at + &s.code;(srcx,srcy)&e.code; to location &s.code;(dstx,dsty)&e.code;. + This function will need to handle copy directions as appropriate. + + </quote> + + &s.code;void BlitTransRect (pScrn, srcx, srcy, w, h, dstx, dsty, color)&e.code; + <quote><p> + This optional function is the same as BlitRect except that pixels + in the source corresponding to the color key &s.code;color&e.code; + should be skipped. + + </quote> + </quote> + +<sect>The XFree86 X Video Extension (Xv) Device Dependent Layer +<p> + +XFree86 offers the X Video Extension which allows clients to treat video +as any another primitive and ``Put'' video into drawables. By default, +the extension reports no video adaptors as being available since the +DDX layer has not been initialized. The driver can initialize the DDX +layer by filling out one or more &s.code;XF86VideoAdaptorRecs&e.code; +as described later in this document and passing a list of +&s.code;XF86VideoAdaptorPtr&e.code; pointers to the following function: + + <quote> + &s.code;Bool xf86XVScreenInit( + &f.indent;ScreenPtr pScreen, + &f.indent;XF86VideoAdaptorPtr *adaptPtrs, + &f.indent;int num)&e.code; + </quote> + +After doing this, the extension will report video adaptors as being +available, providing the data in their respective +&s.code;XF86VideoAdaptorRecs&e.code; was valid. +&s.code;xf86XVScreenInit()&e.code; <em>copies</em> data from the structure +passed to it so the driver may free it after the initialization. At +the moment, the DDX only supports rendering into Window drawables. +Pixmap rendering will be supported after a sufficient survey of suitable +hardware is completed. + +The &s.code;XF86VideoAdaptorRec&e.code;: + +<quote><p> +<verb> +typedef struct { + unsigned int type; + int flags; + char *name; + int nEncodings; + XF86VideoEncodingPtr pEncodings; + int nFormats; + XF86VideoFormatPtr pFormats; + int nPorts; + DevUnion *pPortPrivates; + int nAttributes; + XF86AttributePtr pAttributes; + int nImages; + XF86ImagePtr pImages; + PutVideoFuncPtr PutVideo; + PutStillFuncPtr PutStill; + GetVideoFuncPtr GetVideo; + GetStillFuncPtr GetStill; + StopVideoFuncPtr StopVideo; + SetPortAttributeFuncPtr SetPortAttribute; + GetPortAttributeFuncPtr GetPortAttribute; + QueryBestSizeFuncPtr QueryBestSize; + PutImageFuncPtr PutImage; + QueryImageAttributesFuncPtr QueryImageAttributes; +} XF86VideoAdaptorRec, *XF86VideoAdaptorPtr; +</verb> + + Each adaptor will have its own XF86VideoAdaptorRec. The fields are + as follows: + + &s.code;type&e.code; + <quote><p> + This can be any of the following flags OR'd together. + + &s.code;XvInputMask&e.code; + &s.code;XvOutputMask&e.code; + <quote><p> + These refer to the target drawable and are similar to a Window's + class. &s.code;XvInputMask&e.code; indicates that the adaptor + can put video into a drawable. &s.code;XvOutputMask&e.code; + indicates that the adaptor can get video from a drawable. + </quote> + + &s.code;XvVideoMask&e.code; + &s.code;XvStillMask&e.code; + &s.code;XvImageMask&e.code; + <quote><p> + These indicate that the adaptor supports video, still or + image primitives respectively. + </quote> + + &s.code;XvWindowMask&e.code; + &s.code;XvPixmapMask&e.code; + <quote><p> + These indicate the types of drawables the adaptor is capable + of rendering into. At the moment, Pixmap rendering is not + supported and the &s.code;XvPixmapMask&e.code; flag is ignored. + </quote> + + </quote> + + &s.code;flags&e.code; + <quote><p> + Currently, the following flags are defined: + + &s.code;VIDEO_NO_CLIPPING&e.code; + <quote><p> + This indicates that the video adaptor does not support + clipping. The driver will never receive ``Put'' requests + where less than the entire area determined by + &s.code;drw_x&e.code;, &s.code;drw_y&e.code;, + &s.code;drw_w&e.code; and &s.code;drw_h&e.code; is visible. + This flag does not apply to ``Get'' requests. Hardware + that is incapable of clipping ``Gets'' may punt or get + the extents of the clipping region passed to it. + + </quote> + + &s.code;VIDEO_INVERT_CLIPLIST&e.code; + <quote><p> + This indicates that the video driver requires the clip + list to contain the regions which are obscured rather + than the regions which are are visible. + + </quote> + + &s.code;VIDEO_OVERLAID_STILLS&e.code; + <quote><p> + Implementing PutStill for hardware that does video as an + overlay can be awkward since it's unclear how long to leave + the video up for. When this flag is set, StopVideo will be + called whenever the destination gets clipped or moved so that + the still can be left up until then. + + </quote> + + &s.code;VIDEO_OVERLAID_IMAGES&e.code; + <quote><p> + Same as &s.code;VIDEO_OVERLAID_STILLS&e.code; but for images. + </quote> + + &s.code;VIDEO_CLIP_TO_VIEWPORT&e.code; + <quote><p> + Indicates that the clip region passed to the driver functions + should be clipped to the visible portion of the screen in the + case where the viewport is smaller than the virtual desktop. + </quote> + + </quote> + + &s.code;name&e.code; + <quote><p> + The name of the adaptor. + + </quote> + + &s.code;nEncodings&nl; + pEncodings&e.code; + <quote><p> + The number of encodings the adaptor is capable of and pointer + to the &s.code;XF86VideoEncodingRec&e.code; array. The + &s.code;XF86VideoEncodingRec&e.code; is described later on. + For drivers that only support XvImages there should be an encoding + named "XV_IMAGE" and the width and height should specify + the maximum size source image supported. + + </quote> + + &s.code;nFormats&nl; + pFormats&e.code; + <quote><p> + The number of formats the adaptor is capable of and pointer to + the &s.code;XF86VideoFormatRec&e.code; array. The + &s.code;XF86VideoFormatRec&e.code; is described later on. + + </quote> + + &s.code;nPorts&nl; + pPortPrivates&e.code; + <quote><p> + The number of ports is the number of separate data streams which + the adaptor can handle simultaneously. If you have more than + one port, the adaptor is expected to be able to render into more + than one window at a time. &s.code;pPortPrivates&e.code; is + an array of pointers or ints - one for each port. A port's + private data will be passed to the driver any time the port is + requested to do something like put the video or stop the video. + In the case where there may be many ports, this enables the + driver to know which port the request is intended for. Most + commonly, this will contain a pointer to the data structure + containing information about the port. In Xv, all ports on + a particular adaptor are expected to be identical in their + functionality. + + </quote> + + &s.code;nAttributes&nl; + pAttributes&e.code; + <quote><p> + The number of attributes recognized by the adaptor and a pointer to + the array of &s.code;XF86AttributeRecs&e.code;. The + &s.code;XF86AttributeRec&e.code; is described later on. + + </quote> + + &s.code;nImages&nl; + pImages&e.code; + <quote><p> + The number of &s.code;XF86ImageRecs&e.code; supported by the adaptor + and a pointer to the array of &s.code;XF86ImageRecs&e.code;. The + &s.code;XF86ImageRec&e.code; is described later on. + + </quote> + + + &s.code;PutVideo PutStill GetVideo GetStill StopVideo + SetPortAttribute GetPortAttribute QueryBestSize PutImage + QueryImageAttributes&e.code; + <quote><p> + These functions define the DDX->driver interface. In each + case, the pointer &s.code;data&e.code; is passed to the driver. + This is the port private for that port as described above. All + fields are required except under the following conditions: + + <enum> + <item>&s.code;PutVideo&e.code;, &s.code;PutStill&e.code; and + the image routines &s.code;PutImage&e.code; and + &s.code;QueryImageAttributes&e.code; are not required when the + adaptor type does not contain &s.code;XvInputMask&e.code;. + + <item>&s.code;GetVideo&e.code; and &s.code;GetStill&e.code; + are not required when the adaptor type does not contain + &s.code;XvOutputMask&e.code;. + + <item>&s.code;GetVideo&e.code; and &s.code;PutVideo&e.code; + are not required when the adaptor type does not contain + &s.code;XvVideoMask&e.code;. + + <item>&s.code;GetStill&e.code; and &s.code;PutStill&e.code; + are not required when the adaptor type does not contain + &s.code;XvStillMask&e.code;. + + <item>&s.code;PutImage&e.code; and &s.code;QueryImageAttributes&e.code; + are not required when the adaptor type does not contain + &s.code;XvImageMask&e.code;. + + </enum> + + With the exception of &s.code;QueryImageAttributes&e.code;, these + functions should return &s.code;Success&e.code; if the operation was + completed successfully. They can return &s.code;XvBadAlloc&e.code; + otherwise. &s.code;QueryImageAttributes&e.code; returns the size + of the XvImage queried. + + If the &s.code;VIDEO_NO_CLIPPING&e.code; + flag is set, the &s.code;clipBoxes&e.code; may be ignored by + the driver. &s.code;ClipBoxes&e.code; is an &s.code;X-Y&e.code; + banded region identical to those used throughout the server. + The clipBoxes represent the visible portions of the area determined + by &s.code;drw_x&e.code;, &s.code;drw_y&e.code;, + &s.code;drw_w&e.code; and &s.code;drw_h&e.code; in the Get/Put + function. The boxes are in screen coordinates, are guaranteed + not to overlap and an empty region will never be passed. + If the driver has specified &s.code;VIDEO_INVERT_CLIPLIST&e.code;, + &s.code;clipBoxes&e.code; will indicate the areas of the primitive + which are obscured rather than the areas visible. + + </quote> + + &s.code;typedef int (* PutVideoFuncPtr)( ScrnInfoPtr pScrn, + &f.indent;short vid_x, short vid_y, short drw_x, short drw_y, + &f.indent;short vid_w, short vid_h, short drw_w, short drw_h, + &f.indent;RegionPtr clipBoxes, pointer data )&e.code; + <quote><p> + This indicates that the driver should take a subsection + &s.code;vid_w&e.code; by &s.code;vid_h&e.code; at location + &s.code;(vid_x,vid_y)&e.code; from the video stream and direct + it into the rectangle &s.code;drw_w&e.code; by &s.code;drw_h&e.code; + at location &s.code;(drw_x,drw_y)&e.code; on the screen, scaling as + necessary. Due to the large variations in capabilities of + the various hardware expected to be used with this extension, + it is not expected that all hardware will be able to do this + exactly as described. In that case the driver should just do + ``the best it can,'' scaling as closely to the target rectangle + as it can without rendering outside of it. In the worst case, + the driver can opt to just not turn on the video. + + </quote> + + &s.code;typedef int (* PutStillFuncPtr)( ScrnInfoPtr pScrn, + &f.indent;short vid_x, short vid_y, short drw_x, short drw_y, + &f.indent;short vid_w, short vid_h, short drw_w, short drw_h, + &f.indent;RegionPtr clipBoxes, pointer data )&e.code; + <quote><p> + This is same as &s.code;PutVideo&e.code; except that the driver + should place only one frame from the stream on the screen. + + </quote> + + &s.code;typedef int (* GetVideoFuncPtr)( ScrnInfoPtr pScrn, + &f.indent;short vid_x, short vid_y, short drw_x, short drw_y, + &f.indent;short vid_w, short vid_h, short drw_w, short drw_h, + &f.indent;RegionPtr clipBoxes, pointer data )&e.code; + <quote><p> + This is same as &s.code;PutVideo&e.code; except that the driver + gets video from the screen and outputs it. The driver should + do the best it can to get the requested dimensions correct + without reading from an area larger than requested. + + </quote> + + &s.code;typedef int (* GetStillFuncPtr)( ScrnInfoPtr pScrn, + &f.indent;short vid_x, short vid_y, short drw_x, short drw_y, + &f.indent;short vid_w, short vid_h, short drw_w, short drw_h, + &f.indent;RegionPtr clipBoxes, pointer data )&e.code; + <quote><p> + This is the same as &s.code;GetVideo&e.code; except that the + driver should place only one frame from the screen into the + output stream. + + </quote> + + &s.code;typedef void (* StopVideoFuncPtr)(ScrnInfoPtr pScrn, + &f.indent;pointer data, Bool cleanup)&e.code; + <quote><p> + This indicates the driver should stop displaying the video. + This is used to stop both input and output video. The + &s.code;cleanup&e.code; field indicates that the video is + being stopped because the client requested it to stop or + because the server is exiting the current VT. In that case + the driver should deallocate any offscreen memory areas (if + there are any) being used to put the video to the screen. If + &s.code;cleanup&e.code; is not set, the video is being stopped + temporarily due to clipping or moving of the window, etc... + and video will likely be restarted soon so the driver should + not deallocate any offscreen areas associated with that port. + + </quote> + &s.code;typedef int (* SetPortAttributeFuncPtr)(ScrnInfoPtr pScrn, + &f.indent;Atom attribute,INT32 value, pointer data)&e.code; + + &s.code;typedef int (* GetPortAttributeFuncPtr)(ScrnInfoPtr pScrn, + &f.indent;Atom attribute,INT32 *value, pointer data)&e.code; + + <quote><p> + A port may have particular attributes such as hue, + saturation, brightness or contrast. Xv clients set and + get these attribute values by sending attribute strings + (Atoms) to the server. Such requests end up at these + driver functions. It is recommended that the driver provide + at least the following attributes mentioned in the Xv client + library docs: + <quote> + &s.code;XV_ENCODING&nl; + XV_HUE&nl; + XV_SATURATION&nl; + XV_BRIGHTNESS&nl; + XV_CONTRAST&e.code; + </quote> + but the driver may recognize as many atoms as it wishes. If + a requested attribute is unknown by the driver it should return + &s.code;BadMatch&e.code;. &s.code;XV_ENCODING&e.code; is the + attribute intended to let the client specify which video + encoding the particular port should be using (see the description + of &s.code;XF86VideoEncodingRec&e.code; below). If the + requested encoding is unsupported, the driver should return + &s.code;XvBadEncoding&e.code;. If the value lies outside the + advertised range &s.code;BadValue&e.code; may be returned. + &s.code;Success&e.code; should be returned otherwise. + + </quote> + + &s.code;typedef void (* QueryBestSizeFuncPtr)(ScrnInfoPtr pScrn, + &f.indent;Bool motion, short vid_w, short vid_h, + &f.indent;short drw_w, short drw_h, + &f.indent;unsigned int *p_w, unsigned int *p_h, pointer data)&e.code; + <quote><p> + &s.code;QueryBestSize&e.code; provides the client with a way + to query what the destination dimensions would end up being + if they were to request that an area + &s.code;vid_w&e.code by &s.code;vid_h&e.code; from the video + stream be scaled to rectangle of + &s.code;drw_w&e.code; by &s.code;drw_h&e.code; on the screen. + Since it is not expected that all hardware will be able to + get the target dimensions exactly, it is important that the + driver provide this function. + + </quote> + + &s.code;typedef int (* PutImageFuncPtr)( ScrnInfoPtr pScrn, + &f.indent;short src_x, short src_y, short drw_x, short drw_y, + &f.indent;short src_w, short src_h, short drw_w, short drw_h, + &f.indent;int image, char *buf, short width, short height, + &f.indent;Bool sync, RegionPtr clipBoxes, pointer data )&e.code; + <quote><p> + This is similar to &s.code;PutStill&e.code; except that the + source of the video is not a port but the data stored in a system + memory buffer at &s.code;buf&e.code;. The data is in the format + indicated by the &s.code;image&e.code; descriptor and represents a + source of size &s.code;width&e.code; by &s.code;height&e.code;. + If &s.code;sync&e.code; is TRUE the driver should not return + from this function until it is through reading the data + from &s.code;buf&e.code;. Returning when &s.code;sync&e.code; + is TRUE indicates that it is safe for the data at &s.code;buf&e.code; + to be replaced, freed, or modified. + + </quote> + + &s.code;typedef int (* QueryImageAttributesFuncPtr)( ScrnInfoPtr pScrn, + &f.indent;int image, short *width, short *height, + &f.indent;int *pitches, int *offsets)&e.code; + <quote><p> + This function is called to let the driver specify how data for + a particular &s.code;image&e.code; of size &s.code;width&e.code; + by &s.code;height&e.code; should be stored. Sometimes only + the size and corrected width and height are needed. In that + case &s.code;pitches&e.code; and &s.code;offsets&e.code; are + NULL. The size of the memory required for the image is returned + by this function. The &s.code;width&e.code; and + &s.code;height&e.code; of the requested image can be altered by + the driver to reflect format limitations (such as component + sampling periods that are larger than one). If + &s.code;pitches&e.code; and &s.code;offsets&e.code; are not NULL, + these will be arrays with as many elements in them as there + are planes in the &s.code;image&e.code; format. The driver + should specify the pitch (in bytes) of each scanline in the + particular plane as well as the offset to that plane (in bytes) + from the beginning of the image. + + </quote> + + </quote> + +The XF86VideoEncodingRec: +<quote><p> +<verb> +typedef struct { + int id; + char *name; + unsigned short width, height; + XvRationalRec rate; +} XF86VideoEncodingRec, *XF86VideoEncodingPtr; + +</verb> + The &s.code;XF86VideoEncodingRec&e.code; specifies what encodings + the adaptor can support. Most of this data is just informational + and for the client's benefit, and is what will be reported by + &s.code;XvQueryEncodings&e.code;. The &s.code;id&e.code; field is + expected to be a unique identifier to allow the client to request a + certain encoding via the &s.code;XV_ENCODING&e.code; attribute string. + +</quote> + +The XF86VideoFormatRec: + +<quote><p> +<verb> +typedef struct { + char depth; + short class; +} XF86VideoFormatRec, *XF86VideoFormatPtr; +</verb> + + This specifies what visuals the video is viewable in. + &s.code;depth&e.code; is the depth of the visual (not bpp). + &s.code;class&e.code; is the visual class such as + &s.code;TrueColor&e.code;, &s.code;DirectColor&e.code; or + &s.code;PseudoColor&e.code;. Initialization of an adaptor will fail + if none of the visuals on that screen are supported. + +</quote> + +The XF86AttributeRec: + +<quote><p> +<verb> +typedef struct { + int flags; + int min_value; + int max_value; + char *name; +} XF86AttributeListRec, *XF86AttributeListPtr; + +</verb> + + Each adaptor may have an array of these advertising the attributes + for its ports. Currently defined flags are &s.code;XvGettable&e.code; + and &s.code;XvSettable&e.code; which may be OR'd together indicating that + attribute is ``gettable'' or ``settable'' by the client. The + &s.code;min&e.code; and &s.code;max&e.code; field specify the valid range + for the value. &s.code;Name&e.code; is a text string describing the + attribute by name. + +</quote> + +The XF86ImageRec: + +<quote><p> +<verb> +typedef struct { + int id; + int type; + int byte_order; + char guid[16]; + int bits_per_pixel; + int format; + int num_planes; + + /* for RGB formats */ + int depth; + unsigned int red_mask; + unsigned int green_mask; + unsigned int blue_mask; + + /* for YUV formats */ + unsigned int y_sample_bits; + unsigned int u_sample_bits; + unsigned int v_sample_bits; + unsigned int horz_y_period; + unsigned int horz_u_period; + unsigned int horz_v_period; + unsigned int vert_y_period; + unsigned int vert_u_period; + unsigned int vert_v_period; + char component_order[32]; + int scanline_order; +} XF86ImageRec, *XF86ImagePtr; +</verb> + + XF86ImageRec describes how video source data is laid out in memory. + The fields are as follows: + + &s.code;id&e.code; + <quote><p> + This is a unique descriptor for the format. It is often good to + set this value to the FOURCC for the format when applicable. + </quote> + + &s.code;type&e.code; + <quote><p> + This is &s.code;XvRGB&e.code; or &s.code;XvYUV&e.code;. + </quote> + + &s.code;byte_order&e.code; + <quote><p> + This is &s.code;LSBFirst&e.code; or &s.code;MSBFirst&e.code;. + </quote> + + &s.code;guid&e.code; + <quote><p> + This is the Globally Unique IDentifier for the format. When + not applicable, all characters should be NULL. + </quote> + + &s.code;bits_per_pixel&e.code; + <quote><p> + The number of bits taken up (but not necessarily used) by each + pixel. Note that for some planar formats which have fractional + bits per pixel (such as IF09) this number may be rounded _down_. + </quote> + + &s.code;format&e.code; + <quote><p> + This is &s.code;XvPlanar&e.code; or &s.code;XvPacked&e.code;. + </quote> + + &s.code;num_planes&e.code; + <quote><p> + The number of planes in planar formats. This should be set to + one for packed formats. + </quote> + + &s.code;depth&e.code; + <quote><p> + The significant bits per pixel in RGB formats (analgous to the + depth of a pixmap format). + </quote> + + &s.code;red_mask&e.code; + &s.code;green_mask&e.code; + &s.code;blue_mask&e.code; + <quote><p> + The red, green and blue bitmasks for packed RGB formats. + </quote> + + &s.code;y_sample_bits&e.code; + &s.code;u_sample_bits&e.code; + &s.code;v_sample_bits&e.code; + <quote><p> + The y, u and v sample sizes (in bits). + </quote> + + &s.code;horz_y_period&e.code; + &s.code;horz_u_period&e.code; + &s.code;horz_v_period&e.code; + <quote><p> + The y, u and v sampling periods in the horizontal direction. + </quote> + + &s.code;vert_y_period&e.code; + &s.code;vert_u_period&e.code; + &s.code;vert_v_period&e.code; + <quote><p> + The y, u and v sampling periods in the vertical direction. + </quote> + + &s.code;component_order&e.code; + <quote><p> + Uppercase ascii characters representing the order that + samples are stored within packed formats. For planar formats + this represents the ordering of the planes. Unused characters + in the 32 byte string should be set to NULL. + </quote> + + &s.code;scanline_order&e.code; + <quote><p> + This is &s.code;XvTopToBottom&e.code; or &s.code;XvBottomToTop&e.code;. + </quote> + + Since some formats (particular some planar YUV formats) may not +be completely defined by the parameters above, the guid, when +available, should provide the most accurate description of the +format. + +</quote> + +<sect>The Loader +<p> + +This section describes the interfaces to the module loader. The loader +interfaces can be divided into two groups: those that are only available to +the XFree86 common layer, and those that are also available to modules. + +<sect1>Loader Overview +<p> + +The loader is capable of loading modules in a range of object formats, +and knowledge of these formats is built in to the loader. Knowledge of +new object formats can be added to the loader in a straightforward +manner. This makes it possible to provide OS-independent modules (for +a given CPU architecture type). In addition to this, the loader can +load modules via the OS-provided &s.code;dlopen(3)&e.code; service where +available. Such modules are not platform independent, and the semantics +of &s.code;dlopen()&e.code; on most systems results in significant +limitations in the use of modules of this type. Support for +&s.code;dlopen()&e.code; modules in the loader is primarily for +experimental and development purposes. + +Symbols exported by the loader (on behalf of the core X server) to +modules are determined at compile time. Only those symbols explicitly +exported are available to modules. All external symbols of loaded +modules are exported to other modules, and to the core X server. The +loader can be requested to check for unresolved symbols at any time, +and the action to be taken for unresolved symbols can be controlled by +the caller of the loader. Typically the caller identifies which symbols +can safely remain unresolved and which cannot. + +NOTE: Now that ISO-C allows pointers to functions and pointers to data to +have different internal representations, some of the following interfaces +will need to be revisited. + +<sect1>Semi-private Loader Interface +<p> + +The following is the semi-private loader interface that is available to the +XFree86 common layer. + + <quote><p> + &s.code;void LoaderInit(void)&e.code; + <quote><p> + The &s.code;LoaderInit()&e.code; function initialises the loader, + and it must be called once before calling any other loader functions. + This function initialises the tables of exported symbols, and anything + else that might need to be initialised. + + </quote> + + &s.code;void LoaderSetPath(const char *path)&e.code; + <quote><p> + The &s.code;LoaderSetPath()&e.code; function initialises a default + module search path. This must be called if calls to other functions + are to be made without explicitly specifying a module search path. + The search path &s.code;path&e.code; must be a string of one or more + comma separated absolute paths. Modules are expected to be located + below these paths, possibly in subdirectories of these paths. + + </quote> + + &s.code;pointer LoadModule(const char *module, const char *path, + &f.indent;const char **subdirlist, const char **patternlist, + &f.indent;pointer options, const XF86ModReqInfo * modreq, + &f.indent;int *errmaj, int *errmin)&e.code; + <quote><p> + The &s.code;LoadModule()&e.code; function loads the module called + &s.code;module&e.code;. The return value is a module handle, and + may be used in future calls to the loader that require a reference + to a loaded module. The module name &s.code;module&e.code; is + normally the module's canonical name, which doesn't contain any + directory path information, or any object/library file prefixes of + suffixes. Currently a full pathname and/or filename is also accepted. + This might change. The other parameters are: + + &s.code;path&e.code; + <quote><p> + An optional comma-separated list of module search paths. + When &s.code;NULL&e.code;, the default search path is used. + + </quote> + + &s.code;subdirlist&e.code; + <quote><p> + An optional &s.code;NULL&e.code; terminated list of + subdirectories to search. When &s.code;NULL&e.code;, + the default built-in list is used (refer to + &s.code;stdSubdirs&e.code; in &s.code;loadmod.c&e.code;). + The default list is also substituted for entries in + &s.code;subdirlist&e.code; with the value + &s.code;DEFAULT_LIST&e.code;. This makes is possible + to augment the default list instead of replacing it. + Subdir elements must be relative, and must not contain + &s.code;".."&e.code;. If any violate this requirement, + the load fails. + + </quote> + + &s.code;patternlist&e.code; + <quote><p> + An optional &s.code;NULL&e.code; terminated list of + POSIX regular expressions used to connect module + filenames with canonical module names. Each regex + should contain exactly one subexpression that corresponds + to the canonical module name. When &s.code;NULL&e.code;, + the default built-in list is used (refer to + &s.code;stdPatterns&e.code; in + &s.code;loadmod.c&e.code;). The default list is also + substituted for entries in &s.code;patternlist&e.code; + with the value &s.code;DEFAULT_LIST&e.code;. This + makes it possible to augment the default list instead + of replacing it. + + </quote> + + &s.code;options&e.code; + <quote><p> + An optional parameter that is passed to the newly + loaded module's &s.code;SetupProc&e.code; function + (if it has one). This argument is normally a + &s.code;NULL&e.code; terminated list of + &s.code;Options&e.code;, and must be interpreted that + way by modules loaded directly by the XFree86 common + layer. However, it may be used for application-specific + parameter passing in other situations. + + When loading ``external'' modules (modules that don't + have the standard entry point, for example a + special shared library) the options parameter can be + set to &s.code;EXTERN_MODULE&e.code; to tell the + loader not to reject the module when it doesn't find + the standard entry point. + + </quote> + + &s.code;modreq&e.code; + <quote><p> + An optional &s.code;XF86ModReqInfo*&e.code; containing + version/ABI/vendor information to requirements to + check the newly loaded module against. The main + purpose of this is to allow the loader to verify that + a module of the correct type/version before running + its &s.code;SetupProc&e.code; function. + + The &s.code;XF86ModReqInfo&e.code; struct is defined + as follows: +<verb> +typedef struct { + CARD8 majorversion; /* MAJOR_UNSPEC */ + CARD8 minorversion; /* MINOR_UNSPEC */ + CARD16 patchlevel; /* PATCH_UNSPEC */ + const char * abiclass; /* ABI_CLASS_NONE */ + CARD32 abiversion; /* ABI_VERS_UNSPEC */ + const char * moduleclass; /* MOD_CLASS_NONE */ +} XF86ModReqInfo; +</verb> + + The information here is compared against the equivalent + information in the module's + &s.code;XF86ModuleVersionInfo&e.code; record (which + is described below). The values in comments above + indicate ``don't care'' settings for each of the fields. + The comparisons made are as follows: + + &s.code;majorversion&e.code; + <quote><p> + Must match the module's majorversion + exactly. + + </quote> + &s.code;minorversion&e.code; + <quote><p> + The module's minor version must be + no less than this value. This + comparison is only made if + &s.code;majorversion&e.code; is + specified and matches. + + </quote> + &s.code;patchlevel&e.code; + <quote><p> + The module's patchlevel must be no + less than this value. This comparison + is only made if + &s.code;minorversion&e.code; is + specified and matches. + + </quote> + &s.code;abiclass&e.code; + <quote><p> + String must match the module's abiclass + string. + + </quote> + &s.code;abiversion&e.code; + <quote><p> + Must be consistent with the module's + abiversion (major equal, minor no + older). + + </quote> + &s.code;moduleclass&e.code; + <quote><p> + String must match the module's + moduleclass string. + + </quote> + + </quote> + + &s.code;errmaj&e.code; + <quote><p> + An optional pointer to a variable holding the major + part or the error code. When provided, + &s.code;*errmaj&e.code; is filled in when + &s.code;LoadModule()&e.code; fails. + + </quote> + + &s.code;errmin&e.code; + <quote><p> + Like &s.code;errmaj&e.code;, but for the minor part + of the error code. + + </quote> + + </quote> + + &s.code;void UnloadModule(pointer mod)&e.code; + <quote><p> + This function unloads the module referred to by the handle mod. + All child modules are also unloaded recursively. This function must + not be used to directly unload modules that are child modules (i.e., + those that have been loaded with the &s.code;LoadSubModule()&e.code; + described below). + + </quote> + </quote> + +<sect1>Module Requirements +<p> + +Modules must provide information about themselves to the loader, and +may optionally provide entry points for "setup" and "teardown" functions +(those two functions are referred to here as &s.code;SetupProc&e.code; +and &s.code;TearDownProc&e.code;). + +The module information is contained in the +&s.code;XF86ModuleVersionInfo&e.code; struct, which is defined as follows: + +<quote><p><verb> +typedef struct { + const char * modname; /* name of module, e.g. "foo" */ + const char * vendor; /* vendor specific string */ + CARD32 _modinfo1_; /* constant MODINFOSTRING1/2 to find */ + CARD32 _modinfo2_; /* infoarea with a binary editor/sign tool */ + CARD32 xf86version; /* contains XF86_VERSION_CURRENT */ + CARD8 majorversion; /* module-specific major version */ + CARD8 minorversion; /* module-specific minor version */ + CARD16 patchlevel; /* module-specific patch level */ + const char * abiclass; /* ABI class that the module uses */ + CARD32 abiversion; /* ABI version */ + const char * moduleclass; /* module class */ + CARD32 checksum[4]; /* contains a digital signature of the */ + /* version info structure */ +} XF86ModuleVersionInfo; +</verb> + +The fields are used as follows: + + &s.code;modname&e.code; + <quote><p> + The module's name. This field is currently only for + informational purposes, but the loader may be modified + in future to require it to match the module's canonical + name. + + </quote> + + &s.code;vendor&e.code; + <quote><p> + The module vendor. This field is for informational purposes + only. + + </quote> + + &s.code;_modinfo1_&e.code; + <quote><p> + This field holds the first part of a signature that can + be used to locate this structure in the binary. It should + always be initialised to &s.code;MODINFOSTRING1&e.code;. + + </quote> + + &s.code;_modinfo2_&e.code; + <quote><p> + This field holds the second part of a signature that can + be used to locate this structure in the binary. It should + always be initialised to &s.code;MODINFOSTRING2&e.code;. + + </quote> + + &s.code;xf86version&e.code; + <quote><p> + The XFree86 version against which the module was compiled. + This is mostly for informational/diagnostic purposes. It + should be initialised to &s.code;XF86_VERSION_CURRENT&e.code;, which is + defined in &s.code;xf86Version.h&e.code;. + + </quote> + + &s.code;majorversion&e.code; + <quote><p> + The module-specific major version. For modules where this + version is used for more than simply informational + purposes, the major version should only change (be + incremented) when ABI incompatibilities are introduced, + or ABI components are removed. + + </quote> + + &s.code;minorversion&e.code; + <quote><p> + The module-specific minor version. For modules where this + version is used for more than simply informational + purposes, the minor version should only change (be + incremented) when ABI additions are made in a backward + compatible way. It should be reset to zero when the major + version is increased. + + </quote> + + &s.code;patchlevel&e.code; + <quote><p> + The module-specific patch level. The patch level should + increase with new revisions of the module where there + are no ABI changes, and it should be reset to zero when + the minor version is increased. + + </quote> + + &s.code;abiclass&e.code; + <quote><p> + The ABI class that the module requires. The class is + specified as a string for easy extensibility. It should + indicate which (if any) of the X server's built-in ABI + classes that the module relies on, or a third-party ABI + if appropriate. Built-in ABI classes currently defined are: + + <quote> + &s.code;ABI_CLASS_NONE&e.code; + <quote>no class</quote> + &s.code;ABI_CLASS_ANSIC&e.code; + <quote>only requires the ANSI C interfaces</quote> + &s.code;ABI_CLASS_VIDEODRV&e.code; + <quote>requires the video driver ABI</quote> + &s.code;ABI_CLASS_XINPUT&e.code; + <quote>requires the XInput driver ABI</quote> + &s.code;ABI_CLASS_EXTENSION&e.code; + <quote>requires the extension module ABI</quote> + &s.code;ABI_CLASS_FONT&e.code; + <quote>requires the font module ABI</quote> + </quote> + + </quote> + + &s.code;abiversion&e.code; + <quote><p> + The version of abiclass that the module requires. The + version consists of major and minor components. The + major version must match and the minor version must be + no newer than that provided by the server or parent + module. Version identifiers for the built-in classes + currently defined are: + + <quote> + &s.code;ABI_ANSIC_VERSION&nl; + ABI_VIDEODRV_VERSION&nl; + ABI_XINPUT_VERSION&nl; + ABI_EXTENSION_VERSION&nl; + ABI_FONT_VERSION&e.code; + </quote> + + </quote> + + &s.code;moduleclass&e.code; + <quote><p> + This is similar to the abiclass field, except that it + defines the type of module rather than the ABI it + requires. For example, although all video drivers require + the video driver ABI, not all modules that require the + video driver ABI are video drivers. This distinction + can be made with the moduleclass. Currently pre-defined + module classes are: + + <quote> + &s.code;MOD_CLASS_NONE&nl; + MOD_CLASS_VIDEODRV&nl; + MOD_CLASS_XINPUT&nl; + MOD_CLASS_FONT&nl; + MOD_CLASS_EXTENSION&e.code; + </quote> + + </quote> + + &s.code;checksum&e.code; + <quote><p> + Not currently used. + + </quote> + +</quote> + +The module version information, and the optional &s.code;SetupProc&e.code; +and &s.code;TearDownProc&e.code; entry points are found by the loader +by locating a data object in the module called "modnameModuleData", +where "modname" is the canonical name of the module. Modules must +contain such a data object, and it must be declared with global scope, +be compile-time initialised, and is of the following type: + +<quote> +<verb> +typedef struct { + XF86ModuleVersionInfo * vers; + ModuleSetupProc setup; + ModuleTearDownProc teardown; +} XF86ModuleData; +</verb> +</quote> + +The vers parameter must be initialised to a pointer to a correctly +initialised &s.code;XF86ModuleVersionInfo&e.code; struct. The other +two parameter are optional, and should be initialised to +&s.code;NULL&e.code; when not required. The other parameters are defined +as + + <quote><p> + &s.code;typedef pointer (*ModuleSetupProc)(pointer, pointer, int *, int *)&e.code; + + &s.code;typedef void (*ModuleTearDownProc)(pointer)&e.code; + + + &s.code;pointer SetupProc(pointer module, pointer options, + &f.indent;int *errmaj, int *errmin)&e.code; + <quote><p> + When defined, this function is called by the loader after successfully + loading a module. module is a handle for the newly loaded module, + and maybe used by the &s.code;SetupProc&e.code; if it calls other + loader functions that require a reference to it. The remaining + arguments are those that were passed to the + &s.code;LoadModule()&e.code; (or &s.code;LoadSubModule()&e.code;), + and are described above. When the &s.code;SetupProc&e.code; is + successful it must return a non-&s.code;NULL&e.code; value. The + loader checks this, and if it is &s.code;NULL&e.code; it unloads + the module and reports the failure to the caller of + &s.code;LoadModule()&e.code;. If the &s.code;SetupProc&e.code; + does things that need to be undone when the module is unloaded, + it should define a &s.code;TearDownProc&e.code;, and return a + pointer that the &s.code;TearDownProc&e.code; can use to undo what + has been done. + + When a module is loaded multiple times, the &s.code;SetupProc&e.code; + is called once for each time it is loaded. + + </quote> + + &s.code;void TearDownProc(pointer tearDownData)&e.code; + <quote><p> + When defined, this function is called when the loader unloads a + module. The &s.code;tearDownData&e.code; parameter is the return + value of the &s.code;SetupProc()&e.code; that was called when the + module was loaded. The purpose of this function is to clean up + before the module is unloaded (for example, by freeing allocated + resources). + + </quote> + </quote> + +<sect1>Public Loader Interface +<p> + +The following is the Loader interface that is available to any part of +the server, and may also be used from within modules. + + <quote><p> + &s.code;pointer LoadSubModule(pointer parent, const char *module, + &f.indent;const char **subdirlist, const char **patternlist, + &f.indent;pointer options, const XF86ModReqInfo * modreq, + &f.indent;int *errmaj, int *errmin)&e.code; + <quote><p> + This function is like the &s.code;LoadModule()&e.code; function + described above, except that the module loaded is registered as a + child of the calling module. The &s.code;parent&e.code; parameter + is the calling module's handle. Modules loaded with this function + are automatically unloaded when the parent module is unloaded. The + other difference is that the path parameter may not be specified. + The module search path used for modules loaded with this function + is the default search path as initialised with + &s.code;LoaderSetPath()&e.code;. + + </quote> + + &s.code;void UnloadSubModule(pointer module)&e.code; + <quote><p> + This function unloads the module with handle &s.code;module&e.code;. + If that module itself has children, they are also unloaded. It is + like &s.code;UnloadModule()&e.code;, except that it is safe to use + for unloading child modules. + + </quote> + + &s.code;pointer LoaderSymbol(const char *symbol)&e.code; + <quote><p> + This function returns the address of the symbol with name + &s.code;symbol&e.code;. This may be used to locate a module entry + point with a known name. + + </quote> + + &s.code;char **LoaderlistDirs(const char **subdirlist, + &f.indent;const char **patternlist)&e.code; + <quote><p> + This function returns a &s.code;NULL&e.code; terminated list of + canonical modules names for modules found in the default module + search path. The &s.code;subdirlist&e.code; and + &s.code;patternlist&e.code; parameters are as described above, and + can be used to control the locations and names that are searched. + If no modules are found, the return value is &s.code;NULL&e.code;. + The returned list should be freed by calling + &s.code;LoaderFreeDirList()&e.code; when it is no longer needed. + + </quote> + + &s.code;void LoaderFreeDirList(char **list)&e.code; + <quote><p> + This function frees a module list created by + &s.code;LoaderlistDirs()&e.code;. + + </quote> + + &s.code;void LoaderReqSymLists(const char **list0, ...)&e.code; + <quote><p> + This function allows the registration of required symbols with the + loader. It is normally used by a caller of + &s.code;LoadSubModule()&e.code;. If any symbols registered in this + way are found to be unresolved when + &s.code;LoaderCheckUnresolved()&e.code; is called then + &s.code;LoaderCheckUnresolved()&e.code; will report a failure. + The function takes one or more &s.code;NULL&e.code; terminated + lists of symbols. The end of the argument list is indicated by a + &s.code;NULL&e.code; argument. + + </quote> + + &s.code;void LoaderReqSymbols(const char *sym0, ...)&e.code; + <quote><p> + This function is like &s.code;LoaderReqSymLists()&e.code; except + that its arguments are symbols rather than lists of symbols. This + function is more convenient when single functions are to be registered, + especially when the single function might depend on runtime factors. + The end of the argument list is indicated by a &s.code;NULL&e.code; + argument. + + </quote> + + &s.code;void LoaderRefSymLists(const char **list0, ...)&e.code; + <quote><p> + This function allows the registration of possibly unresolved symbols + with the loader. When &s.code;LoaderCheckUnresolved()&e.code; is + run it won't generate warnings for symbols registered in this way + unless they were also registered as required symbols. + The function takes one or more &s.code;NULL&e.code; terminated + lists of symbols. The end of the argument list is indicated by a + &s.code;NULL&e.code; argument. + + </quote> + + &s.code;void LoaderRefSymbols(const char *sym0, ...)&e.code; + <quote><p> + This function is like &s.code;LoaderRefSymLists()&e.code; except + that its arguments are symbols rather than lists of symbols. This + function is more convenient when single functions are to be registered, + especially when the single function might depend on runtime factors. + The end of the argument list is indicated by a &s.code;NULL&e.code; + argument. + + </quote> + + &s.code;int LoaderCheckUnresolved(int delayflag)&e.code; + <quote><p> + This function checks for unresolved symbols. It generates warnings + for unresolved symbols that have not been registered with + &s.code;LoaderRefSymLists()&e.code;, and maps them to a dummy + function. This behaviour may change in future. If unresolved + symbols are found that have been registered with + &s.code;LoaderReqSymLists()&e.code; or + &s.code;LoaderReqSymbols()&e.code; then this function returns a + non-zero value. If none of these symbols are unresolved the return + value is zero, indicating success. + + The &s.code;delayflag&e.code; parameter should normally be set to + &s.code;LD_RESOLV_IFDONE&e.code;. + + </quote> + + &s.code;LoaderErrorMsg(const char *name, const char *modname, + &f.indent;int errmaj, int errmin)&e.code; + <quote><p> + This function prints an error message that includes the text ``Failed + to load module'', the module name &s.code;modname&e.code;, a message + specific to the &s.code;errmaj&e.code; value, and the value if + &s.code;errmin&e.code;. If &s.code;name&e.code; is + non-&s.code;NULL&e.code;, it is printed as an identifying prefix + to the message (followed by a `:'). + + </quote> + </quote> + +<sect1>Special Registration Functions +<p> + +The loader contains some functions for registering some classes of modules. +These may be moved out of the loader at some point. + + <quote><p> + &s.code;void LoadExtension(ExtensionModule *ext)&e.code; + <quote><p> + This registers the entry points for the extension identified by + &s.code;ext&e.code;. The &s.code;ExtensionModule&e.code; struct is + defined as: + +<quote> +<verb> +typedef struct { + InitExtension initFunc; + char * name; + Bool *disablePtr; + InitExtension setupFunc; +} ExtensionModule; +</verb> +</quote> + + </quote> + + &s.code;void LoadFont(FontModule *font)&e.code; + <quote><p> + This registers the entry points for the font rasteriser module + identified by &s.code;font&e.code;. The &s.code;FontModule&e.code; + struct is defined as: + +<quote> +<verb> +typedef struct { + InitFont initFunc; + char * name; + pointer module; +} FontModule; +</verb> +</quote> + + </quote> + </quote> + +</sect> + + +<sect>Helper Functions +<p> + +This section describe ``helper'' functions that video driver +might find useful. While video drivers are not required to use any of +these to be considered ``compliant'', the use of appropriate helpers is +strongly encouraged to improve the consistency of driver behaviour. + +<sect1>Functions for printing messages +<p> + + <quote><p> + &s.code;ErrorF(const char *format, ...)&e.code; + <quote><p> + This is the basic function for writing to the error log (typically + stderr and/or a log file). Video drivers should usually avoid + using this directly in favour of the more specialised functions + described below. This function is useful for printing messages + while debugging a driver. + + </quote> + + &s.code;FatalError(const char *format, ...)&e.code; + <quote><p> + This prints a message and causes the Xserver to abort. It should + rarely be used within a video driver, as most error conditions + should be flagged by the return values of the driver functions. + This allows the higher layers to decide how to proceed. In rare + cases, this can be used within a driver if a fatal unexpected + condition is found. + + </quote> + + &s.code;xf86ErrorF(const char *format, ...)&e.code; + <quote><p> + This is like &s.code;ErrorF()&e.code;, except that the message is + only printed when the Xserver's verbosity level is set to the + default (&s.code;1&e.code;) or higher. It means that the messages + are not printed when the server is started with the + &s.cmd;-quiet&e.cmd; flag. Typically this function would only be + used for continuing messages started with one of the more specialised + functions described below. + + </quote> + + &s.code;xf86ErrorFVerb(int verb, const char *format, ...)&e.code; + <quote><p> + Like &s.code;xf86ErrorF()&e.code;, except the minimum verbosity + level for which the message is to be printed is given explicitly. + Passing a &s.code;verb&e.code; value of zero means the message + is always printed. A value higher than &s.code;1&e.code; can be + used for information would normally not be needed, but which might + be useful when diagnosing problems. + + </quote> + + &s.code;xf86Msg(MessageType type, const char *format, ...)&e.code; + <quote><p> + This is like &s.code;xf86ErrorF()&e.code;, except that the message + is prefixed with a marker determined by the value of + &s.code;type&e.code;. The marker is used to indicate the type of + message (warning, error, probed value, config value, etc). Note + the &s.code;xf86Verbose&e.code; value is ignored for messages of + type &s.code;X_ERROR&e.code;. + + The marker values are: + + <quote> + &s.code;X_PROBED&e.code; + <quote>Value was probed.</quote> + &s.code;X_CONFIG&e.code; + <quote>Value was given in the config file.</quote> + &s.code;X_DEFAULT&e.code; + <quote>Value is a default.</quote> + &s.code;X_CMDLINE&e.code; + <quote>Value was given on the command line.</quote> + &s.code;X_NOTICE&e.code; + <quote>Notice.</quote> + &s.code;X_ERROR&e.code; + <quote>Error message.</quote> + &s.code;X_WARNING&e.code; + <quote>Warning message.</quote> + &s.code;X_INFO&e.code; + <quote>Informational message.</quote> + &s.code;X_NONE&e.code; + <quote>No prefix.</quote> + &s.code;X_NOT_IMPLEMENTED&e.code; + <quote>The message relates to functionality that is not yet + implemented.</quote> + </quote> + + + </quote> + + &s.code;xf86MsgVerb(MessageType type, int verb, const char *format, ...)&e.code; + <quote><p> + Like &s.code;xf86Msg()&e.code;, but with the verbosity level given + explicitly. + + </quote> + + &s.code;xf86DrvMsg(int scrnIndex, MessageType type, const char *format, ...)&e.code; + <quote><p> + This is like &s.code;xf86Msg()&e.code; except that the driver's + name (the &s.code;name&e.code; field of the + &s.code;ScrnInfoRec&e.code;) followed by the + &s.code;scrnIndex&e.code; in parentheses is printed following the + prefix. This should be used by video drivers in most cases as it + clearly indicates which driver/screen the message is for. If + &s.code;scrnIndex&e.code; is negative, this function behaves + exactly like &s.code;xf86Msg()&e.code;. + + NOTE: This function can only be used after the + &s.code;ScrnInfoRec&e.code; and its &s.code;name&e.code; field + have been allocated. Normally, this means that it can not be + used before the END of the &s.code;ChipProbe()&e.code; function. + Prior to that, use &s.code;xf86Msg()&e.code;, providing the + driver's name explicitly. No screen number can be supplied at + that point. + + </quote> + + &s.code;xf86DrvMsgVerb(int scrnIndex, MessageType type, int verb, + &f.indent;const char *format, ...)&e.code; + <quote><p> + Like &s.code;xf86DrvMsg()&e.code;, but with the verbosity level + given explicitly. + + </quote> + </quote> + + +<sect1>Functions for setting values based on command line and config file +<p> + + <quote><p> + &s.code;Bool xf86SetDepthBpp(ScrnInfoPtr scrp, int depth, int bpp, + &f.indent;int fbbpp, int depth24flags)&e.code; + <quote><p> + This function sets the &s.code;depth&e.code;, &s.code;pixmapBPP&e.code; and &s.code;bitsPerPixel&e.code; fields + of the &s.code;ScrnInfoRec&e.code;. It also determines the defaults for display-wide + attributes and pixmap formats the screen will support, and finds + the Display subsection that matches the depth/bpp. This function + should normally be called very early from the + &s.code;ChipPreInit()&e.code; function. + + It requires that the &s.code;confScreen&e.code; field of the &s.code;ScrnInfoRec&e.code; be + initialised prior to calling it. This is done by the XFree86 + common layer prior to calling &s.code;ChipPreInit()&e.code;. + + The parameters passed are: + + &s.code;depth&e.code; + <quote><p> + driver's preferred default depth if no other is given. + If zero, use the overall server default. + + </quote> + &s.code;bpp&e.code; + <quote><p> + Same, but for the pixmap bpp. + + </quote> + &s.code;fbbpp&e.code; + <quote><p> + Same, but for the framebuffer bpp. + + </quote> + &s.code;depth24flags&e.code; + <quote><p> + Flags that indicate the level of 24/32bpp support + and whether conversion between different framebuffer + and pixmap formats is supported. The flags for this + argument are defined as follows, and multiple flags + may be ORed together: + + &s.code;NoDepth24Support&e.code; + <quote>No depth 24 formats supported</quote> + &s.code;Support24bppFb&e.code; + <quote>24bpp framebuffer supported</quote> + &s.code;Support32bppFb&e.code; + <quote>32bpp framebuffer supported</quote> + &s.code;SupportConvert24to32&e.code; + <quote>Can convert 24bpp pixmap to 32bpp fb</quote> + &s.code;SupportConvert32to24&e.code; + <quote>Can convert 32bpp pixmap to 24bpp fb</quote> + &s.code;ForceConvert24to32&e.code; + <quote>Force 24bpp pixmap to 32bpp fb conversion</quote> + &s.code;ForceConvert32to24&e.code; + <quote>Force 32bpp pixmap to 24bpp fb conversion</quote> + + </quote> + + It uses the command line, config file, and default values in the + correct order of precedence to determine the depth and bpp values. + It is up to the driver to check the results to see that it supports + them. If not the &s.code;ChipPreInit()&e.code; function should + return &s.code;FALSE&e.code;. + + If only one of depth/bpp is given, the other is set to a reasonable + (and consistent) default. + + If a driver finds that the initial &s.code;depth24flags&e.code; + it uses later results in a fb format that requires more video + memory than is available it may call this function a second time + with a different &s.code;depth24flags&e.code; setting. + + On success, the return value is &s.code;TRUE&e.code;. On failure + it prints an error message and returns &s.code;FALSE&e.code;. + + The following fields of the &s.code;ScrnInfoRec&e.code; are + initialised by this function: + + <quote> + &s.code;depth&e.code;, &s.code;bitsPerPixel&e.code;, + &s.code;display&e.code;, &s.code;imageByteOrder&e.code;, + &s.code;bitmapScanlinePad&e.code;, + &s.code;bitmapScanlineUnit&e.code;, &s.code;bitmapBitOrder&e.code;, + &s.code;numFormats&e.code;, &s.code;formats&e.code;, + &s.code;fbFormat&e.code;. + </quote> + + </quote> + + &s.code;void xf86PrintDepthBpp(scrnInfoPtr scrp)&e.code; + <quote><p> + This function can be used to print out the depth and bpp settings. + It should be called after the final call to + &s.code;xf86SetDepthBpp()&e.code;. + + </quote> + + &s.code;Bool xf86SetWeight(ScrnInfoPtr scrp, rgb weight, rgb mask)&e.code; + <quote><p> + This function sets the &s.code;weight&e.code;, &s.code;mask&e.code;, + &s.code;offset&e.code; and &s.code;rgbBits&e.code; fields of the + &s.code;ScrnInfoRec&e.code;. It would normally be called fairly + early in the &s.code;ChipPreInit()&e.code; function for + depths > 8bpp. + + It requires that the &s.code;depth&e.code; and + &s.code;display&e.code; fields of the &s.code;ScrnInfoRec&e.code; + be initialised prior to calling it. + + The parameters passed are: + + &s.code;weight&e.code; + <quote><p> + driver's preferred default weight if no other is given. + If zero, use the overall server default. + + </quote> + + &s.code;mask&e.code; + <quote><p> + Same, but for mask. + + </quote> + + It uses the command line, config file, and default values in the + correct order of precedence to determine the weight value. It + derives the mask and offset values from the weight and the defaults. + It is up to the driver to check the results to see that it supports + them. If not the &s.code;ChipPreInit()&e.code; function should + return &s.code;FALSE&e.code;. + + On success, this function prints a message showing the weight + values selected, and returns &s.code;TRUE&e.code;. + + On failure it prints an error message and returns &s.code;FALSE&e.code;. + + The following fields of the &s.code;ScrnInfoRec&e.code; are + initialised by this function: + + <quote> + &s.code;weight&e.code;, &s.code;mask&e.code;, &s.code;offset&e.code;. + </quote> + + </quote> + + &s.code;Bool xf86SetDefaultVisual(ScrnInfoPtr scrp, int visual)&e.code; + <quote><p> + This function sets the &s.code;defaultVisual&e.code; field of the + &s.code;ScrnInfoRec&e.code;. It would normally be called fairly + early from the &s.code;ChipPreInit()&e.code; function. + + It requires that the &s.code;depth&e.code; and + &s.code;display&e.code; fields of the &s.code;ScrnInfoRec&e.code; + be initialised prior to calling it. + + The parameters passed are: + + &s.code;visual&e.code; + <quote><p> + driver's preferred default visual if no other is given. + If &s.code;-1&e.code;, use the overall server default. + + </quote> + + It uses the command line, config file, and default values in the + correct order of precedence to determine the default visual value. + It is up to the driver to check the result to see that it supports + it. If not the &s.code;ChipPreInit()&e.code; function should + return &s.code;FALSE&e.code;. + + On success, this function prints a message showing the default visual + selected, and returns &s.code;TRUE&e.code;. + + On failure it prints an error message and returns &s.code;FALSE&e.code;. + + </quote> + + &s.code;Bool xf86SetGamma(ScrnInfoPtr scrp, Gamma gamma)&e.code; + <quote><p> + This function sets the &s.code;gamma&e.code; field of the + &s.code;ScrnInfoRec&e.code;. It would normally be called fairly + early from the &s.code;ChipPreInit()&e.code; function in cases + where the driver supports gamma correction. + + It requires that the &s.code;monitor&e.code; field of the + &s.code;ScrnInfoRec&e.code; be initialised prior to calling it. + + The parameters passed are: + + &s.code;gamma&e.code; + <quote><p> + driver's preferred default gamma if no other is given. + If zero (&s.code;< 0.01&e.code;), use the overall server + default. + + </quote> + + It uses the command line, config file, and default values in the + correct order of precedence to determine the gamma value. It is + up to the driver to check the results to see that it supports + them. If not the &s.code;ChipPreInit()&e.code; function should + return &s.code;FALSE&e.code;. + + On success, this function prints a message showing the gamma + value selected, and returns &s.code;TRUE&e.code;. + + On failure it prints an error message and returns &s.code;FALSE&e.code;. + + </quote> + + &s.code;void xf86SetDpi(ScrnInfoPtr pScrn, int x, int y)&e.code; + <quote><p> + This function sets the &s.code;xDpi&e.code; and &s.code;yDpi&e.code; + fields of the &s.code;ScrnInfoRec&e.code;. The driver can specify + preferred defaults by setting &s.code;x&e.code; and &s.code;y&e.code; + to non-zero values. The &s.cmd;-dpi&e.cmd; command line option + overrides all other settings. Otherwise, if the + &s.key;DisplaySize&e.key; entry is present in the screen's &k.monitor; + config file section, it is used together with the virtual size to + calculate the dpi values. This function should be called after + all the mode resolution has been done. + + </quote> + + &s.code;void xf86SetBlackWhitePixels(ScrnInfoPtr pScrn)&e.code; + <quote><p> + This functions sets the &s.code;blackPixel&e.code; and + &s.code;whitePixel&e.code; fields of the &s.code;ScrnInfoRec&e.code; + according to whether or not the &s.cmd;-flipPixels&e.cmd; command + line options is present. + + </quote> + + &s.code;const char *xf86GetVisualName(int visual)&e.code; + <quote><p> + Returns a printable string with the visual name matching the + numerical visual class provided. If the value is outside the + range of valid visual classes, &s.code;NULL&e.code; is returned. + + </quote> + </quote> + + +<sect1>Primary Mode functions +<p> + +The primary mode helper functions are those which would normally be +used by a driver, unless it has unusual requirements which cannot +be catered for the by the helpers. + + <quote><p> + &s.code;int xf86ValidateModes(ScrnInfoPtr scrp, DisplayModePtr availModes, + &f.indent;char **modeNames, ClockRangePtr clockRanges, + &f.indent;int *linePitches, int minPitch, int maxPitch, + &f.indent;int pitchInc, int minHeight, int maxHeight, + &f.indent;int virtualX, int virtualY, + &f.indent;unsigned long apertureSize, + &f.indent;LookupModeFlags strategy)&e.code; + <quote><p> + This function basically selects the set of modes to use based on + those available and the various constraints. It also sets some + other related parameters. It is normally called near the end of + the &s.code;ChipPreInit()&e.code; function. + + The parameters passed to the function are: + + &s.code;availModes&e.code; + <quote><p> + List of modes available for the monitor. + + </quote> + &s.code;modeNames&e.code; + <quote><p> + List of mode names that the screen is requesting. + + </quote> + &s.code;clockRanges&e.code; + <quote><p> + A list of clock ranges allowed by the driver. Each + range includes whether interlaced or multiscan modes + are supported for that range. See below for more on + &s.code;clockRanges&e.code;. + + </quote> + &s.code;linePitches&e.code; + <quote><p> + List of line pitches supported by the driver. + This is optional and should be &s.code;NULL&e.code; when + not used. + + </quote> + &s.code;minPitch&e.code; + <quote><p> + Minimum line pitch supported by the driver. This must + be supplied when &s.code;linePitches&e.code; is + &s.code;NULL&e.code;, and is ignored otherwise. + + </quote> + &s.code;maxPitch&e.code; + <quote><p> + Maximum line pitch supported by the driver. This is + required when &s.code;minPitch&e.code; is required. + + </quote> + &s.code;pitchInc&e.code; + <quote><p> + Granularity of horizontal pitch values as supported by + the chipset. This is expressed in bits. This must be + supplied. + + </quote> + &s.code;minHeight&e.code; + <quote><p> + minimum virtual height allowed. If zero, no limit is + imposed. + + </quote> + &s.code;maxHeight&e.code; + <quote><p> + maximum virtual height allowed. If zero, no limit is + imposed. + + </quote> + &s.code;virtualX&e.code; + <quote><p> + If greater than zero, this is the virtual width value + that will be used. Otherwise, the virtual width is + chosen to be the smallest that can accommodate the modes + selected. + + </quote> + &s.code;virtualY&e.code; + <quote><p> + If greater than zero, this is the virtual height value + that will be used. Otherwise, the virtual height is + chosen to be the smallest that can accommodate the modes + selected. + + </quote> + &s.code;apertureSize&e.code; + <quote><p> + The size (in bytes) of the aperture used to access video + memory. + + </quote> + &s.code;strategy&e.code; + <quote><p> + The strategy to use when choosing from multiple modes + with the same name. The options are: + + &s.code;LOOKUP_DEFAULT&e.code; + <quote>???</quote> + &s.code;LOOKUP_BEST_REFRESH&e.code; + <quote>mode with best refresh rate</quote> + &s.code;LOOKUP_CLOSEST_CLOCK&e.code; + <quote>mode with closest matching clock</quote> + &s.code;LOOKUP_LIST_ORDER&e.code; + <quote>first usable mode in list</quote> + + The following options can also be combined (OR'ed) with + one of the above: + + &s.code;LOOKUP_CLKDIV2&e.code; + <quote>Allow halved clocks</quote> + &s.code;LOOKUP_OPTIONAL_TOLERANCES&e.code; + <quote>Allow missing horizontal sync and/or vertical refresh + ranges in the XF86Config Monitor section</quote> + + &s.code;LOOKUP_OPTIONAL_TOLERANCES&e.code; should only be + specified when the driver can ensure all modes it generates + can sync on, or at least not damage, the monitor or digital + flat panel. Horizontal sync and/or vertical refresh ranges + specified by the user will still be honoured (and acted upon). + + </quote> + + This function requires that the following fields of the + &s.code;ScrnInfoRec&e.code; are initialised prior to calling it: + + &s.code;clock[]&e.code; + <quote>List of discrete clocks (when non-programmable)</quote> + &s.code;numClocks&e.code; + <quote>Number of discrete clocks (when non-programmable)</quote> + &s.code;progClock&e.code; + <quote>Whether the clock is programmable or not</quote> + &s.code;monitor&e.code; + <quote>Pointer to the applicable XF86Config monitor section</quote> + &s.code;fdFormat&e.code; + <quote>Format of the screen buffer</quote> + &s.code;videoRam&e.code; + <quote>total video memory size (in bytes)</quote> + &s.code;maxHValue&e.code; + <quote>Maximum horizontal timing value allowed</quote> + &s.code;maxVValue&e.code; + <quote>Maximum vertical timing value allowed</quote> + &s.code;xInc&e.code; + <quote>Horizontal timing increment in pixels (defaults to 8)</quote> + + This function fills in the following &s.code;ScrnInfoRec&e.code; + fields: + + &s.code;modePool&e.code; + <quote><p> + A subset of the modes available to the monitor which + are compatible with the driver. + + </quote> + &s.code;modes&e.code; + <quote><p> + One mode entry for each of the requested modes, with + the status field of each filled in to indicate if + the mode has been accepted or not. This list of + modes is a circular list. + + </quote> + &s.code;virtualX&e.code; + <quote><p> + The resulting virtual width. + + </quote> + &s.code;virtualY&e.code; + <quote><p> + The resulting virtual height. + + </quote> + &s.code;displayWidth&e.code; + <quote><p> + The resulting line pitch. + + </quote> + &s.code;virtualFrom&e.code; + <quote><p> + Where the virtual size was determined from. + + </quote> + + The first stage of this function checks that the + &s.code;virtualX&e.code; and &s.code;virtualY&e.code; values + supplied (if greater than zero) are consistent with the line pitch + and &s.code;maxHeight&e.code; limitations. If not, an error + message is printed, and the return value is &s.code;-1&e.code;. + + The second stage sets up the mode pool, eliminating immediately + any modes that exceed the driver's line pitch limits, and also + the virtual width and height limits (if greater than zero). For + each mode removed an informational message is printed at verbosity + level &s.code;2&e.code;. If the mode pool ends up being empty, + a warning message is printed, and the return value is + &s.code;0&e.code;. + + The final stage is to lookup each mode name, and fill in the remaining + parameters. If an error condition is encountered, a message is + printed, and the return value is &s.code;-1&e.code;. Otherwise, + the return value is the number of valid modes found + (&s.code;0&e.code; if none are found). + + Even if the supplied mode names include duplicates, no two names will + ever match the same mode. Furthermore, if the supplied mode names do not + yield a valid mode (including the case where no names are passed at all), + the function will continue looking through the mode pool until it finds + a mode that survives all checks, or until the mode pool is exhausted. + + A message is only printed by this function when a fundamental + problem is found. It is intended that this function may be called + more than once if there is more than one set of constraints that + the driver can work within. + + If this function returns &s.code;-1&e.code;, the + &s.code;ChipPreInit()&e.code; function should return + &s.code;FALSE&e.code;. + + &s.code;clockRanges&e.code; is a linked list of clock ranges + allowed by the driver. If a mode doesn't fit in any of the defined + &s.code;clockRanges&e.code;, it is rejected. The first + &s.code;clockRange&e.code; that matches all requirements is used. + This structure needs to be initialized to NULL when allocated. + + &s.code;clockRanges&e.code; contains the following fields: + + &s.code;minClock&nl; + maxClock&e.code; + <quote><p> + The lower and upper mode clock bounds for which the rest + of the &s.code;clockRange&e.code; parameters apply. + Since these are the mode clocks, they are not scaled + with the &s.code;ClockMulFactor&e.code; and + &s.code;ClockDivFactor&e.code;. It is up to the driver + to adjust these values if they depend on the clock + scaling factors. + + </quote> + &s.code;clockIndex&e.code; + <quote><p> + (not used yet) &s.code;-1&e.code; for programmable clocks + + </quote> + &s.code;interlaceAllowed&e.code; + <quote><p> + &s.code;TRUE&e.code; if interlacing is allowed for this + range + + </quote> + &s.code;doubleScanAllowed&e.code; + <quote><p> + &s.code;TRUE&e.code; if doublescan or multiscan is allowed + for this range + + </quote> + &s.code;ClockMulFactor&nl; + ClockDivFactor&e.code; + <quote><p> + Scaling factors that are applied to the mode clocks ONLY + before selecting a clock index (when there is no + programmable clock) or a &s.code;SynthClock&e.code; + value. This is useful for drivers that support pixel + multiplexing or that need to scale the clocks because + of hardware restrictions (like sending 24bpp data to an + 8 bit RAMDAC using a tripled clock). + + Note that these parameters describe what must be done + to the mode clock to achieve the data transport clock + between graphics controller and RAMDAC. For example + for &s.code;2:1&e.code; pixel multiplexing, two pixels + are sent to the RAMDAC on each clock. This allows the + RAMDAC clock to be half of the actual pixel clock. + Hence, &s.code;ClockMulFactor=1&e.code; and + &s.code;ClockDivFactor=2&e.code;. This means that the + clock used for clock selection (ie, determining the + correct clock index from the list of discrete clocks) + or for the &s.code;SynthClock&e.code; field in case of + a programmable clock is: (&s.code;mode->Clock * + ClockMulFactor) / ClockDivFactor&e.code;. + + </quote> + &s.code;PrivFlags&e.code; + <quote><p> + This field is copied into the + &s.code;mode->PrivFlags&e.code; field when this + &s.code;clockRange&e.code; is selected by + &s.code;xf86ValidateModes()&e.code;. It allows the + driver to find out what clock range was selected, so it + knows it needs to set up pixel multiplexing or any other + range-dependent feature. This field is purely + driver-defined: it may contain flag bits, an index or + anything else (as long as it is an &s.code;INT&e.code;). + </quote> + + Note that the &s.code;mode->SynthClock&e.code; field is always + filled in by &s.code;xf86ValidateModes()&e.code;: it will contain + the ``data transport clock'', which is the clock that will have + to be programmed in the chip when it has a programmable clock, or + the clock that will be picked from the clocks list when it is not + a programmable one. Thus: + + &s.code;mode->SynthClock = + &f.indent;(mode->Clock * ClockMulFactor) / ClockDivFactor&e.code; + + </quote> + + &s.code;void xf86PruneDriverModes(ScrnInfoPtr scrp)&e.code; + <quote><p> + This function deletes modes in the modes field of the + &s.code;ScrnInfoRec&e.code; that have been marked as invalid. + This is normally run after having run + &s.code;xf86ValidateModes()&e.code; for the last time. For each + mode that is deleted, a warning message is printed out indicating + the reason for it being deleted. + + </quote> + + &s.code;void xf86SetCrtcForModes(ScrnInfoPtr scrp, int adjustFlags)&e.code; + <quote><p> + This function fills in the &s.code;Crtc*&e.code; fields for all + the modes in the &s.code;modes&e.code; field of the + &s.code;ScrnInfoRec&e.code;. The &s.code;adjustFlags&e.code; + parameter determines how the vertical CRTC values are scaled for + interlaced modes. They are halved if it is + &s.code;INTERLACE_HALVE_V&e.code;. The vertical CRTC values are + doubled for doublescan modes, and are further multiplied by the + &s.code;VScan&e.code; value. + + This function is normally called after calling + &s.code;xf86PruneDriverModes()&e.code;. + + </quote> + + &s.code;void xf86PrintModes(ScrnInfoPtr scrp)&e.code; + <quote><p> + This function prints out the virtual size setting, and the line + pitch being used. It also prints out two lines for each mode being + used. The first line includes the mode's pixel clock, horizontal sync + rate, refresh rate, and whether it is interlaced, doublescanned and/or + multi-scanned. The second line is the mode's Modeline. + + This function is normally called after calling + &s.code;xf86SetCrtcForModes()&e.code;. + + </quote> + </quote> + + +<sect1>Secondary Mode functions +<p> + +The secondary mode helper functions are functions which are normally +used by the primary mode helper functions, and which are not normally +called directly by a driver. If a driver has unusual requirements +and needs to do its own mode validation, it might be able to make +use of some of these secondary mode helper functions. + + <quote><p> + &s.code;int xf86GetNearestClock(ScrnInfoPtr scrp, int freq, Bool allowDiv2, + &f.indent;int *divider)&e.code; + <quote><p> + This function returns the index of the closest clock to the + frequency &s.code;freq&e.code; given (in kHz). It assumes that + the number of clocks is greater than zero. It requires that the + &s.code;numClocks&e.code; and &s.code;clock&e.code; fields of the + &s.code;ScrnInfoRec&e.code; are initialised. The + &s.code;allowDiv2&e.code; field determines if the clocks can be + halved. The &s.code;*divider&e.code; return value indicates + whether clock division is used when determining the clock returned. + + This function is only for non-programmable clocks. + + </quote> + + &s.code;const char *xf86ModeStatusToString(ModeStatus status)&e.code; + <quote><p> + This function converts the &s.code;status&e.code; value to a + descriptive printable string. + + </quote> + + &s.code;ModeStatus xf86LookupMode(ScrnInfoPtr scrp, DisplayModePtr modep, + &f.indent;ClockRangePtr clockRanges, LookupModeFlags strategy)&e.code; + <quote><p> + This function takes a pointer to a mode with the name filled in, + and looks for a mode in the &s.code;modePool&e.code; list which + matches. The parameters of the matching mode are filled in to + &s.code;*modep&e.code;. The &s.code;clockRanges&e.code; and + &s.code;strategy&e.code; parameters are as for the + &s.code;xf86ValidateModes()&e.code; function above. + + This function requires the &s.code;modePool&e.code;, + &s.code;clock[]&e.code;, &s.code;numClocks&e.code; and + &s.code;progClock&e.code; fields of the &s.code;ScrnInfoRec&e.code; + to be initialised before being called. + + The return value is &s.code;MODE_OK&e.code; if a mode was found. + Otherwise it indicates why a matching mode could not be found. + + </quote> + + &s.code;ModeStatus xf86InitialCheckModeForDriver(ScrnInfoPtr scrp, + &f.indent;DisplayModePtr mode, ClockRangePtr clockRanges, + &f.indent;LookupModeFlags strategy, int maxPitch, + &f.indent;int virtualX, int virtualY)&e.code; + <quote><p> + This function checks the passed mode against some basic driver + constraints. Apart from the ones passed explicitly, the + &s.code;maxHValue&e.code; and &s.code;maxVValue&e.code; fields of + the &s.code;ScrnInfoRec&e.code; are also used. If the + &s.code;ValidMode&e.code; field of the &s.code;ScrnInfoRec&e.code; + is set, that function is also called to check the mode. Next, the + mode is checked against the monitor's constraints. + + If the mode is consistent with all constraints, the return value + is &s.code;MODE_OK&e.code;. Otherwise the return value indicates + which constraint wasn't met. + + </quote> + + &s.code;void xf86DeleteMode(DisplayModePtr *modeList, DisplayModePtr mode)&e.code; + <quote><p> + This function deletes the &s.code;mode&e.code; given from the + &s.code;modeList&e.code;. It never prints any messages, so it is + up to the caller to print a message if required. + + </quote> + </quote> + +<sect1>Functions for handling strings and tokens +<p> + + Tables associating strings and numerical tokens combined with the + following functions provide a compact way of handling strings from + the config file, and for converting tokens into printable strings. + The table data structure is: + +<quote><verb> +typedef struct { + int token; + const char * name; +} SymTabRec, *SymTabPtr; +</verb></quote> + + A table is an initialised array of &s.code;SymTabRec&e.code;. The + tokens must be non-negative integers. Multiple names may be mapped + to a single token. The table is terminated with an element with a + &s.code;token&e.code; value of &s.code;-1&e.code; and + &s.code;NULL&e.code; for the &s.code;name&e.code;. + + + <quote><p> + &s.code;const char *xf86TokenToString(SymTabPtr table, int token)&e.code; + <quote><p> + This function returns the first string in &s.code;table&e.code; + that matches &s.code;token&e.code;. If no match is found, + &s.code;NULL&e.code; is returned (NOTE, older versions of this + function would return the string "unknown" when no match is found). + + </quote> + + &s.code;int xf86StringToToken(SymTabPtr table, const char *string)&e.code; + <quote><p> + This function returns the first token in &s.code;table&e.code; + that matches &s.code;string&e.code;. The + &s.code;xf86NameCmp()&e.code; function is used to determine the + match. If no match is found, &s.code;-1&e.code; is returned. + + </quote> + </quote> + + +<sect1>Functions for finding which config file entries to use +<p> + + These functions can be used to select the appropriate config file + entries that match the detected hardware. They are described above + in the <ref id="probe" name="Probe"> and + <ref id="avail" name="Available Functions"> sections. + + +<sect1>Probing discrete clocks on old hardware +<p> + + The &s.code;xf86GetClocks()&e.code; function may be used to assist + in finding the discrete pixel clock values on older hardware. + + + <quote><p> + &s.code;void xf86GetClocks(ScrnInfoPtr pScrn, int num, + &f.indent;Bool (*ClockFunc)(ScrnInfoPtr, int), + &f.indent;void (*ProtectRegs)(ScrnInfoPtr, Bool), + &f.indent;void (*BlankScreen)(ScrnInfoPtr, Bool), + &f.indent;int vertsyncreg, int maskval, int knownclkindex, + &f.indent;int knownclkvalue)&e.code; + <quote><p> + This function uses a comparative sampling method to measure the + discrete pixel clock values. The number of discrete clocks to + measure is given by &s.code;num&e.code;. &s.code;clockFunc&e.code; + is a function that selects the &s.code;n&e.code;'th clock. It + should also save or restore any state affected by programming the + clocks when the index passed is &s.code;CLK_REG_SAVE&e.code; or + &s.code;CLK_REG_RESTORE&e.code;. &s.code;ProtectRegs&e.code; is + a function that does whatever is required to protect the hardware + state while selecting a new clock. &s.code;BlankScreen&e.code; + is a function that blanks the screen. &s.code;vertsyncreg&e.code; + and &s.code;maskval&e.code; are the register and bitmask to + check for the presence of vertical sync pulses. + &s.code;knownclkindex&e.code; and &s.code;knownclkvalue&e.code; + are the index and value of a known clock. These are the known + references on which the comparative measurements are based. The + number of clocks probed is set in &s.code;pScrn->numClocks&e.code;, + and the probed clocks are set in the &s.code;pScrn->clock[]&e.code; + array. All of the clock values are in units of kHz. + + </quote> + + &s.code;void xf86ShowClocks(ScrnInfoPtr scrp, MessageType from)&e.code; + <quote><p> + Print out the pixel clocks &s.code;scrp->clock[]&e.code;. + &s.code;from&e.code; indicates whether the clocks were probed + or from the config file. + + </quote> + </quote> + +<sect1>Other helper functions +<p> + <quote><p> + &s.code;Bool xf86IsUnblank(int mode)&e.code; + <quote><p> + Returns &s.code;TRUE&e.code; when the screen saver mode specified + by &s.code;mode&e.code; requires the screen be unblanked, + and &s.code;FALSE&e.code; otherwise. The screen saver modes that + require blanking are &s.code;SCREEN_SAVER_ON&e.code; and + &s.code;SCREEN_SAVER_CYCLE&e.code;, and the screen saver modes that + require unblanking are &s.code;SCREEN_SAVER_OFF&e.code; and + &s.code;SCREEN_SAVER_FORCER&e.code;. Drivers may call this helper + from their &s.code;SaveScreen()&e.code; function to interpret the + screen saver modes. + + </quote> + </quote> + +<sect>The vgahw module +<p> + +The vgahw modules provides an interface for saving, restoring and +programming the standard VGA registers, and for handling VGA colourmaps. + +<sect1>Data Structures +<p> + + The public data structures used by the vgahw module are + &s.code;vgaRegRec&e.code; and &s.code;vgaHWRec&e.code;. They are + defined in &s.code;vgaHW.h.&e.code; + + +<sect1>General vgahw Functions +<p> + + <quote><p> + &s.code;Bool vgaHWGetHWRec(ScrnInfoPtr pScrn)&e.code; + <quote><p> + This function allocates a &s.code;vgaHWRec&e.code; structure, and + hooks it into the &s.code;ScrnInfoRec&e.code;'s + &s.code;privates&e.code;. Like all information hooked into the + &s.code;privates&e.code;, it is persistent, and only needs to be + allocated once per screen. This function should normally be called + from the driver's &s.code;ChipPreInit()&e.code; function. The + &s.code;vgaHWRec&e.code; is zero-allocated, and the following + fields are explicitly initialised: + + &s.code;ModeReg.DAC[]&e.code; + <quote>initialised with a default colourmap</quote> + &s.code;ModeReg.Attribute[0x11]&e.code; + <quote>initialised with the default overscan index</quote> + &s.code;ShowOverscan&e.code; + <quote>initialised according to the "ShowOverscan" option</quote> + &s.code;paletteEnabled&e.code; + <quote>initialised to FALSE</quote> + &s.code;cmapSaved&e.code; + <quote>initialised to FALSE</quote> + &s.code;pScrn&e.code; + <quote>initialised to pScrn</quote> + + In addition to the above, &s.code;vgaHWSetStdFuncs()&e.code; is + called to initialise the register access function fields with the + standard VGA set of functions. + + Once allocated, a pointer to the &s.code;vgaHWRec&e.code; can be + obtained from the &s.code;ScrnInfoPtr&e.code; with the + &s.code;VGAHWPTR(pScrn)&e.code; macro. + + </quote> + + &s.code;void vgaHWFreeHWRec(ScrnInfoPtr pScrn)&e.code; + <quote><p> + This function frees a &s.code;vgaHWRec&e.code; structure. It + should be called from a driver's &s.code;ChipFreeScreen()&e.code; + function. + + </quote> + + &s.code;Bool vgaHWSetRegCounts(ScrnInfoPtr pScrn, int numCRTC, + &f.indent;int numSequencer, int numGraphics, int numAttribute)&e.code; + <quote><p> + This function allows the number of CRTC, Sequencer, Graphics and + Attribute registers to be changed. This makes it possible for + extended registers to be saved and restored with + &s.code;vgaHWSave()&e.code; and &s.code;vgaHWRestore()&e.code;. + This function should be called after a &s.code;vgaHWRec&e.code; + has been allocated with &s.code;vgaHWGetHWRec()&e.code;. The + default values are defined in &s.code;vgaHW.h&e.code; as follows: + + <quote><verb> +#define VGA_NUM_CRTC 25 +#define VGA_NUM_SEQ 5 +#define VGA_NUM_GFX 9 +#define VGA_NUM_ATTR 21 + </verb></quote> + + </quote> + + &s.code;Bool vgaHWCopyReg(vgaRegPtr dst, vgaRegPtr src)&e.code; + <quote><p> + This function copies the contents of the VGA saved registers in + &s.code;src&e.code; to &s.code;dst&e.code;. Note that it isn't + possible to simply do this with &s.code;memcpy()&e.code; (or + similar). This function returns &s.code;TRUE&e.code; unless there + is a problem allocating space for the &s.code;CRTC&e.code and + related fields in &s.code;dst&e.code;. + + </quote> + + &s.code;void vgaHWSetStdFuncs(vgaHWPtr hwp)&e.code; + <quote><p> + This function initialises the register access function fields of + &s.code;hwp&e.code; with the standard VGA set of functions. This + is called by &s.code;vgaHWGetHWRec()&e.code;, so there is usually + no need to call this explicitly. The register access functions + are described below. If the registers are shadowed in some other + port I/O space (for example a PCI I/O region), these functions + can be used to access the shadowed registers if + &s.code;hwp->PIOOffset&e.code; is initialised with + &s.code;offset&e.code;, calculated in such a way that when the + standard VGA I/O port value is added to it the correct offset into + the PIO area results. This value is initialised to zero in + &s.code;vgaHWGetHWRec()&e.code;. (Note: the PIOOffset functionality + is present in XFree86 4.1.0 and later.) + + </quote> + + &s.code;void vgaHWSetMmioFuncs(vgaHWPtr hwp, CARD8 *base, int offset)&e.code; + <quote><p> + This function initialised the register access function fields of + hwp with a generic MMIO set of functions. + &s.code;hwp->MMIOBase&e.code; is initialised with + &s.code;base&e.code;, which must be the virtual address that the + start of MMIO area is mapped to. &s.code;hwp->MMIOOffset&e.code; + is initialised with &s.code;offset&e.code;, which must be calculated + in such a way that when the standard VGA I/O port value is added + to it the correct offset into the MMIO area results. That means + that these functions are only suitable when the VGA I/O ports are + made available in a direct mapping to the MMIO space. If that is + not the case, the driver will need to provide its own register + access functions. The register access functions are described + below. + + </quote> + + &s.code;Bool vgaHWMapMem(ScrnInfoPtr pScrn)&e.code; + <quote><p> + This function maps the VGA memory window. It requires that the + &s.code;vgaHWRec&e.code; be allocated. If a driver requires + non-default &s.code;MapPhys&e.code; or &s.code;MapSize&e.code; + settings (the physical location and size of the VGA memory window) + then those fields of the &s.code;vgaHWRec&e.code; must be initialised + before calling this function. Otherwise, this function initialiases + the default values of &s.code;0xA0000&e.code; for + &s.code;MapPhys&e.code; and &s.code;(64 * 1024)&e.code; for + &s.code;MapSize&e.code;. This function must be called before + attempting to save or restore the VGA state. If the driver doesn't + call it explicitly, the &s.code;vgaHWSave()&e.code; and + &s.code;vgaHWRestore()&e.code; functions may call it if they need + to access the VGA memory (in which case they will also call + &s.code;vgaHWUnmapMem()&e.code; to unmap the VGA memory before + exiting). + + </quote> + + &s.code;void vgaHWUnmapMem(ScrnInfoPtr pScrn)&e.code; + <quote><p> + This function unmaps the VGA memory window. It must only be called + after the memory has been mapped. The &s.code;Base&e.code; field + of the &s.code;vgaHWRec&e.code; field is set to &s.code;NULL&e.code; + to indicate that the memory is no longer mapped. + + </quote> + + &s.code;void vgaHWGetIOBase(vgaHWPtr hwp)&e.code; + <quote><p> + This function initialises the &s.code;IOBase&e.code; field of the + &s.code;vgaHWRec&e.code;. This function must be called before + using any other functions that access the video hardware. + + A macro &s.code;VGAHW_GET_IOBASE()&e.code; is also available in + &s.code;vgaHW.h&e.code; that returns the I/O base, and this may + be used when the vgahw module is not loaded (for example, in the + &s.code;ChipProbe()&e.code; function). + + </quote> + + &s.code;void vgaHWUnlock(vgaHWPtr hwp)&e.code; + <quote><p> + This function unlocks the VGA &s.code;CRTC[0-7]&e.code; registers, + and must be called before attempting to write to those registers. + + </quote> + + &s.code;void vgaHWLock(vgaHWPtr hwp)&e.code; + <quote><p> + This function locks the VGA &s.code;CRTC[0-7]&e.code; registers. + + </quote> + + &s.code;void vgaHWEnable(vgaHWPtr hwp)&e.code; + <quote><p> + This function enables the VGA subsystem. (Note, this function is + present in XFree86 4.1.0 and later.). + + </quote> + + &s.code;void vgaHWDisable(vgaHWPtr hwp)&e.code; + <quote><p> + This function disables the VGA subsystem. (Note, this function is + present in XFree86 4.1.0 and later.). + + </quote> + + &s.code;void vgaHWSave(ScrnInfoPtr pScrn, vgaRegPtr save, int flags)&e.code; + <quote><p> + This function saves the VGA state. The state is written to the + &s.code;vgaRegRec&e.code; pointed to by &s.code;save&e.code;. + &s.code;flags&e.code; is set to one or more of the following flags + ORed together: + + &s.code;VGA_SR_MODE&e.code; + <quote>the mode setting registers are saved</quote> + &s.code;VGA_SR_FONTS&e.code; + <quote>the text mode font/text data is saved</quote> + &s.code;VGA_SR_CMAP&e.code; + <quote>the colourmap (LUT) is saved</quote> + &s.code;VGA_SR_ALL&e.code; + <quote>all of the above are saved</quote> + + The &s.code;vgaHWRec&e.code; and its &s.code;IOBase&e.code; fields + must be initialised before this function is called. If + &s.code;VGA_SR_FONTS&e.code; is set in &s.code;flags&e.code;, the + VGA memory window must be mapped. If it isn't then + &s.code;vgaHWMapMem()&e.code; will be called to map it, and + &s.code;vgaHWUnmapMem()&e.code; will be called to unmap it + afterwards. &s.code;vgaHWSave()&e.code; uses the three functions + below in the order &s.code;vgaHWSaveColormap()&e.code;, + &s.code;vgaHWSaveMode()&e.code;, &s.code;vgaHWSaveFonts()&e.code; to + carry out the different save phases. It is undecided at this + stage whether they will remain part of the vgahw module's public + interface or not. + + </quote> + + &s.code;void vgaHWSaveMode(ScrnInfoPtr pScrn, vgaRegPtr save)&e.code; + <quote><p> + This function saves the VGA mode registers. They are saved to + the &s.code;vgaRegRec&e.code; pointed to by &s.code;save&e.code;. + The registers saved are: + + <quote> + &s.code;MiscOut&nl; + CRTC[0-0x18]&nl; + Attribute[0-0x14]&nl; + Graphics[0-8]&nl; + Sequencer[0-4]&e.code; + </quote> + + The number of registers actually saved may be modified by a prior call + to &s.code;vgaHWSetRegCounts()&e.code;. + + </quote> + + &s.code;void vgaHWSaveFonts(ScrnInfoPtr pScrn, vgaRegPtr save)&e.code; + <quote><p> + This function saves the text mode font and text data held in the + video memory. If called while in a graphics mode, no save is + done. The VGA memory window must be mapped with + &s.code;vgaHWMapMem()&e.code; before to calling this function. + + On some platforms, one or more of the font/text plane saves may be + no-ops. This is the case when the platform's VC driver already + takes care of this. + + </quote> + + &s.code;void vgaHWSaveColormap(ScrnInfoPtr pScrn, vgaRegPtr save)&e.code; + <quote><p> + This function saves the VGA colourmap (LUT). Before saving it, it + attempts to verify that the colourmap is readable. In rare cases + where it isn't readable, a default colourmap is saved instead. + + </quote> + + &s.code;void vgaHWRestore(ScrnInfoPtr pScrn, vgaRegPtr restore, int flags)&e.code; + <quote><p> + This function programs the VGA state. The state programmed is + that contained in the &s.code;vgaRegRec&e.code; pointed to by + &s.code;restore&e.code;. &s.code;flags&e.code; is the same + as described above for the &s.code;vgaHWSave()&e.code; function. + + The &s.code;vgaHWRec&e.code; and its &s.code;IOBase&e.code; fields + must be initialised before this function is called. If + &s.code;VGA_SR_FONTS&e.code; is set in &s.code;flags&e.code;, the + VGA memory window must be mapped. If it isn't then + &s.code;vgaHWMapMem()&e.code; will be called to map it, and + &s.code;vgaHWUnmapMem()&e.code; will be called to unmap it + afterwards. &s.code;vgaHWRestore()&e.code; uses the three functions + below in the order &s.code;vgaHWRestoreFonts()&e.code;, + &s.code;vgaHWRestoreMode()&e.code;, + &s.code;vgaHWRestoreColormap()&e.code; to carry out the different + restore phases. It is undecided at this stage whether they will + remain part of the vgahw module's public interface or not. + + </quote> + + &s.code;void vgaHWRestoreMode(ScrnInfoPtr pScrn, vgaRegPtr restore)&e.code; + <quote><p> + This function restores the VGA mode registers. They are restored + from the data in the &s.code;vgaRegRec&e.code; pointed to by + &s.code;restore&e.code;. The registers restored are: + + <quote> + &s.code;MiscOut&nl; + CRTC[0-0x18]&nl; + Attribute[0-0x14]&nl; + Graphics[0-8]&nl; + Sequencer[0-4]&e.code; + </quote> + + The number of registers actually restored may be modified by a prior call + to &s.code;vgaHWSetRegCounts()&e.code;. + + </quote> + + &s.code;void vgaHWRestoreFonts(ScrnInfoPtr pScrn, vgaRegPtr restore)&e.code; + <quote><p> + This function restores the text mode font and text data to the + video memory. The VGA memory window must be mapped with + &s.code;vgaHWMapMem()&e.code; before to calling this function. + + On some platforms, one or more of the font/text plane restores + may be no-ops. This is the case when the platform's VC driver + already takes care of this. + + </quote> + + &s.code;void vgaHWRestoreColormap(ScrnInfoPtr pScrn, vgaRegPtr restore)&e.code; + <quote><p> + This function restores the VGA colourmap (LUT). + + </quote> + + &s.code;void vgaHWInit(ScrnInfoPtr pScrn, DisplayModePtr mode)&e.code; + <quote><p> + This function fills in the &s.code;vgaHWRec&e.code;'s + &s.code;ModeReg&e.code; field with the values appropriate for + programming the given video mode. It requires that the + &s.code;ScrnInfoRec&e.code;'s &s.code;depth&e.code; field is + initialised, which determines how the registers are programmed. + + </quote> + + &s.code;void vgaHWSeqReset(vgaHWPtr hwp, Bool start)&e.code; + <quote><p> + Do a VGA sequencer reset. If start is &s.code;TRUE&e.code;, the + reset is started. If start is &s.code;FALSE&e.code;, the reset + is ended. + + </quote> + + &s.code;void vgaHWProtect(ScrnInfoPtr pScrn, Bool on)&e.code; + <quote><p> + This function protects VGA registers and memory from corruption + during loads. It is typically called with on set to + &s.code;TRUE&e.code; before programming, and with on set to + &s.code;FALSE&e.code; after programming. + + </quote> + + &s.code;Bool vgaHWSaveScreen(ScreenPtr pScreen, int mode)&e.code; + <quote><p> + This function blanks and unblanks the screen. It is blanked when + &s.code;mode&e.code; is &s.code;SCREEN_SAVER_ON&e.code; or + &s.code;SCREEN_SAVER_CYCLE&e.code;, and unblanked when + &s.code;mode&e.code; is &s.code;SCREEN_SAVER_OFF&e.code; or + &s.code;SCREEN_SAVER_FORCER&e.code;. + + </quote> + + &s.code;void vgaHWBlankScreen(ScrnInfoPtr pScrn, Bool on)&e.code; + <quote><p> + This function blanks and unblanks the screen. It is blanked when + &s.code;on&e.code; is &s.code;FALSE&e.code;, and unblanked when + &s.code;on&e.code; is &s.code;TRUE&e.code;. This function is + provided for use in cases where the &s.code;ScrnInfoRec&e.code; + can't be derived from the &s.code;ScreenRec&e.code; (while probing + for clocks, for example). + + </quote> + </quote> + +<sect1>VGA Colormap Functions +<p> + + The vgahw module uses the standard colormap support (see the + <ref id="cmap" name="Colormap Handling"> section. This is initialised + with the following function: + + <quote> + &s.code;Bool vgaHWHandleColormaps(ScreenPtr pScreen)&e.code; + </quote> + + +<sect1>VGA Register Access Functions +<p> + + The vgahw module abstracts access to the standard VGA registers by + using a set of functions held in the &s.code;vgaHWRec&e.code;. When + the &s.code;vgaHWRec&e.code; is created these function pointers are + initialised with the set of standard VGA I/O register access functions. + In addition to these, the vgahw module includes a basic set of MMIO + register access functions, and the &s.code;vgaHWRec&e.code; function + pointers can be initialised to these by calling the + &s.code;vgaHWSetMmioFuncs()&e.code; function described above. Some + drivers/platforms may require a different set of functions for VGA + access. The access functions are described here. + + + <quote><p> + &s.code;void writeCrtc(vgaHWPtr hwp, CARD8 index, CARD8 value)&e.code; + <quote><p> + Write &s.code;value&e.code; to CRTC register &s.code;index&e.code;. + + </quote> + + &s.code;CARD8 readCrtc(vgaHWPtr hwp, CARD8 index)&e.code; + <quote><p> + Return the value read from CRTC register &s.code;index&e.code;. + + </quote> + + &s.code;void writeGr(vgaHWPtr hwp, CARD8 index, CARD8 value)&e.code; + <quote><p> + Write &s.code;value&e.code; to Graphics Controller register + &s.code;index&e.code;. + + </quote> + + &s.code;CARD8 readGR(vgaHWPtr hwp, CARD8 index)&e.code; + <quote><p> + Return the value read from Graphics Controller register + &s.code;index&e.code;. + + </quote> + + &s.code;void writeSeq(vgaHWPtr hwp, CARD8 index, CARD8, value)&e.code; + <quote><p> + Write &s.code;value&e.code; to Sequencer register + &s.code;index&e.code;. + + </quote> + + &s.code;CARD8 readSeq(vgaHWPtr hwp, CARD8 index)&e.code; + <quote><p> + Return the value read from Sequencer register &s.code;index&e.code;. + + </quote> + + &s.code;void writeAttr(vgaHWPtr hwp, CARD8 index, CARD8, value)&e.code; + <quote><p> + Write &s.code;value&e.code; to Attribute Controller register + &s.code;index&e.code;. When writing out the index value this + function should set bit 5 (&s.code;0x20&e.code;) according to the + setting of &s.code;hwp->paletteEnabled&e.code; in order to + preserve the palette access state. It should be cleared when + &s.code;hwp->paletteEnabled&e.code; is &s.code;TRUE&e.code; + and set when it is &s.code;FALSE&e.code;. + + </quote> + + &s.code;CARD8 readAttr(vgaHWPtr hwp, CARD8 index)&e.code; + <quote><p> + Return the value read from Attribute Controller register + &s.code;index&e.code;. When writing out the index value this + function should set bit 5 (&s.code;0x20&e.code;) according to the + setting of &s.code;hwp->paletteEnabled&e.code; in order to + preserve the palette access state. It should be cleared when + &s.code;hwp->paletteEnabled&e.code; is &s.code;TRUE&e.code; + and set when it is &s.code;FALSE&e.code;. + + </quote> + + &s.code;void writeMiscOut(vgaHWPtr hwp, CARD8 value)&e.code; + <quote><p> + Write `&s.code;value&e.code;' to the Miscellaneous Output register. + + </quote> + + &s.code;CARD8 readMiscOut(vgwHWPtr hwp)&e.code; + <quote><p> + Return the value read from the Miscellaneous Output register. + + </quote> + + &s.code;void enablePalette(vgaHWPtr hwp)&e.code; + <quote><p> + Clear the palette address source bit in the Attribute Controller + index register and set &s.code;hwp->paletteEnabled&e.code; to + &s.code;TRUE&e.code;. + + </quote> + + &s.code;void disablePalette(vgaHWPtr hwp)&e.code; + <quote><p> + Set the palette address source bit in the Attribute Controller + index register and set &s.code;hwp->paletteEnabled&e.code; to + &s.code;FALSE&e.code;. + + </quote> + + &s.code;void writeDacMask(vgaHWPtr hwp, CARD8 value)&e.code; + <quote><p> + Write &s.code;value&e.code; to the DAC Mask register. + + </quote> + + &s.code;CARD8 readDacMask(vgaHWptr hwp)&e.code; + <quote><p> + Return the value read from the DAC Mask register. + + </quote> + + &s.code;void writeDacReadAddress(vgaHWPtr hwp, CARD8 value)&e.code; + <quote><p> + Write &s.code;value&e.code; to the DAC Read Address register. + + </quote> + + &s.code;void writeDacWriteAddress(vgaHWPtr hwp, CARD8 value)&e.code; + <quote><p> + Write &s.code;value&e.code; to the DAC Write Address register. + + </quote> + + &s.code;void writeDacData(vgaHWPtr hwp, CARD8 value)&e.code; + <quote><p> + Write &s.code;value&e.code; to the DAC Data register. + + </quote> + + &s.code;CARD8 readDacData(vgaHWptr hwp)&e.code; + <quote><p> + Return the value read from the DAC Data register. + + </quote> + + &s.code;CARD8 readEnable(vgaHWptr hwp)&e.code; + <quote><p> + Return the value read from the VGA Enable register. (Note: This + function is present in XFree86 4.1.0 and later.) + + </quote> + + &s.code;void writeEnable(vgaHWPtr hwp, CARD8 value)&e.code; + <quote><p> + Write &s.code;value&e.code; to the VGA Enable register. (Note: This + function is present in XFree86 4.1.0 and later.) + + </quote> + </quote> + +<sect>Some notes about writing a driver<label id="sample"> +<p> + +<em>NOTE: some parts of this are not up to date</em> + +The following is an outline for writing a basic unaccelerated driver +for a PCI video card with a linear mapped framebuffer, and which has a +VGA core. It is includes some general information that is relevant to +most drivers (even those which don't fit that basic description). + +The information here is based on the initial conversion of the Matrox +Millennium driver to the ``new design''. For a fleshing out and sample +implementation of some of the bits outlined here, refer to that driver. +Note that this is an example only. The approach used here will not be +appropriate for all drivers. + +Each driver must reserve a unique driver name, and a string that is used +to prefix all of its externally visible symbols. This is to avoid name +space clashes when loading multiple drivers. The examples here are for +the ``ZZZ'' driver, which uses the ``ZZZ'' or ``zzz'' prefix for its externally +visible symbols. + + +<sect1>Include files +<p> + + All drivers normally include the following headers: + <quote> + &s.code;"xf86.h"&nl; + "xf86_OSproc.h"&nl; + "xf86_ansic.h"&nl; + "xf86Resources.h"&e.code; + </quote> + Wherever inb/outb (and related things) are used the following should be + included: + <quote> + &s.code;"compiler.h"&e.code; + </quote> + Note: in drivers, this must be included after &s.code;"xf86_ansic.h"&e.code;. + + Drivers that need to access PCI vendor/device definitions need this: + <quote> + &s.code;"xf86PciInfo.h"&e.code; + </quote> + + Drivers that need to access the PCI config space need this: + <quote> + &s.code;"xf86Pci.h"&e.code; + </quote> + + Drivers using the mi banking wrapper need: + + <quote> + &s.code;"mibank.h"&e.code; + </quote> + + Drivers that initialise a SW cursor need this: + <quote> + &s.code;"mipointer.h"&e.code; + </quote> + + All drivers implementing backing store need this: + <quote> + &s.code;"mibstore.h"&e.code; + </quote> + + All drivers using the mi colourmap code need this: + <quote> + &s.code;"micmap.h"&e.code; + </quote> + + If a driver uses the vgahw module, it needs this: + <quote> + &s.code;"vgaHW.h"&e.code; + </quote> + + Drivers supporting VGA or Hercules monochrome screens need: + <quote> + &s.code;"xf1bpp.h"&e.code; + </quote> + + Drivers supporting VGA or EGC 16-colour screens need: + <quote> + &s.code;"xf4bpp.h"&e.code; + </quote> + + Drivers using cfb need: + <quote> + &s.code;#define PSZ 8&nl; + #include "cfb.h"&nl; + #undef PSZ&e.code; + </quote> + + Drivers supporting bpp 16, 24 or 32 with cfb need one or more of: + <quote> + &s.code;"cfb16.h"&nl; + "cfb24.h"&nl; + "cfb32.h"&e.code; + </quote> + + The driver's own header file: + <quote> + &s.code;"zzz.h"&e.code; + </quote> + + Drivers must NOT include the following: + + <quote> + &s.code;"xf86Priv.h"&nl; + "xf86Privstr.h"&nl; + "xf86_libc.h"&nl; + "xf86_OSlib.h"&nl; + "Xos.h"&e.code;&nl; + any OS header + </quote> + + +<sect1>Data structures and initialisation +<p> + +<itemize> + <item>The following macros should be defined: + <code> +#define VERSION <version-as-an-int> +#define ZZZ_NAME "ZZZ" /* the name used to prefix messages */ +#define ZZZ_DRIVER_NAME "zzz" /* the driver name as used in config file */ +#define ZZZ_MAJOR_VERSION <int> +#define ZZZ_MINOR_VERSION <int> +#define ZZZ_PATCHLEVEL <int> + </code> +<p> + NOTE: &s.code;ZZZ_DRIVER_NAME&e.code; should match the name of the + driver module without things like the "lib" prefix, the "_drv" suffix + or filename extensions. +<p> + + <item>A DriverRec must be defined, which includes the functions required + at the pre-probe phase. The name of this DriverRec must be an + upper-case version of ZZZ_DRIVER_NAME (for the purposes of static + linking). +<p> + <code> +DriverRec ZZZ = { + VERSION, + ZZZ_DRIVER_NAME, + ZZZIdentify, + ZZZProbe, + ZZZAvailableOptions, + NULL, + 0 +}; + </code> + + <item>Define list of supported chips and their matching ID: +<p> + <code> +static SymTabRec ZZZChipsets[] = { + { PCI_CHIP_ZZZ1234, "zzz1234a" }, + { PCI_CHIP_ZZZ5678, "zzz5678a" }, + { -1, NULL } +}; + </code> +<p> + The token field may be any integer value that the driver may use to + uniquely identify the supported chipsets. For drivers that support + only PCI devices using the PCI device IDs might be a natural choice, + but this isn't mandatory. For drivers that support both PCI and other + devices (like ISA), some other ID should probably used. When other + IDs are used as the tokens it is recommended that the names be + defined as an &s.code;enum&e.code; type. +<p> + <item>If the driver uses the &s.code;xf86MatchPciInstances(&e.code;) + helper (recommended for drivers that support PCI cards) a list that + maps PCI IDs to chip IDs and fixed resources must be defined: +<p> + <code> +static PciChipsets ZZZPciChipsets[] = { + { PCI_CHIP_ZZZ1234, PCI_CHIP_ZZZ1234, RES_SHARED_VGA }, + { PCI_CHIP_ZZZ5678, PCI_CHIP_ZZZ5678, RES_SHARED_VGA }, + { -1, -1, RES_UNDEFINED } +} + </code> +<p> + <item>Define the &s.code;XF86ModuleVersionInfo&e.code; struct for the + driver. This is required for the dynamically loaded version: +<p> + <code> +#ifdef XFree86LOADER +static XF86ModuleVersionInfo zzzVersRec = +{ + "zzz", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XF86_VERSION_CURRENT, + ZZZ_MAJOR_VERSION, ZZZ_MINOR_VERSION, ZZZ_PATCHLEVEL, + ABI_CLASS_VIDEODRV, + ABI_VIDEODRV_VERSION, + MOD_CLASS_VIDEODRV, + {0,0,0,0} +}; +#endif + </code> +<p> + <item>Define a data structure to hold the driver's screen-specific data. + This must be used instead of global variables. This would be defined + in the &s.code;"zzz.h"&e.code; file, something like: +<p> + <code> +typedef struct { + type1 field1; + type2 field2; + int fooHack; + Bool pciRetry; + Bool noAccel; + Bool hwCursor; + CloseScreenProcPtr CloseScreen; + OptionInfoPtr Options; + ... +} ZZZRec, *ZZZPtr; + </code> +<p> + <item>Define the list of config file Options that the driver accepts. For + consistency between drivers those in the list of ``standard'' options + should be used where appropriate before inventing new options. +<p> + <code> +typedef enum { + OPTION_FOO_HACK, + OPTION_PCI_RETRY, + OPTION_HW_CURSOR, + OPTION_NOACCEL +} ZZZOpts; + +static const OptionInfoRec ZZZOptions[] = { + { OPTION_FOO_HACK, "FooHack", OPTV_INTEGER, {0}, FALSE }, + { OPTION_PCI_RETRY, "PciRetry", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, + { -1, NULL, OPTV_NONE, {0}, FALSE } +}; + </code> +<p> +</itemize> + +<sect1>Functions +<p> + + +<sect2>SetupProc +<p> + + For dynamically loaded modules, a &s.code;ModuleData&e.code; + variable is required. It is should be the name of the driver + prepended to "ModuleData". A &s.code;Setup()&e.code; function is + also required, which calls &s.code;xf86AddDriver()&e.code; to add + the driver to the main list of drivers. + + <code> +#ifdef XFree86LOADER + +static MODULESETUPPROTO(mgaSetup); + +XF86ModuleData zzzModuleData = { &zzzVersRec, zzzSetup, NULL }; + +static pointer +zzzSetup(pointer module, pointer opts, int *errmaj, int *errmin) +{ + static Bool setupDone = FALSE; + + /* This module should be loaded only once, but check to be sure. */ + + if (!setupDone) { + /* + * Modules that this driver always requires may be loaded + * here by calling LoadSubModule(). + */ + + setupDone = TRUE; + xf86AddDriver(&MGA, module, 0); + + /* + * The return value must be non-NULL on success even though + * there is no TearDownProc. + */ + return (pointer)1; + } else { + if (errmaj) *errmaj = LDR_ONCEONLY; + return NULL; + } +} +#endif + </code> + +<sect2>GetRec, FreeRec +<p> + + A function is usually required to allocate the driver's + screen-specific data structure and hook it into the + &s.code;ScrnInfoRec&e.code;'s &s.code;driverPrivate&e.code; field. + The &s.code;ScrnInfoRec&e.code;'s &s.code;driverPrivate&e.code; is + initialised to &s.code;NULL&e.code;, so it is easy to check if the + initialisation has already been done. After allocating it, initialise + the fields. By using &s.code;xnfcalloc()&e.code; to do the allocation + it is zeroed, and if the allocation fails the server exits. +<p> + NOTE: + When allocating structures from inside the driver which are defined + on the common level it is important to initialize the structure to + zero. + Only this guarantees that the server remains source compatible to + future changes in common level structures. + + <code> +static Bool +ZZZGetRec(ScrnInfoPtr pScrn) +{ + if (pScrn->driverPrivate != NULL) + return TRUE; + pScrn->driverPrivate = xnfcalloc(sizeof(ZZZRec), 1); + /* Initialise as required */ + ... + return TRUE; +} + </code> + + Define a macro in &s.code;"zzz.h"&e.code; which gets a pointer to + the &s.code;ZZZRec&e.code; when given &s.code;pScrn&e.code;: + + <code> +#define ZZZPTR(p) ((ZZZPtr)((p)->driverPrivate)) + </code> + + Define a function to free the above, setting it to &s.code;NULL&e.code; + once it has been freed: + + <code> +static void +ZZZFreeRec(ScrnInfoPtr pScrn) +{ + if (pScrn->driverPrivate == NULL) + return; + xfree(pScrn->driverPrivate); + pScrn->driverPrivate = NULL; +} + </code> + +<sect2>Identify +<p> + + Define the &s.code;Identify()&e.code; function. It is run before + the Probe, and typically prints out an identifying message, which + might include the chipsets it supports. This function is mandatory: + + <code> +static void +ZZZIdentify(int flags) +{ + xf86PrintChipsets(ZZZ_NAME, "driver for ZZZ Tech chipsets", + ZZZChipsets); +} + </code> + +<sect2>Probe +<p> + + Define the &s.code;Probe()&e.code; function. The purpose of this + is to find all instances of the hardware that the driver supports, + and for the ones not already claimed by another driver, claim the + slot, and allocate a &s.code;ScrnInfoRec&e.code;. This should be + a minimal probe, and it should under no circumstances leave the + state of the hardware changed. Because a device is found, don't + assume that it will be used. Don't do any initialisations other + than the required &s.code;ScrnInfoRec&e.code; initialisations. + Don't allocate any new data structures. + + This function is mandatory. + + NOTE: The &s.code;xf86DrvMsg()&e.code; functions cannot be used from + the Probe. + + <code> +static Bool +ZZZProbe(DriverPtr drv, int flags) +{ + Bool foundScreen = FALSE; + int numDevSections, numUsed; + GDevPtr *devSections; + int *usedChips; + int i; + + /* + * Find the config file Device sections that match this + * driver, and return if there are none. + */ + if ((numDevSections = xf86MatchDevice(ZZZ_DRIVER_NAME, + &devSections)) <= 0) { + return FALSE; + } + + /* + * Since this is a PCI card, "probing" just amounts to checking + * the PCI data that the server has already collected. If there + * is none, return. + * + * Although the config file is allowed to override things, it + * is reasonable to not allow it to override the detection + * of no PCI video cards. + * + * The provided xf86MatchPciInstances() helper takes care of + * the details. + */ + /* test if PCI bus present */ + if (xf86GetPciVideoInfo()) { + + numUsed = xf86MatchPciInstances(ZZZ_NAME, PCI_VENDOR_ZZZ, + ZZZChipsets, ZZZPciChipsets, devSections, + numDevSections, drv, &usedChips); + + for (i = 0; i < numUsed; i++) { + ScrnInfoPtr pScrn = NULL; + if ((pScrn = xf86ConfigPciEntity(pScrn, flags, usedChips[i], + ZZZPciChipsets, NULL, NULL, + NULL, NULL, NULL))) { + /* Allocate a ScrnInfoRec */ + pScrn->driverVersion = VERSION; + pScrn->driverName = ZZZ_DRIVER_NAME; + pScrn->name = ZZZ_NAME; + pScrn->Probe = ZZZProbe; + pScrn->PreInit = ZZZPreInit; + pScrn->ScreenInit = ZZZScreenInit; + pScrn->SwitchMode = ZZZSwitchMode; + pScrn->AdjustFrame = ZZZAdjustFrame; + pScrn->EnterVT = ZZZEnterVT; + pScrn->LeaveVT = ZZZLeaveVT; + pScrn->FreeScreen = ZZZFreeScreen; + pScrn->ValidMode = ZZZValidMode; + foundScreen = TRUE; + /* add screen to entity */ + } + } + xfree(usedChips); + } + +#ifdef HAS_ISA_DEVS + /* + * If the driver supports ISA hardware, the following block + * can be included too. + */ + numUsed = xf86MatchIsaInstances(ZZZ_NAME, ZZZChipsets, + ZZZIsaChipsets, drv, ZZZFindIsaDevice, + devSections, numDevSections, &usedChips); + for (i = 0; i < numUsed; i++) { + ScrnInfoPtr pScrn = NULL; + if ((pScrn = xf86ConfigIsaEntity(pScrn, flags, usedChips[i], + ZZZIsaChipsets, NULL, NULL, NULL, + NULL, NULL))) { + pScrn->driverVersion = VERSION; + pScrn->driverName = ZZZ_DRIVER_NAME; + pScrn->name = ZZZ_NAME; + pScrn->Probe = ZZZProbe; + pScrn->PreInit = ZZZPreInit; + pScrn->ScreenInit = ZZZScreenInit; + pScrn->SwitchMode = ZZZSwitchMode; + pScrn->AdjustFrame = ZZZAdjustFrame; + pScrn->EnterVT = ZZZEnterVT; + pScrn->LeaveVT = ZZZLeaveVT; + pScrn->FreeScreen = ZZZFreeScreen; + pScrn->ValidMode = ZZZValidMode; + foundScreen = TRUE; + } + } + xfree(usedChips); +#endif /* HAS_ISA_DEVS */ + + xfree(devSections); + return foundScreen; + </code> + +<sect2>AvailableOptions +<p> + + Define the &s.code;AvailableOptions()&e.code; function. The purpose + of this is to return the available driver options back to the + -configure option, so that an XF86Config file can be built and the + user can see which options are available for them to use. + +<sect2>PreInit +<p> + + Define the &s.code;PreInit()&e.code; function. The purpose of + this is to find all the information required to determine if the + configuration is usable, and to initialise those parts of the + &s.code;ScrnInfoRec&e.code; that can be set once at the beginning + of the first server generation. The information should be found in + the least intrusive way possible. + + This function is mandatory. + + NOTES: + <enum> + <item>The &s.code;PreInit()&e.code; function is only called once + during the life of the X server (at the start of the first + generation). + + <item>Data allocated here must be of the type that persists for + the life of the X server. This means that data that hooks into + the &s.code;ScrnInfoRec&e.code;'s &s.code;privates&e.code; + field should be allocated here, but data that hooks into the + &s.code;ScreenRec&e.code;'s &s.code;devPrivates&e.code; field + should not be allocated here. The &s.code;driverPrivate&e.code; + field should also be allocated here. + + <item>Although the &s.code;ScrnInfoRec&e.code; has been allocated + before this function is called, the &s.code;ScreenRec&e.code; + has not been allocated. That means that things requiring it + cannot be used in this function. + + <item>Very little of the &s.code;ScrnInfoRec&e.code; has been + initialised when this function is called. It is important to + get the order of doing things right in this function. + + </enum> + + <code> +static Bool +ZZZPreInit(ScrnInfoPtr pScrn, int flags) +{ + /* Fill in the monitor field */ + pScrn->monitor = pScrn->confScreen->monitor; + + /* + * If using the vgahw module, it will typically be loaded + * here by calling xf86LoadSubModule(pScrn, "vgahw"); + */ + + /* + * Set the depth/bpp. Our preferred default depth/bpp is 8, and + * we support both 24bpp and 32bpp framebuffer layouts. + * This sets pScrn->display also. + */ + if (!xf86SetDepthBpp(pScrn, 8, 8, 8, + Support24bppFb | Support32bppFb)) { + return FALSE; + } else { + if (depth/bpp isn't one we support) { + print error message; + return FALSE; + } + } + /* Print out the depth/bpp that was set */ + xf86PrintDepthBpp(pScrn); + + /* Set bits per RGB for 8bpp */ + if (pScrn->depth <= 8) { + /* Take into account a dac_6_bit option here */ + pScrn->rgbBits = 6 or 8; + } + + /* + * xf86SetWeight() and xf86SetDefaultVisual() must be called + * after pScrn->display is initialised. + */ + + /* Set weight/mask/offset for depth > 8 */ + if (pScrn->depth > 8) { + if (!xf86SetWeight(pScrn, defaultWeight, defaultMask)) { + return FALSE; + } else { + if (weight isn't one we support) { + print error message; + return FALSE; + } + } + } + + /* Set the default visual. */ + if (!xf86SetDefaultVisual(pScrn, -1)) { + return FALSE; + } else { + if (visual isn't one we support) { + print error message; + return FALSE; + } + } + + /* If the driver supports gamma correction, set the gamma. */ + if (!xf86SetGamma(pScrn, default_gamma)) { + return FALSE; + } + + /* This driver uses a programmable clock */ + pScrn->progClock = TRUE; + + /* Allocate the ZZZRec driverPrivate */ + if (!ZZZGetRec(pScrn)) { + return FALSE; + } + + pZzz = ZZZPTR(pScrn); + + /* Collect all of the option flags (fill in pScrn->options) */ + xf86CollectOptions(pScrn, NULL); + + /* + * Process the options based on the information in ZZZOptions. + * The results are written to pZzz->Options. If all of the options + * processing is done within this function a local variable "options" + * can be used instead of pZzz->Options. + */ + if (!(pZzz->Options = xalloc(sizeof(ZZZOptions)))) + return FALSE; + (void)memcpy(pZzz->Options, ZZZOptions, sizeof(ZZZOptions)); + xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pZzz->Options); + + /* + * Set various fields of ScrnInfoRec and/or ZZZRec based on + * the options found. + */ + from = X_DEFAULT; + pZzz->hwCursor = FALSE; + if (xf86IsOptionSet(pZzz->Options, OPTION_HW_CURSOR)) { + from = X_CONFIG; + pZzz->hwCursor = TRUE; + } + xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", + pZzz->hwCursor ? "HW" : "SW"); + if (xf86IsOptionSet(pZzz->Options, OPTION_NOACCEL)) { + pZzz->noAccel = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "Acceleration disabled\n"); + } else { + pZzz->noAccel = FALSE; + } + if (xf86IsOptionSet(pZzz->Options, OPTION_PCI_RETRY)) { + pZzz->UsePCIRetry = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry enabled\n"); + } + pZzz->fooHack = 0; + if (xf86GetOptValInteger(pZzz->Options, OPTION_FOO_HACK, + &pZzz->fooHack)) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Foo Hack set to %d\n", + pZzz->fooHack); + } + + /* + * Find the PCI slot(s) that this screen claimed in the probe. + * In this case, exactly one is expected, so complain otherwise. + * Note in this case we're not interested in the card types so + * that parameter is set to NULL. + */ + if ((i = xf86GetPciInfoForScreen(pScrn->scrnIndex, &pciList, NULL)) + != 1) { + print error message; + ZZZFreeRec(pScrn); + if (i > 0) + xfree(pciList); + return FALSE; + } + /* Note that pciList should be freed below when no longer needed */ + + /* + * Determine the chipset, allowing config file chipset and + * chipid values to override the probed information. The config + * chipset value has precedence over its chipid value if both + * are present. + * + * It isn't necessary to fill in pScrn->chipset if the driver + * keeps track of the chipset in its ZZZRec. + */ + + ... + + /* + * Determine video memory, fb base address, I/O addresses, etc, + * allowing the config file to override probed values. + * + * Set the appropriate pScrn fields (videoRam is probably the + * most important one that other code might require), and + * print out the settings. + */ + + ... + + /* Initialise a clockRanges list. */ + + ... + + /* Set any other chipset specific things in the ZZZRec */ + + ... + + /* Select valid modes from those available */ + + i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, + pScrn->display->modes, clockRanges, + NULL, minPitch, maxPitch, rounding, + minHeight, maxHeight, + pScrn->display->virtualX, + pScrn->display->virtualY, + pScrn->videoRam * 1024, + LOOKUP_BEST_REFRESH); + if (i == -1) { + ZZZFreeRec(pScrn); + return FALSE; + } + + /* Prune the modes marked as invalid */ + + xf86PruneDriverModes(pScrn); + + /* If no valid modes, return */ + + if (i == 0 || pScrn->modes == NULL) { + print error message; + ZZZFreeRec(pScrn); + return FALSE; + } + + /* + * Initialise the CRTC fields for the modes. This driver expects + * vertical values to be halved for interlaced modes. + */ + xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); + + /* Set the current mode to the first in the list. */ + pScrn->currentMode = pScrn->modes; + + /* Print the list of modes being used. */ + xf86PrintModes(pScrn); + + /* Set the DPI */ + xf86SetDpi(pScrn, 0, 0); + + /* Load bpp-specific modules */ + switch (pScrn->bitsPerPixel) { + case 1: + mod = "xf1bpp"; + break; + case 4: + mod = "xf4bpp"; + break; + case 8: + mod = "cfb"; + break; + case 16: + mod = "cfb16"; + break; + case 24: + mod = "cfb24"; + break; + case 32: + mod = "cfb32"; + break; + } + if (mod && !xf86LoadSubModule(pScrn, mod)) + ZZZFreeRec(pScrn); + return FALSE; + + /* Load XAA if needed */ + if (!pZzz->noAccel || pZzz->hwCursor) + if (!xf86LoadSubModule(pScrn, "xaa")) { + ZZZFreeRec(pScrn); + return FALSE; + } + + /* Done */ + return TRUE; +} + </code> + +<sect2>MapMem, UnmapMem +<p> + + Define functions to map and unmap the video memory and any other + memory apertures required. These functions are not mandatory, but + it is often useful to have such functions. + + <code> +static Bool +ZZZMapMem(ScrnInfoPtr pScrn) +{ + /* Call xf86MapPciMem() to map each PCI memory area */ + ... + return TRUE or FALSE; +} + +static Bool +ZZZUnmapMem(ScrnInfoPtr pScrn) +{ + /* Call xf86UnMapVidMem() to unmap each memory area */ + ... + return TRUE or FALSE; +} + </code> + +<sect2>Save, Restore +<p> + + Define functions to save and restore the original video state. These + functions are not mandatory, but are often useful. + + <code> +static void +ZZZSave(ScrnInfoPtr pScrn) +{ + /* + * Save state into per-screen data structures. + * If using the vgahw module, vgaHWSave will typically be + * called here. + */ + ... +} + +static void +ZZZRestore(ScrnInfoPtr pScrn) +{ + /* + * Restore state from per-screen data structures. + * If using the vgahw module, vgaHWRestore will typically be + * called here. + */ + ... +} + </code> + +<sect2>ModeInit +<p> + + Define a function to initialise a new video mode. This function isn't + mandatory, but is often useful. + + <code> +static Bool +ZZZModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + /* + * Program a video mode. If using the vgahw module, + * vgaHWInit and vgaRestore will typically be called here. + * Once up to the point where there can't be a failure + * set pScrn->vtSema to TRUE. + */ + ... +} + </code> + +<sect2>ScreenInit +<p> + + Define the &s.code;ScreenInit()&e.code; function. This is called + at the start of each server generation, and should fill in as much + of the &s.code;ScreenRec&e.code; as possible as well as any other + data that is initialised once per generation. It should initialise + the framebuffer layers it is using, and initialise the initial video + mode. + + This function is mandatory. + + NOTE: The &s.code;ScreenRec&e.code; (&s.code;pScreen&e.code;) is + passed to this driver, but it and the + &s.code;ScrnInfoRecs&e.code; are not yet hooked into each + other. This means that in this function, and functions it + calls, one cannot be found from the other. + + <code> +static Bool +ZZZScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) +{ + /* Get the ScrnInfoRec */ + pScrn = xf86Screens[pScreen->myNum]; + + /* + * If using the vgahw module, its data structures and related + * things are typically initialised/mapped here. + */ + + /* Save the current video state */ + ZZZSave(pScrn); + + /* Initialise the first mode */ + ZZZModeInit(pScrn, pScrn->currentMode); + + /* Set the viewport if supported */ + + ZZZAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + + /* + * Setup the screen's visuals, and initialise the framebuffer + * code. + */ + + /* Reset the visual list */ + miClearVisualTypes(); + + /* + * Setup the visuals supported. This driver only supports + * TrueColor for bpp > 8, so the default set of visuals isn't + * acceptable. To deal with this, call miSetVisualTypes with + * the appropriate visual mask. + */ + + if (pScrn->bitsPerPixel > 8) { + if (!miSetVisualTypes(pScrn->depth, TrueColorMask, + pScrn->rgbBits, pScrn->defaultVisual)) + return FALSE; + } else { + if (!miSetVisualTypes(pScrn->depth, + miGetDefaultVisualMask(pScrn->depth), + pScrn->rgbBits, pScrn->defaultVisual)) + return FALSE; + } + + /* + * Initialise the framebuffer. + */ + + switch (pScrn->bitsPerPixel) { + case 1: + ret = xf1bppScreenInit(pScreen, FbBase, + pScrn->virtualX, pScrn->virtualY, + pScrn->xDpi, pScrn->yDpi, + pScrn->displayWidth); + break; + case 4: + ret = xf4bppScreenInit(pScreen, FbBase, + pScrn->virtualX, pScrn->virtualY, + pScrn->xDpi, pScrn->yDpi, + pScrn->displayWidth); + break; + case 8: + ret = cfbScreenInit(pScreen, FbBase, + pScrn->virtualX, pScrn->virtualY, + pScrn->xDpi, pScrn->yDpi, + pScrn->displayWidth); + break; + case 16: + ret = cfb16ScreenInit(pScreen, FbBase, + pScrn->virtualX, pScrn->virtualY, + pScrn->xDpi, pScrn->yDpi, + pScrn->displayWidth); + break; + case 24: + ret = cfb24ScreenInit(pScreen, FbBase, + pScrn->virtualX, pScrn->virtualY, + pScrn->xDpi, pScrn->yDpi, + pScrn->displayWidth); + break; + case 32: + ret = cfb32ScreenInit(pScreen, FbBase, + pScrn->virtualX, pScrn->virtualY, + pScrn->xDpi, pScrn->yDpi, + pScrn->displayWidth); + break; + default: + print a message about an internal error; + ret = FALSE; + break; + } + + if (!ret) + return FALSE; + + /* Override the default mask/offset settings */ + if (pScrn->bitsPerPixel > 8) { + for (i = 0, visual = pScreen->visuals; + i < pScreen->numVisuals; i++, visual++) { + if ((visual->class | DynamicClass) == DirectColor) { + visual->offsetRed = pScrn->offset.red; + visual->offsetGreen = pScrn->offset.green; + visual->offsetBlue = pScrn->offset.blue; + visual->redMask = pScrn->mask.red; + visual->greenMask = pScrn->mask.green; + visual->blueMask = pScrn->mask.blue; + } + } + } + + /* + * If banking is needed, initialise an miBankInfoRec (defined in + * "mibank.h"), and call miInitializeBanking(). + */ + if (!miInitializeBanking(pScreen, pScrn->virtualX, pScrn->virtualY, + pScrn->displayWidth, pBankInfo)) + return FALSE; + + /* + * If backing store is to be supported (as is usually the case), + * initialise it. + */ + miInitializeBackingStore(pScreen); + + /* + * Set initial black & white colourmap indices. + */ + xf86SetBlackWhitePixels(pScreen); + + /* + * Install colourmap functions. If using the vgahw module, + * vgaHandleColormaps would usually be called here. + */ + + ... + + /* + * Initialise cursor functions. This example is for the mi + * software cursor. + */ + miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); + + /* Initialise the default colourmap */ + switch (pScrn->depth) { + case 1: + if (!xf1bppCreateDefColormap(pScreen)) + return FALSE; + break; + case 4: + if (!xf4bppCreateDefColormap(pScreen)) + return FALSE; + break; + default: + if (!cfbCreateDefColormap(pScreen)) + return FALSE; + break; + } + + /* + * Wrap the CloseScreen vector and set SaveScreen. + */ + ZZZPTR(pScrn)->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = ZZZCloseScreen; + pScreen->SaveScreen = ZZZSaveScreen; + + /* Report any unused options (only for the first generation) */ + if (serverGeneration == 1) { + xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); + } + + /* Done */ + return TRUE; +} + </code> + + +<sect2>SwitchMode +<p> + + Define the &s.code;SwitchMode()&e.code; function if mode switching + is supported by the driver. + + <code> +static Bool +ZZZSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) +{ + return ZZZModeInit(xf86Screens[scrnIndex], mode); +} + </code> + + +<sect2>AdjustFrame +<p> + + Define the &s.code;AdjustFrame()&e.code; function if the driver + supports this. + + <code> +static void +ZZZAdjustFrame(int scrnIndex, int x, int y, int flags) +{ + /* Adjust the viewport */ +} + </code> + + +<sect2>EnterVT, LeaveVT +<p> + + Define the &s.code;EnterVT()&e.code; and &s.code;LeaveVT()&e.code; + functions. + + These functions are mandatory. + + <code> +static Bool +ZZZEnterVT(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + return ZZZModeInit(pScrn, pScrn->currentMode); +} + +static void +ZZZLeaveVT(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + ZZZRestore(pScrn); +} + </code> + +<sect2>CloseScreen +<p> + + Define the &s.code;CloseScreen()&e.code; function: + + This function is mandatory. Note that it unwraps the previously + wrapped &s.code;pScreen->CloseScreen&e.code;, and finishes by + calling it. + + <code> +static Bool +ZZZCloseScreen(int scrnIndex, ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + if (pScrn->vtSema) { + ZZZRestore(pScrn); + ZZZUnmapMem(pScrn); + } + pScrn->vtSema = FALSE; + pScreen->CloseScreen = ZZZPTR(pScrn)->CloseScreen; + return (*pScreen->CloseScreen)(scrnIndex, pScreen); +} + </code> + +<sect2>SaveScreen +<p> + + Define the &s.code;SaveScreen()&e.code; function (the screen + blanking function). When using the vgahw module, this will typically + be: + + <code> +static Bool +ZZZSaveScreen(ScreenPtr pScreen, int mode) +{ + return vgaHWSaveScreen(pScreen, mode); +} + </code> + + This function is mandatory. Before modifying any hardware register + directly this function needs to make sure that the Xserver is active + by checking if &s.code;pScrn&e.code; is non-NULL and for + &s.code;pScrn->vtSema == TRUE&e.code;. + +<sect2>FreeScreen +<p> + + Define the &s.code;FreeScreen()&e.code; function. This function + is optional. It should be defined if the &s.code;ScrnInfoRec&e.code; + &s.code;driverPrivate&e.code; field is used so that it can be freed + when a screen is deleted by the common layer for reasons possibly + beyond the driver's control. This function is not used in during + normal (error free) operation. The per-generation data is freed by + the &s.code;CloseScreen()&e.code; function. + + <code> +static void +ZZZFreeScreen(int scrnIndex, int flags) +{ + /* + * If the vgahw module is used vgaHWFreeHWRec() would be called + * here. + */ + ZZZFreeRec(xf86Screens[scrnIndex]); +} + </code> + + +</article> |