xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

lnx_agp.c (9736B)


      1 /*
      2  * Abstraction of the AGP GART interface.
      3  *
      4  * This version is for Linux and Free/Open/NetBSD.
      5  *
      6  * Copyright © 2000 VA Linux Systems, Inc.
      7  * Copyright © 2001 The XFree86 Project, Inc.
      8  */
      9 
     10 #ifdef HAVE_XORG_CONFIG_H
     11 #include <xorg-config.h>
     12 #endif
     13 
     14 #include <X11/X.h>
     15 #include "xf86.h"
     16 #include "xf86Priv.h"
     17 #include "xf86_OSlib.h"
     18 #include "xf86OSpriv.h"
     19 
     20 #if defined(__linux__)
     21 #include <asm/ioctl.h>
     22 #include <linux/agpgart.h>
     23 #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
     24 #include <sys/ioctl.h>
     25 #include <sys/agpio.h>
     26 #endif
     27 
     28 #ifndef AGP_DEVICE
     29 #define AGP_DEVICE		"/dev/agpgart"
     30 #endif
     31 /* AGP page size is independent of the host page size. */
     32 #ifndef AGP_PAGE_SIZE
     33 #define AGP_PAGE_SIZE		4096
     34 #endif
     35 #define AGPGART_MAJOR_VERSION	0
     36 #define AGPGART_MINOR_VERSION	99
     37 
     38 static int gartFd = -1;
     39 static int acquiredScreen = -1;
     40 static Bool initDone = FALSE;
     41 
     42 /*
     43  * Close /dev/agpgart.  This frees all associated memory allocated during
     44  * this server generation.
     45  */
     46 Bool
     47 xf86GARTCloseScreen(int screenNum)
     48 {
     49     if (gartFd != -1) {
     50         close(gartFd);
     51         acquiredScreen = -1;
     52         gartFd = -1;
     53         initDone = FALSE;
     54     }
     55     return TRUE;
     56 }
     57 
     58 /*
     59  * Open /dev/agpgart.  Keep it open until xf86GARTCloseScreen is called.
     60  */
     61 static Bool
     62 GARTInit(int screenNum)
     63 {
     64     struct _agp_info agpinf;
     65 
     66     if (initDone)
     67         return gartFd != -1;
     68 
     69     initDone = TRUE;
     70 
     71     if (gartFd == -1)
     72         gartFd = open(AGP_DEVICE, O_RDWR, 0);
     73     else
     74         return FALSE;
     75 
     76     if (gartFd == -1) {
     77         xf86DrvMsg(screenNum, X_ERROR,
     78                    "GARTInit: Unable to open " AGP_DEVICE " (%s)\n",
     79                    strerror(errno));
     80         return FALSE;
     81     }
     82 
     83     xf86AcquireGART(-1);
     84     /* Check the kernel driver version. */
     85     if (ioctl(gartFd, AGPIOC_INFO, &agpinf) != 0) {
     86         xf86DrvMsg(screenNum, X_ERROR,
     87                    "GARTInit: AGPIOC_INFO failed (%s)\n", strerror(errno));
     88         close(gartFd);
     89         gartFd = -1;
     90         return FALSE;
     91     }
     92     xf86ReleaseGART(-1);
     93 
     94 #if defined(__linux__)
     95     /* Per Dave Jones, every effort will be made to keep the
     96      * agpgart interface backwards compatible, so allow all
     97      * future versions.
     98      */
     99     if (
    100 #if (AGPGART_MAJOR_VERSION > 0) /* quiet compiler */
    101            agpinf.version.major < AGPGART_MAJOR_VERSION ||
    102 #endif
    103            (agpinf.version.major == AGPGART_MAJOR_VERSION &&
    104             agpinf.version.minor < AGPGART_MINOR_VERSION)) {
    105         xf86DrvMsg(screenNum, X_ERROR,
    106                    "GARTInit: Kernel agpgart driver version is not current"
    107                    " (%d.%d vs %d.%d)\n",
    108                    agpinf.version.major, agpinf.version.minor,
    109                    AGPGART_MAJOR_VERSION, AGPGART_MINOR_VERSION);
    110         close(gartFd);
    111         gartFd = -1;
    112         return FALSE;
    113     }
    114 #endif
    115 
    116     return TRUE;
    117 }
    118 
    119 Bool
    120 xf86AgpGARTSupported(void)
    121 {
    122     return GARTInit(-1);
    123 }
    124 
    125 AgpInfoPtr
    126 xf86GetAGPInfo(int screenNum)
    127 {
    128     struct _agp_info agpinf;
    129     AgpInfoPtr info;
    130 
    131     if (!GARTInit(screenNum))
    132         return NULL;
    133 
    134     if ((info = calloc(sizeof(AgpInfo), 1)) == NULL) {
    135         xf86DrvMsg(screenNum, X_ERROR,
    136                    "xf86GetAGPInfo: Failed to allocate AgpInfo\n");
    137         return NULL;
    138     }
    139 
    140     memset((char *) &agpinf, 0, sizeof(agpinf));
    141 
    142     if (ioctl(gartFd, AGPIOC_INFO, &agpinf) != 0) {
    143         xf86DrvMsg(screenNum, X_ERROR,
    144                    "xf86GetAGPInfo: AGPIOC_INFO failed (%s)\n",
    145                    strerror(errno));
    146         free(info);
    147         return NULL;
    148     }
    149 
    150     info->bridgeId = agpinf.bridge_id;
    151     info->agpMode = agpinf.agp_mode;
    152     info->base = agpinf.aper_base;
    153     info->size = agpinf.aper_size;
    154     info->totalPages = agpinf.pg_total;
    155     info->systemPages = agpinf.pg_system;
    156     info->usedPages = agpinf.pg_used;
    157 
    158     xf86DrvMsg(screenNum, X_INFO, "Kernel reported %zu total, %zu used\n",
    159                agpinf.pg_total, agpinf.pg_used);
    160 
    161     return info;
    162 }
    163 
    164 /*
    165  * XXX If multiple screens can acquire the GART, should we have a reference
    166  * count instead of using acquiredScreen?
    167  */
    168 
    169 Bool
    170 xf86AcquireGART(int screenNum)
    171 {
    172     if (screenNum != -1 && !GARTInit(screenNum))
    173         return FALSE;
    174 
    175     if (screenNum == -1 || acquiredScreen != screenNum) {
    176         if (ioctl(gartFd, AGPIOC_ACQUIRE, 0) != 0) {
    177             xf86DrvMsg(screenNum, X_WARNING,
    178                        "xf86AcquireGART: AGPIOC_ACQUIRE failed (%s)\n",
    179                        strerror(errno));
    180             return FALSE;
    181         }
    182         acquiredScreen = screenNum;
    183     }
    184     return TRUE;
    185 }
    186 
    187 Bool
    188 xf86ReleaseGART(int screenNum)
    189 {
    190     if (screenNum != -1 && !GARTInit(screenNum))
    191         return FALSE;
    192 
    193     if (acquiredScreen == screenNum) {
    194         /*
    195          * The FreeBSD agp driver removes allocations on release.
    196          * The Linux driver doesn't.  xf86ReleaseGART() is expected
    197          * to give up access to the GART, but not to remove any
    198          * allocations.
    199          */
    200 #if !defined(__linux__)
    201         if (screenNum == -1)
    202 #endif
    203         {
    204             if (ioctl(gartFd, AGPIOC_RELEASE, 0) != 0) {
    205                 xf86DrvMsg(screenNum, X_WARNING,
    206                            "xf86ReleaseGART: AGPIOC_RELEASE failed (%s)\n",
    207                            strerror(errno));
    208                 return FALSE;
    209             }
    210             acquiredScreen = -1;
    211         }
    212         return TRUE;
    213     }
    214     return FALSE;
    215 }
    216 
    217 int
    218 xf86AllocateGARTMemory(int screenNum, unsigned long size, int type,
    219                        unsigned long *physical)
    220 {
    221     struct _agp_allocate alloc;
    222     int pages;
    223 
    224     /*
    225      * Allocates "size" bytes of GART memory (rounds up to the next
    226      * page multiple) or type "type".  A handle (key) for the allocated
    227      * memory is returned.  On error, the return value is -1.
    228      */
    229 
    230     if (!GARTInit(screenNum) || acquiredScreen != screenNum)
    231         return -1;
    232 
    233     pages = (size / AGP_PAGE_SIZE);
    234     if (size % AGP_PAGE_SIZE != 0)
    235         pages++;
    236 
    237     /* XXX check for pages == 0? */
    238 
    239     alloc.pg_count = pages;
    240     alloc.type = type;
    241 
    242     if (ioctl(gartFd, AGPIOC_ALLOCATE, &alloc) != 0) {
    243         xf86DrvMsg(screenNum, X_WARNING, "xf86AllocateGARTMemory: "
    244                    "allocation of %d pages failed\n\t(%s)\n", pages,
    245                    strerror(errno));
    246         return -1;
    247     }
    248 
    249     if (physical)
    250         *physical = alloc.physical;
    251 
    252     return alloc.key;
    253 }
    254 
    255 Bool
    256 xf86DeallocateGARTMemory(int screenNum, int key)
    257 {
    258     if (!GARTInit(screenNum) || acquiredScreen != screenNum)
    259         return FALSE;
    260 
    261     if (acquiredScreen != screenNum) {
    262         xf86DrvMsg(screenNum, X_ERROR,
    263                    "xf86UnbindGARTMemory: AGP not acquired by this screen\n");
    264         return FALSE;
    265     }
    266 
    267 #ifdef __linux__
    268     if (ioctl(gartFd, AGPIOC_DEALLOCATE, (int *) (uintptr_t) key) != 0) {
    269 #else
    270     if (ioctl(gartFd, AGPIOC_DEALLOCATE, &key) != 0) {
    271 #endif
    272         xf86DrvMsg(screenNum, X_WARNING, "xf86DeAllocateGARTMemory: "
    273                    "deallocation gart memory with key %d failed\n\t(%s)\n",
    274                    key, strerror(errno));
    275         return FALSE;
    276     }
    277 
    278     return TRUE;
    279 }
    280 
    281 /* Bind GART memory with "key" at "offset" */
    282 Bool
    283 xf86BindGARTMemory(int screenNum, int key, unsigned long offset)
    284 {
    285     struct _agp_bind bind;
    286     int pageOffset;
    287 
    288     if (!GARTInit(screenNum) || acquiredScreen != screenNum)
    289         return FALSE;
    290 
    291     if (acquiredScreen != screenNum) {
    292         xf86DrvMsg(screenNum, X_ERROR,
    293                    "xf86BindGARTMemory: AGP not acquired by this screen\n");
    294         return FALSE;
    295     }
    296 
    297     if (offset % AGP_PAGE_SIZE != 0) {
    298         xf86DrvMsg(screenNum, X_WARNING, "xf86BindGARTMemory: "
    299                    "offset (0x%lx) is not page-aligned (%d)\n",
    300                    offset, AGP_PAGE_SIZE);
    301         return FALSE;
    302     }
    303     pageOffset = offset / AGP_PAGE_SIZE;
    304 
    305     xf86DrvMsgVerb(screenNum, X_INFO, 3,
    306                    "xf86BindGARTMemory: bind key %d at 0x%08lx "
    307                    "(pgoffset %d)\n", key, offset, pageOffset);
    308 
    309     bind.pg_start = pageOffset;
    310     bind.key = key;
    311 
    312     if (ioctl(gartFd, AGPIOC_BIND, &bind) != 0) {
    313         xf86DrvMsg(screenNum, X_WARNING, "xf86BindGARTMemory: "
    314                    "binding of gart memory with key %d\n"
    315                    "\tat offset 0x%lx failed (%s)\n",
    316                    key, offset, strerror(errno));
    317         return FALSE;
    318     }
    319 
    320     return TRUE;
    321 }
    322 
    323 /* Unbind GART memory with "key" */
    324 Bool
    325 xf86UnbindGARTMemory(int screenNum, int key)
    326 {
    327     struct _agp_unbind unbind;
    328 
    329     if (!GARTInit(screenNum) || acquiredScreen != screenNum)
    330         return FALSE;
    331 
    332     if (acquiredScreen != screenNum) {
    333         xf86DrvMsg(screenNum, X_ERROR,
    334                    "xf86UnbindGARTMemory: AGP not acquired by this screen\n");
    335         return FALSE;
    336     }
    337 
    338     unbind.priority = 0;
    339     unbind.key = key;
    340 
    341     if (ioctl(gartFd, AGPIOC_UNBIND, &unbind) != 0) {
    342         xf86DrvMsg(screenNum, X_WARNING, "xf86UnbindGARTMemory: "
    343                    "unbinding of gart memory with key %d "
    344                    "failed (%s)\n", key, strerror(errno));
    345         return FALSE;
    346     }
    347 
    348     xf86DrvMsgVerb(screenNum, X_INFO, 3,
    349                    "xf86UnbindGARTMemory: unbind key %d\n", key);
    350 
    351     return TRUE;
    352 }
    353 
    354 /* XXX Interface may change. */
    355 Bool
    356 xf86EnableAGP(int screenNum, CARD32 mode)
    357 {
    358     agp_setup setup;
    359 
    360     if (!GARTInit(screenNum) || acquiredScreen != screenNum)
    361         return FALSE;
    362 
    363     setup.agp_mode = mode;
    364     if (ioctl(gartFd, AGPIOC_SETUP, &setup) != 0) {
    365         xf86DrvMsg(screenNum, X_WARNING, "xf86EnableAGP: "
    366                    "AGPIOC_SETUP with mode %ld failed (%s)\n",
    367                    (unsigned long) mode, strerror(errno));
    368         return FALSE;
    369     }
    370 
    371     return TRUE;
    372 }