sis_mm.c revision 130331
1119895Sanholt/* sis_mm.c -- Private header for Direct Rendering Manager -*- linux-c -*- 2119895Sanholt * Created: Mon Jan 4 10:05:05 1999 by sclin@sis.com.tw 3119895Sanholt * 4119895Sanholt * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan. 5119895Sanholt * All rights reserved. 6119895Sanholt * 7119895Sanholt * Permission is hereby granted, free of charge, to any person obtaining a 8119895Sanholt * copy of this software and associated documentation files (the "Software"), 9119895Sanholt * to deal in the Software without restriction, including without limitation 10119895Sanholt * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11119895Sanholt * and/or sell copies of the Software, and to permit persons to whom the 12119895Sanholt * Software is furnished to do so, subject to the following conditions: 13119895Sanholt * 14119895Sanholt * The above copyright notice and this permission notice (including the next 15119895Sanholt * paragraph) shall be included in all copies or substantial portions of the 16119895Sanholt * Software. 17119895Sanholt * 18119895Sanholt * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19119895Sanholt * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20119895Sanholt * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21119895Sanholt * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 22119895Sanholt * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 23119895Sanholt * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 24119895Sanholt * DEALINGS IN THE SOFTWARE. 25119895Sanholt * 26119895Sanholt * Authors: 27119895Sanholt * Sung-Ching Lin <sclin@sis.com.tw> 28119895Sanholt * 29119895Sanholt * $FreeBSD: head/sys/dev/drm/sis_mm.c 130331 2004-06-11 03:26:59Z anholt $ 30119895Sanholt */ 31119895Sanholt 32119895Sanholt#include "dev/drm/sis.h" 33119895Sanholt#include "dev/drm/drmP.h" 34119895Sanholt#include "dev/drm/sis_drm.h" 35119895Sanholt#include "dev/drm/sis_drv.h" 36119895Sanholt#include "dev/drm/sis_ds.h" 37119895Sanholt#if defined(__linux__) && defined(CONFIG_FB_SIS) 38130331Sanholt#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) 39130331Sanholt#include <video/sisfb.h> 40130331Sanholt#else 41119895Sanholt#include <linux/sisfb.h> 42119895Sanholt#endif 43130331Sanholt#endif 44119895Sanholt 45119895Sanholt#define MAX_CONTEXT 100 46119895Sanholt#define VIDEO_TYPE 0 47119895Sanholt#define AGP_TYPE 1 48119895Sanholt 49119895Sanholttypedef struct { 50119895Sanholt int used; 51119895Sanholt int context; 52119895Sanholt set_t *sets[2]; /* 0 for video, 1 for AGP */ 53119895Sanholt} sis_context_t; 54119895Sanholt 55119895Sanholtstatic sis_context_t global_ppriv[MAX_CONTEXT]; 56119895Sanholt 57119895Sanholt 58119895Sanholtstatic int add_alloc_set(int context, int type, unsigned int val) 59119895Sanholt{ 60119895Sanholt int i, retval = 0; 61119895Sanholt 62119895Sanholt for (i = 0; i < MAX_CONTEXT; i++) { 63119895Sanholt if (global_ppriv[i].used && global_ppriv[i].context == context) 64119895Sanholt { 65119895Sanholt retval = setAdd(global_ppriv[i].sets[type], val); 66119895Sanholt break; 67119895Sanholt } 68119895Sanholt } 69119895Sanholt return retval; 70119895Sanholt} 71119895Sanholt 72119895Sanholtstatic int del_alloc_set(int context, int type, unsigned int val) 73119895Sanholt{ 74119895Sanholt int i, retval = 0; 75119895Sanholt 76119895Sanholt for (i = 0; i < MAX_CONTEXT; i++) { 77119895Sanholt if (global_ppriv[i].used && global_ppriv[i].context == context) 78119895Sanholt { 79119895Sanholt retval = setDel(global_ppriv[i].sets[type], val); 80119895Sanholt break; 81119895Sanholt } 82119895Sanholt } 83119895Sanholt return retval; 84119895Sanholt} 85119895Sanholt 86119895Sanholt/* fb management via fb device */ 87119895Sanholt#if defined(__linux__) && defined(CONFIG_FB_SIS) 88119895Sanholt 89119895Sanholtint sis_fb_init( DRM_IOCTL_ARGS ) 90119895Sanholt{ 91119895Sanholt return 0; 92119895Sanholt} 93119895Sanholt 94119895Sanholtint sis_fb_alloc( DRM_IOCTL_ARGS ) 95119895Sanholt{ 96119895Sanholt drm_sis_mem_t fb; 97119895Sanholt struct sis_memreq req; 98119895Sanholt int retval = 0; 99119895Sanholt 100119895Sanholt DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t *)data, sizeof(fb)); 101119895Sanholt 102119895Sanholt req.size = fb.size; 103119895Sanholt sis_malloc(&req); 104119895Sanholt if (req.offset) { 105119895Sanholt /* TODO */ 106119895Sanholt fb.offset = req.offset; 107119895Sanholt fb.free = req.offset; 108119895Sanholt if (!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)) { 109119895Sanholt DRM_DEBUG("adding to allocation set fails\n"); 110119895Sanholt sis_free(req.offset); 111119895Sanholt retval = DRM_ERR(EINVAL); 112119895Sanholt } 113119895Sanholt } else { 114119895Sanholt fb.offset = 0; 115119895Sanholt fb.size = 0; 116119895Sanholt fb.free = 0; 117119895Sanholt } 118119895Sanholt 119119895Sanholt DRM_COPY_TO_USER_IOCTL((drm_sis_mem_t *)data, fb, sizeof(fb)); 120119895Sanholt 121119895Sanholt DRM_DEBUG("alloc fb, size = %d, offset = %ld\n", fb.size, req.offset); 122119895Sanholt 123119895Sanholt return retval; 124119895Sanholt} 125119895Sanholt 126119895Sanholtint sis_fb_free( DRM_IOCTL_ARGS ) 127119895Sanholt{ 128119895Sanholt drm_sis_mem_t fb; 129119895Sanholt int retval = 0; 130119895Sanholt 131119895Sanholt DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t *)data, sizeof(fb)); 132119895Sanholt 133119895Sanholt if (!fb.free) 134119895Sanholt return DRM_ERR(EINVAL); 135119895Sanholt 136119895Sanholt if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free)) 137119895Sanholt retval = DRM_ERR(EINVAL); 138119895Sanholt sis_free(fb.free); 139119895Sanholt 140121447Sanholt DRM_DEBUG("free fb, offset = 0x%lx\n", fb.free); 141119895Sanholt 142119895Sanholt return retval; 143119895Sanholt} 144119895Sanholt 145119895Sanholt#else 146119895Sanholt 147119895Sanholt/* Called by the X Server to initialize the FB heap. Allocations will fail 148119895Sanholt * unless this is called. Offset is the beginning of the heap from the 149119895Sanholt * framebuffer offset (MaxXFBMem in XFree86). 150119895Sanholt * 151119895Sanholt * Memory layout according to Thomas Winischofer: 152119895Sanholt * |------------------|DDDDDDDDDDDDDDDDDDDDDDDDDDDDD|HHHH|CCCCCCCCCCC| 153119895Sanholt * 154119895Sanholt * X driver/sisfb HW- Command- 155119895Sanholt * framebuffer memory DRI heap Cursor queue 156119895Sanholt */ 157119895Sanholtint sis_fb_init( DRM_IOCTL_ARGS ) 158119895Sanholt{ 159119895Sanholt DRM_DEVICE; 160119895Sanholt drm_sis_private_t *dev_priv = dev->dev_private; 161119895Sanholt drm_sis_fb_t fb; 162119895Sanholt 163119895Sanholt DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_fb_t *)data, sizeof(fb)); 164119895Sanholt 165119895Sanholt if (dev_priv == NULL) { 166119895Sanholt dev->dev_private = DRM(calloc)(1, sizeof(drm_sis_private_t), 167119895Sanholt DRM_MEM_DRIVER); 168119895Sanholt dev_priv = dev->dev_private; 169119895Sanholt if (dev_priv == NULL) 170119895Sanholt return ENOMEM; 171119895Sanholt } 172119895Sanholt 173119895Sanholt if (dev_priv->FBHeap != NULL) 174119895Sanholt return DRM_ERR(EINVAL); 175119895Sanholt 176119895Sanholt dev_priv->FBHeap = mmInit(fb.offset, fb.size); 177119895Sanholt 178119895Sanholt DRM_DEBUG("offset = %u, size = %u", fb.offset, fb.size); 179119895Sanholt 180119895Sanholt return 0; 181119895Sanholt} 182119895Sanholt 183119895Sanholtint sis_fb_alloc( DRM_IOCTL_ARGS ) 184119895Sanholt{ 185119895Sanholt DRM_DEVICE; 186119895Sanholt drm_sis_private_t *dev_priv = dev->dev_private; 187119895Sanholt drm_sis_mem_t fb; 188119895Sanholt PMemBlock block; 189119895Sanholt int retval = 0; 190119895Sanholt 191119895Sanholt if (dev_priv == NULL || dev_priv->FBHeap == NULL) 192119895Sanholt return DRM_ERR(EINVAL); 193119895Sanholt 194119895Sanholt DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t *)data, sizeof(fb)); 195119895Sanholt 196119895Sanholt block = mmAllocMem(dev_priv->FBHeap, fb.size, 0, 0); 197119895Sanholt if (block) { 198119895Sanholt /* TODO */ 199119895Sanholt fb.offset = block->ofs; 200119895Sanholt fb.free = (unsigned long)block; 201119895Sanholt if (!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)) { 202119895Sanholt DRM_DEBUG("adding to allocation set fails\n"); 203119895Sanholt mmFreeMem((PMemBlock)fb.free); 204119895Sanholt retval = DRM_ERR(EINVAL); 205119895Sanholt } 206119895Sanholt } else { 207119895Sanholt fb.offset = 0; 208119895Sanholt fb.size = 0; 209119895Sanholt fb.free = 0; 210119895Sanholt } 211119895Sanholt 212119895Sanholt DRM_COPY_TO_USER_IOCTL((drm_sis_mem_t *)data, fb, sizeof(fb)); 213119895Sanholt 214119895Sanholt DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, fb.offset); 215119895Sanholt 216119895Sanholt return retval; 217119895Sanholt} 218119895Sanholt 219119895Sanholtint sis_fb_free( DRM_IOCTL_ARGS ) 220119895Sanholt{ 221119895Sanholt DRM_DEVICE; 222119895Sanholt drm_sis_private_t *dev_priv = dev->dev_private; 223119895Sanholt drm_sis_mem_t fb; 224119895Sanholt 225119895Sanholt if (dev_priv == NULL || dev_priv->FBHeap == NULL) 226119895Sanholt return DRM_ERR(EINVAL); 227119895Sanholt 228119895Sanholt DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t *)data, sizeof(fb)); 229119895Sanholt 230119895Sanholt if (!mmBlockInHeap(dev_priv->FBHeap, (PMemBlock)fb.free)) 231119895Sanholt return DRM_ERR(EINVAL); 232119895Sanholt 233119895Sanholt if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free)) 234119895Sanholt return DRM_ERR(EINVAL); 235119895Sanholt mmFreeMem((PMemBlock)fb.free); 236119895Sanholt 237119895Sanholt DRM_DEBUG("free fb, free = 0x%lx\n", fb.free); 238119895Sanholt 239119895Sanholt return 0; 240119895Sanholt} 241119895Sanholt 242119895Sanholt#endif 243119895Sanholt 244119895Sanholt/* agp memory management */ 245119895Sanholt 246119895Sanholtint sis_ioctl_agp_init( DRM_IOCTL_ARGS ) 247119895Sanholt{ 248119895Sanholt DRM_DEVICE; 249119895Sanholt drm_sis_private_t *dev_priv = dev->dev_private; 250119895Sanholt drm_sis_agp_t agp; 251119895Sanholt 252119895Sanholt if (dev_priv == NULL) { 253119895Sanholt dev->dev_private = DRM(calloc)(1, sizeof(drm_sis_private_t), 254119895Sanholt DRM_MEM_DRIVER); 255119895Sanholt dev_priv = dev->dev_private; 256119895Sanholt if (dev_priv == NULL) 257119895Sanholt return ENOMEM; 258119895Sanholt } 259119895Sanholt 260119895Sanholt if (dev_priv->AGPHeap != NULL) 261119895Sanholt return DRM_ERR(EINVAL); 262119895Sanholt 263119895Sanholt DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_agp_t *)data, sizeof(agp)); 264119895Sanholt 265119895Sanholt dev_priv->AGPHeap = mmInit(agp.offset, agp.size); 266119895Sanholt 267119895Sanholt DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size); 268119895Sanholt 269119895Sanholt return 0; 270119895Sanholt} 271119895Sanholt 272119895Sanholtint sis_ioctl_agp_alloc( DRM_IOCTL_ARGS ) 273119895Sanholt{ 274119895Sanholt DRM_DEVICE; 275119895Sanholt drm_sis_private_t *dev_priv = dev->dev_private; 276119895Sanholt drm_sis_mem_t agp; 277119895Sanholt PMemBlock block; 278119895Sanholt int retval = 0; 279119895Sanholt 280119895Sanholt if (dev_priv == NULL || dev_priv->AGPHeap == NULL) 281119895Sanholt return DRM_ERR(EINVAL); 282119895Sanholt 283119895Sanholt DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_mem_t *)data, sizeof(agp)); 284119895Sanholt 285119895Sanholt block = mmAllocMem(dev_priv->AGPHeap, agp.size, 0, 0); 286119895Sanholt if (block) { 287119895Sanholt /* TODO */ 288119895Sanholt agp.offset = block->ofs; 289119895Sanholt agp.free = (unsigned long)block; 290119895Sanholt if (!add_alloc_set(agp.context, AGP_TYPE, agp.free)) { 291119895Sanholt DRM_DEBUG("adding to allocation set fails\n"); 292119895Sanholt mmFreeMem((PMemBlock)agp.free); 293119895Sanholt retval = -1; 294119895Sanholt } 295119895Sanholt } else { 296119895Sanholt agp.offset = 0; 297119895Sanholt agp.size = 0; 298119895Sanholt agp.free = 0; 299119895Sanholt } 300119895Sanholt 301119895Sanholt DRM_COPY_TO_USER_IOCTL((drm_sis_mem_t *)data, agp, sizeof(agp)); 302119895Sanholt 303119895Sanholt DRM_DEBUG("alloc agp, size = %d, offset = %d\n", agp.size, agp.offset); 304119895Sanholt 305119895Sanholt return retval; 306119895Sanholt} 307119895Sanholt 308119895Sanholtint sis_ioctl_agp_free( DRM_IOCTL_ARGS ) 309119895Sanholt{ 310119895Sanholt DRM_DEVICE; 311119895Sanholt drm_sis_private_t *dev_priv = dev->dev_private; 312119895Sanholt drm_sis_mem_t agp; 313119895Sanholt 314119895Sanholt if (dev_priv == NULL || dev_priv->AGPHeap == NULL) 315119895Sanholt return DRM_ERR(EINVAL); 316119895Sanholt 317119895Sanholt DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_mem_t *)data, sizeof(agp)); 318119895Sanholt 319119895Sanholt if (!mmBlockInHeap(dev_priv->AGPHeap, (PMemBlock)agp.free)) 320119895Sanholt return DRM_ERR(EINVAL); 321119895Sanholt 322119895Sanholt mmFreeMem((PMemBlock)agp.free); 323119895Sanholt if (!del_alloc_set(agp.context, AGP_TYPE, agp.free)) 324119895Sanholt return DRM_ERR(EINVAL); 325119895Sanholt 326119895Sanholt DRM_DEBUG("free agp, free = 0x%lx\n", agp.free); 327119895Sanholt 328119895Sanholt return 0; 329119895Sanholt} 330119895Sanholt 331119895Sanholtint sis_init_context(int context) 332119895Sanholt{ 333119895Sanholt int i; 334119895Sanholt 335119895Sanholt for (i = 0; i < MAX_CONTEXT ; i++) { 336119895Sanholt if (global_ppriv[i].used && 337119895Sanholt (global_ppriv[i].context == context)) 338119895Sanholt break; 339119895Sanholt } 340119895Sanholt 341119895Sanholt if (i >= MAX_CONTEXT) { 342119895Sanholt for (i = 0; i < MAX_CONTEXT ; i++) { 343119895Sanholt if (!global_ppriv[i].used) { 344119895Sanholt global_ppriv[i].context = context; 345119895Sanholt global_ppriv[i].used = 1; 346119895Sanholt global_ppriv[i].sets[0] = setInit(); 347119895Sanholt global_ppriv[i].sets[1] = setInit(); 348119895Sanholt DRM_DEBUG("init allocation set, socket=%d, " 349119895Sanholt "context = %d\n", i, context); 350119895Sanholt break; 351119895Sanholt } 352119895Sanholt } 353119895Sanholt if ((i >= MAX_CONTEXT) || (global_ppriv[i].sets[0] == NULL) || 354119895Sanholt (global_ppriv[i].sets[1] == NULL)) 355119895Sanholt { 356119895Sanholt return 0; 357119895Sanholt } 358119895Sanholt } 359119895Sanholt 360119895Sanholt return 1; 361119895Sanholt} 362119895Sanholt 363119895Sanholtint sis_final_context(int context) 364119895Sanholt{ 365119895Sanholt int i; 366119895Sanholt 367119895Sanholt for (i=0; i<MAX_CONTEXT; i++) { 368119895Sanholt if (global_ppriv[i].used && 369119895Sanholt (global_ppriv[i].context == context)) 370119895Sanholt break; 371119895Sanholt } 372119895Sanholt 373119895Sanholt if (i < MAX_CONTEXT) { 374119895Sanholt set_t *set; 375126525Sobrien ITEM_TYPE item; 376119895Sanholt int retval; 377119895Sanholt 378119895Sanholt DRM_DEBUG("find socket %d, context = %d\n", i, context); 379119895Sanholt 380119895Sanholt /* Video Memory */ 381119895Sanholt set = global_ppriv[i].sets[0]; 382119895Sanholt retval = setFirst(set, &item); 383119895Sanholt while (retval) { 384126525Sobrien DRM_DEBUG("free video memory 0x%lx\n", item); 385119895Sanholt#if defined(__linux__) && defined(CONFIG_FB_SIS) 386119895Sanholt sis_free(item); 387119895Sanholt#else 388119895Sanholt mmFreeMem((PMemBlock)item); 389119895Sanholt#endif 390119895Sanholt retval = setNext(set, &item); 391119895Sanholt } 392119895Sanholt setDestroy(set); 393119895Sanholt 394119895Sanholt /* AGP Memory */ 395119895Sanholt set = global_ppriv[i].sets[1]; 396119895Sanholt retval = setFirst(set, &item); 397119895Sanholt while (retval) { 398126525Sobrien DRM_DEBUG("free agp memory 0x%lx\n", item); 399119895Sanholt mmFreeMem((PMemBlock)item); 400119895Sanholt retval = setNext(set, &item); 401119895Sanholt } 402119895Sanholt setDestroy(set); 403119895Sanholt 404119895Sanholt global_ppriv[i].used = 0; 405119895Sanholt } 406119895Sanholt 407119895Sanholt return 1; 408119895Sanholt} 409