xfree86: Remove {set,undo}WC from VidMemInfo
Now that mapMem is gone this can never actually get called. Reviewed-by: Eric Anholt <eric@anholt.net> Signed-off-by: Adam Jackson <ajax@redhat.com>
This commit is contained in:
		
							parent
							
								
									9db2af6f75
								
							
						
					
					
						commit
						ec0e29ed5b
					
				|  | @ -86,15 +86,8 @@ static int devMemFd = -1; | |||
| #endif | ||||
| 
 | ||||
| #ifdef HAS_MTRR_SUPPORT | ||||
| static void *setWC(int, unsigned long, unsigned long, Bool, MessageType); | ||||
| static void undoWC(int, void *); | ||||
| static Bool cleanMTRR(void); | ||||
| #endif | ||||
| #if defined(HAS_MTRR_BUILTIN) && defined(__NetBSD__) | ||||
| static void *NetBSDsetWC(int, unsigned long, unsigned long, Bool, | ||||
|                            MessageType); | ||||
| static void NetBSDundoWC(int, void *); | ||||
| #endif | ||||
| 
 | ||||
| /*
 | ||||
|  * Check if /dev/mem can be mmap'd.  If it can't print a warning when | ||||
|  | @ -192,15 +185,8 @@ xf86OSInitVidMem(VidMemInfoPtr pVidMem) | |||
| 
 | ||||
| #ifdef HAS_MTRR_SUPPORT | ||||
|     if (useDevMem) { | ||||
|         if (cleanMTRR()) { | ||||
|             pVidMem->setWC = setWC; | ||||
|             pVidMem->undoWC = undoWC; | ||||
|         } | ||||
|         cleanMTRR(); | ||||
|     } | ||||
| #endif | ||||
| #if defined(HAS_MTRR_BUILTIN) && defined(__NetBSD__) | ||||
|     pVidMem->setWC = NetBSDsetWC; | ||||
|     pVidMem->undoWC = NetBSDundoWC; | ||||
| #endif | ||||
|     pVidMem->initialised = TRUE; | ||||
| } | ||||
|  | @ -503,334 +489,4 @@ cleanMTRR() | |||
|     return TRUE; | ||||
| } | ||||
| 
 | ||||
| typedef struct x_RangeRec { | ||||
|     struct mem_range_desc mrd; | ||||
|     Bool wasWC; | ||||
|     struct x_RangeRec *next; | ||||
| } RangeRec, *RangePtr; | ||||
| 
 | ||||
| static void | ||||
| freeRangeList(RangePtr range) | ||||
| { | ||||
|     RangePtr rp; | ||||
| 
 | ||||
|     while (range) { | ||||
|         rp = range; | ||||
|         range = rp->next; | ||||
|         free(rp); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static RangePtr | ||||
| dupRangeList(RangePtr list) | ||||
| { | ||||
|     RangePtr new = NULL, rp, p; | ||||
| 
 | ||||
|     rp = list; | ||||
|     while (rp) { | ||||
|         p = xnfalloc(sizeof(RangeRec)); | ||||
|         *p = *rp; | ||||
|         p->next = new; | ||||
|         new = p; | ||||
|         rp = rp->next; | ||||
|     } | ||||
|     return new; | ||||
| } | ||||
| 
 | ||||
| static RangePtr | ||||
| sortRangeList(RangePtr list) | ||||
| { | ||||
|     RangePtr rp1, rp2, copy, sorted = NULL, minp, prev, minprev; | ||||
|     unsigned long minBase; | ||||
| 
 | ||||
|     /* Sort by base address */ | ||||
|     rp1 = copy = dupRangeList(list); | ||||
|     while (rp1) { | ||||
|         minBase = rp1->mrd.mr_base; | ||||
|         minp = rp1; | ||||
|         minprev = NULL; | ||||
|         prev = rp1; | ||||
|         rp2 = rp1->next; | ||||
|         while (rp2) { | ||||
|             if (rp2->mrd.mr_base < minBase) { | ||||
|                 minBase = rp2->mrd.mr_base; | ||||
|                 minp = rp2; | ||||
|                 minprev = prev; | ||||
|             } | ||||
|             prev = rp2; | ||||
|             rp2 = rp2->next; | ||||
|         } | ||||
|         if (minprev) { | ||||
|             minprev->next = minp->next; | ||||
|             rp1 = copy; | ||||
|         } | ||||
|         else { | ||||
|             rp1 = minp->next; | ||||
|         } | ||||
|         minp->next = sorted; | ||||
|         sorted = minp; | ||||
|     } | ||||
|     return sorted; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * findRanges returns a list of ranges that overlap the specified range. | ||||
|  */ | ||||
| 
 | ||||
| static void | ||||
| findRanges(unsigned long base, unsigned long size, RangePtr * ucp, | ||||
|            RangePtr * wcp) | ||||
| { | ||||
|     struct mem_range_desc *mrd; | ||||
|     int nmr, i; | ||||
|     RangePtr rp, *p; | ||||
| 
 | ||||
|     if (!(mrd = getAllRanges(&nmr))) | ||||
|         return; | ||||
| 
 | ||||
|     for (i = 0; i < nmr; i++) { | ||||
|         if ((mrd[i].mr_flags & MDF_ACTIVE) && | ||||
|             mrd[i].mr_base < base + size && | ||||
|             mrd[i].mr_base + mrd[i].mr_len > base) { | ||||
|             if (mrd[i].mr_flags & MDF_WRITECOMBINE) | ||||
|                 p = wcp; | ||||
|             else if (mrd[i].mr_flags & MDF_UNCACHEABLE) | ||||
|                 p = ucp; | ||||
|             else | ||||
|                 continue; | ||||
|             rp = xnfalloc(sizeof(RangeRec)); | ||||
|             rp->mrd = mrd[i]; | ||||
|             rp->next = *p; | ||||
|             *p = rp; | ||||
|         } | ||||
|     } | ||||
|     free(mrd); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * This checks if the existing overlapping ranges fully cover the requested | ||||
|  * range.  Is this overkill? | ||||
|  */ | ||||
| 
 | ||||
| static Bool | ||||
| fullCoverage(unsigned long base, unsigned long size, RangePtr overlap) | ||||
| { | ||||
|     RangePtr rp1, sorted = NULL; | ||||
|     unsigned long end; | ||||
| 
 | ||||
|     sorted = sortRangeList(overlap); | ||||
|     /* Look for gaps */ | ||||
|     rp1 = sorted; | ||||
|     end = base + size; | ||||
|     while (rp1) { | ||||
|         if (rp1->mrd.mr_base > base) { | ||||
|             freeRangeList(sorted); | ||||
|             return FALSE; | ||||
|         } | ||||
|         else { | ||||
|             base = rp1->mrd.mr_base + rp1->mrd.mr_len; | ||||
|         } | ||||
|         if (base >= end) { | ||||
|             freeRangeList(sorted); | ||||
|             return TRUE; | ||||
|         } | ||||
|         rp1 = rp1->next; | ||||
|     } | ||||
|     freeRangeList(sorted); | ||||
|     return FALSE; | ||||
| } | ||||
| 
 | ||||
| static void * | ||||
| addWC(int screenNum, unsigned long base, unsigned long size, MessageType from) | ||||
| { | ||||
|     RangePtr uc = NULL, wc = NULL, retlist = NULL; | ||||
|     struct mem_range_desc mrd; | ||||
|     struct mem_range_op mro; | ||||
| 
 | ||||
|     findRanges(base, size, &uc, &wc); | ||||
| 
 | ||||
|     /* See of the full range is already WC */ | ||||
|     if (!uc && fullCoverage(base, size, wc)) { | ||||
|         xf86DrvMsg(screenNum, from, | ||||
|                    "Write-combining range (0x%lx,0x%lx) was already set\n", | ||||
|                    base, size); | ||||
|         return NULL; | ||||
|     } | ||||
| 
 | ||||
|     /* Otherwise, try to add the new range */ | ||||
|     mrd.mr_base = base; | ||||
|     mrd.mr_len = size; | ||||
|     strcpy(mrd.mr_owner, X_MTRR_ID); | ||||
|     mrd.mr_flags = MDF_WRITECOMBINE; | ||||
|     mro.mo_desc = &mrd; | ||||
|     mro.mo_arg[0] = MEMRANGE_SET_UPDATE; | ||||
|     if (ioctl(devMemFd, MEMRANGE_SET, &mro)) { | ||||
|         xf86DrvMsg(screenNum, X_WARNING, | ||||
|                    "Failed to set write-combining range " | ||||
|                    "(0x%lx,0x%lx)\n", base, size); | ||||
|         return NULL; | ||||
|     } | ||||
|     else { | ||||
|         xf86DrvMsg(screenNum, from, | ||||
|                    "Write-combining range (0x%lx,0x%lx)\n", base, size); | ||||
|         retlist = xnfalloc(sizeof(RangeRec)); | ||||
|         retlist->mrd = mrd; | ||||
|         retlist->wasWC = FALSE; | ||||
|         retlist->next = NULL; | ||||
|         return retlist; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void * | ||||
| delWC(int screenNum, unsigned long base, unsigned long size, MessageType from) | ||||
| { | ||||
|     RangePtr uc = NULL, wc = NULL, retlist = NULL; | ||||
|     struct mem_range_desc mrd; | ||||
|     struct mem_range_op mro; | ||||
| 
 | ||||
|     findRanges(base, size, &uc, &wc); | ||||
| 
 | ||||
|     /*
 | ||||
|      * See of the full range is already not WC, or if there is full | ||||
|      * coverage from UC ranges. | ||||
|      */ | ||||
|     if (!wc || fullCoverage(base, size, uc)) { | ||||
|         xf86DrvMsg(screenNum, from, | ||||
|                    "Write-combining range (0x%lx,0x%lx) was already clear\n", | ||||
|                    base, size); | ||||
|         return NULL; | ||||
|     } | ||||
| 
 | ||||
|     /* Otherwise, try to add the new range */ | ||||
|     mrd.mr_base = base; | ||||
|     mrd.mr_len = size; | ||||
|     strcpy(mrd.mr_owner, X_MTRR_ID); | ||||
|     mrd.mr_flags = MDF_UNCACHEABLE; | ||||
|     mro.mo_desc = &mrd; | ||||
|     mro.mo_arg[0] = MEMRANGE_SET_UPDATE; | ||||
|     if (ioctl(devMemFd, MEMRANGE_SET, &mro)) { | ||||
|         xf86DrvMsg(screenNum, X_WARNING, | ||||
|                    "Failed to remove write-combining range " | ||||
|                    "(0x%lx,0x%lx)\n", base, size); | ||||
|         /* XXX Should then remove all of the overlapping WC ranges */ | ||||
|         return NULL; | ||||
|     } | ||||
|     else { | ||||
|         xf86DrvMsg(screenNum, from, | ||||
|                    "Removed Write-combining range (0x%lx,0x%lx)\n", base, size); | ||||
|         retlist = xnfalloc(sizeof(RangeRec)); | ||||
|         retlist->mrd = mrd; | ||||
|         retlist->wasWC = TRUE; | ||||
|         retlist->next = NULL; | ||||
|         return retlist; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void * | ||||
| setWC(int screenNum, unsigned long base, unsigned long size, Bool enable, | ||||
|       MessageType from) | ||||
| { | ||||
|     if (enable) | ||||
|         return addWC(screenNum, base, size, from); | ||||
|     else | ||||
|         return delWC(screenNum, base, size, from); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| undoWC(int screenNum, void *list) | ||||
| { | ||||
|     RangePtr rp; | ||||
|     struct mem_range_op mro; | ||||
|     Bool failed; | ||||
| 
 | ||||
|     rp = list; | ||||
|     while (rp) { | ||||
| #ifdef DEBUG | ||||
|         ErrorF("Undo for (0x%lx,0x%lx), %d\n", | ||||
|                (unsigned long) rp->mrd.mr_base, | ||||
|                (unsigned long) rp->mrd.mr_len, rp->wasWC); | ||||
| #endif | ||||
|         failed = FALSE; | ||||
|         if (rp->wasWC) { | ||||
|             mro.mo_arg[0] = MEMRANGE_SET_UPDATE; | ||||
|             rp->mrd.mr_flags = MDF_WRITECOMBINE; | ||||
|             strcpy(rp->mrd.mr_owner, "unknown"); | ||||
|         } | ||||
|         else { | ||||
|             mro.mo_arg[0] = MEMRANGE_SET_REMOVE; | ||||
|         } | ||||
|         mro.mo_desc = &rp->mrd; | ||||
| 
 | ||||
|         if (ioctl(devMemFd, MEMRANGE_SET, &mro)) { | ||||
|             if (!rp->wasWC) { | ||||
|                 mro.mo_arg[0] = MEMRANGE_SET_UPDATE; | ||||
|                 rp->mrd.mr_flags = MDF_UNCACHEABLE; | ||||
|                 strcpy(rp->mrd.mr_owner, "unknown"); | ||||
|                 if (ioctl(devMemFd, MEMRANGE_SET, &mro)) | ||||
|                     failed = TRUE; | ||||
|             } | ||||
|             else | ||||
|                 failed = TRUE; | ||||
|         } | ||||
|         if (failed) { | ||||
|             xf86DrvMsg(screenNum, X_WARNING, | ||||
|                        "Failed to restore MTRR range (0x%lx,0x%lx)\n", | ||||
|                        (unsigned long) rp->mrd.mr_base, | ||||
|                        (unsigned long) rp->mrd.mr_len); | ||||
|         } | ||||
|         rp = rp->next; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #endif                          /* HAS_MTRR_SUPPORT */ | ||||
| 
 | ||||
| #if defined(HAS_MTRR_BUILTIN) && defined(__NetBSD__) | ||||
| static void * | ||||
| NetBSDsetWC(int screenNum, unsigned long base, unsigned long size, Bool enable, | ||||
|             MessageType from) | ||||
| { | ||||
|     struct mtrr *mtrrp; | ||||
|     int n; | ||||
| 
 | ||||
|     xf86DrvMsg(screenNum, X_WARNING, | ||||
|                "%s MTRR %lx - %lx\n", enable ? "set" : "remove", | ||||
|                base, (base + size)); | ||||
| 
 | ||||
|     mtrrp = xnfalloc(sizeof(struct mtrr)); | ||||
|     mtrrp->base = base; | ||||
|     mtrrp->len = size; | ||||
|     mtrrp->type = MTRR_TYPE_WC; | ||||
| 
 | ||||
|     /*
 | ||||
|      * MTRR_PRIVATE will make this MTRR get reset automatically | ||||
|      * if this process exits, so we have no need for an explicit | ||||
|      * cleanup operation when starting a new server. | ||||
|      */ | ||||
| 
 | ||||
|     if (enable) | ||||
|         mtrrp->flags = MTRR_VALID | MTRR_PRIVATE; | ||||
|     else | ||||
|         mtrrp->flags = 0; | ||||
|     n = 1; | ||||
| 
 | ||||
|     if (i386_set_mtrr(mtrrp, &n) < 0) { | ||||
|         free(mtrrp); | ||||
|         return NULL; | ||||
|     } | ||||
|     return mtrrp; | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| NetBSDundoWC(int screenNum, void *list) | ||||
| { | ||||
|     struct mtrr *mtrrp = (struct mtrr *) list; | ||||
|     int n; | ||||
| 
 | ||||
|     if (mtrrp == NULL) | ||||
|         return; | ||||
|     n = 1; | ||||
|     mtrrp->flags &= ~MTRR_VALID; | ||||
|     i386_set_mtrr(mtrrp, &n); | ||||
|     free(mtrrp); | ||||
| } | ||||
| #endif | ||||
|  |  | |||
|  | @ -42,10 +42,6 @@ | |||
| #include "shared/xf86Axp.h" | ||||
| #endif | ||||
| 
 | ||||
| #ifdef HAS_MTRR_SUPPORT | ||||
| #include <asm/mtrr.h> | ||||
| #endif | ||||
| 
 | ||||
| static Bool ExtendedEnabled = FALSE; | ||||
| 
 | ||||
| #ifdef __ia64__ | ||||
|  | @ -95,265 +91,6 @@ static unsigned long hae_mask; | |||
| static unsigned long bus_base; | ||||
| #endif | ||||
| 
 | ||||
| #ifdef HAS_MTRR_SUPPORT | ||||
| 
 | ||||
| #define SPLIT_WC_REGIONS 1 | ||||
| 
 | ||||
| static void *setWC(int, unsigned long, unsigned long, Bool, MessageType); | ||||
| static void undoWC(int, void *); | ||||
| 
 | ||||
| /* The file desc for /proc/mtrr. Once opened, left opened, and the mtrr
 | ||||
|    driver will clean up when we exit. */ | ||||
| #define MTRR_FD_UNOPENED (-1)   /* We have yet to open /proc/mtrr */ | ||||
| #define MTRR_FD_PROBLEM (-2)    /* We tried to open /proc/mtrr, but had | ||||
|                                    a problem. */ | ||||
| static int mtrr_fd = MTRR_FD_UNOPENED; | ||||
| 
 | ||||
| /* Open /proc/mtrr. FALSE on failure. Will always fail on Linux 2.0, 
 | ||||
|    and will fail on Linux 2.2 with MTRR support configured out, | ||||
|    so verbosity should be chosen appropriately. */ | ||||
| static Bool | ||||
| mtrr_open(int verbosity) | ||||
| { | ||||
|     /* Only report absence of /proc/mtrr once. */ | ||||
|     static Bool warned = FALSE; | ||||
| 
 | ||||
|     if (mtrr_fd == MTRR_FD_UNOPENED) { | ||||
|         mtrr_fd = open("/proc/mtrr", O_WRONLY); | ||||
| 
 | ||||
|         if (mtrr_fd < 0) | ||||
|             mtrr_fd = MTRR_FD_PROBLEM; | ||||
|     } | ||||
| 
 | ||||
|     if (mtrr_fd == MTRR_FD_PROBLEM) { | ||||
|         /* To make sure we only ever warn once, need to check
 | ||||
|            verbosity outside xf86MsgVerb */ | ||||
|         if (!warned && verbosity <= xf86GetVerbosity()) { | ||||
|             xf86MsgVerb(X_WARNING, verbosity, | ||||
|                         "System lacks support for changing MTRRs\n"); | ||||
|             warned = TRUE; | ||||
|         } | ||||
| 
 | ||||
|         return FALSE; | ||||
|     } | ||||
|     else | ||||
|         return TRUE; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * We maintain a list of WC regions for each physical mapping so they can | ||||
|  * be undone when unmapping. | ||||
|  */ | ||||
| 
 | ||||
| struct mtrr_wc_region { | ||||
|     struct mtrr_sentry sentry; | ||||
|     Bool added;                 /* added WC or removed it */ | ||||
|     struct mtrr_wc_region *next; | ||||
| }; | ||||
| 
 | ||||
| static struct mtrr_wc_region * | ||||
| mtrr_cull_wc_region(int screenNum, unsigned long base, unsigned long size, | ||||
|                     MessageType from) | ||||
| { | ||||
|     /* Some BIOS writers thought that setting wc over the mmio
 | ||||
|        region of a graphics devices was a good idea. Try to fix | ||||
|        it. */ | ||||
| 
 | ||||
|     struct mtrr_gentry gent; | ||||
|     struct mtrr_wc_region *wcreturn = NULL, *wcr; | ||||
|     int count, ret = 0; | ||||
| 
 | ||||
|     /* Linux 2.0 users should not get a warning without -verbose */ | ||||
|     if (!mtrr_open(2)) | ||||
|         return NULL; | ||||
| 
 | ||||
|     for (gent.regnum = 0; | ||||
|          ioctl(mtrr_fd, MTRRIOC_GET_ENTRY, &gent) >= 0; gent.regnum++) { | ||||
|         if (gent.type != MTRR_TYPE_WRCOMB | ||||
|             || gent.base + gent.size <= base || base + size <= gent.base) | ||||
|             continue; | ||||
| 
 | ||||
|         /* Found an overlapping region. Delete it. */ | ||||
| 
 | ||||
|         wcr = malloc(sizeof(*wcr)); | ||||
|         if (!wcr) | ||||
|             return NULL; | ||||
|         wcr->sentry.base = gent.base; | ||||
|         wcr->sentry.size = gent.size; | ||||
|         wcr->sentry.type = MTRR_TYPE_WRCOMB; | ||||
|         wcr->added = FALSE; | ||||
| 
 | ||||
|         count = 3; | ||||
|         while (count-- && | ||||
|                (ret = ioctl(mtrr_fd, MTRRIOC_KILL_ENTRY, &(wcr->sentry))) < 0); | ||||
| 
 | ||||
|         if (ret >= 0) { | ||||
|             xf86DrvMsg(screenNum, from, | ||||
|                        "Removed MMIO write-combining range " | ||||
|                        "(0x%lx,0x%lx)\n", | ||||
|                        (unsigned long) gent.base, (unsigned long) gent.size); | ||||
|             wcr->next = wcreturn; | ||||
|             wcreturn = wcr; | ||||
|             gent.regnum--; | ||||
|         } | ||||
|         else { | ||||
|             free(wcr); | ||||
|             xf86DrvMsgVerb(screenNum, X_WARNING, 0, | ||||
|                            "Failed to remove MMIO " | ||||
|                            "write-combining range (0x%lx,0x%lx)\n", | ||||
|                            (unsigned long)gent.base, (unsigned long) gent.size); | ||||
|         } | ||||
|     } | ||||
|     return wcreturn; | ||||
| } | ||||
| 
 | ||||
| static struct mtrr_wc_region * | ||||
| mtrr_remove_offending(int screenNum, unsigned long base, unsigned long size, | ||||
|                       MessageType from) | ||||
| { | ||||
|     struct mtrr_gentry gent; | ||||
|     struct mtrr_wc_region *wcreturn = NULL, **wcr; | ||||
| 
 | ||||
|     if (!mtrr_open(2)) | ||||
|         return NULL; | ||||
| 
 | ||||
|     wcr = &wcreturn; | ||||
|     for (gent.regnum = 0; | ||||
|          ioctl(mtrr_fd, MTRRIOC_GET_ENTRY, &gent) >= 0; gent.regnum++) { | ||||
|         if (gent.type == MTRR_TYPE_WRCOMB | ||||
|             && ((gent.base >= base && gent.base + gent.size < base + size) || | ||||
|                 (gent.base > base && gent.base + gent.size <= base + size))) { | ||||
|             *wcr = mtrr_cull_wc_region(screenNum, gent.base, gent.size, from); | ||||
|             if (*wcr) | ||||
|                 gent.regnum--; | ||||
|             while (*wcr) { | ||||
|                 wcr = &((*wcr)->next); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     return wcreturn; | ||||
| } | ||||
| 
 | ||||
| static struct mtrr_wc_region * | ||||
| mtrr_add_wc_region(int screenNum, unsigned long base, unsigned long size, | ||||
|                    MessageType from) | ||||
| { | ||||
|     struct mtrr_wc_region **wcr, *wcreturn, *curwcr; | ||||
| 
 | ||||
|     /*
 | ||||
|      * There can be only one.... | ||||
|      */ | ||||
| 
 | ||||
|     wcreturn = mtrr_remove_offending(screenNum, base, size, from); | ||||
|     wcr = &wcreturn; | ||||
|     while (*wcr) { | ||||
|         wcr = &((*wcr)->next); | ||||
|     } | ||||
| 
 | ||||
|     /* Linux 2.0 should not warn, unless the user explicitly asks for
 | ||||
|        WC. */ | ||||
| 
 | ||||
|     if (!mtrr_open(from == X_CONFIG ? 0 : 2)) | ||||
|         return wcreturn; | ||||
| 
 | ||||
|     *wcr = curwcr = malloc(sizeof(**wcr)); | ||||
|     if (!curwcr) | ||||
|         return wcreturn; | ||||
| 
 | ||||
|     curwcr->sentry.base = base; | ||||
|     curwcr->sentry.size = size; | ||||
|     curwcr->sentry.type = MTRR_TYPE_WRCOMB; | ||||
|     curwcr->added = TRUE; | ||||
|     curwcr->next = NULL; | ||||
| 
 | ||||
| #if SPLIT_WC_REGIONS | ||||
|     /*
 | ||||
|      * Splits up the write-combining region if it is not aligned on a | ||||
|      * size boundary. | ||||
|      */ | ||||
| 
 | ||||
|     { | ||||
|         unsigned long lbase, d_size = 1; | ||||
|         unsigned long n_size = size; | ||||
|         unsigned long n_base = base; | ||||
| 
 | ||||
|         for (lbase = n_base, d_size = 1; !(lbase & 1); | ||||
|              lbase = lbase >> 1, d_size <<= 1); | ||||
|         while (d_size > n_size) | ||||
|             d_size = d_size >> 1; | ||||
|         DebugF("WC_BASE: 0x%lx WC_END: 0x%lx\n", base, base + d_size - 1); | ||||
|         n_base += d_size; | ||||
|         n_size -= d_size; | ||||
|         if (n_size) { | ||||
|             xf86DrvMsgVerb(screenNum, X_INFO, 3, "Splitting WC range: " | ||||
|                            "base: 0x%lx, size: 0x%lx\n", base, size); | ||||
|             curwcr->next = mtrr_add_wc_region(screenNum, n_base, n_size, from); | ||||
|         } | ||||
|         curwcr->sentry.size = d_size; | ||||
|     } | ||||
| 
 | ||||
|         /*****************************************************************/ | ||||
| #endif                          /* SPLIT_WC_REGIONS */ | ||||
| 
 | ||||
|     if (ioctl(mtrr_fd, MTRRIOC_ADD_ENTRY, &curwcr->sentry) >= 0) { | ||||
|         /* Avoid printing on every VT switch */ | ||||
|         if (xf86ServerIsInitialising()) { | ||||
|             xf86DrvMsg(screenNum, from, | ||||
|                        "Write-combining range (0x%lx,0x%lx)\n", base, size); | ||||
|         } | ||||
|         return wcreturn; | ||||
|     } | ||||
|     else { | ||||
|         *wcr = curwcr->next; | ||||
|         free(curwcr); | ||||
| 
 | ||||
|         /* Don't complain about the VGA region: MTRR fixed
 | ||||
|            regions aren't currently supported, but might be in | ||||
|            the future. */ | ||||
|         if ((unsigned long) base >= 0x100000) { | ||||
|             xf86DrvMsgVerb(screenNum, X_WARNING, 0, | ||||
|                            "Failed to set up write-combining range " | ||||
|                            "(0x%lx,0x%lx)\n", base, size); | ||||
|         } | ||||
|         return wcreturn; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| mtrr_undo_wc_region(int screenNum, struct mtrr_wc_region *wcr) | ||||
| { | ||||
|     struct mtrr_wc_region *p, *prev; | ||||
| 
 | ||||
|     if (mtrr_fd >= 0) { | ||||
|         p = wcr; | ||||
|         while (p) { | ||||
|             if (p->added) | ||||
|                 ioctl(mtrr_fd, MTRRIOC_DEL_ENTRY, &p->sentry); | ||||
|             prev = p; | ||||
|             p = p->next; | ||||
|             free(prev); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void * | ||||
| setWC(int screenNum, unsigned long base, unsigned long size, Bool enable, | ||||
|       MessageType from) | ||||
| { | ||||
|     if (enable) | ||||
|         return mtrr_add_wc_region(screenNum, base, size, from); | ||||
|     else | ||||
|         return mtrr_cull_wc_region(screenNum, base, size, from); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| undoWC(int screenNum, void *regioninfo) | ||||
| { | ||||
|     mtrr_undo_wc_region(screenNum, regioninfo); | ||||
| } | ||||
| 
 | ||||
| #endif                          /* HAS_MTRR_SUPPORT */ | ||||
| 
 | ||||
| void | ||||
| xf86OSInitVidMem(VidMemInfoPtr pVidMem) | ||||
| { | ||||
|  | @ -375,10 +112,6 @@ xf86OSInitVidMem(VidMemInfoPtr pVidMem) | |||
|     } | ||||
| #endif                          /* __alpha__ */ | ||||
| 
 | ||||
| #ifdef HAS_MTRR_SUPPORT | ||||
|     pVidMem->setWC = setWC; | ||||
|     pVidMem->undoWC = undoWC; | ||||
| #endif | ||||
|     pVidMem->initialised = TRUE; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -129,7 +129,7 @@ xf86CheckMTRR(int ScreenNum) | |||
|      */ | ||||
|     checkMtrrOption(vp); | ||||
| 
 | ||||
|     if (vp->mtrrEnabled && vidMemInfo.setWC) | ||||
|     if (vp->mtrrEnabled) | ||||
|         return TRUE; | ||||
| 
 | ||||
|     return FALSE; | ||||
|  |  | |||
|  | @ -32,14 +32,8 @@ | |||
| #ifndef _XF86OSPRIV_H | ||||
| #define _XF86OSPRIV_H | ||||
| 
 | ||||
| typedef void *(*SetWCProcPtr) (int, unsigned long, unsigned long, Bool, | ||||
|                                  MessageType); | ||||
| typedef void (*UndoWCProcPtr) (int, void *); | ||||
| 
 | ||||
| typedef struct { | ||||
|     Bool initialised; | ||||
|     SetWCProcPtr setWC; | ||||
|     UndoWCProcPtr undoWC; | ||||
|     Bool linearSupported; | ||||
| } VidMemInfo, *VidMemInfoPtr; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue