~ubuntu-branches/ubuntu/gutsy/vnc4/gutsy

« back to all changes in this revision

Viewing changes to unix/xc/programs/Xserver/hw/xfree86/os-support/lynxos/lynx_video.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2006-05-15 20:35:17 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060515203517-l4lre1ku942mn26k
Tags: 4.1.1+X4.3.0-10
* Correction of critical security issue. Thanks to Martin Kogler
  <e9925248@student.tuwien.ac.at> that informed me about the issue,
  and provided the patch.
  This flaw was originally found by Steve Wiseman of intelliadmin.com.
* Applied patch from Javier Kohen <jkohen@users.sourceforge.net> that
  inform the user that only 8 first characters of the password will
  actually be used when typing more than 8 characters, closes:
  #355619.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 1993 by Thomas Mueller
 
3
 *
 
4
 * Permission to use, copy, modify, distribute, and sell this software and its
 
5
 * documentation for any purpose is hereby granted without fee, provided that
 
6
 * the above copyright notice appear in all copies and that both that
 
7
 * copyright notice and this permission notice appear in supporting
 
8
 * documentation, and that the name of Thomas Mueller not be used in
 
9
 * advertising or publicity pertaining to distribution of the software without
 
10
 * specific, written prior permission.  Thomas Mueller makes no representations
 
11
 * about the suitability of this software for any purpose.  It is provided
 
12
 * "as is" without express or implied warranty.
 
13
 *
 
14
 * THOMAS MUELLER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 
15
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 
16
 * EVENT SHALL THOMAS MUELLER BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 
17
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 
18
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 
19
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 
20
 * PERFORMANCE OF THIS SOFTWARE.
 
21
 *
 
22
 */
 
23
 
 
24
/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/lynxos/lynx_video.c,v 3.18 2002/12/14 04:41:14 dawes Exp $ */
 
25
 
 
26
#include "X.h"
 
27
#include "input.h"
 
28
#include "scrnintstr.h"
 
29
 
 
30
#include "xf86.h"
 
31
#include "xf86Priv.h"
 
32
#include "xf86_OSlib.h"
 
33
#include "xf86OSpriv.h"
 
34
 
 
35
#if defined(__powerpc__)
 
36
 
 
37
# if defined(USE_MACHINE_ABSOLUTE)
 
38
#   include <machine/absolute.h>
 
39
# else
 
40
#   define __USER_SPACE_INCLUDE
 
41
#   include <hw_absolute.h>
 
42
# endif
 
43
 
 
44
void ppcPciIoMap(int bus);
 
45
#endif
 
46
 
 
47
#if 0
 
48
#define DEBUG   
 
49
#endif
 
50
 
 
51
#ifdef HAS_MTRR_SUPPORT
 
52
#include <sys/memrange.h>
 
53
#define X_MTRR_ID "XFree86"
 
54
 
 
55
static pointer setWC(int, unsigned long, unsigned long, Bool, MessageType);
 
56
static void undoWC(int, pointer);
 
57
static Bool cleanMTRR(void);
 
58
static int devMemFd = -1;
 
59
#define MTRR_DEVICE     "/dev/mtrr"
 
60
#endif
 
61
 
 
62
 
 
63
#if !defined(NO_MMAP)
 
64
#include <sys/mman.h>
 
65
 
 
66
int smem_remove(char *name)
 
67
{
 
68
  return(0);
 
69
}
 
70
 
 
71
char *smem_create(char *name, char *arg_addr, long size, int mode)
 
72
{
 
73
  int fd;
 
74
  void *addr = 0;
 
75
  char *retval;
 
76
  size_t len = size;
 
77
  int prot = PROT_READ|PROT_WRITE|PROT_UNCACHE;
 
78
  int flags = MAP_SHARED;
 
79
  off_t off = (off_t)arg_addr;
 
80
 
 
81
  if ((fd = open("/dev/mem" , O_RDWR)) < 0)
 
82
  {
 
83
    retval = (char *)-1;
 
84
  }
 
85
  else
 
86
  {
 
87
    if (mode == SM_DETACH)
 
88
    {
 
89
      munmap(arg_addr, len);
 
90
      retval = 0;
 
91
    }
 
92
    else
 
93
    {
 
94
      if ((retval = mmap (addr, len, prot, flags, fd, off) ) == MAP_FAILED)
 
95
      {
 
96
        retval = (char *)-1;
 
97
      }
 
98
    }
 
99
 
 
100
    close(fd);
 
101
  }
 
102
 
 
103
  return(retval);
 
104
}
 
105
 
 
106
#endif
 
107
 
 
108
 
 
109
/***************************************************************************/
 
110
/* Video Memory Mapping section                                            */
 
111
/***************************************************************************/
 
112
 
 
113
typedef struct
 
114
{
 
115
        char    name[16];
 
116
        unsigned long   Base;
 
117
        unsigned long   Size;
 
118
        char    *ptr;
 
119
        int     RefCnt;
 
120
}
 
121
_SMEMS;
 
122
 
 
123
#define MAX_SMEMS       16
 
124
 
 
125
static _SMEMS   smems[MAX_SMEMS];
 
126
 
 
127
 
 
128
#ifndef MAP_FAILED
 
129
#define MAP_FAILED ((void *)-1)
 
130
#endif
 
131
 
 
132
static void
 
133
smemCleanup(void)
 
134
{
 
135
        int i;
 
136
 
 
137
        for (i = 0; i < MAX_SMEMS; i++) {
 
138
                if (*smems[i].name && smems[i].ptr) {
 
139
                        (void)smem_create(NULL, smems[i].ptr, 0, SM_DETACH);
 
140
                        (void)smem_remove(smems[i].name);
 
141
                        *smems[i].name = '\0';
 
142
                        smems[i].ptr = NULL;
 
143
                        smems[i].Base = 0;
 
144
                        smems[i].Size = 0;
 
145
                        smems[i].RefCnt = 0;
 
146
                }
 
147
        }
 
148
}
 
149
 
 
150
static pointer
 
151
MapVidMem(int ScreenNum, unsigned long Base, unsigned long Size, int flags)
 
152
{
 
153
        static int once;
 
154
        int     free_slot = -1;
 
155
        int     i;
 
156
 
 
157
        if (!once)
 
158
        {
 
159
                atexit(smemCleanup);
 
160
                once = 1;
 
161
        }
 
162
        for (i = 0; i < MAX_SMEMS; i++)
 
163
        {
 
164
                if (!*smems[i].name && free_slot == -1)
 
165
                        free_slot = i;
 
166
                if (smems[i].Base == Base && smems[i].Size == Size 
 
167
                    && *smems[i].name) {
 
168
                        smems[i].RefCnt++;
 
169
                        return smems[i].ptr;
 
170
                }
 
171
        }
 
172
        if (i == MAX_SMEMS && free_slot == -1)
 
173
        {
 
174
                FatalError("MapVidMem: failed to smem_create Base %x Size %x (out of SMEMS entries)\n",
 
175
                        Base, Size);
 
176
        }
 
177
 
 
178
        i = free_slot;
 
179
        sprintf(smems[i].name, "Video-%d", i);
 
180
        smems[i].Base = Base;
 
181
        smems[i].Size = Size;
 
182
        
 
183
        xf86MsgVerb(X_INFO, 3, "MapVidMem: Base=0x%x Size=0x%x\n",
 
184
                Base, Size);
 
185
 
 
186
#if defined(__powerpc__)
 
187
        if (((unsigned long)Base & PHYS_IO_MEM_START) != PHYS_IO_MEM_START) {
 
188
                Base = Base | PHYS_IO_MEM_START;
 
189
        }
 
190
#endif
 
191
 
 
192
        smems[i].ptr = smem_create(smems[i].name, (char *)Base, Size, SM_READ|SM_WRITE);
 
193
        smems[i].RefCnt = 1;
 
194
        if (smems[i].ptr == NULL)
 
195
        {
 
196
                /* check if there is a stale segment around */
 
197
                if (smem_remove(smems[i].name) == 0) {
 
198
                        xf86Msg(X_INFO,
 
199
                            "MapVidMem: removed stale smem_ segment %s\n",
 
200
                            smems[i].name);
 
201
                        smems[i].ptr = smem_create(smems[i].name, 
 
202
                                                (char *)Base, Size, SM_READ|SM_WRITE);
 
203
                }
 
204
                if (smems[i].ptr == NULL) {
 
205
                        *smems[i].name = '\0';
 
206
                        FatalError("MapVidMem: failed to smem_create Base %x Size %x (%s)\n",
 
207
                                Base, Size, strerror(errno));
 
208
                }
 
209
        }
 
210
        xf86MsgVerb(X_INFO, 3, "MapVidMem: Base=0x%x Size=0x%x Ptr=0x%x\n",
 
211
                         Base, Size, smems[i].ptr);
 
212
        return smems[i].ptr;
 
213
}
 
214
 
 
215
static void
 
216
UnMapVidMem(int ScreenNum, pointer Base, unsigned long Size)
 
217
{
 
218
        int     i;
 
219
 
 
220
        xf86MsgVerb(X_INFO, 3, "UnMapVidMem: Base/Ptr=0x%x Size=0x%x\n",
 
221
                Base, Size);
 
222
        for (i = 0; i < MAX_SMEMS; i++)
 
223
        {
 
224
                if (*smems[i].name && smems[i].ptr == Base 
 
225
                        && smems[i].Size == Size)
 
226
                {
 
227
                        if (--smems[i].RefCnt > 0)
 
228
                                return;
 
229
 
 
230
                        (void)smem_create(NULL, smems[i].ptr, 0, SM_DETACH);
 
231
                        xf86MsgVerb(X_INFO, 3,
 
232
                           "UnMapVidMem: smem_create(%s, 0x%08x, ... "
 
233
                           "SM_DETACH)\n", smems[i].name, smems[i].ptr);
 
234
                        (void)smem_remove(smems[i].name);
 
235
                        *smems[i].name = '\0';
 
236
                        smems[i].RefCnt = 0;
 
237
                        return;
 
238
                }
 
239
        }
 
240
        xf86MsgVerb(X_WARNING, 2,
 
241
                "UnMapVidMem: no SMEM found for Base = %lx Size = %lx\n",
 
242
                Base, Size);
 
243
}
 
244
 
 
245
 
 
246
void
 
247
xf86OSInitVidMem(VidMemInfoPtr pVidMem)
 
248
{
 
249
  pVidMem->linearSupported = TRUE;
 
250
  pVidMem->mapMem = MapVidMem;
 
251
  pVidMem->unmapMem = UnMapVidMem;
 
252
  pVidMem->setWC = 0;
 
253
  pVidMem->undoWC = 0;
 
254
#ifdef HAS_MTRR_SUPPORT
 
255
  if (cleanMTRR()) {
 
256
        pVidMem->setWC = setWC;
 
257
        pVidMem->undoWC = undoWC;
 
258
  }
 
259
#endif
 
260
  pVidMem->initialised = TRUE;
 
261
}
 
262
 
 
263
 
 
264
/***************************************************************************/
 
265
/* Interrupt Handling section                                              */
 
266
/***************************************************************************/
 
267
 
 
268
Bool
 
269
xf86DisableInterrupts()
 
270
{
 
271
        return(TRUE);
 
272
}
 
273
 
 
274
void
 
275
xf86EnableInterrupts()
 
276
{
 
277
        return;
 
278
}
 
279
 
 
280
/***************************************************************************/
 
281
/* I/O Permissions section for PowerPC                                     */
 
282
/***************************************************************************/
 
283
 
 
284
#if defined(__powerpc__)
 
285
 
 
286
volatile unsigned char *ioBase = MAP_FAILED;
 
287
volatile unsigned char *pciConfBase = MAP_FAILED;
 
288
 
 
289
static int IOEnabled;
 
290
 
 
291
 
 
292
static void
 
293
removeIOSmem(void)
 
294
{
 
295
        smem_create(NULL, (char *) ioBase, 0, SM_DETACH);
 
296
        smem_remove("IOBASE");
 
297
        ioBase = MAP_FAILED;    
 
298
}
 
299
 
 
300
void
 
301
xf86EnableIO()
 
302
{
 
303
        if (IOEnabled++ == 0) {
 
304
            ioBase = (unsigned char *) smem_create("IOBASE",
 
305
                        (char *)PHYS_ISA_IO_SPACE, 64*1024, SM_READ|SM_WRITE);
 
306
                if (ioBase == MAP_FAILED) {
 
307
                        --IOEnabled;
 
308
                        FatalError("xf86EnableIO: Failed to map I/O\n");
 
309
                } else {
 
310
#ifdef DEBUG
 
311
                        ErrorF("xf86EnableIO: mapped I/O at vaddr 0x%08x\n",
 
312
                                ioBase);
 
313
#endif
 
314
                        atexit(removeIOSmem);
 
315
                }
 
316
        }        
 
317
        return;
 
318
}
 
319
 
 
320
void
 
321
xf86DisableIO()
 
322
{
 
323
        if (!IOEnabled)
 
324
                return;
 
325
 
 
326
        if (--IOEnabled == 0) 
 
327
                removeIOSmem();
 
328
        return;
 
329
}
 
330
 
 
331
#if 0
 
332
void
 
333
xf86DisableIOPrivs(void)
 
334
{
 
335
        return;
 
336
}
 
337
#endif
 
338
void
 
339
ppcPciIoMap(int bus)
 
340
{
 
341
        xf86EnableIO();
 
342
}
 
343
 
 
344
#endif
 
345
 
 
346
 
 
347
#ifdef HAS_MTRR_SUPPORT
 
348
/* memory range (MTRR) support for LynxOS (taken from BSD MTRR support) */
 
349
 
 
350
/*
 
351
 * This code is experimental.  Some parts may be overkill, and other parts
 
352
 * may be incomplete.
 
353
 */
 
354
 
 
355
/*
 
356
 * getAllRanges returns the full list of memory ranges with attributes set.
 
357
 */
 
358
 
 
359
static struct mem_range_desc *
 
360
getAllRanges(int *nmr)
 
361
{
 
362
        struct mem_range_desc *mrd;
 
363
        struct mem_range_op mro;
 
364
 
 
365
        /*
 
366
         * Find how many ranges there are.  If this fails, then the kernel
 
367
         * probably doesn't have MTRR support.
 
368
         */
 
369
        mro.mo_arg[0] = 0;
 
370
        if (ioctl(devMemFd, MEMRANGE_GET, &mro))
 
371
                return NULL;
 
372
        *nmr = mro.mo_arg[0];
 
373
        mrd = xnfalloc(*nmr * sizeof(struct mem_range_desc));
 
374
        mro.mo_arg[0] = *nmr;
 
375
        mro.mo_desc = mrd;
 
376
        if (ioctl(devMemFd, MEMRANGE_GET, &mro)) {
 
377
                xfree(mrd);
 
378
                return NULL;
 
379
        }
 
380
        return mrd;
 
381
}
 
382
 
 
383
/*
 
384
 * cleanMTRR removes any memory attribute that may be left by a previous
 
385
 * X server.  Normally there won't be any, but this takes care of the
 
386
 * case where a server crashed without being able finish cleaning up.
 
387
 */
 
388
 
 
389
static Bool
 
390
cleanMTRR()
 
391
{
 
392
        struct mem_range_desc *mrd;
 
393
        struct mem_range_op mro;
 
394
        int nmr, i;
 
395
 
 
396
        /* This shouldn't happen */
 
397
        if (devMemFd < 0) {
 
398
                if ((devMemFd = open(MTRR_DEVICE, O_RDONLY)) < 0) {
 
399
perror("open MTRR");
 
400
                        return FALSE;
 
401
                }
 
402
        }
 
403
 
 
404
        if (!(mrd = getAllRanges(&nmr)))
 
405
                return FALSE;
 
406
 
 
407
        for (i = 0; i < nmr; i++) {
 
408
                if (strcmp(mrd[i].mr_owner, X_MTRR_ID) == 0 &&
 
409
                    (mrd[i].mr_flags & MDF_ACTIVE)) {
 
410
#ifdef DEBUG
 
411
                        ErrorF("Clean for (0x%lx,0x%lx)\n",
 
412
                                (unsigned long)mrd[i].mr_base,
 
413
                                (unsigned long)mrd[i].mr_len);
 
414
#endif
 
415
                        if (mrd[i].mr_flags & MDF_FIXACTIVE) {
 
416
                                mro.mo_arg[0] = MEMRANGE_SET_UPDATE;
 
417
                                mrd[i].mr_flags = MDF_UNCACHEABLE;
 
418
                        } else {
 
419
                                mro.mo_arg[0] = MEMRANGE_SET_REMOVE;
 
420
                        }
 
421
                        mro.mo_desc = mrd + i;
 
422
                        ioctl(devMemFd, MEMRANGE_SET, &mro);
 
423
                }
 
424
        }
 
425
#ifdef DEBUG
 
426
        sleep(10);
 
427
#endif
 
428
        xfree(mrd);
 
429
        return TRUE;
 
430
}
 
431
 
 
432
typedef struct x_RangeRec {
 
433
        struct mem_range_desc   mrd;
 
434
        Bool                    wasWC;
 
435
        struct x_RangeRec *     next;
 
436
} RangeRec, *RangePtr;
 
437
 
 
438
static void
 
439
freeRangeList(RangePtr range)
 
440
{
 
441
        RangePtr rp;
 
442
 
 
443
        while (range) {
 
444
                rp = range;
 
445
                range = rp->next;
 
446
                xfree(rp);
 
447
        }
 
448
}
 
449
 
 
450
static RangePtr
 
451
dupRangeList(RangePtr list)
 
452
{
 
453
        RangePtr new = NULL, rp, p;
 
454
 
 
455
        rp = list;
 
456
        while (rp) {
 
457
                p = xnfalloc(sizeof(RangeRec));
 
458
                *p = *rp;
 
459
                p->next = new;
 
460
                new = p;
 
461
                rp = rp->next;
 
462
        }
 
463
        return new;
 
464
}
 
465
 
 
466
static RangePtr
 
467
sortRangeList(RangePtr list)
 
468
{
 
469
        RangePtr rp1, rp2, copy, sorted = NULL, minp, prev, minprev;
 
470
        unsigned long minBase;
 
471
 
 
472
        /* Sort by base address */
 
473
        rp1 = copy = dupRangeList(list);
 
474
        while (rp1) {
 
475
                minBase = rp1->mrd.mr_base;
 
476
                minp = rp1;
 
477
                minprev = NULL;
 
478
                prev = rp1;
 
479
                rp2 = rp1->next;
 
480
                while (rp2) {
 
481
                        if (rp2->mrd.mr_base < minBase) {
 
482
                                minBase = rp2->mrd.mr_base;
 
483
                                minp = rp2;
 
484
                                minprev = prev;
 
485
                        }
 
486
                        prev = rp2;
 
487
                        rp2 = rp2->next;
 
488
                }
 
489
                if (minprev) {
 
490
                        minprev->next = minp->next;
 
491
                        rp1 = copy;
 
492
                } else {
 
493
                        rp1 = minp->next;
 
494
                }
 
495
                minp->next = sorted;
 
496
                sorted = minp;
 
497
        }
 
498
        return sorted;
 
499
}
 
500
 
 
501
/*
 
502
 * findRanges returns a list of ranges that overlap the specified range.
 
503
 */
 
504
 
 
505
static void
 
506
findRanges(unsigned long base, unsigned long size, RangePtr *ucp, RangePtr *wcp)
 
507
{
 
508
        struct mem_range_desc *mrd;
 
509
        int nmr, i;
 
510
        RangePtr rp, *p;
 
511
        
 
512
        if (!(mrd = getAllRanges(&nmr)))
 
513
                return;
 
514
 
 
515
        for (i = 0; i < nmr; i++) {
 
516
                if ((mrd[i].mr_flags & MDF_ACTIVE) &&
 
517
                    mrd[i].mr_base < base + size &&
 
518
                    mrd[i].mr_base + mrd[i].mr_len > base) {
 
519
                        if (mrd[i].mr_flags & MDF_WRITECOMBINE)
 
520
                                p = wcp;
 
521
                        else if (mrd[i].mr_flags & MDF_UNCACHEABLE)
 
522
                                p = ucp;
 
523
                        else
 
524
                                continue;
 
525
                        rp = xnfalloc(sizeof(RangeRec));
 
526
                        rp->mrd = mrd[i];
 
527
                        rp->next = *p;
 
528
                        *p = rp;
 
529
                }
 
530
        }
 
531
        xfree(mrd);
 
532
}
 
533
 
 
534
/*
 
535
 * This checks if the existing overlapping ranges fully cover the requested
 
536
 * range.  Is this overkill?
 
537
 */
 
538
 
 
539
static Bool
 
540
fullCoverage(unsigned long base, unsigned long size, RangePtr overlap)
 
541
{
 
542
        RangePtr rp1, sorted = NULL;
 
543
        unsigned long end;
 
544
 
 
545
        sorted = sortRangeList(overlap);
 
546
        /* Look for gaps */
 
547
        rp1 = sorted;
 
548
        end = base + size;
 
549
        while (rp1) {
 
550
                if (rp1->mrd.mr_base > base) {
 
551
                        freeRangeList(sorted);
 
552
                        return FALSE;
 
553
                } else {
 
554
                        base = rp1->mrd.mr_base + rp1->mrd.mr_len;
 
555
                }
 
556
                if (base >= end) {
 
557
                        freeRangeList(sorted);
 
558
                        return TRUE;
 
559
                }
 
560
                rp1 = rp1->next;
 
561
        }
 
562
        freeRangeList(sorted);
 
563
        return FALSE;
 
564
}
 
565
 
 
566
static pointer
 
567
addWC(int screenNum, unsigned long base, unsigned long size, MessageType from)
 
568
{
 
569
        RangePtr uc = NULL, wc = NULL, retlist = NULL;
 
570
        struct mem_range_desc mrd;
 
571
        struct mem_range_op mro;
 
572
 
 
573
        findRanges(base, size, &uc, &wc);
 
574
 
 
575
        /* See of the full range is already WC */
 
576
        if (!uc && fullCoverage(base, size, wc)) {
 
577
                xf86DrvMsg(screenNum, from, 
 
578
                   "Write-combining range (0x%lx,0x%lx) was already set\n",
 
579
                    base, size);
 
580
                return NULL;
 
581
        }
 
582
 
 
583
        /* Otherwise, try to add the new range */
 
584
        mrd.mr_base = base;
 
585
        mrd.mr_len = size;
 
586
        strcpy(mrd.mr_owner, X_MTRR_ID);
 
587
        mrd.mr_flags = MDF_WRITECOMBINE;
 
588
        mro.mo_desc = &mrd;
 
589
        mro.mo_arg[0] = MEMRANGE_SET_UPDATE;
 
590
        if (ioctl(devMemFd, MEMRANGE_SET, &mro)) {
 
591
                xf86DrvMsg(screenNum, X_WARNING,
 
592
                           "Failed to set write-combining range "
 
593
                           "(0x%lx,0x%lx)\n", base, size);
 
594
                return NULL;
 
595
        } else {
 
596
                xf86DrvMsg(screenNum, from,
 
597
                           "Write-combining range (0x%lx,0x%lx)\n", base, size);
 
598
                retlist = xnfalloc(sizeof(RangeRec));
 
599
                retlist->mrd = mrd;
 
600
                retlist->wasWC = FALSE;
 
601
                retlist->next = NULL;
 
602
                return retlist;
 
603
        }
 
604
}
 
605
 
 
606
static pointer
 
607
delWC(int screenNum, unsigned long base, unsigned long size, MessageType from)
 
608
{
 
609
        RangePtr uc = NULL, wc = NULL, retlist = NULL;
 
610
        struct mem_range_desc mrd;
 
611
        struct mem_range_op mro;
 
612
 
 
613
        findRanges(base, size, &uc, &wc);
 
614
 
 
615
        /*
 
616
         * See of the full range is already not WC, or if there is full
 
617
         * coverage from UC ranges.
 
618
         */
 
619
        if (!wc || fullCoverage(base, size, uc)) {
 
620
                xf86DrvMsg(screenNum, from, 
 
621
                   "Write-combining range (0x%lx,0x%lx) was already clear\n",
 
622
                    base, size);
 
623
                return NULL;
 
624
        }
 
625
 
 
626
        /* Otherwise, try to add the new range */
 
627
        mrd.mr_base = base;
 
628
        mrd.mr_len = size;
 
629
        strcpy(mrd.mr_owner, X_MTRR_ID);
 
630
        mrd.mr_flags = MDF_UNCACHEABLE;
 
631
        mro.mo_desc = &mrd;
 
632
        mro.mo_arg[0] = MEMRANGE_SET_UPDATE;
 
633
        if (ioctl(devMemFd, MEMRANGE_SET, &mro)) {
 
634
                xf86DrvMsg(screenNum, X_WARNING,
 
635
                           "Failed to remove write-combining range "
 
636
                           "(0x%lx,0x%lx)\n", base, size);
 
637
                /* XXX Should then remove all of the overlapping WC ranges */
 
638
                return NULL;
 
639
        } else {
 
640
                xf86DrvMsg(screenNum, from,
 
641
                           "Removed Write-combining range (0x%lx,0x%lx)\n",
 
642
                           base, size);
 
643
                retlist = xnfalloc(sizeof(RangeRec));
 
644
                retlist->mrd = mrd;
 
645
                retlist->wasWC = TRUE;
 
646
                retlist->next = NULL;
 
647
                return retlist;
 
648
        }
 
649
}
 
650
 
 
651
static pointer
 
652
setWC(int screenNum, unsigned long base, unsigned long size, Bool enable,
 
653
        MessageType from)
 
654
{
 
655
        if (enable)
 
656
                return addWC(screenNum, base, size, from);
 
657
        else
 
658
                return delWC(screenNum, base, size, from);
 
659
}
 
660
 
 
661
static void
 
662
undoWC(int screenNum, pointer list)
 
663
{
 
664
        RangePtr rp;
 
665
        struct mem_range_op mro;
 
666
        Bool failed;
 
667
 
 
668
        rp = list;
 
669
        while (rp) {
 
670
#ifdef DEBUG
 
671
                ErrorF("Undo for (0x%lx,0x%lx), %d\n",
 
672
                        (unsigned long)rp->mrd.mr_base,
 
673
                        (unsigned long)rp->mrd.mr_len, rp->wasWC);
 
674
#endif
 
675
                failed = FALSE;
 
676
                if (rp->wasWC) {
 
677
                        mro.mo_arg[0] = MEMRANGE_SET_UPDATE;
 
678
                        rp->mrd.mr_flags = MDF_WRITECOMBINE;
 
679
                        strcpy(rp->mrd.mr_owner, "unknown");
 
680
                } else {
 
681
                        mro.mo_arg[0] = MEMRANGE_SET_REMOVE;
 
682
                }
 
683
                mro.mo_desc = &rp->mrd;
 
684
 
 
685
                if (ioctl(devMemFd, MEMRANGE_SET, &mro)) {
 
686
                        if (!rp->wasWC) {
 
687
                                mro.mo_arg[0] = MEMRANGE_SET_UPDATE;
 
688
                                rp->mrd.mr_flags = MDF_UNCACHEABLE;
 
689
                                strcpy(rp->mrd.mr_owner, "unknown");
 
690
                                if (ioctl(devMemFd, MEMRANGE_SET, &mro))
 
691
                                        failed = TRUE;
 
692
                        } else
 
693
                                failed = TRUE;
 
694
                }
 
695
                if (failed) {
 
696
                        xf86DrvMsg(screenNum, X_WARNING,
 
697
                                "Failed to restore MTRR range (0x%lx,0x%lx)\n",
 
698
                                (unsigned long)rp->mrd.mr_base,
 
699
                                (unsigned long)rp->mrd.mr_len);
 
700
                }
 
701
                rp = rp->next;
 
702
        }
 
703
}
 
704
 
 
705
#endif /* HAS_MTRR_SUPPORT */
 
706