~ubuntu-branches/ubuntu/intrepid/xserver-xgl/intrepid

« back to all changes in this revision

Viewing changes to hw/xfree86/os-support/lynxos/lynx_video.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthew Garrett
  • Date: 2006-02-13 14:21:43 UTC
  • Revision ID: james.westby@ubuntu.com-20060213142143-mad6z9xzem7hzxz9
Tags: upstream-7.0.0
ImportĀ upstreamĀ versionĀ 7.0.0

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