xf86Bus.c revision 8aefa95b
1/*
2 * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * Except as contained in this notice, the name of the copyright holder(s)
23 * and author(s) shall not be used in advertising or otherwise to promote
24 * the sale, use or other dealings in this Software without prior written
25 * authorization from the copyright holder(s) and author(s).
26 */
27
28/*
29 * This file contains the interfaces to the bus-specific code
30 */
31
32#ifdef HAVE_XORG_CONFIG_H
33#include <xorg-config.h>
34#endif
35
36#include <ctype.h>
37#include <stdlib.h>
38#include <unistd.h>
39#include <X11/X.h>
40#include "os.h"
41#include "xf86.h"
42#include "xf86Priv.h"
43#include "xf86Resources.h"
44
45/* Bus-specific headers */
46
47#include "xf86Bus.h"
48
49#define XF86_OS_PRIVS
50#define NEED_OS_RAC_PROTOS
51#include "xf86_OSproc.h"
52
53#include "xf86RAC.h"
54#include "Pci.h"
55
56/* Entity data */
57EntityPtr *xf86Entities = NULL;	/* Bus slots claimed by drivers */
58int xf86NumEntities = 0;
59static int xf86EntityPrivateCount = 0;
60BusAccPtr xf86BusAccInfo = NULL;
61
62static void
63noopEnableDisable(void *arg) { }
64
65xf86AccessRec AccessNULL = { noopEnableDisable, noopEnableDisable, NULL };
66
67xf86CurrentAccessRec xf86CurrentAccess = {NULL,NULL};
68
69BusRec primaryBus = { BUS_NONE, {0}};
70
71static Bool xf86ResAccessEnter = FALSE;
72
73
74/* resource lists */
75resPtr Acc = NULL;
76
77/* predefined special resources */
78_X_EXPORT resRange resVgaExclusive[] = {_VGA_EXCLUSIVE, _END};
79_X_EXPORT resRange resVgaShared[] = {_VGA_SHARED, _END};
80_X_EXPORT resRange resVgaMemShared[] = {_VGA_SHARED_MEM,_END};
81_X_EXPORT resRange resVgaIoShared[] = {_VGA_SHARED_IO,_END};
82_X_EXPORT resRange resVgaUnusedExclusive[] = {_VGA_EXCLUSIVE_UNUSED, _END};
83_X_EXPORT resRange resVgaUnusedShared[] = {_VGA_SHARED_UNUSED, _END};
84_X_EXPORT resRange resVgaSparseExclusive[] = {_VGA_EXCLUSIVE_SPARSE, _END};
85_X_EXPORT resRange resVgaSparseShared[] = {_VGA_SHARED_SPARSE, _END};
86_X_EXPORT resRange res8514Exclusive[] = {_8514_EXCLUSIVE, _END};
87_X_EXPORT resRange res8514Shared[] = {_8514_SHARED, _END};
88
89/* Flag: do we need RAC ? */
90static Bool needRAC = FALSE;
91static Bool doFramebufferMode = FALSE;
92
93/* state change notification callback list */
94static StateChangeNotificationPtr StateChangeNotificationList;
95static void notifyStateChange(xf86NotifyState state);
96
97/*
98 * Call the bus probes relevant to the architecture.
99 *
100 * The only one available so far is for PCI and SBUS.
101 */
102
103void
104xf86BusProbe(void)
105{
106    xf86PciProbe();
107#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
108    xf86SbusProbe();
109#endif
110}
111
112/*
113 * Determine what bus type the busID string represents.  The start of the
114 * bus-dependent part of the string is returned as retID.
115 */
116
117BusType
118StringToBusType(const char* busID, const char **retID)
119{
120    char *p, *s;
121    BusType ret = BUS_NONE;
122
123    /* If no type field, Default to PCI */
124    if (isdigit(busID[0])) {
125	if (retID)
126	    *retID = busID;
127	return BUS_PCI;
128    }
129
130    s = xstrdup(busID);
131    p = strtok(s, ":");
132    if (p == NULL || *p == 0) {
133	xfree(s);
134	return BUS_NONE;
135    }
136    if (!xf86NameCmp(p, "pci") || !xf86NameCmp(p, "agp"))
137	ret = BUS_PCI;
138    if (!xf86NameCmp(p, "sbus"))
139	ret = BUS_SBUS;
140    if (ret != BUS_NONE)
141	if (retID)
142	    *retID = busID + strlen(p) + 1;
143    xfree(s);
144    return ret;
145}
146
147/*
148 * Entity related code.
149 */
150
151void
152xf86EntityInit(void)
153{
154    int i;
155    xf86AccessPtr pacc;
156
157    for (i = 0; i < xf86NumEntities; i++)
158	if (xf86Entities[i]->entityInit) {
159	    if (xf86Entities[i]->access->busAcc)
160		((BusAccPtr)xf86Entities[i]->access->busAcc)->set_f
161		    (xf86Entities[i]->access->busAcc);
162	    pacc = xf86Entities[i]->access->fallback;
163	    pacc->AccessEnable(pacc->arg);
164	    xf86Entities[i]->entityInit(i,xf86Entities[i]->private);
165	    pacc->AccessDisable(pacc->arg);
166	}
167}
168
169int
170xf86AllocateEntity(void)
171{
172    xf86NumEntities++;
173    xf86Entities = xnfrealloc(xf86Entities,
174			      sizeof(EntityPtr) * xf86NumEntities);
175    xf86Entities[xf86NumEntities - 1] = xnfcalloc(1,sizeof(EntityRec));
176    xf86Entities[xf86NumEntities - 1]->entityPrivates =
177               xnfcalloc(sizeof(DevUnion) * xf86EntityPrivateCount, 1);
178    return (xf86NumEntities - 1);
179}
180
181static void
182EntityEnter(void)
183{
184    int i;
185    xf86AccessPtr pacc;
186
187    for (i = 0; i < xf86NumEntities; i++)
188	if (xf86Entities[i]->entityEnter) {
189	    if (xf86Entities[i]->access->busAcc)
190		((BusAccPtr)xf86Entities[i]->access->busAcc)->set_f
191		    (xf86Entities[i]->access->busAcc);
192	    pacc = xf86Entities[i]->access->fallback;
193	    pacc->AccessEnable(pacc->arg);
194	    xf86Entities[i]->entityEnter(i,xf86Entities[i]->private);
195	    pacc->AccessDisable(pacc->arg);
196	}
197}
198
199static void
200EntityLeave(void)
201{
202    int i;
203    xf86AccessPtr pacc;
204
205    for (i = 0; i < xf86NumEntities; i++)
206	if (xf86Entities[i]->entityLeave) {
207	    if (xf86Entities[i]->access->busAcc)
208		((BusAccPtr)xf86Entities[i]->access->busAcc)->set_f
209		    (xf86Entities[i]->access->busAcc);
210	    pacc = xf86Entities[i]->access->fallback;
211	    pacc->AccessEnable(pacc->arg);
212	    xf86Entities[i]->entityLeave(i,xf86Entities[i]->private);
213	    pacc->AccessDisable(pacc->arg);
214	}
215}
216
217_X_EXPORT Bool
218xf86IsEntityPrimary(int entityIndex)
219{
220    EntityPtr pEnt = xf86Entities[entityIndex];
221
222    if (primaryBus.type != pEnt->busType) return FALSE;
223
224    switch (pEnt->busType) {
225    case BUS_PCI:
226	return (pEnt->bus.id.pci == primaryBus.id.pci);
227    case BUS_SBUS:
228	return (pEnt->sbusBusId.fbNum == primaryBus.id.sbus.fbNum);
229    default:
230	return FALSE;
231    }
232}
233
234Bool
235xf86SetEntityFuncs(int entityIndex, EntityProc init, EntityProc enter,
236		   EntityProc leave, pointer private)
237{
238    if (entityIndex >= xf86NumEntities)
239	return FALSE;
240    xf86Entities[entityIndex]->entityInit = init;
241    xf86Entities[entityIndex]->entityEnter = enter;
242    xf86Entities[entityIndex]->entityLeave = leave;
243    xf86Entities[entityIndex]->private = private;
244    return TRUE;
245}
246
247Bool
248xf86DriverHasEntities(DriverPtr drvp)
249{
250    int i;
251    for (i = 0; i < xf86NumEntities; i++) {
252	if (xf86Entities[i]->driver == drvp)
253	    return TRUE;
254    }
255    return FALSE;
256}
257
258_X_EXPORT void
259xf86AddEntityToScreen(ScrnInfoPtr pScrn, int entityIndex)
260{
261    if (entityIndex == -1)
262	return;
263    if (xf86Entities[entityIndex]->inUse &&
264	!(xf86Entities[entityIndex]->entityProp & IS_SHARED_ACCEL)) {
265	ErrorF("Requested Entity already in use!\n");
266	return;
267    }
268
269    pScrn->numEntities++;
270    pScrn->entityList = xnfrealloc(pScrn->entityList,
271				    pScrn->numEntities * sizeof(int));
272    pScrn->entityList[pScrn->numEntities - 1] = entityIndex;
273    xf86Entities[entityIndex]->access->next = pScrn->access;
274    pScrn->access = xf86Entities[entityIndex]->access;
275    xf86Entities[entityIndex]->inUse = TRUE;
276    pScrn->entityInstanceList = xnfrealloc(pScrn->entityInstanceList,
277				    pScrn->numEntities * sizeof(int));
278    pScrn->entityInstanceList[pScrn->numEntities - 1] = 0;
279    pScrn->domainIOBase = xf86Entities[entityIndex]->domainIO;
280}
281
282_X_EXPORT void
283xf86SetEntityInstanceForScreen(ScrnInfoPtr pScrn, int entityIndex, int instance)
284{
285    int i;
286
287    if (entityIndex == -1 || entityIndex >= xf86NumEntities)
288	return;
289
290    for (i = 0; i < pScrn->numEntities; i++) {
291	if (pScrn->entityList[i] == entityIndex) {
292	    pScrn->entityInstanceList[i] = instance;
293	    break;
294	}
295    }
296}
297
298/*
299 * XXX  This needs to be updated for the case where a single entity may have
300 * instances associated with more than one screen.
301 */
302_X_EXPORT ScrnInfoPtr
303xf86FindScreenForEntity(int entityIndex)
304{
305    int i,j;
306
307    if (entityIndex == -1) return NULL;
308
309    if (xf86Screens) {
310	for (i = 0; i < xf86NumScreens; i++) {
311	    for (j = 0; j < xf86Screens[i]->numEntities; j++) {
312		if ( xf86Screens[i]->entityList[j] == entityIndex )
313		    return (xf86Screens[i]);
314	    }
315	}
316    }
317    return NULL;
318}
319
320_X_EXPORT void
321xf86RemoveEntityFromScreen(ScrnInfoPtr pScrn, int entityIndex)
322{
323    int i;
324    EntityAccessPtr *ptr = (EntityAccessPtr *)&pScrn->access;
325    EntityAccessPtr peacc;
326
327    for (i = 0; i < pScrn->numEntities; i++) {
328	if (pScrn->entityList[i] == entityIndex) {
329	    peacc = xf86Entities[pScrn->entityList[i]]->access;
330	    (*ptr) = peacc->next;
331	    /* disable entity: call disable func */
332	    if (peacc->pAccess)
333		peacc->pAccess->AccessDisable(peacc->pAccess->arg);
334	    /* also disable fallback - just in case */
335	    if (peacc->fallback)
336		peacc->fallback->AccessDisable(peacc->fallback->arg);
337	    for (i++; i < pScrn->numEntities; i++)
338		pScrn->entityList[i-1] = pScrn->entityList[i];
339	    pScrn->numEntities--;
340	    xf86Entities[entityIndex]->inUse = FALSE;
341	    break;
342	}
343	ptr = &(xf86Entities[pScrn->entityList[i]]->access->next);
344    }
345}
346
347/*
348 * xf86ClearEntitiesForScreen() - called when a screen is deleted
349 * to mark it's entities unused. Called by xf86DeleteScreen().
350 */
351void
352xf86ClearEntityListForScreen(int scrnIndex)
353{
354    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
355    EntityAccessPtr peacc;
356    int i, entityIndex;
357
358    if (pScrn->entityList == NULL || pScrn->numEntities == 0) return;
359
360    for (i = 0; i < pScrn->numEntities; i++) {
361	entityIndex = pScrn->entityList[i];
362	xf86Entities[entityIndex]->inUse = FALSE;
363	/* disable resource: call the disable function */
364	peacc = xf86Entities[entityIndex]->access;
365	if (peacc->pAccess)
366	    peacc->pAccess->AccessDisable(peacc->pAccess->arg);
367	/* and the fallback function */
368	if (peacc->fallback)
369	    peacc->fallback->AccessDisable(peacc->fallback->arg);
370	/* shared resources are only needed when entity is active: remove */
371	xf86DeallocateResourcesForEntity(entityIndex, ResShared);
372    }
373    xfree(pScrn->entityList);
374    xfree(pScrn->entityInstanceList);
375    if (pScrn->CurrentAccess->pIoAccess == (EntityAccessPtr)pScrn->access)
376	pScrn->CurrentAccess->pIoAccess = NULL;
377    if (pScrn->CurrentAccess->pMemAccess == (EntityAccessPtr)pScrn->access)
378	pScrn->CurrentAccess->pMemAccess = NULL;
379    pScrn->entityList = NULL;
380    pScrn->entityInstanceList = NULL;
381}
382
383void
384xf86DeallocateResourcesForEntity(int entityIndex, unsigned long type)
385{
386    resPtr *pprev_next = &Acc;
387    resPtr res = Acc;
388
389    while (res) {
390	if (res->entityIndex == entityIndex &&
391	    (type & ResAccMask & res->res_type))
392	{
393	    (*pprev_next) = res->next;
394	    xfree(res);
395	} else
396	    pprev_next = &(res->next);
397	res = (*pprev_next);
398    }
399}
400
401/*
402 * Add an extra device section (GDevPtr) to an entity.
403 */
404
405void
406xf86AddDevToEntity(int entityIndex, GDevPtr dev)
407{
408    EntityPtr pEnt;
409
410    if (entityIndex >= xf86NumEntities)
411	return;
412
413    pEnt = xf86Entities[entityIndex];
414    pEnt->numInstances++;
415    pEnt->devices = xnfrealloc(pEnt->devices,
416				pEnt->numInstances * sizeof(GDevPtr));
417    pEnt->devices[pEnt->numInstances - 1] = dev;
418    dev->claimed = TRUE;
419}
420
421/*
422 * xf86GetEntityInfo() -- This function hands information from the
423 * EntityRec struct to the drivers. The EntityRec structure itself
424 * remains invisible to the driver.
425 */
426_X_EXPORT EntityInfoPtr
427xf86GetEntityInfo(int entityIndex)
428{
429    EntityInfoPtr pEnt;
430    int i;
431
432    if (entityIndex >= xf86NumEntities)
433	return NULL;
434
435    pEnt = xnfcalloc(1,sizeof(EntityInfoRec));
436    pEnt->index = entityIndex;
437    pEnt->location = xf86Entities[entityIndex]->bus;
438    pEnt->active = xf86Entities[entityIndex]->active;
439    pEnt->chipset = xf86Entities[entityIndex]->chipset;
440    pEnt->resources = xf86Entities[entityIndex]->resources;
441    pEnt->driver = xf86Entities[entityIndex]->driver;
442    if ( (xf86Entities[entityIndex]->devices) &&
443         (xf86Entities[entityIndex]->devices[0]) ) {
444	for (i = 0; i < xf86Entities[entityIndex]->numInstances; i++)
445	    if (xf86Entities[entityIndex]->devices[i]->screen == 0)
446	        break;
447	pEnt->device = xf86Entities[entityIndex]->devices[i];
448    } else
449	pEnt->device = NULL;
450
451    return pEnt;
452}
453
454_X_EXPORT int
455xf86GetNumEntityInstances(int entityIndex)
456{
457    if (entityIndex >= xf86NumEntities)
458	return -1;
459
460    return xf86Entities[entityIndex]->numInstances;
461}
462
463_X_EXPORT GDevPtr
464xf86GetDevFromEntity(int entityIndex, int instance)
465{
466    int i;
467
468    /* We might not use AddDevtoEntity */
469    if ( (!xf86Entities[entityIndex]->devices) ||
470         (!xf86Entities[entityIndex]->devices[0]) )
471	return NULL;
472
473    if (entityIndex >= xf86NumEntities ||
474	instance >= xf86Entities[entityIndex]->numInstances)
475	return NULL;
476
477    for (i = 0; i < xf86Entities[entityIndex]->numInstances; i++)
478	if (xf86Entities[entityIndex]->devices[i]->screen == instance)
479	    break;
480    return xf86Entities[entityIndex]->devices[i];
481}
482
483/*
484 * general generic disable function.
485 */
486static void
487disableAccess(void)
488{
489    int i;
490    xf86AccessPtr pacc;
491    EntityAccessPtr peacc;
492
493    /* call disable funcs and reset current access pointer */
494    /* the entity specific access funcs are in an enabled  */
495    /* state - driver must restore their state explicitely */
496    for (i = 0; i < xf86NumScreens; i++) {
497	peacc = xf86Screens[i]->CurrentAccess->pIoAccess;
498	while (peacc) {
499	    if (peacc->pAccess)
500		peacc->pAccess->AccessDisable(peacc->pAccess->arg);
501	    peacc = peacc->next;
502	}
503	xf86Screens[i]->CurrentAccess->pIoAccess = NULL;
504	peacc = xf86Screens[i]->CurrentAccess->pMemAccess;
505	while (peacc) {
506	    if (peacc->pAccess)
507		peacc->pAccess->AccessDisable(peacc->pAccess->arg);
508	    peacc = peacc->next;
509	}
510	xf86Screens[i]->CurrentAccess->pMemAccess = NULL;
511    }
512    /* then call the generic entity disable funcs */
513    for (i = 0; i < xf86NumEntities; i++) {
514	pacc = xf86Entities[i]->access->fallback;
515	pacc->AccessDisable(pacc->arg);
516    }
517}
518
519static void
520clearAccess(void)
521{
522    int i;
523
524    /* call disable funcs and reset current access pointer */
525    /* the entity specific access funcs are in an enabled  */
526    /* state - driver must restore their state explicitely */
527    for (i = 0; i < xf86NumScreens; i++) {
528	xf86Screens[i]->CurrentAccess->pIoAccess = NULL;
529	xf86Screens[i]->CurrentAccess->pMemAccess = NULL;
530    }
531
532}
533
534/*
535 * Generic interface to bus specific code - add other buses here
536 */
537
538/*
539 * xf86AccessInit() - set up everything needed for access control
540 * called only once on first server generation.
541 */
542void
543xf86AccessInit(void)
544{
545    initPciState();
546    initPciBusState();
547    DisablePciBusAccess();
548    DisablePciAccess();
549
550    xf86ResAccessEnter = TRUE;
551}
552
553/*
554 * xf86AccessEnter() -- gets called to save the text mode VGA IO
555 * resources when reentering the server after a VT switch.
556 */
557void
558xf86AccessEnter(void)
559{
560    if (xf86ResAccessEnter)
561	return;
562
563    /*
564     * on enter we simply disable routing of special resources
565     * to any bus and let the RAC code to "open" the right bridges.
566     */
567    PciBusStateEnter();
568    DisablePciBusAccess();
569    PciStateEnter();
570    disableAccess();
571    EntityEnter();
572    notifyStateChange(NOTIFY_ENTER);
573    xf86EnterServerState(SETUP);
574    xf86ResAccessEnter = TRUE;
575}
576
577/*
578 * xf86AccessLeave() -- prepares access for and calls the
579 * entityLeave() functions.
580 * xf86AccessLeaveState() --- gets called to restore the
581 * access to the VGA IO resources when switching VT or on
582 * server exit.
583 * This was split to call xf86AccessLeaveState() from
584 * ddxGiveUp().
585 */
586void
587xf86AccessLeave(void)
588{
589    if (!xf86ResAccessEnter)
590	return;
591    notifyStateChange(NOTIFY_LEAVE);
592    disableAccess();
593    DisablePciBusAccess();
594    EntityLeave();
595}
596
597void
598xf86AccessLeaveState(void)
599{
600    if (!xf86ResAccessEnter)
601	return;
602    xf86ResAccessEnter = FALSE;
603    PciStateLeave();
604    PciBusStateLeave();
605}
606
607/*
608 * xf86AccessRestoreState() - Restore the access registers to the
609 * state before X was started. This is handy for framebuffers.
610 */
611static void
612xf86AccessRestoreState(void)
613{
614    if (!xf86ResAccessEnter)
615	return;
616    PciStateLeave();
617    PciBusStateLeave();
618}
619
620/*
621 * xf86EnableAccess() -- enable access to controlled resources.
622 * To reduce latency when switching access the ScrnInfoRec has
623 * a linked list of the EntityAccPtr of all screen entities.
624 */
625/*
626 * switching access needs to be done in te following oder:
627 * disable
628 * 1. disable old entity
629 * 2. reroute bus
630 * 3. enable new entity
631 * Otherwise resources needed for access control might be shadowed
632 * by other resources!
633 */
634
635_X_EXPORT void
636xf86EnableAccess(ScrnInfoPtr pScrn)
637{
638    register EntityAccessPtr peAcc = (EntityAccessPtr) pScrn->access;
639    register EntityAccessPtr pceAcc;
640    register xf86AccessPtr pAcc;
641    EntityAccessPtr tmp;
642
643#ifdef DEBUG
644    ErrorF("Enable access %i\n",pScrn->scrnIndex);
645#endif
646
647    /* Entity is not under access control or currently enabled */
648    if (!pScrn->access) {
649	if (pScrn->busAccess) {
650	    ((BusAccPtr)pScrn->busAccess)->set_f(pScrn->busAccess);
651	}
652	return;
653    }
654
655    switch (pScrn->resourceType) {
656    case IO:
657	pceAcc = pScrn->CurrentAccess->pIoAccess;
658	if (peAcc == pceAcc) {
659	    return;
660	}
661	if (pScrn->CurrentAccess->pMemAccess == pceAcc)
662	    pScrn->CurrentAccess->pMemAccess = NULL;
663	while (pceAcc) {
664	    pAcc = pceAcc->pAccess;
665	    if (pAcc)
666		pAcc->AccessDisable(pAcc->arg);
667	    pceAcc = pceAcc->next;
668	}
669	if (pScrn->busAccess)
670	    ((BusAccPtr)pScrn->busAccess)->set_f(pScrn->busAccess);
671	while (peAcc) {
672	    pAcc = peAcc->pAccess;
673	    if (pAcc)
674		pAcc->AccessEnable(pAcc->arg);
675	    peAcc = peAcc->next;
676	}
677	pScrn->CurrentAccess->pIoAccess = (EntityAccessPtr) pScrn->access;
678	return;
679
680    case MEM_IO:
681	pceAcc = pScrn->CurrentAccess->pIoAccess;
682	if (peAcc != pceAcc) { /* current Io != pAccess */
683	    tmp = pceAcc;
684	    while (pceAcc) {
685		pAcc = pceAcc->pAccess;
686		if (pAcc)
687		    pAcc->AccessDisable(pAcc->arg);
688		pceAcc = pceAcc->next;
689	    }
690	    pceAcc = pScrn->CurrentAccess->pMemAccess;
691	    if (peAcc != pceAcc /* current Mem != pAccess */
692		&& tmp !=pceAcc) {
693		while (pceAcc) {
694		    pAcc = pceAcc->pAccess;
695		    if (pAcc)
696			pAcc->AccessDisable(pAcc->arg);
697		    pceAcc = pceAcc->next;
698		}
699	    }
700	} else {    /* current Io == pAccess */
701	    pceAcc = pScrn->CurrentAccess->pMemAccess;
702	    if (pceAcc == peAcc) { /* current Mem == pAccess */
703		return;
704	    }
705	    while (pceAcc) {  /* current Mem != pAccess */
706		pAcc = pceAcc->pAccess;
707		if (pAcc)
708		    pAcc->AccessDisable(pAcc->arg);
709		pceAcc = pceAcc->next;
710	    }
711	}
712	if (pScrn->busAccess)
713	    ((BusAccPtr)pScrn->busAccess)->set_f(pScrn->busAccess);
714	while (peAcc) {
715	    pAcc = peAcc->pAccess;
716	    if (pAcc)
717		pAcc->AccessEnable(pAcc->arg);
718		peAcc = peAcc->next;
719	}
720	pScrn->CurrentAccess->pMemAccess =
721	    pScrn->CurrentAccess->pIoAccess = (EntityAccessPtr) pScrn->access;
722	return;
723
724    case MEM:
725	pceAcc = pScrn->CurrentAccess->pMemAccess;
726	if (peAcc == pceAcc) {
727	    return;
728	}
729	if (pScrn->CurrentAccess->pIoAccess == pceAcc)
730	    pScrn->CurrentAccess->pIoAccess = NULL;
731	while (pceAcc) {
732	    pAcc = pceAcc->pAccess;
733	    if (pAcc)
734		pAcc->AccessDisable(pAcc->arg);
735	    pceAcc = pceAcc->next;
736	}
737	if (pScrn->busAccess)
738	    ((BusAccPtr)pScrn->busAccess)->set_f(pScrn->busAccess);
739	while (peAcc) {
740	    pAcc = peAcc->pAccess;
741	    if (pAcc)
742		pAcc->AccessEnable(pAcc->arg);
743	    peAcc = peAcc->next;
744	}
745	pScrn->CurrentAccess->pMemAccess = (EntityAccessPtr) pScrn->access;
746	return;
747
748    case NONE:
749	if (pScrn->busAccess) {
750	    ((BusAccPtr)pScrn->busAccess)->set_f(pScrn->busAccess);
751	}
752	return;
753    }
754}
755
756_X_EXPORT void
757xf86SetCurrentAccess(Bool Enable, ScrnInfoPtr pScrn)
758{
759    EntityAccessPtr pceAcc2 = NULL;
760    register EntityAccessPtr pceAcc = NULL;
761    register xf86AccessPtr pAcc;
762
763
764    switch(pScrn->resourceType) {
765    case IO:
766	pceAcc = pScrn->CurrentAccess->pIoAccess;
767	break;
768    case MEM:
769	pceAcc = pScrn->CurrentAccess->pMemAccess;
770	break;
771    case MEM_IO:
772	pceAcc = pScrn->CurrentAccess->pMemAccess;
773	pceAcc2 = pScrn->CurrentAccess->pIoAccess;
774	break;
775    default:
776	break;
777    }
778
779    while (pceAcc) {
780	pAcc = pceAcc->pAccess;
781	if (pAcc) {
782	    if (Enable) {
783		pAcc->AccessEnable(pAcc->arg);
784	    } else {
785		pAcc->AccessDisable(pAcc->arg);
786	    }
787	}
788	pceAcc = pceAcc->next;
789	if (!pceAcc) {
790	    pceAcc = pceAcc2;
791	    pceAcc2 = NULL;
792	}
793    }
794}
795
796_X_EXPORT void
797xf86SetAccessFuncs(EntityInfoPtr pEnt, xf86SetAccessFuncPtr funcs,
798		   xf86SetAccessFuncPtr oldFuncs)
799{
800    AccessFuncPtr rac;
801
802    if (!xf86Entities[pEnt->index]->rac)
803	xf86Entities[pEnt->index]->rac = xnfcalloc(1,sizeof(AccessFuncRec));
804
805    rac = xf86Entities[pEnt->index]->rac;
806
807    rac->mem_new = funcs->mem;
808    rac->io_new = funcs->io;
809    rac->io_mem_new = funcs->io_mem;
810
811    rac->old = oldFuncs;
812}
813
814/*
815 * Conflict checking
816 */
817
818static memType
819getMask(memType val)
820{
821    memType mask = 0;
822    memType tmp = 0;
823
824    mask=~mask;
825    tmp = ~((~tmp) >> 1);
826
827    while (!(val & tmp)) {
828	mask = mask >> 1;
829	val = val << 1;
830    }
831    return mask;
832}
833
834/*
835 * checkConflictBlock() -- check for conflicts of a block resource range.
836 * If conflict is found return end of conflicting range. Else return 0.
837 */
838static memType
839checkConflictBlock(resRange *range, resPtr pRes)
840{
841    memType val,tmp,prev;
842    int i;
843
844    switch (pRes->res_type & ResExtMask) {
845    case ResBlock:
846	if (range->rBegin < pRes->block_end &&
847	    range->rEnd > pRes->block_begin) {
848#ifdef DEBUG
849	    ErrorF("b-b conflict w: %lx %lx\n",
850		   pRes->block_begin,pRes->block_end);
851#endif
852	    return pRes->block_end < range->rEnd ?
853		pRes->block_end : range->rEnd;
854	}
855	return 0;
856    case ResSparse:
857	if (pRes->sparse_base > range->rEnd) return 0;
858
859	val = (~pRes->sparse_mask | pRes->sparse_base) & getMask(range->rEnd);
860#ifdef DEBUG
861	ErrorF("base = 0x%lx, mask = 0x%lx, begin = 0x%lx, end = 0x%lx ,"
862	       "val = 0x%lx\n",
863		pRes->sparse_base, pRes->sparse_mask, range->rBegin,
864		range->rEnd, val);
865#endif
866	i = sizeof(memType) * 8;
867	tmp = prev = pRes->sparse_base;
868
869	while (i) {
870	    tmp |= 1<< (--i) & val;
871	    if (tmp > range->rEnd)
872		tmp = prev;
873	    else
874		prev = tmp;
875	}
876	if (tmp >= range->rBegin) {
877#ifdef DEBUG
878	    ErrorF("conflict found at: 0x%lx\n",tmp);
879	    ErrorF("b-d conflict w: %lx %lx\n",
880		   pRes->sparse_base,pRes->sparse_mask);
881#endif
882	    return tmp;
883	}
884	else
885	    return 0;
886    }
887    return 0;
888}
889
890/*
891 * checkConflictSparse() -- check for conflicts of a sparse resource range.
892 * If conflict is found return base of conflicting region. Else return 0.
893 */
894#define mt_max ~(memType)0
895#define length sizeof(memType) * 8
896static memType
897checkConflictSparse(resRange *range, resPtr pRes)
898{
899    memType val, tmp, prev;
900    int i;
901
902    switch (pRes->res_type & ResExtMask) {
903    case ResSparse:
904	tmp = pRes->sparse_mask & range->rMask;
905	if ((tmp & pRes->sparse_base) == (tmp & range->rBase)) {
906#ifdef DEBUG
907	    ErrorF("s-b conflict w: %lx %lx\n",
908		   pRes->sparse_base,pRes->sparse_mask);
909#endif
910	    return pRes->sparse_mask;
911	}
912	return 0;
913
914    case ResBlock:
915	if (pRes->block_end < range->rBase) return 0;
916
917	val = (~range->rMask | range->rBase) & getMask(pRes->block_end);
918	i = length;
919	tmp = prev = range->rBase;
920
921	while (i) {
922#ifdef DEBUG
923	    ErrorF("tmp = 0x%lx\n",tmp);
924#endif
925	    tmp |= 1<< (--i) & val;
926	    if (tmp > pRes->block_end)
927		tmp = prev;
928	    else
929		prev = tmp;
930	}
931	if (tmp < pRes->block_begin)
932	    return 0;
933	else {
934	    /*
935	     * now we subdivide the block region in sparse regions
936	     * with base values = 2^n and find the smallest mask.
937	     * This might be done in a simpler way....
938	     */
939	    memType mask, m_mask = 0, base = pRes->block_begin;
940	    int i;
941	    while (base < pRes->block_end) {
942		for (i = 1; i < length; i++)
943		    if ( base != (base & (mt_max << i))) break;
944		mask = mt_max >> (length - i);
945		do mask >>= 1;
946		while ((mask + base + 1) > pRes->block_end);
947		/* m_mask and are _inverted_ sparse masks */
948		m_mask = mask > m_mask ? mask : m_mask;
949		base = base + mask + 1;
950	    }
951#ifdef DEBUG
952	    ErrorF("conflict found at: 0x%lx\n",tmp);
953	    ErrorF("b-b conflict w: %lx %lx\n",
954		   pRes->block_begin,pRes->block_end);
955#endif
956	    return ~m_mask;
957	}
958    }
959    return 0;
960}
961#undef mt_max
962#undef length
963
964/*
965 * needCheck() -- this function decides whether to check for conflicts
966 * depending on the types of the resource ranges and their locations
967 */
968static Bool
969needCheck(resPtr pRes, unsigned long type, int entityIndex, xf86State state)
970{
971    /* the same entity shouldn't conflict with itself */
972    ScrnInfoPtr pScrn;
973    int i;
974    BusType loc = BUS_NONE;
975    BusType r_loc = BUS_NONE;
976
977    if ((pRes->res_type & ResTypeMask) != (type & ResTypeMask))
978        return FALSE;
979
980    /*
981     * Resources set by BIOS (ResBios) are allowed to conflict
982     * with resources marked (ResBios).
983     */
984    if (pRes->res_type & type & ResBios)
985	return FALSE;
986
987    if (type & pRes->res_type & ResUnused)
988 	return FALSE;
989
990    if (state == OPERATING) {
991	if (type & ResDisableOpr || pRes->res_type & ResDisableOpr)
992	    return FALSE;
993	if (type & pRes->res_type & ResUnusedOpr) return FALSE;
994	/*
995	 * Maybe we should have ResUnused set The resUnusedOpr
996	 * bit, too. This way we could avoid this confusion
997	 */
998	if ((type & ResUnusedOpr && pRes->res_type & ResUnused) ||
999	    (type & ResUnused && pRes->res_type & ResUnusedOpr))
1000	    return FALSE;
1001    }
1002
1003    if (entityIndex > -1)
1004	loc = xf86Entities[entityIndex]->busType;
1005    if (pRes->entityIndex > -1)
1006	r_loc = xf86Entities[pRes->entityIndex]->busType;
1007
1008    if ((type & ResAccMask) == ResShared &&
1009	(pRes->res_type & ResAccMask) == ResShared)
1010	return FALSE;
1011
1012    if (pRes->entityIndex == entityIndex) return FALSE;
1013
1014    if (pRes->entityIndex > -1 &&
1015	(pScrn = xf86FindScreenForEntity(entityIndex))) {
1016	for (i = 0; i < pScrn->numEntities; i++)
1017	    if (pScrn->entityList[i] == pRes->entityIndex) return FALSE;
1018    }
1019    return TRUE;
1020}
1021
1022/*
1023 * checkConflict() - main conflict checking function which all other
1024 * function call.
1025 */
1026static memType
1027checkConflict(resRange *rgp, resPtr pRes, int entityIndex,
1028	      xf86State state, Bool ignoreIdentical)
1029{
1030    memType ret;
1031
1032    while(pRes) {
1033	if (!needCheck(pRes,rgp->type, entityIndex ,state)) {
1034	    pRes = pRes->next;
1035	    continue;
1036	}
1037	switch (rgp->type & ResExtMask) {
1038	case ResBlock:
1039	    if (rgp->rEnd < rgp->rBegin) {
1040		xf86Msg(X_ERROR,"end of block range 0x%lx < begin 0x%lx\n",
1041			(long)rgp->rEnd, (long)rgp->rBegin);
1042		return 0;
1043	    }
1044	    if ((ret = checkConflictBlock(rgp, pRes))) {
1045		if (!ignoreIdentical || (rgp->rBegin != pRes->block_begin)
1046		    || (rgp->rEnd != pRes->block_end))
1047		    return ret;
1048	    }
1049    break;
1050	case ResSparse:
1051	    if ((rgp->rBase & rgp->rMask) != rgp->rBase) {
1052		xf86Msg(X_ERROR,"sparse io range (base: 0x%lx  mask: 0x%lx)"
1053			"doesn't satisfy (base & mask = mask)\n",
1054			(long)rgp->rBase, (long)rgp->rMask);
1055		return 0;
1056	    }
1057	    if ((ret = checkConflictSparse(rgp, pRes))) {
1058		if (!ignoreIdentical || (rgp->rBase != pRes->sparse_base)
1059		    || (rgp->rMask != pRes->sparse_mask))
1060		    return ret;
1061	    }
1062	    break;
1063	}
1064	pRes = pRes->next;
1065    }
1066    return 0;
1067}
1068
1069/*
1070 * xf86ChkConflict() - This function is the low level interface to
1071 * the resource broker that gets exported. Tests all resources ie.
1072 * performs test with SETUP flag.
1073 */
1074static memType
1075xf86ChkConflict(resRange *rgp, int entityIndex)
1076{
1077    return checkConflict(rgp, Acc, entityIndex, SETUP, FALSE);
1078}
1079
1080/*
1081 * Resources List handling
1082 */
1083
1084static resPtr
1085xf86JoinResLists(resPtr rlist1, resPtr rlist2)
1086{
1087    resPtr pRes;
1088
1089    if (!rlist1)
1090	return rlist2;
1091
1092    if (!rlist2)
1093	return rlist1;
1094
1095    for (pRes = rlist1; pRes->next; pRes = pRes->next)
1096	;
1097    pRes->next = rlist2;
1098    return rlist1;
1099}
1100
1101resPtr
1102xf86AddResToList(resPtr rlist, resRange *range, int entityIndex)
1103{
1104    resPtr new;
1105
1106    switch (range->type & ResExtMask) {
1107    case ResBlock:
1108	if (range->rEnd < range->rBegin) {
1109		xf86Msg(X_ERROR,"end of block range 0x%lx < begin 0x%lx\n",
1110			(long)range->rEnd, (long)range->rBegin);
1111		return rlist;
1112	}
1113	break;
1114    case ResSparse:
1115	if ((range->rBase & range->rMask) != range->rBase) {
1116	    xf86Msg(X_ERROR,"sparse io range (base: 0x%lx  mask: 0x%lx)"
1117		    "doesn't satisfy (base & mask = mask)\n",
1118		    (long)range->rBase, (long)range->rMask);
1119	    return rlist;
1120	}
1121	break;
1122    }
1123
1124    new = xnfalloc(sizeof(resRec));
1125    /*
1126     * Only background resources may be registered with ResBios
1127     * and ResEstimated set. Other resources only set it for
1128     * testing.
1129     */
1130    if (entityIndex != (-1))
1131        range->type &= ~(ResBios | ResEstimated);
1132    new->val = *range;
1133    new->entityIndex = entityIndex;
1134    new->next = rlist;
1135    return new;
1136}
1137
1138_X_EXPORT void
1139xf86FreeResList(resPtr rlist)
1140{
1141    resPtr pRes;
1142
1143    if (!rlist)
1144	return;
1145
1146    for (pRes = rlist->next; pRes; rlist = pRes, pRes = pRes->next)
1147	xfree(rlist);
1148    xfree(rlist);
1149}
1150
1151static resPtr
1152xf86DupResList(const resPtr rlist)
1153{
1154    resPtr pRes, ret, prev, new;
1155
1156    if (!rlist)
1157	return NULL;
1158
1159    ret = xnfalloc(sizeof(resRec));
1160    *ret = *rlist;
1161    prev = ret;
1162    for (pRes = rlist->next; pRes; pRes = pRes->next) {
1163	new = xnfalloc(sizeof(resRec));
1164	*new = *pRes;
1165	prev->next = new;
1166	prev = new;
1167    }
1168    return ret;
1169}
1170
1171static void
1172xf86PrintResList(int verb, resPtr list)
1173{
1174    int i = 0;
1175    const char *s, *r;
1176    resPtr tmp = list;
1177    unsigned long type;
1178
1179    if (!list)
1180	return;
1181
1182    type = ResMem;
1183    r = "M";
1184    while (1) {
1185	while (list) {
1186	    if ((list->res_type & ResPhysMask) == type) {
1187		switch (list->res_type & ResExtMask) {
1188		case ResBlock:
1189		    xf86ErrorFVerb(verb,
1190				   "\t[%d] %d\t%ld\t0x%08lx - 0x%08lx (0x%lx)",
1191				   i, list->entityIndex,
1192				   (list->res_type & ResDomain) >> 24,
1193				   (long)list->block_begin,
1194				   (long)list->block_end,
1195				   (long)(list->block_end -
1196					  list->block_begin + 1));
1197		    break;
1198		case ResSparse:
1199		    xf86ErrorFVerb(verb, "\t[%d] %d\t%ld\t0x%08lx - 0x%08lx ",
1200				   i, list->entityIndex,
1201				   (list->res_type & ResDomain) >> 24,
1202				   (long)list->sparse_base,
1203				   (long)list->sparse_mask);
1204		    break;
1205		default:
1206		    list = list->next;
1207		    continue;
1208		}
1209		xf86ErrorFVerb(verb, " %s", r);
1210		switch (list->res_type & ResAccMask) {
1211		case ResExclusive:
1212		    if (list->res_type & ResUnused)
1213			s = "x";
1214		    else
1215			s = "X";
1216		    break;
1217		case ResShared:
1218		    if (list->res_type & ResUnused)
1219			s = "s";
1220		    else
1221			s = "S";
1222		    break;
1223		default:
1224		    s = "?";
1225		}
1226		xf86ErrorFVerb(verb, "%s", s);
1227		switch (list->res_type & ResExtMask) {
1228		case ResBlock:
1229		    s = "[B]";
1230		    break;
1231		case ResSparse:
1232		    s = "[S]";
1233		    break;
1234		default:
1235		    s = "[?]";
1236		}
1237		xf86ErrorFVerb(verb, "%s", s);
1238		if (list->res_type & ResInit)
1239		    xf86ErrorFVerb(verb, "t");
1240		if (list->res_type & ResBios)
1241		    xf86ErrorFVerb(verb, "(B)");
1242		if (list->res_type & ResBus)
1243		    xf86ErrorFVerb(verb, "(b)");
1244		if (list->res_type & ResOprMask) {
1245		    switch (list->res_type & ResOprMask) {
1246		    case ResUnusedOpr:
1247			s = "(OprU)";
1248			break;
1249		    case ResDisableOpr:
1250			s = "(OprD)";
1251			break;
1252		    default:
1253			s = "(Opr?)";
1254			break;
1255		    }
1256		    xf86ErrorFVerb(verb, "%s", s);
1257		}
1258		xf86ErrorFVerb(verb, "\n");
1259		i++;
1260	    }
1261	    list = list->next;
1262	}
1263	if (type == ResIo) break;
1264	type = ResIo;
1265	r = "I";
1266	list = tmp;
1267    }
1268}
1269
1270resPtr
1271xf86AddRangesToList(resPtr list, resRange *pRange, int entityIndex)
1272{
1273    while(pRange && pRange->type != ResEnd) {
1274	list = xf86AddResToList(list,pRange,entityIndex);
1275	pRange++;
1276    }
1277    return list;
1278}
1279
1280void
1281xf86ResourceBrokerInit(void)
1282{
1283    Acc = NULL;
1284
1285    /* Get the ranges used exclusively by the system */
1286    Acc = xf86AccResFromOS(Acc);
1287    xf86MsgVerb(X_INFO, 3, "System resource ranges:\n");
1288    xf86PrintResList(3, Acc);
1289}
1290
1291/*
1292 * Resource registration
1293 */
1294
1295static void
1296convertRange2Host(int entityIndex, resRange *pRange)
1297{
1298    if (pRange->type & ResBus) {
1299	switch (xf86Entities[entityIndex]->busType) {
1300	case BUS_PCI:
1301	    pciConvertRange2Host(entityIndex,pRange);
1302	    break;
1303	default:
1304	    break;
1305	}
1306
1307	pRange->type &= ~ResBus;
1308    }
1309}
1310
1311static void
1312xf86ConvertListToHost(int entityIndex, resPtr list)
1313{
1314    while (list) {
1315	convertRange2Host(entityIndex, &list->val);
1316	list = list->next;
1317    }
1318}
1319
1320/*
1321 * xf86RegisterResources() -- attempts to register listed resources.
1322 * Returns a resPtr listing all resources not successfully registered, by
1323 * which we mean, NULL.
1324 */
1325
1326_X_EXPORT resPtr
1327xf86RegisterResources(int entityIndex, resList list, unsigned long access)
1328{
1329    resRange range;
1330    resList list_f = NULL;
1331
1332    if (!list)
1333	return NULL;
1334
1335    while(list->type != ResEnd) {
1336	range = *list;
1337
1338	convertRange2Host(entityIndex,&range);
1339
1340	if ((access != ResNone) && (access & ResAccMask)) {
1341	    range.type = (range.type & ~ResAccMask) | (access & ResAccMask);
1342	}
1343 	range.type &= ~ResEstimated;	/* Not allowed for drivers */
1344	Acc = xf86AddResToList(Acc,&range,entityIndex);
1345	list++;
1346    }
1347    if (list_f)
1348      xfree(list_f);
1349
1350#ifdef DEBUG
1351    xf86MsgVerb(X_INFO, 3,"Resources after driver initialization\n");
1352    xf86PrintResList(3, Acc);
1353#endif
1354    return NULL;
1355
1356}
1357
1358static void
1359busTypeSpecific(EntityPtr pEnt, xf86AccessPtr *acc_mem,
1360		xf86AccessPtr *acc_io, xf86AccessPtr *acc_mem_io)
1361{
1362    switch (pEnt->bus.type) {
1363    case BUS_SBUS:
1364	*acc_mem = *acc_io = *acc_mem_io = &AccessNULL;
1365	break;
1366    case BUS_PCI: {
1367	struct pci_device *const dev = pEnt->bus.id.pci;
1368
1369	if ((dev != NULL) && ((void *)dev->user_data != NULL)) {
1370	    pciAccPtr const paccp = (pciAccPtr) dev->user_data;
1371
1372	    *acc_io = & paccp->ioAccess;
1373	    *acc_mem = & paccp->memAccess;
1374	    *acc_mem_io = & paccp->io_memAccess;
1375	}
1376	else {
1377	    /* FIXME: This is an error path.  We should probably have an
1378	     * FIXME: assertion here or something.
1379	     */
1380	    *acc_io = NULL;
1381	    *acc_mem = NULL;
1382	    *acc_mem_io = NULL;
1383	}
1384	break;
1385    }
1386    default:
1387	*acc_mem = *acc_io = *acc_mem_io = NULL;
1388	break;
1389    }
1390    return;
1391}
1392
1393static void
1394setAccess(EntityPtr pEnt, xf86State state)
1395{
1396
1397    xf86AccessPtr acc_mem, acc_io, acc_mem_io;
1398    xf86AccessPtr org_mem = NULL, org_io = NULL, org_mem_io = NULL;
1399    int prop;
1400
1401    busTypeSpecific(pEnt, &acc_mem, &acc_io, &acc_mem_io);
1402
1403    /* The replacement function needs to handle _all_ shared resources */
1404    /* unless they are handeled locally and disabled otherwise         */
1405    if (pEnt->rac) {
1406	if (pEnt->rac->io_new) {
1407	    org_io = acc_io;
1408	    acc_io = pEnt->rac->io_new;
1409	}
1410	if (pEnt->rac->mem_new) {
1411	    org_mem = acc_mem;
1412	    acc_mem = pEnt->rac->mem_new;
1413	}
1414	if (pEnt->rac->io_mem_new) {
1415	    org_mem_io = acc_mem_io;
1416	    acc_mem_io = pEnt->rac->io_mem_new;
1417	}
1418    }
1419
1420    if (state == OPERATING) {
1421	prop = pEnt->entityProp;
1422	switch(pEnt->entityProp & NEED_SHARED) {
1423	case NEED_SHARED:
1424	    pEnt->access->rt = MEM_IO;
1425	    break;
1426	case NEED_IO_SHARED:
1427	    pEnt->access->rt = IO;
1428	    break;
1429	case NEED_MEM_SHARED:
1430	    pEnt->access->rt = MEM;
1431	    break;
1432	default:
1433	    pEnt->access->rt = NONE;
1434	}
1435    } else {
1436	prop = NEED_SHARED | NEED_MEM | NEED_IO;
1437	pEnt->access->rt = MEM_IO;
1438    }
1439
1440    switch(pEnt->access->rt) {
1441    case IO:
1442	pEnt->access->pAccess = acc_io;
1443	break;
1444    case MEM:
1445	pEnt->access->pAccess = acc_mem;
1446	break;
1447    case MEM_IO:
1448	pEnt->access->pAccess = acc_mem_io;
1449	break;
1450    default: /* no conflicts at all */
1451	pEnt->access->pAccess =  NULL; /* remove from RAC */
1452	break;
1453    }
1454
1455    if (org_io) {
1456	/* does the driver want the old access func? */
1457	if (pEnt->rac->old) {
1458	    /* give it to the driver, leave state disabled */
1459	    pEnt->rac->old->io = org_io;
1460	} else {
1461	    /* driver doesn't want it - enable generic access */
1462	    org_io->AccessEnable(org_io->arg);
1463	}
1464    }
1465
1466    if (org_mem_io) {
1467	/* does the driver want the old access func? */
1468	if (pEnt->rac->old) {
1469	    /* give it to the driver, leave state disabled */
1470	    pEnt->rac->old->io_mem = org_mem_io;
1471	} else {
1472	    /* driver doesn't want it - enable generic access */
1473	    org_mem_io->AccessEnable(org_mem_io->arg);
1474	}
1475    }
1476
1477    if (org_mem) {
1478	/* does the driver want the old access func? */
1479	if (pEnt->rac->old) {
1480	    /* give it to the driver, leave state disabled */
1481	    pEnt->rac->old->mem = org_mem;
1482	} else {
1483	    /* driver doesn't want it - enable generic access */
1484	    org_mem->AccessEnable(org_mem->arg);
1485	}
1486    }
1487
1488    if (!(prop & NEED_MEM_SHARED)){
1489	if (prop & NEED_MEM) {
1490	    if (acc_mem)
1491		acc_mem->AccessEnable(acc_mem->arg);
1492	} else {
1493	    if (acc_mem)
1494		acc_mem->AccessDisable(acc_mem->arg);
1495	}
1496    }
1497
1498    if (!(prop & NEED_IO_SHARED)) {
1499	if (prop & NEED_IO) {
1500	    if (acc_io)
1501		acc_io->AccessEnable(acc_io->arg);
1502	} else {
1503	    if (acc_io)
1504		acc_io->AccessDisable(acc_io->arg);
1505	}
1506    }
1507
1508    /* disable shared resources */
1509    if (pEnt->access->pAccess)
1510	pEnt->access->pAccess->AccessDisable(pEnt->access->pAccess->arg);
1511
1512    /*
1513     * If device is not under access control it is enabled.
1514     * If it needs bus routing do it here as it isn't bus
1515     * type specific. Any conflicts should be checked at this
1516     * stage
1517     */
1518    if (!pEnt->access->pAccess
1519	&& (pEnt->entityProp & (state == SETUP ? NEED_VGA_ROUTED_SETUP :
1520				NEED_VGA_ROUTED)))
1521	((BusAccPtr)pEnt->busAcc)->set_f(pEnt->busAcc);
1522}
1523
1524
1525/*
1526 * xf86EnterServerState() -- set state the server is in.
1527 */
1528
1529typedef enum { TRI_UNSET, TRI_TRUE, TRI_FALSE } TriState;
1530
1531static void
1532SetSIGIOForState(xf86State state)
1533{
1534    static int sigio_state;
1535    static TriState sigio_blocked = TRI_UNSET;
1536
1537    if ((state == SETUP) && (sigio_blocked != TRI_TRUE)) {
1538        sigio_state = xf86BlockSIGIO();
1539	sigio_blocked = TRI_TRUE;
1540    } else if ((state == OPERATING) && (sigio_blocked != TRI_UNSET)) {
1541        xf86UnblockSIGIO(sigio_state);
1542        sigio_blocked = TRI_FALSE;
1543    }
1544}
1545
1546void
1547xf86EnterServerState(xf86State state)
1548{
1549    EntityPtr pEnt;
1550    ScrnInfoPtr pScrn;
1551    int i,j;
1552    int needVGA = 0;
1553    resType rt;
1554    /*
1555     * This is a good place to block SIGIO during SETUP state.
1556     * SIGIO should be blocked in SETUP state otherwise (u)sleep()
1557     * might get interrupted early.
1558     * We take care not to call xf86BlockSIGIO() twice.
1559     */
1560    SetSIGIOForState(state);
1561#ifdef DEBUG
1562    if (state == SETUP)
1563	ErrorF("Entering SETUP state\n");
1564    else
1565	ErrorF("Entering OPERATING state\n");
1566#endif
1567
1568    /* When servicing a dumb framebuffer we don't need to do anything */
1569    if (doFramebufferMode) return;
1570
1571    for (i=0; i<xf86NumScreens; i++) {
1572	pScrn = xf86Screens[i];
1573	j = pScrn->entityList[pScrn->numEntities - 1];
1574	pScrn->access = xf86Entities[j]->access;
1575
1576 	for (j = 0; j<xf86Screens[i]->numEntities; j++) {
1577 	    pEnt = xf86Entities[xf86Screens[i]->entityList[j]];
1578 	    if (pEnt->entityProp & (state == SETUP ? NEED_VGA_ROUTED_SETUP
1579 				    : NEED_VGA_ROUTED))
1580		xf86Screens[i]->busAccess = pEnt->busAcc;
1581 	}
1582	if (xf86Screens[i]->busAccess)
1583	    needVGA ++;
1584    }
1585
1586    /*
1587     * if we just have one screen we don't have RAC.
1588     * Therefore just enable the screen and return.
1589     */
1590    if (!needRAC) {
1591	xf86EnableAccess(xf86Screens[0]);
1592	notifyStateChange(NOTIFY_ENABLE);
1593	return;
1594    }
1595
1596    if (state == SETUP)
1597	notifyStateChange(NOTIFY_SETUP_TRANSITION);
1598    else
1599	notifyStateChange(NOTIFY_OPERATING_TRANSITION);
1600
1601    clearAccess();
1602    for (i=0; i<xf86NumScreens;i++) {
1603
1604	rt = NONE;
1605
1606	for (j = 0; j<xf86Screens[i]->numEntities; j++) {
1607	    pEnt = xf86Entities[xf86Screens[i]->entityList[j]];
1608	    setAccess(pEnt,state);
1609
1610	    if (pEnt->access->rt != NONE) {
1611		if (rt != NONE && rt != pEnt->access->rt)
1612		    rt = MEM_IO;
1613		else
1614		    rt = pEnt->access->rt;
1615	    }
1616	}
1617	xf86Screens[i]->resourceType = rt;
1618	if (rt == NONE) {
1619	    xf86Screens[i]->access = NULL;
1620	    if (needVGA < 2)
1621		xf86Screens[i]->busAccess = NULL;
1622	}
1623
1624#ifdef DEBUG
1625	if (xf86Screens[i]->busAccess)
1626	    ErrorF("Screen %i setting vga route\n",i);
1627#endif
1628	switch (rt) {
1629	case MEM_IO:
1630	    xf86MsgVerb(X_INFO, 3, "Screen %i shares mem & io resources\n",i);
1631	    break;
1632	case IO:
1633	    xf86MsgVerb(X_INFO, 3, "Screen %i shares io resources\n",i);
1634	    break;
1635	case MEM:
1636	    xf86MsgVerb(X_INFO, 3, "Screen %i shares mem resources\n",i);
1637	    break;
1638	default:
1639	    xf86MsgVerb(X_INFO, 3, "Entity %i shares no resources\n",i);
1640	    break;
1641	}
1642    }
1643    if (state == SETUP)
1644	notifyStateChange(NOTIFY_SETUP);
1645    else
1646	notifyStateChange(NOTIFY_OPERATING);
1647}
1648
1649/*
1650 * xf86SetOperatingState() -- Set ResOperMask for resources listed.
1651 */
1652_X_EXPORT resPtr
1653xf86SetOperatingState(resList list, int entityIndex, int mask)
1654{
1655    resPtr acc;
1656    resPtr r_fail = NULL;
1657    resRange range;
1658
1659    while (list->type != ResEnd) {
1660	range = *list;
1661	convertRange2Host(entityIndex,&range);
1662
1663	acc = Acc;
1664	while (acc) {
1665#define MASK (ResTypeMask | ResExtMask)
1666	    if ((acc->entityIndex == entityIndex)
1667		&& (acc->val.a == range.a) && (acc->val.b == range.b)
1668		&& ((acc->val.type & MASK) == (range.type & MASK)))
1669		break;
1670#undef MASK
1671	    acc = acc->next;
1672	}
1673	if (acc)
1674	    acc->val.type = (acc->val.type & ~ResOprMask)
1675		| (mask & ResOprMask);
1676	else {
1677	    r_fail = xf86AddResToList(r_fail,&range,entityIndex);
1678	}
1679	list ++;
1680    }
1681
1682     return r_fail;
1683}
1684
1685/*
1686 * Stage specific code
1687 */
1688
1689/*
1690 * xf86ClaimFixedResources() is used to allocate non-relocatable resources.
1691 * This should only be done by a driver's Probe() function.
1692 */
1693_X_EXPORT void
1694xf86ClaimFixedResources(resList list, int entityIndex)
1695{
1696    resPtr ptr = NULL;
1697    resRange range;
1698
1699    if (!list) return;
1700
1701    while (list->type !=ResEnd) {
1702 	range = *list;
1703
1704	convertRange2Host(entityIndex,&range);
1705
1706 	range.type &= ~ResEstimated;	/* Not allowed for drivers */
1707 	switch (range.type & ResAccMask) {
1708  	case ResExclusive:
1709 	    if (!xf86ChkConflict(&range, entityIndex)) {
1710 		Acc = xf86AddResToList(Acc, &range, entityIndex);
1711	    } else FatalError("xf86ClaimFixedResources conflict\n");
1712	    break;
1713	case ResShared:
1714	    /* at this stage the resources are just added to the
1715	     * EntityRec. After the Probe() phase this list is checked by
1716	     * xf86PostProbe(). All resources which don't
1717	     * conflict with already allocated ones are allocated
1718	     * and removed from the EntityRec. Thus a non-empty resource
1719	     * list in the EntityRec indicates resource conflicts the
1720	     * driver should either handle or fail.
1721	     */
1722	    if (xf86Entities[entityIndex]->active)
1723		ptr = xf86AddResToList(ptr,&range,entityIndex);
1724	    break;
1725	}
1726	list++;
1727    }
1728    xf86Entities[entityIndex]->resources =
1729	xf86JoinResLists(xf86Entities[entityIndex]->resources,ptr);
1730    xf86MsgVerb(X_INFO, 3,
1731	"resource ranges after xf86ClaimFixedResources() call:\n");
1732    xf86PrintResList(3,Acc);
1733#ifdef DEBUG
1734    if (ptr) {
1735	xf86MsgVerb(X_INFO, 3, "to be registered later:\n");
1736	xf86PrintResList(3,ptr);
1737    }
1738#endif
1739}
1740
1741static void
1742checkRoutingForScreens(xf86State state)
1743{
1744    resList list = resVgaUnusedExclusive;
1745    resPtr pResVGA = NULL;
1746    resPtr pResVGAHost;
1747    pointer vga = NULL;
1748    int i,j;
1749    int entityIndex;
1750    EntityPtr pEnt;
1751    resPtr pAcc;
1752    resRange range;
1753
1754    /*
1755     * find devices that need VGA routed: ie the ones that have
1756     * registered VGA resources without ResUnused. ResUnused
1757     * doesn't conflict with itself therefore use it here.
1758     */
1759    while (list->type != ResEnd) { /* create resPtr from resList for VGA */
1760	range = *list;
1761	range.type &= ~(ResBios | ResEstimated); /* if set remove them */
1762	pResVGA = xf86AddResToList(pResVGA, &range, -1);
1763	list++;
1764    }
1765
1766    for (i = 0; i < xf86NumScreens; i++) {
1767	for (j = 0; j < xf86Screens[i]->numEntities; j++) {
1768	    entityIndex = xf86Screens[i]->entityList[j];
1769	    pEnt = xf86Entities[entityIndex];
1770	    pAcc = Acc;
1771	    vga = NULL;
1772	    pResVGAHost = xf86DupResList(pResVGA);
1773	    xf86ConvertListToHost(entityIndex,pResVGAHost);
1774	    while (pAcc) {
1775		if (pAcc->entityIndex == entityIndex)
1776		    if (checkConflict(&pAcc->val, pResVGAHost,
1777				      entityIndex, state, FALSE)) {
1778			if (vga && vga != pEnt->busAcc) {
1779			    xf86Msg(X_ERROR, "Screen %i needs vga routed to"
1780				    "different buses - deleting\n",i);
1781			    xf86DeleteScreen(i--,0);
1782			}
1783#ifdef DEBUG
1784			{
1785			    resPtr rlist = xf86AddResToList(NULL,&pAcc->val,
1786							    pAcc->entityIndex);
1787			    xf86MsgVerb(X_INFO,3,"====== %s\n",
1788					state == OPERATING ? "OPERATING"
1789					: "SETUP");
1790			    xf86MsgVerb(X_INFO,3,"%s Resource:\n",
1791					(pAcc->val.type) & ResMem ? "Mem" :"Io");
1792			    xf86PrintResList(3,rlist);
1793			    xf86FreeResList(rlist);
1794			    xf86MsgVerb(X_INFO,3,"Conflicts with:\n");
1795			    xf86PrintResList(3,pResVGAHost);
1796			    xf86MsgVerb(X_INFO,3,"=====\n");
1797			}
1798#endif
1799			vga = pEnt->busAcc;
1800			pEnt->entityProp |= (state == SETUP
1801			    ? NEED_VGA_ROUTED_SETUP : NEED_VGA_ROUTED);
1802			if (state == OPERATING) {
1803			    if (pAcc->val.type & ResMem)
1804				pEnt->entityProp |= NEED_VGA_MEM;
1805			    else
1806				pEnt->entityProp |= NEED_VGA_IO;
1807			}
1808		    }
1809		pAcc = pAcc->next;
1810	    }
1811	    if (vga)
1812		xf86MsgVerb(X_INFO, 3,"Setting vga for screen %i.\n",i);
1813	    xf86FreeResList(pResVGAHost);
1814	}
1815    }
1816    xf86FreeResList(pResVGA);
1817}
1818
1819/*
1820 * xf86PostProbe() -- Allocate all non conflicting resources
1821 * This function gets called by xf86Init().
1822 */
1823void
1824xf86PostProbe(void)
1825{
1826    memType val;
1827    int i,j;
1828    resPtr resp, acc, tmp, resp_x;
1829
1830    if (fbSlotClaimed) {
1831        if (pciSlotClaimed
1832#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
1833	    || sbusSlotClaimed
1834#endif
1835	    ) {
1836	    FatalError("Cannot run in framebuffer mode. Please specify busIDs "
1837		       "       for all framebuffer devices\n");
1838	    return;
1839	} else  {
1840	    xf86Msg(X_INFO,"Running in FRAMEBUFFER Mode\n");
1841	    xf86AccessRestoreState();
1842	    notifyStateChange(NOTIFY_ENABLE);
1843	    doFramebufferMode = TRUE;
1844
1845	    return;
1846	}
1847    }
1848    acc = tmp = xf86DupResList(Acc);
1849
1850    for (i=0; i<xf86NumEntities; i++) {
1851	resp = xf86Entities[i]->resources;
1852	xf86Entities[i]->resources = NULL;
1853	resp_x = NULL;
1854	while (resp) {
1855	    if (! (val = checkConflict(&resp->val,acc,i,SETUP,FALSE)))  {
1856 	        resp->res_type &= ~(ResBios); /* just used for chkConflict() */
1857		tmp = resp_x;
1858		resp_x = resp;
1859		resp = resp->next;
1860		resp_x->next = tmp;
1861		} else {
1862		    xf86MsgVerb(X_INFO, 3, "Found conflict at: 0x%lx\n",
1863				(long)val);
1864 		    resp->res_type &= ~ResEstimated;
1865		    tmp = xf86Entities[i]->resources;
1866		    xf86Entities[i]->resources = resp;
1867		    resp = resp->next;
1868		    xf86Entities[i]->resources->next = tmp;
1869		}
1870	}
1871	xf86JoinResLists(Acc,resp_x);
1872    }
1873    xf86FreeResList(acc);
1874
1875    xf86MsgVerb(X_INFO, 3, "resource ranges after probing:\n");
1876    xf86PrintResList(3, Acc);
1877    checkRoutingForScreens(SETUP);
1878
1879    for (i = 0; i < xf86NumScreens; i++) {
1880	for (j = 0; j<xf86Screens[i]->numEntities; j++) {
1881	    EntityPtr pEnt = xf86Entities[xf86Screens[i]->entityList[j]];
1882 	    if ((pEnt->entityProp & NEED_VGA_ROUTED_SETUP) &&
1883 		((xf86Screens[i]->busAccess = pEnt->busAcc)))
1884		break;
1885	}
1886    }
1887}
1888
1889static void
1890checkRequiredResources(int entityIndex)
1891{
1892    resRange range;
1893    resPtr pAcc = Acc;
1894    const EntityPtr pEnt = xf86Entities[entityIndex];
1895    while (pAcc) {
1896	if (pAcc->entityIndex == entityIndex) {
1897	    range = pAcc->val;
1898	    /*  ResAny to find conflicts with anything. */
1899	    range.type = (range.type & ~ResAccMask) | ResAny | ResBios;
1900	    if (checkConflict(&range,Acc,entityIndex,OPERATING,FALSE))
1901		switch (pAcc->res_type & ResPhysMask) {
1902		case ResMem:
1903		    pEnt->entityProp |= NEED_MEM_SHARED;
1904		    break;
1905		case ResIo:
1906		    pEnt->entityProp |= NEED_IO_SHARED;
1907		    break;
1908		}
1909	    if (!(pAcc->res_type & ResOprMask)) {
1910		switch (pAcc->res_type & ResPhysMask) {
1911		case ResMem:
1912		    pEnt->entityProp |= NEED_MEM;
1913		    break;
1914		case ResIo:
1915		    pEnt->entityProp |= NEED_IO;
1916		    break;
1917		}
1918	    }
1919	}
1920	pAcc = pAcc->next;
1921    }
1922
1923    /*
1924     * After we have checked all resources of an entity agains any
1925     * other resource we know if the entity need this resource type
1926     * (ie. mem/io) at all. if not we can disable this type completely,
1927     * so no need to share it either.
1928     */
1929    if ((pEnt->entityProp & NEED_MEM_SHARED)
1930	&& (!(pEnt->entityProp & NEED_MEM)))
1931	pEnt->entityProp &= ~(unsigned long)NEED_MEM_SHARED;
1932
1933    if ((pEnt->entityProp & NEED_IO_SHARED)
1934	&& (!(pEnt->entityProp & NEED_IO)))
1935	pEnt->entityProp &= ~(unsigned long)NEED_IO_SHARED;
1936}
1937
1938void
1939xf86PostPreInit()
1940{
1941  if (doFramebufferMode) return;
1942
1943    if (xf86NumScreens > 1)
1944	needRAC = TRUE;
1945
1946    xf86MsgVerb(X_INFO, 3, "do I need RAC?");
1947
1948    if (needRAC) {
1949	xf86ErrorFVerb(3, "  Yes, I do.\n");
1950    } else {
1951	xf86ErrorFVerb(3, "  No, I don't.\n");
1952    }
1953
1954    xf86MsgVerb(X_INFO, 3, "resource ranges after preInit:\n");
1955    xf86PrintResList(3, Acc);
1956}
1957
1958void
1959xf86PostScreenInit(void)
1960{
1961    int i,j;
1962    ScreenPtr pScreen;
1963    unsigned int flags;
1964    int nummem = 0, numio = 0;
1965
1966    if (doFramebufferMode) {
1967	SetSIGIOForState(OPERATING);
1968	return;
1969    }
1970
1971#ifdef DEBUG
1972    ErrorF("PostScreenInit  generation: %i\n",serverGeneration);
1973#endif
1974    if (serverGeneration == 1) {
1975	checkRoutingForScreens(OPERATING);
1976	for (i=0; i<xf86NumEntities; i++) {
1977	    checkRequiredResources(i);
1978	}
1979
1980	/*
1981	 * after removing NEED_XXX_SHARED from entities that
1982	 * don't need need XXX resources at all we might have
1983	 * a single entity left that has NEED_XXX_SHARED set.
1984	 * In this case we can delete that, too.
1985	 */
1986	for (i = 0; i < xf86NumEntities; i++) {
1987	    if (xf86Entities[i]->entityProp & NEED_MEM_SHARED)
1988		nummem++;
1989	    if (xf86Entities[i]->entityProp & NEED_IO_SHARED)
1990		numio++;
1991	}
1992	for (i = 0; i < xf86NumEntities; i++) {
1993	    if (nummem < 2)
1994		xf86Entities[i]->entityProp &= ~NEED_MEM_SHARED;
1995	    if (numio < 2)
1996		xf86Entities[i]->entityProp &= ~NEED_IO_SHARED;
1997	}
1998    }
1999
2000    if (xf86Screens && needRAC) {
2001	int needRACforVga = 0;
2002
2003	for (i = 0; i < xf86NumScreens; i++) {
2004	    for (j = 0; j < xf86Screens[i]->numEntities; j++) {
2005		if (xf86Entities[xf86Screens[i]->entityList[j]]->entityProp
2006		    & NEED_VGA_ROUTED) {
2007		    needRACforVga ++;
2008		    break; /* only count each screen once */
2009		}
2010	    }
2011	}
2012
2013	for (i = 0; i < xf86NumScreens; i++) {
2014	    Bool needRACforMem = FALSE, needRACforIo = FALSE;
2015
2016	    for (j = 0; j < xf86Screens[i]->numEntities; j++) {
2017		if (xf86Entities[xf86Screens[i]->entityList[j]]->entityProp
2018		    & NEED_MEM_SHARED)
2019		    needRACforMem = TRUE;
2020		if (xf86Entities[xf86Screens[i]->entityList[j]]->entityProp
2021		    & NEED_IO_SHARED)
2022		    needRACforIo = TRUE;
2023		/*
2024		 * We may need RAC although we don't share any resources
2025		 * as we need to route VGA to the correct bus. This can
2026		 * only be done simultaniously for MEM and IO.
2027		 */
2028		if (needRACforVga > 1) {
2029		    if (xf86Entities[xf86Screens[i]->entityList[j]]->entityProp
2030			& NEED_VGA_MEM)
2031			needRACforMem = TRUE;
2032		    if (xf86Entities[xf86Screens[i]->entityList[j]]->entityProp
2033			& NEED_VGA_IO)
2034			needRACforIo = TRUE;
2035		}
2036	    }
2037
2038	    pScreen = xf86Screens[i]->pScreen;
2039	    flags = 0;
2040	    if (needRACforMem) {
2041		flags |= xf86Screens[i]->racMemFlags;
2042		xf86ErrorFVerb(3, "Screen %d is using RAC for mem\n", i);
2043	    }
2044	    if (needRACforIo) {
2045		flags |= xf86Screens[i]->racIoFlags;
2046		xf86ErrorFVerb(3, "Screen %d is using RAC for io\n", i);
2047	    }
2048
2049	    xf86RACInit(pScreen,flags);
2050	}
2051    }
2052
2053    xf86EnterServerState(OPERATING);
2054
2055}
2056
2057/*
2058 * Sets
2059 */
2060
2061
2062static resPtr
2063decomposeSparse(resRange range)
2064{
2065    resRange new;
2066    resPtr ret = NULL;
2067    memType val = range.rBegin;
2068    int i = 0;
2069
2070    new.type = (range.type & ~ResExtMask) | ResSparse;
2071
2072    while (1) {
2073	if (val & 0x01) {
2074	    new.rBase = (val << i);
2075	    new.rMask = ~((1 << i) - 1);
2076	    ret = xf86AddResToList(ret,&new,-1);
2077	    val ++;
2078	}
2079	i++;
2080	val >>= 1;
2081	if ((((val + 1) << i) - 1) > range.rEnd)
2082	    break;
2083    }
2084    i--;
2085    val <<= 1;
2086
2087    while (1) {
2088	if((((val + 1) << i) - 1)> range.rEnd) {
2089	    if (--i < 0) break;
2090	    val <<= 1;
2091	} else {
2092	    new.rBase = (val << i);
2093	    new.rMask = ~((1 << i) - 1);
2094	    val++;
2095	    ret = xf86AddResToList(ret,&new,-1);
2096	}
2097    }
2098    return ret;
2099}
2100
2101static Bool
2102x_isSubsetOf(resRange range, resPtr list1, resPtr list2)
2103{
2104    resRange range1, range2;
2105    memType m1_A_m2;
2106    Bool ret;
2107    resPtr list;
2108
2109    if (list1) {
2110	list = list1;
2111	if ((range.type & ResTypeMask) == (list->res_type & ResTypeMask)) {
2112	    switch (range.type & ResExtMask) {
2113	    case ResBlock:
2114		if ((list->res_type & ResExtMask) == ResBlock) {
2115		    if (range.rBegin >= list->block_begin
2116			&& range.rEnd <= list->block_end)
2117			return TRUE;
2118		    else if (range.rBegin < list->block_begin
2119			     && range.rEnd > list->block_end) {
2120			RANGE(range1, range.rBegin, list->block_begin - 1,
2121			      range.type);
2122			RANGE(range2, list->block_end + 1, range.rEnd,
2123			      range.type);
2124			return (x_isSubsetOf(range1,list->next,list2) &&
2125				x_isSubsetOf(range2,list->next,list2));
2126		    }
2127		    else if (range.rBegin >= list->block_begin
2128			     && range.rBegin <= list->block_end) {
2129			RANGE(range1, list->block_end + 1, range.rEnd,
2130			      range.type);
2131			return (x_isSubsetOf(range1,list->next,list2));
2132		    } else if (range.rEnd >= list->block_begin
2133			       && range.rEnd <= list->block_end) {
2134			RANGE(range1,range.rBegin, list->block_begin - 1,
2135			      range.type);
2136			return (x_isSubsetOf(range1,list->next,list2));
2137		    }
2138		}
2139		break;
2140	    case ResSparse:
2141		if ((list->res_type & ResExtMask) == ResSparse) {
2142		    memType test;
2143		    int i;
2144
2145		    m1_A_m2 = range.rMask & list->sparse_mask;
2146		    if ((range.rBase ^ list->sparse_base) & m1_A_m2)
2147			break;
2148		    /*
2149		     * We use the following system:
2150		     * let 0 ^= mask:1 base:0, 1 ^= mask:1 base:1,
2151		     * X mask:0 ; S: set TSS: test set for subset
2152		     * NTSS: new test set after test
2153		     *    S: 1   0   1   0   X   X   0   1   X
2154		     *  TSS: 1   0   0   1   1   0   X   X   X
2155		     *    T: 0   0   1   1   0   0   0   0   0
2156		     * NTSS: 1   0  0/X  1/X 1   0   1   0   X
2157		     *    R: 0   0   0   0   0   0   1   1   0
2158		     * If R != 0 TSS and S are disjunct
2159		     * If R == 0 TSS is subset of S
2160		     * If R != 0 NTSS contains elements from TSS
2161		     * which are not also members of S.
2162		     * If a T is set one of the correspondig bits
2163		     * in NTSS must be set to the specified value
2164		     * all other are X
2165		     */
2166		    test = list->sparse_mask & ~range.rMask;
2167		    if (test == 0)
2168			return TRUE;
2169		    for (i = 0; i < sizeof(memType); i++) {
2170			if ((test >> i) & 0x1) {
2171			    RANGE(range1, ((range.rBase & list->sparse_base)
2172				  | (range.rBase & ~list->sparse_mask)
2173				  | ((~list->sparse_base & list->sparse_mask)
2174				     & ~range.rMask)) & range1.rMask,
2175				  ((range.rMask | list->sparse_mask) & ~test)
2176				  | (1 << i), range.type);
2177			    return (x_isSubsetOf(range1,list->next,list2));
2178			}
2179		    }
2180		}
2181		break;
2182	    }
2183	}
2184	return (x_isSubsetOf(range,list->next,list2));
2185    } else if (list2) {
2186	resPtr tmpList = NULL;
2187	switch (range.type & ResExtMask) {
2188	case ResBlock:
2189	    tmpList = decomposeSparse(range);
2190	    while (tmpList) {
2191		if (!x_isSubsetOf(tmpList->val,list2,NULL)) {
2192		    xf86FreeResList(tmpList);
2193		    return FALSE;
2194		}
2195		tmpList = tmpList->next;
2196	    }
2197	    xf86FreeResList(tmpList);
2198	    return TRUE;
2199	    break;
2200	case ResSparse:
2201	    while (list2) {
2202		tmpList = xf86JoinResLists(tmpList,decomposeSparse(list2->val));
2203		list2 = list2->next;
2204	    }
2205	    ret = x_isSubsetOf(range,tmpList,NULL);
2206	    xf86FreeResList(tmpList);
2207	    return ret;
2208	    break;
2209	}
2210    } else
2211	return FALSE;
2212
2213    return FALSE;
2214}
2215
2216Bool
2217xf86IsSubsetOf(resRange range, resPtr list)
2218{
2219    resPtr dup = xf86DupResList(list);
2220    resPtr r_sp = NULL, r = NULL, tmp = NULL;
2221    Bool ret = FALSE;
2222
2223    while (dup) {
2224	tmp = dup;
2225	dup = dup->next;
2226	switch (tmp->res_type & ResExtMask) {
2227	case ResBlock:
2228	    tmp->next = r;
2229	    r = tmp;
2230	    break;
2231	case ResSparse:
2232	    tmp->next = r_sp;
2233	    r_sp = tmp;
2234	    break;
2235	}
2236    }
2237
2238    switch (range.type & ResExtMask) {
2239    case ResBlock:
2240	ret = x_isSubsetOf(range,r,r_sp);
2241	break;
2242    case ResSparse:
2243	ret = x_isSubsetOf(range,r_sp,r);
2244	break;
2245    }
2246    xf86FreeResList(r);
2247    xf86FreeResList(r_sp);
2248
2249    return ret;
2250}
2251
2252static resPtr
2253findIntersect(resRange Range, resPtr list)
2254{
2255    resRange range;
2256    resPtr new = NULL;
2257
2258    while (list) {
2259	    if ((Range.type & ResTypeMask) == (list->res_type & ResTypeMask)) {
2260		switch (Range.type & ResExtMask) {
2261		case ResBlock:
2262		    switch (list->res_type & ResExtMask) {
2263		    case ResBlock:
2264			if (Range.rBegin >= list->block_begin)
2265			    range.rBegin = Range.rBegin;
2266			else
2267			    range.rBegin = list->block_begin;
2268			if (Range.rEnd <= list->block_end)
2269			    range.rEnd = Range.rEnd;
2270			else
2271			    range.rEnd = list->block_end;
2272			if (range.rEnd > range.rBegin) {
2273			    range.type = Range.type;
2274			    new = xf86AddResToList(new,&range,-1);
2275			}
2276			break;
2277		    case ResSparse:
2278			new = xf86JoinResLists(new,xf86FindIntersectOfLists(new,decomposeSparse(list->val)));
2279			break;
2280		    }
2281		    break;
2282		case ResSparse:
2283		    switch (list->res_type & ResExtMask) {
2284		    case ResSparse:
2285			if (!((~(range.rBase ^ list->sparse_base)
2286			    & (range.rMask & list->sparse_mask)))) {
2287			    RANGE(range, (range.rBase & list->sparse_base)
2288				  | (~range.rMask & list->sparse_base)
2289				  | (~list->sparse_mask & range.rBase),
2290				  range.rMask | list->sparse_mask,
2291				  Range.type);
2292			    new = xf86AddResToList(new,&range,-1);
2293			}
2294			break;
2295		    case ResBlock:
2296			new = xf86JoinResLists(new,xf86FindIntersectOfLists(
2297			    decomposeSparse(range),list));
2298			break;
2299		    }
2300		}
2301	    }
2302	list = list->next;
2303    }
2304    return new;
2305}
2306
2307resPtr
2308xf86FindIntersectOfLists(resPtr l1, resPtr l2)
2309{
2310    resPtr ret = NULL;
2311
2312    while (l1) {
2313	ret = xf86JoinResLists(ret,findIntersect(l1->val,l2));
2314	l1 = l1->next;
2315    }
2316    return ret;
2317}
2318
2319#if 0	/* Not used */
2320static resPtr
2321xf86FindComplement(resRange Range)
2322{
2323    resRange range;
2324    memType tmp;
2325    resPtr new = NULL;
2326    int i;
2327
2328    switch (Range.type & ResExtMask) {
2329    case ResBlock:
2330	if (Range.rBegin > 0) {
2331	    RANGE(range, 0, Range.rBegin - 1, Range.type);
2332	    new = xf86AddResToList(new,&range,-1);
2333	}
2334	if (Range.rEnd < (memType)~0) {
2335	    RANGE(range,Range.rEnd + 1, (memType)~0, Range.type);
2336	    new = xf86AddResToList(new,&range,-1);
2337	}
2338	break;
2339    case ResSparse:
2340	tmp = Range.rMask;
2341	for (i = 0; i < sizeof(memType); i++) {
2342	    if (tmp & 0x1) {
2343		RANGE(range,(~Range.rMask & range.rMask),(1 << i), Range.type);
2344		new = xf86AddResToList(new,&range,-1);
2345	    }
2346	}
2347	break;
2348    default:
2349	break;
2350    }
2351    return new;
2352}
2353#endif
2354
2355resPtr
2356xf86ExtractTypeFromList(resPtr list, unsigned long type)
2357{
2358    resPtr ret = NULL;
2359
2360    while (list) {
2361	if ((list->res_type & ResTypeMask) == type)
2362	    ret = xf86AddResToList(ret,&(list->val),list->entityIndex);
2363	list = list->next;
2364    }
2365    return ret;
2366}
2367
2368/*
2369 * xf86FindPrimaryDevice() - Find the display device which
2370 * was active when the server was started.
2371 */
2372void
2373xf86FindPrimaryDevice()
2374{
2375    if (primaryBus.type != BUS_NONE) {
2376	char *bus;
2377	char loc[16];
2378
2379	switch (primaryBus.type) {
2380	case BUS_PCI:
2381	    bus = "PCI";
2382	    snprintf(loc, sizeof(loc), " %2.2x@%2.2x:%2.2x:%1.1x",
2383		     primaryBus.id.pci->bus,
2384		     primaryBus.id.pci->domain,
2385		     primaryBus.id.pci->dev,
2386		     primaryBus.id.pci->func);
2387	    break;
2388	case BUS_SBUS:
2389	    bus = "SBUS";
2390	    snprintf(loc, sizeof(loc), " %2.2x", primaryBus.id.sbus.fbNum);
2391	    break;
2392	default:
2393	    bus = "";
2394	    loc[0] = '\0';
2395	}
2396
2397	xf86MsgVerb(X_INFO, 2, "Primary Device is: %s%s\n",bus,loc);
2398    }
2399}
2400
2401Bool
2402xf86NoSharedResources(int screenIndex,resType res)
2403{
2404    int j;
2405
2406    if (screenIndex > xf86NumScreens)
2407	return TRUE;
2408
2409    for (j = 0; j < xf86Screens[screenIndex]->numEntities; j++) {
2410      switch (res) {
2411      case IO:
2412	if ( xf86Entities[xf86Screens[screenIndex]->entityList[j]]->entityProp
2413	     & NEED_IO_SHARED)
2414	  return FALSE;
2415	break;
2416      case MEM:
2417	if ( xf86Entities[xf86Screens[screenIndex]->entityList[j]]->entityProp
2418	     & NEED_MEM_SHARED)
2419	  return FALSE;
2420	break;
2421      case MEM_IO:
2422	if ( xf86Entities[xf86Screens[screenIndex]->entityList[j]]->entityProp
2423	     & NEED_SHARED)
2424	  return FALSE;
2425	break;
2426      case NONE:
2427	break;
2428      }
2429    }
2430    return TRUE;
2431}
2432
2433_X_EXPORT void
2434xf86RegisterStateChangeNotificationCallback(xf86StateChangeNotificationCallbackFunc func, pointer arg)
2435{
2436    StateChangeNotificationPtr ptr =
2437	(StateChangeNotificationPtr)xnfalloc(sizeof(StateChangeNotificationRec));
2438
2439    ptr->func = func;
2440    ptr->arg = arg;
2441    ptr->next = StateChangeNotificationList;
2442    StateChangeNotificationList = ptr;
2443}
2444
2445_X_EXPORT Bool
2446xf86DeregisterStateChangeNotificationCallback(xf86StateChangeNotificationCallbackFunc func)
2447{
2448    StateChangeNotificationPtr *ptr = &StateChangeNotificationList;
2449    StateChangeNotificationPtr tmp;
2450
2451    while (*ptr) {
2452	if ((*ptr)->func == func) {
2453	    tmp = (*ptr);
2454	    (*ptr) = (*ptr)->next;
2455	    xfree(tmp);
2456	    return TRUE;
2457	}
2458	ptr = &((*ptr)->next);
2459    }
2460    return FALSE;
2461}
2462
2463static void
2464notifyStateChange(xf86NotifyState state)
2465{
2466    StateChangeNotificationPtr ptr = StateChangeNotificationList;
2467    while (ptr) {
2468	ptr->func(state,ptr->arg);
2469	ptr = ptr->next;
2470    }
2471}
2472
2473/* Multihead accel sharing accessor functions and entity Private handling */
2474
2475_X_EXPORT int
2476xf86GetLastScrnFlag(int entityIndex)
2477{
2478    if(entityIndex < xf86NumEntities) {
2479        return(xf86Entities[entityIndex]->lastScrnFlag);
2480    } else {
2481        return -1;
2482    }
2483}
2484
2485_X_EXPORT void
2486xf86SetLastScrnFlag(int entityIndex, int scrnIndex)
2487{
2488    if(entityIndex < xf86NumEntities) {
2489        xf86Entities[entityIndex]->lastScrnFlag = scrnIndex;
2490    }
2491}
2492
2493_X_EXPORT Bool
2494xf86IsEntityShared(int entityIndex)
2495{
2496    if(entityIndex < xf86NumEntities) {
2497        if(xf86Entities[entityIndex]->entityProp & IS_SHARED_ACCEL) {
2498	    return TRUE;
2499	}
2500    }
2501    return FALSE;
2502}
2503
2504_X_EXPORT void
2505xf86SetEntityShared(int entityIndex)
2506{
2507    if(entityIndex < xf86NumEntities) {
2508        xf86Entities[entityIndex]->entityProp |= IS_SHARED_ACCEL;
2509    }
2510}
2511
2512_X_EXPORT Bool
2513xf86IsEntitySharable(int entityIndex)
2514{
2515    if(entityIndex < xf86NumEntities) {
2516        if(xf86Entities[entityIndex]->entityProp & ACCEL_IS_SHARABLE) {
2517	    return TRUE;
2518	}
2519    }
2520    return FALSE;
2521}
2522
2523_X_EXPORT void
2524xf86SetEntitySharable(int entityIndex)
2525{
2526    if(entityIndex < xf86NumEntities) {
2527        xf86Entities[entityIndex]->entityProp |= ACCEL_IS_SHARABLE;
2528    }
2529}
2530
2531_X_EXPORT Bool
2532xf86IsPrimInitDone(int entityIndex)
2533{
2534    if(entityIndex < xf86NumEntities) {
2535        if(xf86Entities[entityIndex]->entityProp & SA_PRIM_INIT_DONE) {
2536	    return TRUE;
2537	}
2538    }
2539    return FALSE;
2540}
2541
2542_X_EXPORT void
2543xf86SetPrimInitDone(int entityIndex)
2544{
2545    if(entityIndex < xf86NumEntities) {
2546        xf86Entities[entityIndex]->entityProp |= SA_PRIM_INIT_DONE;
2547    }
2548}
2549
2550_X_EXPORT void
2551xf86ClearPrimInitDone(int entityIndex)
2552{
2553    if(entityIndex < xf86NumEntities) {
2554        xf86Entities[entityIndex]->entityProp &= ~SA_PRIM_INIT_DONE;
2555    }
2556}
2557
2558
2559/*
2560 * Allocate a private in the entities.
2561 */
2562
2563_X_EXPORT int
2564xf86AllocateEntityPrivateIndex(void)
2565{
2566    int idx, i;
2567    EntityPtr pEnt;
2568    DevUnion *nprivs;
2569
2570    idx = xf86EntityPrivateCount++;
2571    for (i = 0; i < xf86NumEntities; i++) {
2572	pEnt = xf86Entities[i];
2573	nprivs = xnfrealloc(pEnt->entityPrivates,
2574			    xf86EntityPrivateCount * sizeof(DevUnion));
2575	/* Zero the new private */
2576	bzero(&nprivs[idx], sizeof(DevUnion));
2577	pEnt->entityPrivates = nprivs;
2578    }
2579    return idx;
2580}
2581
2582_X_EXPORT DevUnion *
2583xf86GetEntityPrivate(int entityIndex, int privIndex)
2584{
2585    if (entityIndex >= xf86NumEntities || privIndex >= xf86EntityPrivateCount)
2586	return NULL;
2587
2588    return &(xf86Entities[entityIndex]->entityPrivates[privIndex]);
2589}
2590
2591