sun_agp.c (8944B)
1 /* 2 * Abstraction of the AGP GART interface. 3 * 4 * This version is for Solaris. 5 * 6 * Copyright © 2000 VA Linux Systems, Inc. 7 * Copyright © 2001 The XFree86 Project, Inc. 8 */ 9 /* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. 10 * 11 * Permission is hereby granted, free of charge, to any person obtaining a 12 * copy of this software and associated documentation files (the "Software"), 13 * to deal in the Software without restriction, including without limitation 14 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 15 * and/or sell copies of the Software, and to permit persons to whom the 16 * Software is furnished to do so, subject to the following conditions: 17 * 18 * The above copyright notice and this permission notice (including the next 19 * paragraph) shall be included in all copies or substantial portions of the 20 * Software. 21 * 22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 25 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 28 * DEALINGS IN THE SOFTWARE. 29 */ 30 31 #ifdef HAVE_XORG_CONFIG_H 32 #include <xorg-config.h> 33 #endif 34 35 #include <X11/X.h> 36 #include "xf86.h" 37 #include "xf86Priv.h" 38 #include "xf86_OSlib.h" 39 #include "xf86_OSproc.h" 40 #include <unistd.h> 41 #include <sys/ioccom.h> 42 #include <sys/types.h> 43 #include <fcntl.h> 44 #include <sys/agpgart.h> 45 46 /* AGP page size is independent of the host page size. */ 47 #ifndef AGP_PAGE_SIZE 48 #define AGP_PAGE_SIZE 4096 49 #endif 50 51 static int gartFd = -1; 52 static int acquiredScreen = -1; 53 static Bool initDone = FALSE; 54 55 /* 56 * Close /dev/agpgart. This frees all associated memory allocated during 57 * this server generation. 58 */ 59 Bool 60 xf86GARTCloseScreen(int screenNum) 61 { 62 if (gartFd != -1) { 63 close(gartFd); 64 acquiredScreen = -1; 65 gartFd = -1; 66 initDone = FALSE; 67 68 xf86DrvMsg(screenNum, X_INFO, 69 "xf86GARTCloseScreen: device closed successfully\n"); 70 71 } 72 return TRUE; 73 } 74 75 /* 76 * Open /dev/agpgart. Keep it open until xf86GARTCloseScreen is called. 77 */ 78 static Bool 79 GARTInit(int screenNum) 80 { 81 if (initDone) 82 return gartFd != -1; 83 84 if (gartFd == -1) 85 gartFd = open(AGP_DEVICE, O_RDWR); 86 else 87 return FALSE; 88 89 if (gartFd == -1) { 90 xf86DrvMsg(screenNum, X_ERROR, 91 "GARTInit: Unable to open " AGP_DEVICE " (%s)\n", 92 strerror(errno)); 93 return FALSE; 94 } 95 96 initDone = TRUE; 97 xf86DrvMsg(screenNum, X_INFO, 98 "GARTInit: " AGP_DEVICE " opened successfully\n"); 99 100 return TRUE; 101 } 102 103 Bool 104 xf86AgpGARTSupported(void) 105 { 106 return (GARTInit(-1)); 107 108 } 109 110 AgpInfoPtr 111 xf86GetAGPInfo(int screenNum) 112 { 113 agp_info_t agpinf; 114 AgpInfoPtr info; 115 116 if (!GARTInit(screenNum)) 117 return NULL; 118 119 if (ioctl(gartFd, AGPIOC_INFO, &agpinf) != 0) { 120 xf86DrvMsg(screenNum, X_ERROR, 121 "xf86GetAGPInfo: AGPIOC_INFO failed (%s)\n", 122 strerror(errno)); 123 return NULL; 124 } 125 126 if ((info = calloc(sizeof(AgpInfo), 1)) == NULL) { 127 xf86DrvMsg(screenNum, X_ERROR, 128 "xf86GetAGPInfo: Failed to allocate AgpInfo\n"); 129 return NULL; 130 } 131 132 info->bridgeId = agpinf.agpi_devid; 133 info->agpMode = agpinf.agpi_mode; 134 info->base = agpinf.agpi_aperbase; 135 info->size = agpinf.agpi_apersize; 136 info->totalPages = (unsigned long) agpinf.agpi_pgtotal; 137 info->systemPages = (unsigned long) agpinf.agpi_pgsystem; 138 info->usedPages = (unsigned long) agpinf.agpi_pgused; 139 140 return info; 141 } 142 143 Bool 144 xf86AcquireGART(int screenNum) 145 { 146 147 if (!GARTInit(screenNum)) 148 return FALSE; 149 150 if (acquiredScreen != screenNum) { 151 if (ioctl(gartFd, AGPIOC_ACQUIRE, 0) != 0) { 152 xf86DrvMsg(screenNum, X_WARNING, 153 "xf86AcquireGART: AGPIOC_ACQUIRE failed (%s)\n", 154 strerror(errno)); 155 return FALSE; 156 } 157 acquiredScreen = screenNum; 158 xf86DrvMsg(screenNum, X_INFO, 159 "xf86AcquireGART: AGPIOC_ACQUIRE succeeded\n"); 160 } 161 return TRUE; 162 } 163 164 Bool 165 xf86ReleaseGART(int screenNum) 166 { 167 168 if (!GARTInit(screenNum)) 169 return FALSE; 170 171 if (acquiredScreen == screenNum) { 172 /* 173 * The FreeBSD agp driver removes allocations on release. 174 * The Solaris driver doesn't. xf86ReleaseGART() is expected 175 * to give up access to the GART, but not to remove any 176 * allocations. 177 */ 178 179 if (ioctl(gartFd, AGPIOC_RELEASE, 0) != 0) { 180 xf86DrvMsg(screenNum, X_WARNING, 181 "xf86ReleaseGART: AGPIOC_RELEASE failed (%s)\n", 182 strerror(errno)); 183 return FALSE; 184 } 185 acquiredScreen = -1; 186 xf86DrvMsg(screenNum, X_INFO, 187 "xf86ReleaseGART: AGPIOC_RELEASE succeeded\n"); 188 return TRUE; 189 } 190 return FALSE; 191 } 192 193 int 194 xf86AllocateGARTMemory(int screenNum, unsigned long size, int type, 195 unsigned long *physical) 196 { 197 agp_allocate_t alloc; 198 int pages; 199 200 /* 201 * Allocates "size" bytes of GART memory (rounds up to the next 202 * page multiple) or type "type". A handle (key) for the allocated 203 * memory is returned. On error, the return value is -1. 204 * "size" should be larger than 0, or AGPIOC_ALLOCATE ioctl will 205 * return error. 206 */ 207 208 if (!GARTInit(screenNum) || (acquiredScreen != screenNum)) 209 return -1; 210 211 pages = (size / AGP_PAGE_SIZE); 212 if (size % AGP_PAGE_SIZE != 0) 213 pages++; 214 215 alloc.agpa_pgcount = pages; 216 alloc.agpa_type = type; 217 218 if (ioctl(gartFd, AGPIOC_ALLOCATE, &alloc) != 0) { 219 xf86DrvMsg(screenNum, X_WARNING, "xf86AllocateGARTMemory: " 220 "allocation of %d pages failed\n\t(%s)\n", pages, 221 strerror(errno)); 222 return -1; 223 } 224 225 if (physical) 226 *physical = (unsigned long) alloc.agpa_physical; 227 228 return alloc.agpa_key; 229 } 230 231 Bool 232 xf86DeallocateGARTMemory(int screenNum, int key) 233 { 234 if (!GARTInit(screenNum) || (acquiredScreen != screenNum)) 235 return FALSE; 236 237 if (ioctl(gartFd, AGPIOC_DEALLOCATE, (int *) (uintptr_t) key) != 0) { 238 xf86DrvMsg(screenNum, X_WARNING, "xf86DeAllocateGARTMemory: " 239 "deallocation of gart memory with key %d failed\n" 240 "\t(%s)\n", key, strerror(errno)); 241 return FALSE; 242 } 243 244 return TRUE; 245 } 246 247 /* Bind GART memory with "key" at "offset" */ 248 Bool 249 xf86BindGARTMemory(int screenNum, int key, unsigned long offset) 250 { 251 agp_bind_t bind; 252 int pageOffset; 253 254 if (!GARTInit(screenNum) || (acquiredScreen != screenNum)) 255 return FALSE; 256 257 if (offset % AGP_PAGE_SIZE != 0) { 258 xf86DrvMsg(screenNum, X_WARNING, "xf86BindGARTMemory: " 259 "offset (0x%lx) is not page-aligned (%d)\n", 260 offset, AGP_PAGE_SIZE); 261 return FALSE; 262 } 263 pageOffset = offset / AGP_PAGE_SIZE; 264 265 xf86DrvMsgVerb(screenNum, X_INFO, 3, 266 "xf86BindGARTMemory: bind key %d at 0x%08lx " 267 "(pgoffset %d)\n", key, offset, pageOffset); 268 269 bind.agpb_pgstart = pageOffset; 270 bind.agpb_key = key; 271 272 if (ioctl(gartFd, AGPIOC_BIND, &bind) != 0) { 273 xf86DrvMsg(screenNum, X_WARNING, "xf86BindGARTMemory: " 274 "binding of gart memory with key %d\n" 275 "\tat offset 0x%lx failed (%s)\n", 276 key, offset, strerror(errno)); 277 return FALSE; 278 } 279 280 return TRUE; 281 } 282 283 /* Unbind GART memory with "key" */ 284 Bool 285 xf86UnbindGARTMemory(int screenNum, int key) 286 { 287 agp_unbind_t unbind; 288 289 if (!GARTInit(screenNum) || (acquiredScreen != screenNum)) 290 return FALSE; 291 292 unbind.agpu_pri = 0; 293 unbind.agpu_key = key; 294 295 if (ioctl(gartFd, AGPIOC_UNBIND, &unbind) != 0) { 296 xf86DrvMsg(screenNum, X_WARNING, "xf86UnbindGARTMemory: " 297 "unbinding of gart memory with key %d " 298 "failed (%s)\n", key, strerror(errno)); 299 return FALSE; 300 } 301 302 xf86DrvMsgVerb(screenNum, X_INFO, 3, 303 "xf86UnbindGARTMemory: unbind key %d\n", key); 304 305 return TRUE; 306 } 307 308 /* XXX Interface may change. */ 309 Bool 310 xf86EnableAGP(int screenNum, CARD32 mode) 311 { 312 agp_setup_t setup; 313 314 if (!GARTInit(screenNum) || (acquiredScreen != screenNum)) 315 return FALSE; 316 317 setup.agps_mode = mode; 318 if (ioctl(gartFd, AGPIOC_SETUP, &setup) != 0) { 319 xf86DrvMsg(screenNum, X_WARNING, "xf86EnableAGP: " 320 "AGPIOC_SETUP with mode %x failed (%s)\n", 321 (unsigned int) mode, strerror(errno)); 322 return FALSE; 323 } 324 325 return TRUE; 326 }