4 Graphics devices are accessed thru ranges in I/O or memory space. While
5 most modern graphics devices allow relocation of such ranges many of
6 them still require the use of well established interfaces such as VGA
7 memory and IO ranges or 8514/A IO ranges. Up to version 3.3 of
8 XFree86 only a single graphics device could be driven. Therfore there
9 was no need to address the issue of sharing such memory or I/O ranges
10 among several devices. Starting with version 4.0 XFree86 is capable of
11 driving more than one graphics interface in a multi-head environment.
12 Therefore a mechanism needed to be designed which was capable of
13 controlling the sharing the access to memory and I/O ranges. In this
14 document we describe to use of the RAC (Resource Access Control)
15 system in the XFree86 server which provides the service of controlling
16 access to interface resources.
21 Terms and definitions:
26 'Bus' is ambiguous as it is used for different things: It may refer to
27 physical incompatible extension connectors in a computer system. The
28 RAC system knows two such systems: The ISA bus and the PCI bus. (On
29 the software level EISA, MC and VL buses are currently treated like
30 ISA buses). 'Bus' may always refer to logically different entities on
31 a single bus system which are connected via bridges. A PCI system may
32 have several distinct PCI buses connecting each other by PCI-PCI
33 bridges or to the host CPU by HOST-PCI bridges.
35 Systems that host more than one bus system link these together using
36 bridges. Bridges are a concern to RAC as they might block or pass
37 specific resources. PCI-PCI bridges may be set up to pass VGA
38 resources to the secondary bus. PCI-ISA buses pass any resources not
39 decoded on the primary PCI bus to the ISA bus. This way VGA resources
40 (although exclusive on the ISA bus) can be shared by ISA and PCI
41 cards. Currently HOST-PCI bridges are not yet handled by RACY as they
42 require specific drivers.
47 The smallest independently addressable unit on a system bus is
48 referred to as an entity. So far we know ISA and PCI entities. PCI
49 entities can be located on the PCI bus by an unique ID consisting of
50 the bus, card and function number.
55 'Resource' refers to a range of memory or I/O addresses an entity
58 If a device is capable of disabling this decoding the resource is
59 called sharable. For PCI devices a generic method is provided to
60 control resource decoding. Other devices will have to provide a device
61 specific function to control decoding.
63 If the entity is capable of decoding this range at a different
64 location this resource is considered relocatable. Resource which start
65 at a specific address and occupy a single continuous range are called
68 Alternatively resource addresses can be decoded in a way that they
69 satisfy the condition:
71 address & mask == base
73 with base & mask == base. Resources addressed in such a way are
74 considered sparse resources.
80 The resource access control system knows two server states: the SETUP
81 and the OPERATING state. The setup state is entered whenever a mode
82 change takes place or the server exits or does VT switching. During
83 this state any entity resource is under resource access control.
84 During OPERATING state only those entities are controlled which
85 actually have shared resources that conflict with others. The
86 determination which entity is to be placed under RAC during OPERATING
87 state takes place after ScreenInit() during the first server
88 generation. This doesn't apply if only one screen is active: in this
89 case no RAC is needed and the screen is simply left enabled while the
93 III. Theory of operation
94 ========================
99 The common level has knowledge of generic access control mechanisms
100 for devices on certain bus systems (currently the PCI bus) as well as
101 of methods to enable or disable access to the buses
102 itself. Furthermore it can access information on resources decoded by
103 these devices and if necessary modify it.
105 When first starting the Xserver collects all this information, saves
106 it for restoration checks it for consistency and if necessary corrects
107 it. Finally it disables all resources on a generic level prior to
108 calling any driver function.
110 The user should provide a device section in XF86Config for each
111 graphics device installed in his system. Each such entity which is
112 never to be used as X display device might be marked as inactive by
113 adding the keyword "Inactive" to the device section.
115 When the Probe() function of each driver is called the device sections
116 are matched against the devices found in the system. The driver may
117 probe devices at this stage that cannot be identified by using device
118 independent methods. Access to all resources that can be controlled in
119 a device independent way is disabled. The Probe() function should
120 register all non-relocatable resources at this stage. If a resource
121 conflict is found between exclusive resources the driver will fail
122 immediately. Optionally the driver might specify an EntityInit(),
123 EntityLeave() and EntityEnter() function.
125 EntityInit() can be used to disable any shared resources that are not
126 controlled by the generic access control functions. It is called prior
127 to the PreInit phase regardless if an entity is active or not. When
128 calling the EntityInit(), EntityEnter() and EntityLeave() functions
129 the common level will disable access to all other entities on a
130 generic level. Since the common level has no knowledge of device
131 specific methods to disable access to resources it cannot be
132 guaranteed that certain resources are not decoded by any other entity
133 until the EntityInit() or EntityEnter() phase is finished. Device
134 drivers should therefore register all those resources which they are
135 going to disable. If these resources are never to be used by any
136 driver function they may be flagged 'ResInit' so that they can be
137 removed from the resource list after processing all EntityInit()
138 functions. EntityEnter() should disable decoding of all resources
139 which are not registered as exclusive and which are not handled by the
140 generic access control in the common level. The difference to
141 EntityInit() is that the latter one is only called once during
142 lifetime of the server. It can therefore be used to set up variables
143 prior to disabling resources. EntityLeave() should restore the
144 original state when exiting the server or switching to a different vt.
145 It also needs to disable device specific access functions if they need
146 to be disabled on server exit or VT switch. The default state is to
147 enable them before giving up the VT.
149 In PreInit() phase each driver should check if any sharable resources
150 it has registered during Probe() has been denied and take appropriate
151 action which could simply be to fail. If it needs to access resources
152 it has disabled during EntitySetup() it can do so provided it has
153 registered these and will disable them before returning from
154 PreInit(). This also applies to all other driver functions. Several
155 functions are provided to request resource ranges, register these,
156 correct PCI config space and add replacements for the generic access
157 functions. Resources may be marked 'disabled' or 'unused' during
158 OPERATING stage. Although these steps could also be performed in
159 ScreenInit(), this is not desirable.
161 Following PreInit() phase the common level determines if resource
162 access control is needed. This is the case if more than one screen is
163 used. If necessary the RAC wrapper module is loaded. In ScreenInit()
164 the drivers can decide which operations need to be placed under
165 RAC. Available are the frame buffer operations, the pointer operations
166 and the colormap operations. Any operation that requires resources
167 which might be disabled during OPERATING state should be set to use
168 RAC. This can be specified separately for memory and IO resources.
170 When ScreenInit() phase is done the common level will determine which
171 shared resources are requested by more than one driver and set the
172 access functions accordingly. This is done following these rules:
174 a. The sharable resources registered by each entity are compared. if
175 a resource is registered by more than one entity the entity will be
176 marked to need to share this resources type (IO or MEM).
178 b. A resource marked 'disabled' during OPERATING state will be ignored
181 c. A resource marked 'unused' will only conflicts with an overlapping
182 resource of an other entity if the second is actually in use during
185 d. If an 'unused' resource was found to conflict however the entity
186 does not use any other resource of this type the entire resource
187 type will be disabled for that entity.
189 The driver has the choice among different ways to control access to
192 a. It can relay on the generic access functions. This is probably the
193 most common case. Here the driver only needs to register any
194 resource it is going to use.
196 b. It can replace the generic access functions by driver specific
197 ones. This will mostly be used in cases where no generic access
198 functions are available. In this case the driver has to make sure
199 these resources are disabled when entering the PreInit() stage.
200 Since the replacement functions are registered in PreInit() the
201 driver will have to enable these resources itself if it needs to
202 access them during this state. The driver can specify if the
203 replacement functions can control memory and/or I/O resources
206 c. The driver can enable resources itself when it needs them. Each
207 driver function enabling them needs to disable them before it will
208 return. This should be used if a resource which can be controlled
209 in a device dependent way is only required during SETUP state. This
210 way it can be marked 'unused' during OPERATING state.
212 A resource which is decoded during OPERATING state however never
213 accessed by the driver should be marked unused.
215 Since access switching latencies are an issue during Xserver
216 operation, the common level attempts to minimize the number of
217 entities that need to be placed under RAC control. When a wrapped
218 operation is called, the EnableAccess() function is called before
219 control is passed on. EnableAccess() checks if a screen is under
220 access control. If not it just establishes bus routing and returns. If
221 the screen needs to be under access control, EnableAccess() determines
222 which resource types (MEM,IO) are required. Then it tests if this
223 access is already established. If so it simply returns. If not it
224 disables the currently established access, fixes bus routing and
225 enables access to all entities registered for this screen.
227 Whenever a mode switch or a vt-switch is performed the common level
228 will return to SETUP state.
230 III.3. Resource Types
231 ---------------------
233 Resource have certain properties. When registering resources each
234 range is accompanied by a flag consisting of the or'ed flags of the
235 different properties the resource has. Each resource range may be
236 classified according to
238 - its physical properties ie. if it addresses
245 - its access properties.
247 There are two known access properties:
250 for resources which may not be shared with any other device and
252 for resources which can be disabled and therefore can be shared.
254 If it is desirable to test a resource against any type a generic
255 access type 'ResAny' is provided. If this is set the resource will
256 conflict with any resource of a different entity intersecting its
257 range. Further it can be specified that a resource is decoded however
258 never used during any stage (ResUnused) or during OPERATING state
259 (ResUnusedOpr). A resource only visible during the init functions (ie.
260 EntityInit(), EntityEnter() and EntityLeave() should be registered
261 with the flag 'ResInit'. A resource that might conflict with
262 background resource ranges may be flagged with 'ResBios'. This might
263 be useful when registering resources ranges that were assigned by the
266 Several predefined resource lists are available for VGA and 8514/A
267 resources in common/sf86Resources.h.
269 IV. Available Functions
270 =======================
272 The functions provided for resource management will be listed in order
273 of use in the driver.
278 In this stage each driver detects those resources it is able to drive,
279 creates an entity record for each of them, registers non-relocatable
280 resources and allocates screens and adds the resources to screens.
282 Two helper functions are provided for matching device sections in the
283 XF86Config file to the devices:
285 int xf86MatchPciInstances(const char *driverName, int vendorID,
286 SymTabPtr chipsets, PciChipsets *PCIchipsets,
287 GDevPtr *devList, int numDevs, DriverPtr drvp,
288 int **foundEntities);
290 int xf86MatchIsaInstances(const char *driverName, SymTabPtr chipsets,
291 IsaChipsets *ISAchipsets, DriverPtr drvp,
292 FindIsaDevProc FindIsaDevice, GDevPtr *devList,
293 int numDevs, int **foundEntities);
295 Both functions return the number of matched entities and their indices
296 in foundEntities list.
298 They make use of several sub functions which are also available on the
301 Bool xf86ComparePciBusString(const char *busID, int bus,
302 int device, int func);
306 Bool xf86ParseIsaBusString(const char *busID);
308 are called to interpret the busID in the device section. The functions:
310 int xf86ClaimPciSlot(int bus, int device, int func, DriverPtr drvp,
311 int chipset, GDevPtr dev, Bool active);
313 int xf86ClaimIsaSlot(DriverPtr drvp, int chipset, GDevPtr dev, Bool
316 are used to allocate the entities and initialize their data
317 structures. Both functions return the index of the newly allocated
318 entity record or (-1) should the function fail. Before probing an ISA
321 Bool xf86IsPrimaryIsa();
323 gets called to determine if the primary card was not detected on the
326 Two helper functions are provided to aid configuring entities:
328 Bool xf86ConfigActivePciEntity(ScrnInfoPtr pScrn, int entityIndex,
329 PciChipsets *p_chip, resList res,
330 EntityProc init, EntityProc enter,
331 EntityProc leave, pointer private);
332 Bool xf86ConfigActiveIsaEntity(ScrnInfoPtr pScrn, int entityIndex,
333 IsaChipsets *i_chip, resList res,
334 EntityProc init, EntityProc enter,
335 EntityProc leave, pointer private);
337 They are used to register the init/enter/leave functions described
338 above as well as the non-relocatable resources. Generally the list of
339 fixed resources is obtained from the Isa/PciChipsets lists. However
340 an additional list of resources may be passed. Generally this is not
341 required. The init/enter/leave functions have to be of type
343 typedef void (*EntityProc)(int entityIndex,pointer private);
345 They are passed the entity index and a pointer to a private scratch
346 area. This are can be set up during Probe() and its address can be
347 passed to xf86ConfigActiveIsaEntity() xf86ConfigActivePciEntity() as
350 These helper functions use:
352 void xf86ClaimFixedResources(resList list, int entityIndex);
354 To register the non relocatable resources which cannot be disabled
355 and which therefore would cause the server to fail immediately if
356 they were found to conflict. It also records non-relocatable but
357 sharable resources for processing after the Probe() phase.
359 Bool xf86SetEntityFuncs(int entityIndex, EntityProc init,
360 EntityProc enter, EntityProc leave, pointer);
362 This function registers the init/enter/leave() functions along with
363 the pointer to their private area to the entity.
365 void xf86AddEntityToScreen(ScrnInfoPtr pScrn, int entityIndex);
367 adds the entity to the screen.
369 These functions are also available on the driver level. A detailed
370 Probe() function is listed below. For most drivers this can be used
373 Please note that VGA resources have to be claimed in Probe()
374 phase. Otherwise they are not routed to the bus.
376 IV.2. PreInit() phase
377 ---------------------
379 During this phase the remaining resource should be registered.
380 PreInit() should call
382 EntityInfoPtr xf86GetEntityInfo(int entityIndex);
384 To obtain a pointer to an EntityInfoRec for each entity it is able to
385 drive and check if any resource are listed in 'resources'. These have
386 been rejected in the post-Probe() phase. The driver should decide if
387 it can continue without using these or if it should fail. The pointer
388 to the EntityInfoRec should be freed if not needed any more.
390 Several functions are provided to simplify resource registration:
392 Bool xf86IsEntityPrimary(int entityIndex);
394 is used to determine if the entity is the display device that is used
395 during boot-up and text mode.
397 Bool xf86IsScreenPrimary(int scrnIndex);
399 finds out if the primary entity is registered for the screen with
402 pciVideoPtr xf86GetPciInfoForEntity(int entityIndex);
404 returns a pointer to the pciVideoRec of the specified entity. If the
405 entity is not a PCI device NULL is returned.
407 The primary function for registration of resources is
409 resPtr xf86RegisterResources(int entityIndex, resList list, int access);
411 it tries to register the resources in 'list'. If list is NULL it tries
412 to determine the resources automatically. This only works for entities
413 that provide a generic way to read out the resource ranges they
414 decode. So far this is only the case for PCI devices. By default the
415 PCI resources are registered as shared (ResShared) if the driver wants
416 to set a different access type it can do so by specifying the access
417 flags in the third argument. A value of 0 means to use the default
418 settings. If for any reason the resource broker is not able to
419 register some of the requested resources the function will return a
420 pointer to a list of the failed ones. In this case the driver may move
421 the resource to different locations. In case of PCI bus entities this
422 is done by passing the list of failed resources to
424 resPtr xf86ReallocatePciResources(int entityIndex, resPtr pRes);
426 this function returns a list of reallocated resource. This list needs
427 to be passed to xf86RegisterResources() again to be registered with
430 Two functions are provided to obtain a resource range of a given type:
432 resRange xf86GetBlock(long type, memType size,
433 memType window_start, memType window_end,
434 memType align_mask, resPtr avoid);
435 resRange xf86GetSparse(long type, unsigned long fixed_bits,
436 unsigned long decode_mask, unsigned long address_mask,
439 The first one tries to find a block range of size 'size' and type
440 'type' in a window bound by window_start and window_end with the
441 alignment specified in alignment mask. Optionally a list of resource
442 ranges which should be avoided inside this window can be passed. On
443 failure it will return a zero range of type 'ResEnd'.
445 The latter function does the same for sparse resources. A spares range
446 is determined by to parameters: the mask and the base value. An
449 mask & address == base
451 belongs to the specific spares range. 'mask' and 'base' themselves
456 Here three values have to be specified: the address mask which marks
457 all bits of the mask part of the address, the decode_mask which masks
458 out the bits which are hard coded and are therefore not available for
459 relocation and the values of the fixed bits. The function tries to
460 find a base that satisfies the given condition. If the function fails
461 it will return a zero range of type 'ResEnd'. Optionally it might be
462 passed a list of resource ranges to avoid.
464 Certain PCI devices are broken in the sense that they return invalid
465 size information for a certain resource. In this case the driver can
466 supply the correct size and make sure that the resource range
467 allocated for the card is large enough to hold the address range
468 decoded by the card. The function:
470 Bool xf86FixPciResource(int entityIndex, unsigned int prt, CARD32 alignment,
473 is used for that. The parameter prt contains the number of the PCI
474 base register that needs to be modified. A value of 6 refers to the
475 BIOS base register. The size is specified in the alignment
476 register. Since PCI resources need to span an integral range of the
477 size 2^n the alignment also specifies the number of addresses that
478 will be decoded. If the driver specifies a type mask it can override
479 the default type for PCI resources which is 'ResShared'. The resource
480 broker needs to know that to find a matching resource range. This
481 function should be called before calling xf86RegisterResources().
483 Bool xf86CheckPciMemBase(pciVideoPtr pPci, unsigned long base);
485 checks that the memory base value specified in base matches one of the
486 PCI base address register values for the given PCI device.
488 The driver may replace the generic access control functions for an
489 entity by it's own ones.
491 void xf86SetAccessFuncs(EntityInfoPtr pEnt, xf86SetAccessFuncPtr funcs,
492 xf86SetAccessFuncPtr oldFuncs);
499 xf86AccessPtr io_mem;
500 } xf86SetAccessFuncRec, *xf86SetAccessFuncPtr;
502 is used for that. The driver can pass three functions: one for I/O
503 access, one for memory access and one for combined memory and I/O
504 access. If the memory access and combined access functions are
505 identical the common level assumes that the memory access cannot be
506 controlled independently of I/O access, if the I/O access function and
507 the combined access functions are the same it is assumed that I/O can
508 not be controlled independently. If memory and I/O have to be
509 controlled together all three values should be the same. If a non
510 NULL value is passed as third argument it is interpreted as an address
511 where to store the old access records. If the third argument is NULL
512 it will be assumed that the generic access should be enabled before
513 replacing the access functions. Otherwise it will be disabled. The
514 driver may enable them itself using the returned values. It should do
515 this from his replacement access functions as the generic access may
516 be disabled by the common level on certain occasions. If replacement
517 functions are specified they must control all resources of the
518 specific type registered for the entity.
520 To find out if specific resource range is conflicting with another
523 memType xf86ChkConflict(resRange *rgp, int entityIndex);
525 may be called. If a non-zero value is returned a conflict is found.
527 resPtr xf86SetOperatingState(resList list, int entityIndex, int mask);
529 is used to set the state of a resource during OPERATING state. 'list'
530 holds a list to which 'mask' is to be applied. The parameter 'mask'
531 may have the value 'ResUnusedOpr' and 'ResDisableOpr'. The first one
532 should be used if a resource isn't used during OPERATING state however
533 decoded by the device while the latter one indicates that the resource
534 is not decoded during OPERATING state. Note that the resource ranges
535 have to match those specified during registration. If a range has been
536 specified starting at A and ending at B and suppose C us a value
537 satisfying A < C < B one may not specify the resource range (A,B) by
538 splitting it into two ranges (A,C) and (C,B).
540 Two functions are provided for special cases:
542 void xf86RemoveEntityFromScreen(ScrnInfoPtr pScrn, int entityIndex);
544 may be used to remove an entity from a screen. This only makes sense
545 if a screen has more than one entity assigned or the screen is to be
546 deleted. No test is made if the screen has any entities left.
548 void xf86DeallocateResourcesForEntity(int entityIndex, long type);
550 deallocates all resources of a given type registered for a certain
551 entity from the resource broker list.
553 IV.3. ScreenInit() phase
554 ------------------------
556 Setting up the rac flags is all that remains to do in ScreenInit()
557 phase (Note that these flags might also be set up in PreInit() phase).
558 The ScrnInfoRec has separate flags for memory and PIO access:
559 racIoFlags and racMemFlags. They specifies which graphics operations
560 might require the use of resources which might be disabled for some
561 reason. Note that even exclusive resources might be disabled if they
562 are disabled along with shared resources. For example if a driver has
563 registered the VGA PIO resources and lets the common level disable
564 these by disabling PIO access in PCI config space (the standard way),
565 exclusive PCI PIO ranges will also be disabled. Therefore the driver
566 has to flag any operations requiring PCI PIO resources in racIoFlags.
567 The avaliable flags are defined in rac/xf86RAC.h. Available are:
569 RAC_FB for framebuffer operations (including hw acceleration)
570 RAC_CURSOR for Cursor operations
571 (??? I'm not sure if we need this for SW cursor it depends
572 on which level the sw cursor is drawn)
573 RAC_COLORMAP for colormap operations
574 RAC_VIEWPORT for the call to RACAdjustFrame()
581 A. Sample Probe() Function
582 --------------------------
585 XXXProbe(DriverPtr drv, int flags)
587 Bool foundScreen = FALSE;
588 int numDevSections, numUsed;
589 GDevPtr *devSections;
594 * Find the config file Device sections that match this
595 * driver, and return if there are none.
597 if ((numDevSections = xf86MatchDevice(CHIPS_DRIVER_NAME,
598 &devSections)) <= 0) {
602 /* test if PCI bus present */
603 if (xf86GetPciVideoInfo() ) {
604 /* match PCI instances with ones supported by the driver */
605 numUsed = xf86MatchPciInstances(XXX_NAME, PCI_VENDOR_XXX,
606 XXXChipsets, XXXPCIchipsets,
607 devSections,numDevSections, drv,
610 for (i = 0; i < numUsed; i++) {
611 /* Allocate a ScrnInfoRec */
612 ScrnInfoPtr pScrn = xf86AllocateScreen(drv,0);
613 pScrn->driverVersion = VERSION;
614 pScrn->driverName = XXX_DRIVER_NAME;
615 pScrn->name = XXX_NAME;
616 pScrn->Probe = XXXProbe;
617 pScrn->PreInit = XXXPreInit;
618 pScrn->ScreenInit = XXXScreenInit;
619 pScrn->SwitchMode = XXXSwitchMode;
620 pScrn->AdjustFrame = XXXAdjustFrame;
621 pScrn->EnterVT = XXXEnterVT;
622 pScrn->LeaveVT = XXXLeaveVT;
623 pScrn->FreeScreen = XXXFreeScreen;
624 pScrn->ValidMode = XXXValidMode;
626 /* add screen to entity */
627 xf86ConfigActivePciEntity(pScrn,usedChips[i],XXXPCIchipsets,
628 NULL,NULL,NULL,NULL,NULL);
634 numUsed = xf86MatchIsaInstances(XXX_NAME,XXXChipsets,XXXISAchipsets,
635 drv,chipsFindIsaDevice,devSections,
636 numDevSections,&usedChips);
638 for (i = 0; i < numUsed; i++) {
639 ScrnInfoPtr pScrn = xf86AllocateScreen(drv,0);
641 pScrn->driverVersion = VERSION;
642 pScrn->driverName = XXX_DRIVER_NAME;
643 pScrn->name = XXX_NAME;
644 pScrn->Probe = XXXProbe;
645 pScrn->PreInit = XXXPreInit;
646 pScrn->ScreenInit = XXXScreenInit;
647 pScrn->SwitchMode = XXXSwitchMode;
648 pScrn->AdjustFrame = XXXAdjustFrame;
649 pScrn->EnterVT = XXXEnterVT;
650 pScrn->LeaveVT = XXXLeaveVT;
651 pScrn->FreeScreen = XXXFreeScreen;
652 pScrn->ValidMode = XXXValidMode;
654 xf86ConfigActiveIsaEntity(pScrn,usedChips[i],XXXISAchipsets,
655 NULL,NULL,NULL,NULL,NULL);
664 Here are some hints on porting code developed for RAC 1 to RAC 2.
666 1. a. Initialization of RAC is now entirely done on the common level.
667 Therefore the call to xf86RACInit() can be removed.
669 b. Also there is no need for the racSymbols list.
671 c. LoadSubModule(..,rac) should be removed.
673 d. racSymbols should be removed from LoaderRequestSymList(racSymbols,..)
675 2. a. if the driver uses the predefined resource lists xf86Resources.h
676 needs to be included.
678 b. RES_VGA should be changed to RES_EXCLUSIVE_VGA
680 3. The device list now belongs to the EntityInfoRec.
681 Change pScrn->device to xxx->pEnt->device.
683 4. Rewrite the Probe() function. The example given above should work
686 5. Register all necessary resources in PreInit() by calling
687 xf86RegisterResources().
689 6. If applicable set the operating state of the registered resources
690 by calling xf86SetOperatingState(). This should be done during
691 PreInit(). If necessary it might still be done in ScreenInit()
693 7. Set up the racIoFlags and racMemFlags.