
# Author : Manuel Teira <manuel.teira@telefonica.net> (sirfred in #oe)
# Description: Support for multiple memory video zones in kdrive. Make offscreen
# areas aware of the memory video zone it belongs to. Change the fbdev driver to
# honour this new model.

#
# Patch managed by http://www.holgerschurig.de/patcher.html
#

--- xorg-server-X11R7.1-1.1.0.orig/hw/kdrive/src/kdrive.c~kdrive-vidmemarea
+++ xorg-server-X11R7.1-1.1.0.orig/hw/kdrive/src/kdrive.c
@@ -908,9 +908,10 @@
         ret = (*pScreen->CloseScreen) (index, pScreen);
     else
 	ret = TRUE;
-    
-    if (screen->off_screen_base < screen->memory_size)
-	KdOffscreenFini (pScreen);
+
+    if (KdHasOffscreen(screen)) {
+        KdOffscreenFini(pScreen);
+    }
     
     if (pScreenPriv->dpmsState != KD_DPMS_NORMAL)
 	(*card->cfuncs->dpms) (pScreen, KD_DPMS_NORMAL);
@@ -1219,8 +1220,9 @@
 	if (!(*card->cfuncs->initAccel) (pScreen))
 	    screen->dumb = TRUE;
 
-    if (screen->off_screen_base < screen->memory_size)
-	KdOffscreenInit (pScreen);
+    if (KdHasOffscreen(screen)) {
+        KdOffscreenInit(pScreen);
+    }
     
 #ifdef PSEUDO8
     (void) p8Init (pScreen, PSEUDO8_USE_DEFAULT);
--- xorg-server-X11R7.1-1.1.0.orig/hw/kdrive/src/kdrive.h~kdrive-vidmemarea
+++ xorg-server-X11R7.1-1.1.0.orig/hw/kdrive/src/kdrive.h
@@ -63,6 +63,9 @@
 #define KD_MAX_CARD_ADDRESS 8
 #endif
 
+#define KD_VIDMEM_MINPRIO 0
+#define KD_VIDMEM_MAXPRIO 255
+
 /*
  * Configuration information per video card
  */
@@ -115,6 +118,13 @@
 
 typedef void (*KdOffscreenSaveProc) (ScreenPtr pScreen, KdOffscreenArea *area);
 
+typedef struct _KdVideoMemArea {
+    CARD8  priority;
+    CARD8 *base;
+    CARD32 size;
+    CARD32 available_offset;
+} KdVideoMemArea;
+
 typedef enum _KdOffscreenState {
     KdOffscreenAvail,
     KdOffscreenRemovable,
@@ -127,7 +137,8 @@
     int			size;
     int			score;
     pointer		privData;
-    
+    KdVideoMemArea      *vidmem;
+    int                 pool;
     KdOffscreenSaveProc save;
 
     KdOffscreenState	state;
@@ -138,6 +149,7 @@
 #define RR_Rotate_All	(RR_Rotate_0|RR_Rotate_90|RR_Rotate_180|RR_Rotate_270)
 #define RR_Reflect_All	(RR_Reflect_X|RR_Reflect_Y)
 
+
 typedef struct _KdScreenInfo {
     struct _KdScreenInfo    *next;
     KdCardInfo	*card;
@@ -155,9 +167,8 @@
     int		mynum;
     DDXPointRec	origin;
     KdFrameBuffer   fb[KD_MAX_FB];
-    CARD8	*memory_base;
-    unsigned long   memory_size;
-    unsigned long   off_screen_base;
+    KdVideoMemArea **videomem_areas;
+    int             num_videomem_areas;
 } KdScreenInfo;
 
 typedef struct _KdCardFuncs {
@@ -187,7 +198,6 @@
 
     void        (*getColors) (ScreenPtr, int, int, xColorItem *);
     void        (*putColors) (ScreenPtr, int, int, xColorItem *);
-
 } KdCardFuncs;
 
 #define KD_MAX_PSEUDO_DEPTH 8
@@ -203,7 +213,8 @@
 
     int		    dpmsState;
     
-    KdOffscreenArea *off_screen_areas;
+    KdOffscreenArea **offscreen_pools;
+    int             num_offscreen_pools;
 
     ColormapPtr     pInstalledmap[KD_MAX_FB];         /* current colormap */
     xColorItem      systemPalette[KD_MAX_PSEUDO_SIZE];/* saved windows colors */
@@ -881,6 +892,15 @@
 KdOffscreenInit (ScreenPtr pScreen);
 
 KdOffscreenArea *
+KdOffscreenAllocPrio (ScreenPtr pScreen, int size, int align,
+                      Bool locked,
+                      KdOffscreenSaveProc save,
+                      pointer privData,
+                      int minPriority,
+                      int maxPriority,
+                      Bool allowEviction);
+
+KdOffscreenArea *
 KdOffscreenAlloc (ScreenPtr pScreen, int size, int align,
 		  Bool locked,
 		  KdOffscreenSaveProc save,
--- xorg-server-X11R7.1-1.1.0.orig/hw/kdrive/src/kaa.c~kdrive-vidmemarea
+++ xorg-server-X11R7.1-1.1.0.orig/hw/kdrive/src/kaa.c
@@ -160,7 +160,7 @@
 		  pPixmap->drawable.width,
 		  pPixmap->drawable.height));
     pPixmap->devKind = pitch;
-    pPixmap->devPrivate.ptr = (pointer) ((CARD8 *) pScreenPriv->screen->memory_base + pKaaPixmap->area->offset);
+    pPixmap->devPrivate.ptr = (pointer) ((CARD8 *) pKaaPixmap->area->vidmem->base + pKaaPixmap->area->offset);
     pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
     return TRUE;
 }
@@ -198,7 +198,7 @@
 
     dst = pPixmap->devPrivate.ptr;
     dst_pitch = pPixmap->devKind;
-    
+
     bytes = src_pitch < dst_pitch ? src_pitch : dst_pitch;
 
     kaaWaitSync (pPixmap->drawable.pScreen);
@@ -336,10 +336,16 @@
 {
     ScreenPtr	pScreen = p->drawable.pScreen;
     KdScreenPriv(pScreen);
+    int index;
 
-    return ((unsigned long) ((CARD8 *) p->devPrivate.ptr - 
-			     (CARD8 *) pScreenPriv->screen->memory_base) <
-	    pScreenPriv->screen->memory_size);
+    for (index = 0; index < pScreenPriv->screen->num_videomem_areas; index++) {
+        KdVideoMemArea *vidmem = pScreenPriv->screen->videomem_areas[index];
+        if ((((CARD8 *)p->devPrivate.ptr) >= vidmem->base) &&
+            (((CARD8 *)p->devPrivate.ptr) <= (vidmem->base + vidmem->size))) {
+            return TRUE;
+        }
+    }
+    return FALSE;
 }
 
 PixmapPtr
@@ -1060,6 +1066,7 @@
     KdCheckPaintWindow (pWin, pRegion, what);
 }
 
+
 Bool
 kaaDrawInit (ScreenPtr		pScreen,
 	     KaaScreenInfoPtr	pScreenInfo)
@@ -1109,7 +1116,7 @@
      * Hookup offscreen pixmaps
      */
     if ((pKaaScr->info->flags & KAA_OFFSCREEN_PIXMAPS) &&
-	screen->off_screen_base < screen->memory_size)
+	KdHasOffscreen(screen))
     {
 	if (!AllocatePixmapPrivate(pScreen, kaaPixmapPrivateIndex,
 				   sizeof (KaaPixmapPrivRec)))
--- xorg-server-X11R7.1-1.1.0.orig/hw/kdrive/src/koffscreen.c~kdrive-vidmemarea
+++ xorg-server-X11R7.1-1.1.0.orig/hw/kdrive/src/koffscreen.c
@@ -41,16 +41,20 @@
 {
     KdScreenPriv (pScreen);
     KdOffscreenArea *prev = 0, *area;
-
-    assert (pScreenPriv->screen->off_screen_areas->area.offset == 0);
-    for (area = pScreenPriv->off_screen_areas; area; area = area->next)
-    {
-	if (prev)
-	    assert (prev->offset + prev->size == area->offset);
+    int index;
+    
+    for (index = 0; index < pScreenPriv->num_offscreen_pools; index++) {
+        area = pScreenPriv->offscreen_pools[index];
+        assert (area->vidmem->available_offset - area.offset == 0);
+        while(area) {
+            if (prev)
+                assert (prev->offset + prev->size == area->offset);
 	    
-	prev = area;
+            prev = area;
+            area = area->next;
+        }
+        assert (prev->offset + prev->size == prev->vidmem->size);
     }
-    assert (prev->offset + prev->size == pScreenPriv->screen->memory_size);
 }
 #else
 #define KdOffscreenValidate(s)
@@ -65,101 +69,133 @@
 }
 
 KdOffscreenArea *
-KdOffscreenAlloc (ScreenPtr pScreen, int size, int align,
-		  Bool locked,
-		  KdOffscreenSaveProc save,
-		  pointer privData)
+KdOffscreenAllocPrio (ScreenPtr pScreen, int size, int align,
+                      Bool locked,
+                      KdOffscreenSaveProc save,
+                      pointer privData,
+                      int minPriority,
+                      int maxPriority,
+                      Bool allowEviction)
 {
     KdOffscreenArea *area, *begin, *best;
     KdScreenPriv (pScreen);
     int tmp, real_size = 0, best_score;
+    int index;
+    Bool canFit = FALSE;
 
-    KdOffscreenValidate (pScreen);
     if (!align)
 	align = 1;
 
     if (!size)
     {
-	DBG_OFFSCREEN (("Alloc 0x%x -> EMPTY\n", size));
+	DBG_OFFSCREEN(("Alloc 0x%x -> EMPTY\n", size));
 	return NULL;
     }
 
     /* throw out requests that cannot fit */
-    if (size > (pScreenPriv->screen->memory_size - pScreenPriv->screen->off_screen_base))
-    {
-	DBG_OFFSCREEN (("Alloc 0x%x -> TOBIG\n", size));
-	return NULL;
+    for (index = 0; index < pScreenPriv->screen->num_videomem_areas; index++) {
+        KdVideoMemArea *vidmem = pScreenPriv->screen->videomem_areas[index];
+        if ((vidmem->priority <= maxPriority) && 
+            (vidmem->priority >= minPriority)) {
+            if (size <= (vidmem->size - vidmem->available_offset)) {
+                canFit = TRUE;
+                break;
+            }
+        }
     }
-    
-    /* Try to find a free space that'll fit. */
-    for (area = pScreenPriv->off_screen_areas; area; area = area->next)
+    if (!canFit)
     {
-	/* skip allocated areas */
-	if (area->state != KdOffscreenAvail)
-	    continue;
+        DBG_OFFSCREEN(("Alloc 0x%x -> TOOBIG\n", size));
+        return NULL;
+    }
 
-	/* adjust size to match alignment requirement */
-	real_size = size;
-	tmp = area->offset % align;
-	if (tmp)
-	    real_size += (align - tmp);
-	
-	/* does it fit? */
-	if (real_size <= area->size)
-	    break;
+    for (index = 0; index < pScreenPriv->num_offscreen_pools; index++) {
+        /* Look just in the head, as all the areas of the pool have
+           the same vidmem */
+        area = pScreenPriv->offscreen_pools[index];
+        if ((area->vidmem->priority > maxPriority) || 
+            (area->vidmem->priority < minPriority))
+            continue;
+
+        /* Try to find a free space that'll fit. */
+        for (area = pScreenPriv->offscreen_pools[index]; area;
+             area = area->next) {
+            /* skip allocated areas */
+            if (area->state != KdOffscreenAvail)
+                continue;
+            
+            /* adjust size to match alignment requirement */
+            real_size = size;
+            tmp = area->offset % align;
+            if (tmp)
+                real_size += (align - tmp);
+            
+            /* does it fit? */
+            if (real_size <= area->size)
+                break;
+        }
+        if (area)
+            break;
     }
-    
-    if (!area)
-    {
+
+    if (!area && allowEviction) {
 	/* 
 	 * Kick out existing users to make space.
 	 *
 	 * First, locate a region which can hold the desired object.
 	 */
+        for (index = 0; index < pScreenPriv->num_offscreen_pools; index++) {
+            if ((area->vidmem->priority > maxPriority) || 
+                (area->vidmem->priority < minPriority))
+                continue;
 	
-	/* prev points at the first object to boot */
-	best = NULL;
-	best_score = MAXINT;
-	for (begin = pScreenPriv->off_screen_areas; begin != NULL;
-	     begin = begin->next)
-	{
-	    int avail, score;
-	    KdOffscreenArea *scan;
+            /* prev points at the first object to boot */
+            best = NULL;
+            best_score = MAXINT;
 
-	    if (begin->state == KdOffscreenLocked)
-		continue;
+            for (begin = pScreenPriv->offscreen_pools[index]; begin != NULL;
+                 begin = begin->next) {
+                int avail, score;
+                KdOffscreenArea *scan;
 
-	    /* adjust size to match alignment requirement */
-	    real_size = size;
-	    tmp = begin->offset % align;
-	    if (tmp)
-		real_size += (align - tmp);
+                if (begin->state == KdOffscreenLocked)
+                    continue;
+
+                /* adjust size to match alignment requirement */
+                real_size = size;
+                tmp = begin->offset % align;
+                if (tmp)
+                    real_size += (align - tmp);
 	    
-	    avail = 0;
-	    score = 0;
-	    /* now see if we can make room here, and how "costly" it'll be. */
-	    for (scan = begin; scan != NULL; scan = scan->next)
-	    {
-		if (scan->state == KdOffscreenLocked) {
-		    /* Can't make room here, start after this locked area. */
-		    begin = scan->next;
-		    break;
-		}
-		/* Score should only be non-zero for KdOffscreenRemovable */
-		score += scan->score;
-		avail += scan->size;
-		if (avail >= real_size)
-		    break;
-	    }
-	    /* Is it the best option we've found so far? */
-	    if (avail >= real_size && score < best_score) {
-		best = begin;
-		best_score = score;
-	    }
-	}
-	area = best;
-	if (!area)
-	{
+                avail = 0;
+                score = 0;
+                /* now see if we can make room here, 
+                   and how "costly" it'll be. */
+                for (scan = begin; scan != NULL; scan = scan->next) {
+                    if (scan->state == KdOffscreenLocked) {
+                        /* Can't make room here, 
+                           start after this locked area. */
+                        begin = scan->next;
+                        break;
+                    }
+                    /* Score should only be non-zero for KdOffscreenRemovable */
+                    score += scan->score;
+                    avail += scan->size;
+                    if (avail >= real_size)
+                        break;
+                }
+                /* Is it the best option we've found so far? */
+                if (avail >= real_size && score < best_score) {
+                    best = begin;
+                    best_score = score;
+                }
+            }
+            area = best;
+            if (area) 
+                break;
+        }
+
+	if (!area) {
 	    DBG_OFFSCREEN (("Alloc 0x%x -> NOSPACE\n", size));
 	    /* Could not allocate memory */
 	    KdOffscreenValidate (pScreen);
@@ -180,16 +216,14 @@
 	/*
 	 * Now get the system to merge the other needed areas together
 	 */
-	while (area->size < real_size)
-	{
-	    assert (area->next && area->next->state == KdOffscreenRemovable);
+	while (area->size < real_size) {
+            assert (area->next && area->next->state == KdOffscreenRemovable);
 	    (void) KdOffscreenKickOut (pScreen, area->next);
 	}
     }
-    
+
     /* save extra space in new area */
-    if (real_size < area->size)
-    {
+    if (real_size < area->size) {
 	KdOffscreenArea   *new_area = xalloc (sizeof (KdOffscreenArea));
 	if (!new_area)
 	    return NULL;
@@ -198,9 +232,14 @@
 	new_area->state = KdOffscreenAvail;
 	new_area->save = 0;
 	new_area->score = 0;
+        new_area->vidmem = area->vidmem;
+        new_area->pool = area->pool;
 	new_area->next = area->next;
 	area->next = new_area;
 	area->size = real_size;
+        DBG_OFFSCREEN (("New OffscreenArea at %p (offset:0x%08x, size:0x%08x, pool:%d\n", area, area->offset, area->size, area->pool));
+
+
     }
     /*
      * Mark this area as in use
@@ -212,42 +251,80 @@
     area->privData = privData;
     area->save = save;
     area->score = 0;
-
+    
     area->save_offset = area->offset;
     {
 	int tmp = area->offset % align;
 	if (tmp)
 	    area->offset += (align - tmp);
     }
-
+    
     KdOffscreenValidate (pScreen);
     
     DBG_OFFSCREEN (("Alloc 0x%x -> 0x%x\n", size, area->offset));
     return area;
 }
 
+Bool
+KdHasOffscreen(KdScreenInfo *screen)
+{
+    int index;
+    DBG_OFFSCREEN (("KdHasOffscreen\n"));
+
+    for (index = 0; index < screen->num_videomem_areas; index++) {
+        KdVideoMemArea *vidmem = screen->videomem_areas[index];
+        if (vidmem->available_offset < vidmem->size) {
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+    
+KdOffscreenArea *
+KdOffscreenAlloc (ScreenPtr pScreen, int size, int align,
+		  Bool locked,
+		  KdOffscreenSaveProc save,
+		  pointer privData)
+{
+    DBG_OFFSCREEN (("KdOffscreenAlloc(size:%d, align:%d, locked:%d)\n",
+                    size, align, locked));
+    return KdOffscreenAllocPrio(pScreen, size, align,
+                                locked,
+                                save,
+                                privData,
+                                KD_VIDMEM_MINPRIO,
+                                KD_VIDMEM_MAXPRIO,
+                                TRUE);
+}
+
 void
 KdOffscreenSwapOut (ScreenPtr pScreen)
 {
     KdScreenPriv (pScreen);
+    int index;
+
+    DBG_OFFSCREEN (("KdOffscreenSwapOut\n"));
 
     KdOffscreenValidate (pScreen);
-    /* loop until a single free area spans the space */
-    for (;;)
-    {
-	KdOffscreenArea *area = pScreenPriv->off_screen_areas;
+
+    for (index = 0; index < pScreenPriv->num_offscreen_pools; index++) {
+        /* loop until a single free area spans the space */
+        for (;;)
+        {
+            KdOffscreenArea *area = pScreenPriv->offscreen_pools[index];
 	
-	if (!area)
-	    break;
-	if (area->state == KdOffscreenAvail)
-	{
-	    area = area->next;
-	    if (!area)
-		break;
-	}
-	assert (area->state != KdOffscreenAvail);
-	(void) KdOffscreenKickOut (pScreen, area);
-	KdOffscreenValidate (pScreen);
+            if (!area)
+                break;
+            if (area->state == KdOffscreenAvail)
+            {
+                area = area->next;
+                if (!area)
+                    break;
+            }
+            assert (area->state != KdOffscreenAvail);
+            (void) KdOffscreenKickOut (pScreen, area);
+            KdOffscreenValidate (pScreen);
+        }
     }    
     KdOffscreenValidate (pScreen);
     KdOffscreenFini (pScreen);
@@ -256,6 +333,8 @@
 void
 KdOffscreenSwapIn (ScreenPtr pScreen)
 {
+    KdScreenPriv (pScreen);
+    DBG_OFFSCREEN (("KdOffscreenSwapIn\n"));
     KdOffscreenInit (pScreen);
 }
 
@@ -264,7 +343,7 @@
 KdOffscreenMerge (KdOffscreenArea *area)
 {
     KdOffscreenArea	*next = area->next;
-
+    //DBG_OFFSCREEN (("KdOffscreenMerge %p\n", area));
     /* account for space */
     area->size += next->size;
     /* frob pointer */
@@ -278,8 +357,9 @@
     KdScreenPriv(pScreen);
     KdOffscreenArea	*next = area->next;
     KdOffscreenArea	*prev;
-    
-    DBG_OFFSCREEN (("Free 0x%x -> 0x%x\n", area->size, area->offset));
+
+    DBG_OFFSCREEN (("KdOffscreenFree 0x%x -> 0x%x\n", 
+                    area->size, area->offset));
     KdOffscreenValidate (pScreen);
 
     area->state = KdOffscreenAvail;
@@ -290,10 +370,11 @@
     /*
      * Find previous area
      */
-    if (area == pScreenPriv->off_screen_areas)
+    if (area == pScreenPriv->offscreen_pools[area->pool])
 	prev = 0;
     else
-	for (prev = pScreenPriv->off_screen_areas; prev; prev = prev->next)
+	for (prev = pScreenPriv->offscreen_pools[area->pool]; 
+             prev; prev = prev->next)
 	    if (prev->next == area)
 		break;
     
@@ -317,21 +398,30 @@
 {
     KaaPixmapPriv (pPixmap);
     KdScreenPriv (pPixmap->drawable.pScreen);
+    int index;
     static int iter = 0;
 
+
     if (!pKaaPixmap->area)
 	return;
 
+    /*
+    DBG_OFFSCREEN(("KdOffscreenMarkUsed(offset:0x%08x, pool:%d)\n", 
+                   pKaaPixmap->area->offset,
+                   pKaaPixmap->area->pool));
+    */
     /* The numbers here are arbitrary.  We may want to tune these. */
     pKaaPixmap->area->score += 100;
     if (++iter == 10) {
 	KdOffscreenArea *area;
-	for (area = pScreenPriv->off_screen_areas; area != NULL;
-	     area = area->next)
-	{
-	    if (area->state == KdOffscreenRemovable)
-		area->score = (area->score * 7) / 8;
-	}
+        for (index = 0; index < pScreenPriv->num_offscreen_pools; index++) {
+            for (area = pScreenPriv->offscreen_pools[index]; area != NULL;
+                 area = area->next)
+            {
+                if (area->state == KdOffscreenRemovable)
+                    area->score = (area->score * 7) / 8;
+            }
+        }
     }
 }
 
@@ -340,23 +430,41 @@
 {
     KdScreenPriv (pScreen);
     KdOffscreenArea *area;
+    KdVideoMemArea *vidmem;
+    int index, num_offscreen;
 
-    /* Allocate a big free area */
-    area = xalloc (sizeof (KdOffscreenArea));
+    DBG_OFFSCREEN (("KdOffscreenInit\n"));
+    num_offscreen = 0;
+    pScreenPriv->num_offscreen_pools = 0;
+    pScreenPriv->offscreen_pools = NULL;
 
-    if (!area)
-	return FALSE;
+    for (index = 0; index < pScreenPriv->screen->num_videomem_areas; index++) {
+        vidmem = pScreenPriv->screen->videomem_areas[index];
+        DBG_OFFSCREEN (("Searching vidmemarea base:0x%p, size:0x%08x, available_offset:0x%08x\n", vidmem->base, vidmem->size, vidmem->available_offset));
+        if (vidmem->available_offset < vidmem->size) {
+            pScreenPriv->offscreen_pools = xrealloc(pScreenPriv->offscreen_pools,
+                                                    sizeof(KdOffscreenArea*) * (pScreenPriv->num_offscreen_pools + 1));
+            if (!pScreenPriv->offscreen_pools) {
+                return FALSE;
+            }
+            pScreenPriv->offscreen_pools[pScreenPriv->num_offscreen_pools] =
+                area = xcalloc(sizeof(KdOffscreenArea), 1);
+            if (!area) 
+                return FALSE;
+
+            area->state = KdOffscreenAvail;
+            area->vidmem = vidmem;
+            area->offset = vidmem->available_offset;
+            area->size = vidmem->size - vidmem->available_offset;
+            area->save = 0;
+            area->pool = pScreenPriv->num_offscreen_pools;
+            area->next = NULL;
+            area->score = 0;
+            pScreenPriv->num_offscreen_pools++;
+            DBG_OFFSCREEN (("New OffscreenArea at %p (offset:0x%08x, size:0x%08x, pool:%d)\n", area, area->offset, area->size, area->pool));
+        }
+    }
 
-    area->state = KdOffscreenAvail;
-    area->offset = pScreenPriv->screen->off_screen_base;
-    area->size = pScreenPriv->screen->memory_size - area->offset;
-    area->save = 0;
-    area->next = NULL;
-    area->score = 0;
-    
-    /* Add it to the free areas */
-    pScreenPriv->off_screen_areas = area;
-    
     KdOffscreenValidate (pScreen);
 
     return TRUE;
@@ -367,11 +475,17 @@
 {
     KdScreenPriv (pScreen);
     KdOffscreenArea *area;
-    
-    /* just free all of the area records */
-    while ((area = pScreenPriv->off_screen_areas))
-    {
-	pScreenPriv->off_screen_areas = area->next;
-	xfree (area);
+    int index;
+
+    DBG_OFFSCREEN (("KdOffscreenFini\n"));
+    for (index = 0; index < pScreenPriv->num_offscreen_pools; index++) {
+        /* just free all of the area records */
+        while ((area = pScreenPriv->offscreen_pools[index])) {
+            pScreenPriv->offscreen_pools[index] = area->next;
+            xfree (area);
+        }
     }
+    xfree(pScreenPriv->offscreen_pools);
+    pScreenPriv->offscreen_pools = NULL;
+    pScreenPriv->num_offscreen_pools = 0;
 }
--- xorg-server-X11R7.1-1.1.0.orig/hw/kdrive/fbdev/fbdev.c~kdrive-vidmemarea
+++ xorg-server-X11R7.1-1.1.0.orig/hw/kdrive/fbdev/fbdev.c
@@ -330,6 +330,7 @@
     FbdevScrPriv	*scrpriv = screen->driver;
     KdMouseMatrix	m;
     FbdevPriv		*priv = screen->card->driver;
+    KdVideoMemArea      *vidmem;
 
     if (scrpriv->randr != RR_Rotate_0)
 	scrpriv->shadow = TRUE;
@@ -342,15 +343,20 @@
     
     screen->width = priv->var.xres;
     screen->height = priv->var.yres;
-    screen->memory_base = (CARD8 *) (priv->fb);
-    screen->memory_size = priv->fix.smem_len;
+    screen->videomem_areas = xcalloc(sizeof(KdVideoMemArea*), 1);
+    screen->videomem_areas[0] = vidmem = xcalloc(sizeof(KdVideoMemArea), 1);
+    screen->num_videomem_areas = 1;
+    
+    vidmem->priority = KD_VIDMEM_MINPRIO;
+    vidmem->base = (CARD8 *) (priv->fb);
+    vidmem->size = priv->fix.smem_len;
     
     if (scrpriv->shadow)
     {
 	if (!KdShadowFbAlloc (screen, 0, 
 			      scrpriv->randr & (RR_Rotate_90|RR_Rotate_270)))
 	    return FALSE;
-	screen->off_screen_base = screen->memory_size;
+        vidmem->available_offset = vidmem->size;
     }
     else
     {
@@ -358,7 +364,7 @@
         screen->fb[0].pixelStride = (priv->fix.line_length * 8 / 
     				 priv->var.bits_per_pixel);
         screen->fb[0].frameBuffer = (CARD8 *) (priv->fb);
-	screen->off_screen_base = screen->fb[0].byteStride * screen->height;
+	vidmem->available_offset = screen->fb[0].byteStride * screen->height;
     }
     
     return TRUE;
