697 lines
29 KiB
Plaintext
697 lines
29 KiB
Plaintext
I. Abstract
|
|
===========
|
|
|
|
Graphics devices are accessed thru 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. Up to version 3.3 of
|
|
XFree86 only a single graphics device could be driven. Therfore there
|
|
was no need to address the issue of sharing such memory or I/O ranges
|
|
among several devices. Starting with version 4.0 XFree86 is capable of
|
|
driving more than one graphics interface in a multi-head environment.
|
|
Therefore a mechanism needed to be designed which was capable of
|
|
controlling the sharing the access to memory and I/O ranges. In this
|
|
document we describe to use of the RAC (Resource Access Control)
|
|
system in the XFree86 server which provides the service of controlling
|
|
access to interface resources.
|
|
|
|
II. Introduction
|
|
================
|
|
|
|
Terms and definitions:
|
|
|
|
II.1. Bus
|
|
---------
|
|
|
|
'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, MC and VL buses are currently treated like
|
|
ISA buses). 'Bus' may always 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 RACY as they
|
|
require specific drivers.
|
|
|
|
II.2. Entity
|
|
------------
|
|
|
|
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.
|
|
|
|
II.3. Resource
|
|
--------------
|
|
|
|
'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. Resource 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 condition:
|
|
|
|
address & mask == base
|
|
|
|
with base & mask == base. Resources addressed in such a way are
|
|
considered sparse resources.
|
|
|
|
|
|
II.4. Server States
|
|
------------------
|
|
|
|
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 any entity resource is under resource access control.
|
|
During OPERATING state only those entities are controlled which
|
|
actually have shared resources that conflict with others. The
|
|
determination which entity is to be placed under RAC during OPERATING
|
|
state takes place after ScreenInit() during the first server
|
|
generation. This doesn't apply if only one screen is active: in this
|
|
case no RAC is needed and the screen is simply left enabled while the
|
|
server is active.
|
|
|
|
|
|
III. Theory of operation
|
|
========================
|
|
|
|
III.1. General
|
|
--------------
|
|
|
|
The common level 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.
|
|
|
|
The user should provide a device section in XF86Config for each
|
|
graphics device installed in his system. Each such entity which is
|
|
never to be used as X display device might be marked as inactive by
|
|
adding the keyword "Inactive" to the device section.
|
|
|
|
When the Probe() 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 Probe() 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 EntityInit(),
|
|
EntityLeave() and EntityEnter() function.
|
|
|
|
EntityInit() 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 EntityInit(), EntityEnter() and EntityLeave() 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 EntityInit() or EntityEnter() 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 'ResInit' so that they can be
|
|
removed from the resource list after processing all EntityInit()
|
|
functions. EntityEnter() 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
|
|
EntityInit() 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. EntityLeave() 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 PreInit() phase each driver should check if any sharable resources
|
|
it has registered during Probe() has been denied and take appropriate
|
|
action which could simply be to fail. If it needs to access resources
|
|
it has disabled during EntitySetup() it can do so provided it has
|
|
registered these and will disable them before returning from
|
|
PreInit(). 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
|
|
ScreenInit(), this is not desirable.
|
|
|
|
Following PreInit() 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 ScreenInit()
|
|
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 ScreenInit() 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:
|
|
|
|
a. 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 (IO or MEM).
|
|
|
|
b. A resource marked 'disabled' during OPERATING state will be ignored
|
|
entirely.
|
|
|
|
c. 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.
|
|
|
|
d. 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.
|
|
|
|
The driver has the choice among different ways to control access to
|
|
certain resources:
|
|
|
|
a. It can relay 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.
|
|
|
|
b. 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 PreInit() stage.
|
|
Since the replacement functions are registered in PreInit() 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.
|
|
|
|
c. 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.
|
|
|
|
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 EnableAccess() function is called before
|
|
control is passed on. EnableAccess() 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, EnableAccess() determines
|
|
which resource types (MEM,IO) 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.
|
|
|
|
III.3. Resource Types
|
|
---------------------
|
|
|
|
Resource have certain properties. When registering resources each
|
|
range is accompanied by a flag consisting of the or'ed flags of the
|
|
different properties the resource has. Each resource range may be
|
|
classified according to
|
|
|
|
- its physical properties ie. if it addresses
|
|
memory (ResMem) or
|
|
I/O space (ResIo),
|
|
- if it addresses a
|
|
block (ResBlock) or
|
|
sparse (ResSparse)
|
|
range,
|
|
- its access properties.
|
|
|
|
There are two known access properties:
|
|
|
|
- ResExclusive
|
|
for resources which may not be shared with any other device and
|
|
- ResShared
|
|
for resources which can be disabled and therefore can be shared.
|
|
|
|
If it is desirable to test a resource against any type a generic
|
|
access type 'ResAny' 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 (ResUnused) or during OPERATING state
|
|
(ResUnusedOpr). A resource only visible during the init functions (ie.
|
|
EntityInit(), EntityEnter() and EntityLeave() should be registered
|
|
with the flag 'ResInit'. A resource that might conflict with
|
|
background resource ranges may be flagged with 'ResBios'. 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 common/sf86Resources.h.
|
|
|
|
IV. Available Functions
|
|
=======================
|
|
|
|
The functions provided for resource management will be listed in order
|
|
of use in the driver.
|
|
|
|
IV.1. Probe phase
|
|
-----------------
|
|
|
|
In this stage 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:
|
|
|
|
int xf86MatchPciInstances(const char *driverName, int vendorID,
|
|
SymTabPtr chipsets, PciChipsets *PCIchipsets,
|
|
GDevPtr *devList, int numDevs, DriverPtr drvp,
|
|
int **foundEntities);
|
|
|
|
int xf86MatchIsaInstances(const char *driverName, SymTabPtr chipsets,
|
|
IsaChipsets *ISAchipsets, DriverPtr drvp,
|
|
FindIsaDevProc FindIsaDevice, GDevPtr *devList,
|
|
int numDevs, int **foundEntities);
|
|
|
|
Both functions return the number of matched entities and their indices
|
|
in foundEntities list.
|
|
|
|
They make use of several sub functions which are also available on the
|
|
driver level:
|
|
|
|
Bool xf86ComparePciBusString(const char *busID, int bus,
|
|
int device, int func);
|
|
|
|
and
|
|
|
|
Bool xf86ParseIsaBusString(const char *busID);
|
|
|
|
are called to interpret the busID in the device section. The functions:
|
|
|
|
int xf86ClaimPciSlot(int bus, int device, int func, DriverPtr drvp,
|
|
int chipset, GDevPtr dev, Bool active);
|
|
|
|
int xf86ClaimIsaSlot(DriverPtr drvp, int chipset, GDevPtr dev, Bool
|
|
active);
|
|
|
|
are used to allocate the entities and initialize their data
|
|
structures. Both functions return the index of the newly allocated
|
|
entity record or (-1) should the function fail. Before probing an ISA
|
|
card
|
|
|
|
Bool xf86IsPrimaryIsa();
|
|
|
|
gets called to determine if the primary card was not detected on the
|
|
PCI bus.
|
|
|
|
Two helper functions are provided to aid configuring entities:
|
|
|
|
Bool xf86ConfigActivePciEntity(ScrnInfoPtr pScrn, int entityIndex,
|
|
PciChipsets *p_chip, resList res,
|
|
EntityProc init, EntityProc enter,
|
|
EntityProc leave, pointer private);
|
|
Bool xf86ConfigActiveIsaEntity(ScrnInfoPtr pScrn, int entityIndex,
|
|
IsaChipsets *i_chip, resList res,
|
|
EntityProc init, EntityProc enter,
|
|
EntityProc leave, pointer private);
|
|
|
|
They are used to register the init/enter/leave functions described
|
|
above as well as the non-relocatable resources. Generally 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. The init/enter/leave functions have to be of type
|
|
|
|
typedef void (*EntityProc)(int entityIndex,pointer private);
|
|
|
|
They are passed the entity index and a pointer to a private scratch
|
|
area. This are can be set up during Probe() and its address can be
|
|
passed to xf86ConfigActiveIsaEntity() xf86ConfigActivePciEntity() as
|
|
the last argument.
|
|
|
|
These helper functions use:
|
|
|
|
void xf86ClaimFixedResources(resList list, int entityIndex);
|
|
|
|
To register 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 Probe() phase.
|
|
|
|
Bool xf86SetEntityFuncs(int entityIndex, EntityProc init,
|
|
EntityProc enter, EntityProc leave, pointer);
|
|
|
|
This function registers the init/enter/leave() functions along with
|
|
the pointer to their private area to the entity.
|
|
|
|
void xf86AddEntityToScreen(ScrnInfoPtr pScrn, int entityIndex);
|
|
|
|
adds the entity to the screen.
|
|
|
|
These functions are also available on the driver level. A detailed
|
|
Probe() function is listed below. For most drivers this can be used
|
|
with little change.
|
|
|
|
Please note that VGA resources have to be claimed in Probe()
|
|
phase. Otherwise they are not routed to the bus.
|
|
|
|
IV.2. PreInit() phase
|
|
---------------------
|
|
|
|
During this phase the remaining resource should be registered.
|
|
PreInit() should call
|
|
|
|
EntityInfoPtr xf86GetEntityInfo(int entityIndex);
|
|
|
|
To obtain a pointer to an EntityInfoRec for each entity it is able to
|
|
drive and check if any resource are listed in 'resources'. These have
|
|
been rejected in the post-Probe() phase. The driver should decide if
|
|
it can continue without using these or if it should fail. The pointer
|
|
to the EntityInfoRec should be freed if not needed any more.
|
|
|
|
Several functions are provided to simplify resource registration:
|
|
|
|
Bool xf86IsEntityPrimary(int entityIndex);
|
|
|
|
is used to determine if the entity is the display device that is used
|
|
during boot-up and text mode.
|
|
|
|
Bool xf86IsScreenPrimary(int scrnIndex);
|
|
|
|
finds out if the primary entity is registered for the screen with
|
|
specified index.
|
|
|
|
pciVideoPtr xf86GetPciInfoForEntity(int entityIndex);
|
|
|
|
returns a pointer to the pciVideoRec of the specified entity. If the
|
|
entity is not a PCI device NULL is returned.
|
|
|
|
The primary function for registration of resources is
|
|
|
|
resPtr xf86RegisterResources(int entityIndex, resList list, int access);
|
|
|
|
it tries to register the resources in 'list'. If list is NULL 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 (ResShared) 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 0 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 move
|
|
the resource to different locations. In case of PCI bus entities this
|
|
is done by passing the list of failed resources to
|
|
|
|
resPtr xf86ReallocatePciResources(int entityIndex, resPtr pRes);
|
|
|
|
this function returns a list of reallocated resource. This list needs
|
|
to be passed to xf86RegisterResources() again to be registered with
|
|
the broker.
|
|
|
|
Two functions are provided to obtain a resource range of a given type:
|
|
|
|
resRange xf86GetBlock(long type, memType size,
|
|
memType window_start, memType window_end,
|
|
memType align_mask, resPtr avoid);
|
|
resRange xf86GetSparse(long type, unsigned long fixed_bits,
|
|
unsigned long decode_mask, unsigned long address_mask,
|
|
resPtr avoid);
|
|
|
|
The first one tries to find a block range of size 'size' and type
|
|
'type' in a window bound by window_start and window_end with the
|
|
alignment specified in alignment mask. Optionally a list of resource
|
|
ranges which should be avoided inside this window can be passed. On
|
|
failure it will return a zero range of type 'ResEnd'.
|
|
|
|
The latter function does the same for sparse resources. A spares range
|
|
is determined by to parameters: the mask and the base value. An
|
|
address satisfying
|
|
|
|
mask & address == base
|
|
|
|
belongs to the specific spares range. 'mask' and 'base' themselves
|
|
have to satisfy:
|
|
|
|
mask & base == base.
|
|
|
|
Here three values have to be specified: the address mask which marks
|
|
all bits of the mask part of the address, the decode_mask which masks
|
|
out the bits which are hard coded 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 'ResEnd'. Optionally it might be
|
|
passed a list of resource ranges to avoid.
|
|
|
|
Certain 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:
|
|
|
|
Bool xf86FixPciResource(int entityIndex, unsigned int prt, CARD32 alignment,
|
|
long type);
|
|
|
|
is used for that. The parameter prt contains the number of the PCI
|
|
base register that needs to be modified. A value of 6 refers to the
|
|
BIOS base register. The size is specified in the alignment
|
|
register. Since PCI resources need to span an integral range of the
|
|
size 2^n 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 'ResShared'. The resource
|
|
broker needs to know that to find a matching resource range. This
|
|
function should be called before calling xf86RegisterResources().
|
|
|
|
Bool xf86CheckPciMemBase(pciVideoPtr pPci, unsigned long base);
|
|
|
|
checks that the memory base value specified in base matches one of the
|
|
PCI base address register values for the given PCI device.
|
|
|
|
The driver may replace the generic access control functions for an
|
|
entity by it's own ones.
|
|
|
|
void xf86SetAccessFuncs(EntityInfoPtr pEnt, xf86SetAccessFuncPtr funcs,
|
|
xf86SetAccessFuncPtr oldFuncs);
|
|
|
|
with:
|
|
|
|
typedef struct {
|
|
xf86AccessPtr mem;
|
|
xf86AccessPtr io;
|
|
xf86AccessPtr io_mem;
|
|
} xf86SetAccessFuncRec, *xf86SetAccessFuncPtr;
|
|
|
|
is used for that. 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
|
|
NULL value is passed as third argument it is interpreted as an address
|
|
where to store the old access records. If the third argument is NULL
|
|
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 his 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.
|
|
|
|
To find out if specific resource range is conflicting with another
|
|
resource
|
|
|
|
memType xf86ChkConflict(resRange *rgp, int entityIndex);
|
|
|
|
may be called. If a non-zero value is returned a conflict is found.
|
|
|
|
resPtr xf86SetOperatingState(resList list, int entityIndex, int mask);
|
|
|
|
is used to set the state of a resource during OPERATING state. 'list'
|
|
holds a list to which 'mask' is to be applied. The parameter 'mask'
|
|
may have the value 'ResUnusedOpr' and 'ResDisableOpr'. The first one
|
|
should be used if a resource isn't used during OPERATING state however
|
|
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 A and ending at B and suppose C us a value
|
|
satisfying A < C < B one may not specify the resource range (A,B) by
|
|
splitting it into two ranges (A,C) and (C,B).
|
|
|
|
Two functions are provided for special cases:
|
|
|
|
void xf86RemoveEntityFromScreen(ScrnInfoPtr pScrn, int entityIndex);
|
|
|
|
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.
|
|
|
|
void xf86DeallocateResourcesForEntity(int entityIndex, long type);
|
|
|
|
deallocates all resources of a given type registered for a certain
|
|
entity from the resource broker list.
|
|
|
|
IV.3. ScreenInit() phase
|
|
------------------------
|
|
|
|
Setting up the rac flags is all that remains to do in ScreenInit()
|
|
phase (Note that these flags might also be set up in PreInit() phase).
|
|
The ScrnInfoRec has separate flags for memory and PIO access:
|
|
racIoFlags and racMemFlags. They specifies which graphics operations
|
|
might require the use of resources which might be disabled for some
|
|
reason. Note that even exclusive resources might be disabled if they
|
|
are disabled along with shared resources. For example if a driver has
|
|
registered the VGA PIO resources and lets the common level disable
|
|
these by disabling PIO access in PCI config space (the standard way),
|
|
exclusive PCI PIO ranges will also be disabled. Therefore the driver
|
|
has to flag any operations requiring PCI PIO resources in racIoFlags.
|
|
The avaliable flags are defined in rac/xf86RAC.h. Available are:
|
|
|
|
RAC_FB for framebuffer operations (including hw acceleration)
|
|
RAC_CURSOR for Cursor operations
|
|
(??? I'm not sure if we need this for SW cursor it depends
|
|
on which level the sw cursor is drawn)
|
|
RAC_COLORMAP for colormap operations
|
|
RAC_VIEWPORT for the call to RACAdjustFrame()
|
|
|
|
The flags are or'ed.
|
|
|
|
V. Appendix
|
|
===========
|
|
|
|
A. Sample Probe() Function
|
|
--------------------------
|
|
|
|
static Bool
|
|
XXXProbe(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(CHIPS_DRIVER_NAME,
|
|
&devSections)) <= 0) {
|
|
return FALSE;
|
|
}
|
|
/* PCI BUS */
|
|
/* test if PCI bus present */
|
|
if (xf86GetPciVideoInfo() ) {
|
|
/* match PCI instances with ones supported by the driver */
|
|
numUsed = xf86MatchPciInstances(XXX_NAME, PCI_VENDOR_XXX,
|
|
XXXChipsets, XXXPCIchipsets,
|
|
devSections,numDevSections, drv,
|
|
&usedChips);
|
|
if (numUsed > 0) {
|
|
for (i = 0; i < numUsed; i++) {
|
|
/* Allocate a ScrnInfoRec */
|
|
ScrnInfoPtr pScrn = xf86AllocateScreen(drv,0);
|
|
pScrn->driverVersion = VERSION;
|
|
pScrn->driverName = XXX_DRIVER_NAME;
|
|
pScrn->name = XXX_NAME;
|
|
pScrn->Probe = XXXProbe;
|
|
pScrn->PreInit = XXXPreInit;
|
|
pScrn->ScreenInit = XXXScreenInit;
|
|
pScrn->SwitchMode = XXXSwitchMode;
|
|
pScrn->AdjustFrame = XXXAdjustFrame;
|
|
pScrn->EnterVT = XXXEnterVT;
|
|
pScrn->LeaveVT = XXXLeaveVT;
|
|
pScrn->FreeScreen = XXXFreeScreen;
|
|
pScrn->ValidMode = XXXValidMode;
|
|
foundScreen = TRUE;
|
|
/* add screen to entity */
|
|
xf86ConfigActivePciEntity(pScrn,usedChips[i],XXXPCIchipsets,
|
|
NULL,NULL,NULL,NULL,NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Isa Bus */
|
|
numUsed = xf86MatchIsaInstances(XXX_NAME,XXXChipsets,XXXISAchipsets,
|
|
drv,chipsFindIsaDevice,devSections,
|
|
numDevSections,&usedChips);
|
|
if(numUsed >= 0)
|
|
for (i = 0; i < numUsed; i++) {
|
|
ScrnInfoPtr pScrn = xf86AllocateScreen(drv,0);
|
|
|
|
pScrn->driverVersion = VERSION;
|
|
pScrn->driverName = XXX_DRIVER_NAME;
|
|
pScrn->name = XXX_NAME;
|
|
pScrn->Probe = XXXProbe;
|
|
pScrn->PreInit = XXXPreInit;
|
|
pScrn->ScreenInit = XXXScreenInit;
|
|
pScrn->SwitchMode = XXXSwitchMode;
|
|
pScrn->AdjustFrame = XXXAdjustFrame;
|
|
pScrn->EnterVT = XXXEnterVT;
|
|
pScrn->LeaveVT = XXXLeaveVT;
|
|
pScrn->FreeScreen = XXXFreeScreen;
|
|
pScrn->ValidMode = XXXValidMode;
|
|
foundScreen = TRUE;
|
|
xf86ConfigActiveIsaEntity(pScrn,usedChips[i],XXXISAchipsets,
|
|
NULL,NULL,NULL,NULL,NULL);
|
|
}
|
|
xfree(devSections);
|
|
return foundScreen;
|
|
}
|
|
|
|
B. Porting Issues
|
|
-----------------
|
|
|
|
Here are some hints on porting code developed for RAC 1 to RAC 2.
|
|
|
|
1. a. Initialization of RAC is now entirely done on the common level.
|
|
Therefore the call to xf86RACInit() can be removed.
|
|
|
|
b. Also there is no need for the racSymbols list.
|
|
|
|
c. LoadSubModule(..,rac) should be removed.
|
|
|
|
d. racSymbols should be removed from LoaderRequestSymList(racSymbols,..)
|
|
|
|
2. a. if the driver uses the predefined resource lists xf86Resources.h
|
|
needs to be included.
|
|
|
|
b. RES_VGA should be changed to RES_EXCLUSIVE_VGA
|
|
|
|
3. The device list now belongs to the EntityInfoRec.
|
|
Change pScrn->device to xxx->pEnt->device.
|
|
|
|
4. Rewrite the Probe() function. The example given above should work
|
|
as a guideline.
|
|
|
|
5. Register all necessary resources in PreInit() by calling
|
|
xf86RegisterResources().
|
|
|
|
6. If applicable set the operating state of the registered resources
|
|
by calling xf86SetOperatingState(). This should be done during
|
|
PreInit(). If necessary it might still be done in ScreenInit()
|
|
|
|
7. Set up the racIoFlags and racMemFlags.
|
|
|
|
|
|
LocalWords: ISA
|