Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.18 414 lines 10 kB view raw
1/* sis_mm.c -- Private header for Direct Rendering Manager -*- linux-c -*- 2 * Created: Mon Jan 4 10:05:05 1999 by sclin@sis.com.tw 3 * 4 * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan. 5 * All rights reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the next 15 * paragraph) shall be included in all copies or substantial portions of the 16 * Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 24 * DEALINGS IN THE SOFTWARE. 25 * 26 * Authors: 27 * Sung-Ching Lin <sclin@sis.com.tw> 28 * 29 */ 30 31#include "drmP.h" 32#include "sis_drm.h" 33#include "sis_drv.h" 34#include "sis_ds.h" 35#if defined(__linux__) && defined(CONFIG_FB_SIS) 36#include <video/sisfb.h> 37#endif 38 39#define MAX_CONTEXT 100 40#define VIDEO_TYPE 0 41#define AGP_TYPE 1 42 43typedef struct { 44 int used; 45 int context; 46 set_t *sets[2]; /* 0 for video, 1 for AGP */ 47} sis_context_t; 48 49static sis_context_t global_ppriv[MAX_CONTEXT]; 50 51static int add_alloc_set(int context, int type, unsigned int val) 52{ 53 int i, retval = 0; 54 55 for (i = 0; i < MAX_CONTEXT; i++) { 56 if (global_ppriv[i].used && global_ppriv[i].context == context) { 57 retval = setAdd(global_ppriv[i].sets[type], val); 58 break; 59 } 60 } 61 return retval; 62} 63 64static int del_alloc_set(int context, int type, unsigned int val) 65{ 66 int i, retval = 0; 67 68 for (i = 0; i < MAX_CONTEXT; i++) { 69 if (global_ppriv[i].used && global_ppriv[i].context == context) { 70 retval = setDel(global_ppriv[i].sets[type], val); 71 break; 72 } 73 } 74 return retval; 75} 76 77/* fb management via fb device */ 78#if defined(__linux__) && defined(CONFIG_FB_SIS) 79 80static int sis_fb_init(DRM_IOCTL_ARGS) 81{ 82 return 0; 83} 84 85static int sis_fb_alloc(DRM_IOCTL_ARGS) 86{ 87 drm_sis_mem_t fb; 88 struct sis_memreq req; 89 drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *)data; 90 int retval = 0; 91 92 DRM_COPY_FROM_USER_IOCTL(fb, argp, sizeof(fb)); 93 94 req.size = fb.size; 95 sis_malloc(&req); 96 if (req.offset) { 97 /* TODO */ 98 fb.offset = req.offset; 99 fb.free = req.offset; 100 if (!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)) { 101 DRM_DEBUG("adding to allocation set fails\n"); 102 sis_free(req.offset); 103 retval = DRM_ERR(EINVAL); 104 } 105 } else { 106 fb.offset = 0; 107 fb.size = 0; 108 fb.free = 0; 109 } 110 111 DRM_COPY_TO_USER_IOCTL(argp, fb, sizeof(fb)); 112 113 DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, req.offset); 114 115 return retval; 116} 117 118static int sis_fb_free(DRM_IOCTL_ARGS) 119{ 120 drm_sis_mem_t fb; 121 int retval = 0; 122 123 DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t __user *) data, sizeof(fb)); 124 125 if (!fb.free) 126 return DRM_ERR(EINVAL); 127 128 if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free)) 129 retval = DRM_ERR(EINVAL); 130 sis_free(fb.free); 131 132 DRM_DEBUG("free fb, offset = 0x%lx\n", fb.free); 133 134 return retval; 135} 136 137#else 138 139/* Called by the X Server to initialize the FB heap. Allocations will fail 140 * unless this is called. Offset is the beginning of the heap from the 141 * framebuffer offset (MaxXFBMem in XFree86). 142 * 143 * Memory layout according to Thomas Winischofer: 144 * |------------------|DDDDDDDDDDDDDDDDDDDDDDDDDDDDD|HHHH|CCCCCCCCCCC| 145 * 146 * X driver/sisfb HW- Command- 147 * framebuffer memory DRI heap Cursor queue 148 */ 149static int sis_fb_init(DRM_IOCTL_ARGS) 150{ 151 DRM_DEVICE; 152 drm_sis_private_t *dev_priv = dev->dev_private; 153 drm_sis_fb_t fb; 154 155 DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_fb_t __user *) data, sizeof(fb)); 156 157 if (dev_priv == NULL) { 158 dev->dev_private = drm_calloc(1, sizeof(drm_sis_private_t), 159 DRM_MEM_DRIVER); 160 dev_priv = dev->dev_private; 161 if (dev_priv == NULL) 162 return ENOMEM; 163 } 164 165 if (dev_priv->FBHeap != NULL) 166 return DRM_ERR(EINVAL); 167 168 dev_priv->FBHeap = mmInit(fb.offset, fb.size); 169 170 DRM_DEBUG("offset = %u, size = %u", fb.offset, fb.size); 171 172 return 0; 173} 174 175static int sis_fb_alloc(DRM_IOCTL_ARGS) 176{ 177 DRM_DEVICE; 178 drm_sis_private_t *dev_priv = dev->dev_private; 179 drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *)data; 180 drm_sis_mem_t fb; 181 PMemBlock block; 182 int retval = 0; 183 184 if (dev_priv == NULL || dev_priv->FBHeap == NULL) 185 return DRM_ERR(EINVAL); 186 187 DRM_COPY_FROM_USER_IOCTL(fb, argp, sizeof(fb)); 188 189 block = mmAllocMem(dev_priv->FBHeap, fb.size, 0, 0); 190 if (block) { 191 /* TODO */ 192 fb.offset = block->ofs; 193 fb.free = (unsigned long)block; 194 if (!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)) { 195 DRM_DEBUG("adding to allocation set fails\n"); 196 mmFreeMem((PMemBlock) fb.free); 197 retval = DRM_ERR(EINVAL); 198 } 199 } else { 200 fb.offset = 0; 201 fb.size = 0; 202 fb.free = 0; 203 } 204 205 DRM_COPY_TO_USER_IOCTL(argp, fb, sizeof(fb)); 206 207 DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, fb.offset); 208 209 return retval; 210} 211 212static int sis_fb_free(DRM_IOCTL_ARGS) 213{ 214 DRM_DEVICE; 215 drm_sis_private_t *dev_priv = dev->dev_private; 216 drm_sis_mem_t fb; 217 218 if (dev_priv == NULL || dev_priv->FBHeap == NULL) 219 return DRM_ERR(EINVAL); 220 221 DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t __user *) data, sizeof(fb)); 222 223 if (!mmBlockInHeap(dev_priv->FBHeap, (PMemBlock) fb.free)) 224 return DRM_ERR(EINVAL); 225 226 if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free)) 227 return DRM_ERR(EINVAL); 228 mmFreeMem((PMemBlock) fb.free); 229 230 DRM_DEBUG("free fb, free = 0x%lx\n", fb.free); 231 232 return 0; 233} 234 235#endif 236 237/* agp memory management */ 238 239static int sis_ioctl_agp_init(DRM_IOCTL_ARGS) 240{ 241 DRM_DEVICE; 242 drm_sis_private_t *dev_priv = dev->dev_private; 243 drm_sis_agp_t agp; 244 245 if (dev_priv == NULL) { 246 dev->dev_private = drm_calloc(1, sizeof(drm_sis_private_t), 247 DRM_MEM_DRIVER); 248 dev_priv = dev->dev_private; 249 if (dev_priv == NULL) 250 return ENOMEM; 251 } 252 253 if (dev_priv->AGPHeap != NULL) 254 return DRM_ERR(EINVAL); 255 256 DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_agp_t __user *) data, 257 sizeof(agp)); 258 259 dev_priv->AGPHeap = mmInit(agp.offset, agp.size); 260 261 DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size); 262 263 return 0; 264} 265 266static int sis_ioctl_agp_alloc(DRM_IOCTL_ARGS) 267{ 268 DRM_DEVICE; 269 drm_sis_private_t *dev_priv = dev->dev_private; 270 drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *)data; 271 drm_sis_mem_t agp; 272 PMemBlock block; 273 int retval = 0; 274 275 if (dev_priv == NULL || dev_priv->AGPHeap == NULL) 276 return DRM_ERR(EINVAL); 277 278 DRM_COPY_FROM_USER_IOCTL(agp, argp, sizeof(agp)); 279 280 block = mmAllocMem(dev_priv->AGPHeap, agp.size, 0, 0); 281 if (block) { 282 /* TODO */ 283 agp.offset = block->ofs; 284 agp.free = (unsigned long)block; 285 if (!add_alloc_set(agp.context, AGP_TYPE, agp.free)) { 286 DRM_DEBUG("adding to allocation set fails\n"); 287 mmFreeMem((PMemBlock) agp.free); 288 retval = -1; 289 } 290 } else { 291 agp.offset = 0; 292 agp.size = 0; 293 agp.free = 0; 294 } 295 296 DRM_COPY_TO_USER_IOCTL(argp, agp, sizeof(agp)); 297 298 DRM_DEBUG("alloc agp, size = %d, offset = %d\n", agp.size, agp.offset); 299 300 return retval; 301} 302 303static int sis_ioctl_agp_free(DRM_IOCTL_ARGS) 304{ 305 DRM_DEVICE; 306 drm_sis_private_t *dev_priv = dev->dev_private; 307 drm_sis_mem_t agp; 308 309 if (dev_priv == NULL || dev_priv->AGPHeap == NULL) 310 return DRM_ERR(EINVAL); 311 312 DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_mem_t __user *) data, 313 sizeof(agp)); 314 315 if (!mmBlockInHeap(dev_priv->AGPHeap, (PMemBlock) agp.free)) 316 return DRM_ERR(EINVAL); 317 318 mmFreeMem((PMemBlock) agp.free); 319 if (!del_alloc_set(agp.context, AGP_TYPE, agp.free)) 320 return DRM_ERR(EINVAL); 321 322 DRM_DEBUG("free agp, free = 0x%lx\n", agp.free); 323 324 return 0; 325} 326 327int sis_init_context(struct drm_device *dev, int context) 328{ 329 int i; 330 331 for (i = 0; i < MAX_CONTEXT; i++) { 332 if (global_ppriv[i].used && 333 (global_ppriv[i].context == context)) 334 break; 335 } 336 337 if (i >= MAX_CONTEXT) { 338 for (i = 0; i < MAX_CONTEXT; i++) { 339 if (!global_ppriv[i].used) { 340 global_ppriv[i].context = context; 341 global_ppriv[i].used = 1; 342 global_ppriv[i].sets[0] = setInit(); 343 global_ppriv[i].sets[1] = setInit(); 344 DRM_DEBUG("init allocation set, socket=%d, " 345 "context = %d\n", i, context); 346 break; 347 } 348 } 349 if ((i >= MAX_CONTEXT) || (global_ppriv[i].sets[0] == NULL) || 350 (global_ppriv[i].sets[1] == NULL)) { 351 return 0; 352 } 353 } 354 355 return 1; 356} 357 358int sis_final_context(struct drm_device *dev, int context) 359{ 360 int i; 361 362 for (i = 0; i < MAX_CONTEXT; i++) { 363 if (global_ppriv[i].used && 364 (global_ppriv[i].context == context)) 365 break; 366 } 367 368 if (i < MAX_CONTEXT) { 369 set_t *set; 370 ITEM_TYPE item; 371 int retval; 372 373 DRM_DEBUG("find socket %d, context = %d\n", i, context); 374 375 /* Video Memory */ 376 set = global_ppriv[i].sets[0]; 377 retval = setFirst(set, &item); 378 while (retval) { 379 DRM_DEBUG("free video memory 0x%lx\n", item); 380#if defined(__linux__) && defined(CONFIG_FB_SIS) 381 sis_free(item); 382#else 383 mmFreeMem((PMemBlock) item); 384#endif 385 retval = setNext(set, &item); 386 } 387 setDestroy(set); 388 389 /* AGP Memory */ 390 set = global_ppriv[i].sets[1]; 391 retval = setFirst(set, &item); 392 while (retval) { 393 DRM_DEBUG("free agp memory 0x%lx\n", item); 394 mmFreeMem((PMemBlock) item); 395 retval = setNext(set, &item); 396 } 397 setDestroy(set); 398 399 global_ppriv[i].used = 0; 400 } 401 402 return 1; 403} 404 405drm_ioctl_desc_t sis_ioctls[] = { 406 [DRM_IOCTL_NR(DRM_SIS_FB_ALLOC)] = {sis_fb_alloc, DRM_AUTH}, 407 [DRM_IOCTL_NR(DRM_SIS_FB_FREE)] = {sis_fb_free, DRM_AUTH}, 408 [DRM_IOCTL_NR(DRM_SIS_AGP_INIT)] = {sis_ioctl_agp_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, 409 [DRM_IOCTL_NR(DRM_SIS_AGP_ALLOC)] = {sis_ioctl_agp_alloc, DRM_AUTH}, 410 [DRM_IOCTL_NR(DRM_SIS_AGP_FREE)] = {sis_ioctl_agp_free, DRM_AUTH}, 411 [DRM_IOCTL_NR(DRM_SIS_FB_INIT)] = {sis_fb_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY} 412}; 413 414int sis_max_ioctl = DRM_ARRAY_SIZE(sis_ioctls);