sis_mm.c revision 119895
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 119895 2003-09-09 00:24:31Z 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) 38119895Sanholt#include <linux/sisfb.h> 39119895Sanholt#endif 40119895Sanholt 41119895Sanholt#define MAX_CONTEXT 100 42119895Sanholt#define VIDEO_TYPE 0 43119895Sanholt#define AGP_TYPE 1 44119895Sanholt 45119895Sanholttypedef struct { 46119895Sanholt int used; 47119895Sanholt int context; 48119895Sanholt set_t *sets[2]; /* 0 for video, 1 for AGP */ 49119895Sanholt} sis_context_t; 50119895Sanholt 51119895Sanholtstatic sis_context_t global_ppriv[MAX_CONTEXT]; 52119895Sanholt 53119895Sanholt 54119895Sanholtstatic int add_alloc_set(int context, int type, unsigned int val) 55119895Sanholt{ 56119895Sanholt int i, retval = 0; 57119895Sanholt 58119895Sanholt for (i = 0; i < MAX_CONTEXT; i++) { 59119895Sanholt if (global_ppriv[i].used && global_ppriv[i].context == context) 60119895Sanholt { 61119895Sanholt retval = setAdd(global_ppriv[i].sets[type], val); 62119895Sanholt break; 63119895Sanholt } 64119895Sanholt } 65119895Sanholt return retval; 66119895Sanholt} 67119895Sanholt 68119895Sanholtstatic int del_alloc_set(int context, int type, unsigned int val) 69119895Sanholt{ 70119895Sanholt int i, retval = 0; 71119895Sanholt 72119895Sanholt for (i = 0; i < MAX_CONTEXT; i++) { 73119895Sanholt if (global_ppriv[i].used && global_ppriv[i].context == context) 74119895Sanholt { 75119895Sanholt retval = setDel(global_ppriv[i].sets[type], val); 76119895Sanholt break; 77119895Sanholt } 78119895Sanholt } 79119895Sanholt return retval; 80119895Sanholt} 81119895Sanholt 82119895Sanholt/* fb management via fb device */ 83119895Sanholt#if defined(__linux__) && defined(CONFIG_FB_SIS) 84119895Sanholt 85119895Sanholtint sis_fb_init( DRM_IOCTL_ARGS ) 86119895Sanholt{ 87119895Sanholt return 0; 88119895Sanholt} 89119895Sanholt 90119895Sanholtint sis_fb_alloc( DRM_IOCTL_ARGS ) 91119895Sanholt{ 92119895Sanholt drm_sis_mem_t fb; 93119895Sanholt struct sis_memreq req; 94119895Sanholt int retval = 0; 95119895Sanholt 96119895Sanholt DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t *)data, sizeof(fb)); 97119895Sanholt 98119895Sanholt req.size = fb.size; 99119895Sanholt sis_malloc(&req); 100119895Sanholt if (req.offset) { 101119895Sanholt /* TODO */ 102119895Sanholt fb.offset = req.offset; 103119895Sanholt fb.free = req.offset; 104119895Sanholt if (!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)) { 105119895Sanholt DRM_DEBUG("adding to allocation set fails\n"); 106119895Sanholt sis_free(req.offset); 107119895Sanholt retval = DRM_ERR(EINVAL); 108119895Sanholt } 109119895Sanholt } else { 110119895Sanholt fb.offset = 0; 111119895Sanholt fb.size = 0; 112119895Sanholt fb.free = 0; 113119895Sanholt } 114119895Sanholt 115119895Sanholt DRM_COPY_TO_USER_IOCTL((drm_sis_mem_t *)data, fb, sizeof(fb)); 116119895Sanholt 117119895Sanholt DRM_DEBUG("alloc fb, size = %d, offset = %ld\n", fb.size, req.offset); 118119895Sanholt 119119895Sanholt return retval; 120119895Sanholt} 121119895Sanholt 122119895Sanholtint sis_fb_free( DRM_IOCTL_ARGS ) 123119895Sanholt{ 124119895Sanholt drm_sis_mem_t fb; 125119895Sanholt int retval = 0; 126119895Sanholt 127119895Sanholt DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t *)data, sizeof(fb)); 128119895Sanholt 129119895Sanholt if (!fb.free) 130119895Sanholt return DRM_ERR(EINVAL); 131119895Sanholt 132119895Sanholt if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free)) 133119895Sanholt retval = DRM_ERR(EINVAL); 134119895Sanholt sis_free(fb.free); 135119895Sanholt 136119895Sanholt DRM_DEBUG("free fb, offset = %d\n", fb.free); 137119895Sanholt 138119895Sanholt return retval; 139119895Sanholt} 140119895Sanholt 141119895Sanholt#else 142119895Sanholt 143119895Sanholt/* Called by the X Server to initialize the FB heap. Allocations will fail 144119895Sanholt * unless this is called. Offset is the beginning of the heap from the 145119895Sanholt * framebuffer offset (MaxXFBMem in XFree86). 146119895Sanholt * 147119895Sanholt * Memory layout according to Thomas Winischofer: 148119895Sanholt * |------------------|DDDDDDDDDDDDDDDDDDDDDDDDDDDDD|HHHH|CCCCCCCCCCC| 149119895Sanholt * 150119895Sanholt * X driver/sisfb HW- Command- 151119895Sanholt * framebuffer memory DRI heap Cursor queue 152119895Sanholt */ 153119895Sanholtint sis_fb_init( DRM_IOCTL_ARGS ) 154119895Sanholt{ 155119895Sanholt DRM_DEVICE; 156119895Sanholt drm_sis_private_t *dev_priv = dev->dev_private; 157119895Sanholt drm_sis_fb_t fb; 158119895Sanholt 159119895Sanholt DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_fb_t *)data, sizeof(fb)); 160119895Sanholt 161119895Sanholt if (dev_priv == NULL) { 162119895Sanholt dev->dev_private = DRM(calloc)(1, sizeof(drm_sis_private_t), 163119895Sanholt DRM_MEM_DRIVER); 164119895Sanholt dev_priv = dev->dev_private; 165119895Sanholt if (dev_priv == NULL) 166119895Sanholt return ENOMEM; 167119895Sanholt } 168119895Sanholt 169119895Sanholt if (dev_priv->FBHeap != NULL) 170119895Sanholt return DRM_ERR(EINVAL); 171119895Sanholt 172119895Sanholt dev_priv->FBHeap = mmInit(fb.offset, fb.size); 173119895Sanholt 174119895Sanholt DRM_DEBUG("offset = %u, size = %u", fb.offset, fb.size); 175119895Sanholt 176119895Sanholt return 0; 177119895Sanholt} 178119895Sanholt 179119895Sanholtint sis_fb_alloc( DRM_IOCTL_ARGS ) 180119895Sanholt{ 181119895Sanholt DRM_DEVICE; 182119895Sanholt drm_sis_private_t *dev_priv = dev->dev_private; 183119895Sanholt drm_sis_mem_t fb; 184119895Sanholt PMemBlock block; 185119895Sanholt int retval = 0; 186119895Sanholt 187119895Sanholt if (dev_priv == NULL || dev_priv->FBHeap == NULL) 188119895Sanholt return DRM_ERR(EINVAL); 189119895Sanholt 190119895Sanholt DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t *)data, sizeof(fb)); 191119895Sanholt 192119895Sanholt block = mmAllocMem(dev_priv->FBHeap, fb.size, 0, 0); 193119895Sanholt if (block) { 194119895Sanholt /* TODO */ 195119895Sanholt fb.offset = block->ofs; 196119895Sanholt fb.free = (unsigned long)block; 197119895Sanholt if (!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)) { 198119895Sanholt DRM_DEBUG("adding to allocation set fails\n"); 199119895Sanholt mmFreeMem((PMemBlock)fb.free); 200119895Sanholt retval = DRM_ERR(EINVAL); 201119895Sanholt } 202119895Sanholt } else { 203119895Sanholt fb.offset = 0; 204119895Sanholt fb.size = 0; 205119895Sanholt fb.free = 0; 206119895Sanholt } 207119895Sanholt 208119895Sanholt DRM_COPY_TO_USER_IOCTL((drm_sis_mem_t *)data, fb, sizeof(fb)); 209119895Sanholt 210119895Sanholt DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, fb.offset); 211119895Sanholt 212119895Sanholt return retval; 213119895Sanholt} 214119895Sanholt 215119895Sanholtint sis_fb_free( DRM_IOCTL_ARGS ) 216119895Sanholt{ 217119895Sanholt DRM_DEVICE; 218119895Sanholt drm_sis_private_t *dev_priv = dev->dev_private; 219119895Sanholt drm_sis_mem_t fb; 220119895Sanholt 221119895Sanholt if (dev_priv == NULL || dev_priv->FBHeap == NULL) 222119895Sanholt return DRM_ERR(EINVAL); 223119895Sanholt 224119895Sanholt DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t *)data, sizeof(fb)); 225119895Sanholt 226119895Sanholt if (!mmBlockInHeap(dev_priv->FBHeap, (PMemBlock)fb.free)) 227119895Sanholt return DRM_ERR(EINVAL); 228119895Sanholt 229119895Sanholt if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free)) 230119895Sanholt return DRM_ERR(EINVAL); 231119895Sanholt mmFreeMem((PMemBlock)fb.free); 232119895Sanholt 233119895Sanholt DRM_DEBUG("free fb, free = 0x%lx\n", fb.free); 234119895Sanholt 235119895Sanholt return 0; 236119895Sanholt} 237119895Sanholt 238119895Sanholt#endif 239119895Sanholt 240119895Sanholt/* agp memory management */ 241119895Sanholt 242119895Sanholtint sis_ioctl_agp_init( DRM_IOCTL_ARGS ) 243119895Sanholt{ 244119895Sanholt DRM_DEVICE; 245119895Sanholt drm_sis_private_t *dev_priv = dev->dev_private; 246119895Sanholt drm_sis_agp_t agp; 247119895Sanholt 248119895Sanholt if (dev_priv == NULL) { 249119895Sanholt dev->dev_private = DRM(calloc)(1, sizeof(drm_sis_private_t), 250119895Sanholt DRM_MEM_DRIVER); 251119895Sanholt dev_priv = dev->dev_private; 252119895Sanholt if (dev_priv == NULL) 253119895Sanholt return ENOMEM; 254119895Sanholt } 255119895Sanholt 256119895Sanholt if (dev_priv->AGPHeap != NULL) 257119895Sanholt return DRM_ERR(EINVAL); 258119895Sanholt 259119895Sanholt DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_agp_t *)data, sizeof(agp)); 260119895Sanholt 261119895Sanholt dev_priv->AGPHeap = mmInit(agp.offset, agp.size); 262119895Sanholt 263119895Sanholt DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size); 264119895Sanholt 265119895Sanholt return 0; 266119895Sanholt} 267119895Sanholt 268119895Sanholtint sis_ioctl_agp_alloc( DRM_IOCTL_ARGS ) 269119895Sanholt{ 270119895Sanholt DRM_DEVICE; 271119895Sanholt drm_sis_private_t *dev_priv = dev->dev_private; 272119895Sanholt drm_sis_mem_t agp; 273119895Sanholt PMemBlock block; 274119895Sanholt int retval = 0; 275119895Sanholt 276119895Sanholt if (dev_priv == NULL || dev_priv->AGPHeap == NULL) 277119895Sanholt return DRM_ERR(EINVAL); 278119895Sanholt 279119895Sanholt DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_mem_t *)data, sizeof(agp)); 280119895Sanholt 281119895Sanholt block = mmAllocMem(dev_priv->AGPHeap, agp.size, 0, 0); 282119895Sanholt if (block) { 283119895Sanholt /* TODO */ 284119895Sanholt agp.offset = block->ofs; 285119895Sanholt agp.free = (unsigned long)block; 286119895Sanholt if (!add_alloc_set(agp.context, AGP_TYPE, agp.free)) { 287119895Sanholt DRM_DEBUG("adding to allocation set fails\n"); 288119895Sanholt mmFreeMem((PMemBlock)agp.free); 289119895Sanholt retval = -1; 290119895Sanholt } 291119895Sanholt } else { 292119895Sanholt agp.offset = 0; 293119895Sanholt agp.size = 0; 294119895Sanholt agp.free = 0; 295119895Sanholt } 296119895Sanholt 297119895Sanholt DRM_COPY_TO_USER_IOCTL((drm_sis_mem_t *)data, agp, sizeof(agp)); 298119895Sanholt 299119895Sanholt DRM_DEBUG("alloc agp, size = %d, offset = %d\n", agp.size, agp.offset); 300119895Sanholt 301119895Sanholt return retval; 302119895Sanholt} 303119895Sanholt 304119895Sanholtint sis_ioctl_agp_free( DRM_IOCTL_ARGS ) 305119895Sanholt{ 306119895Sanholt DRM_DEVICE; 307119895Sanholt drm_sis_private_t *dev_priv = dev->dev_private; 308119895Sanholt drm_sis_mem_t agp; 309119895Sanholt 310119895Sanholt if (dev_priv == NULL || dev_priv->AGPHeap == NULL) 311119895Sanholt return DRM_ERR(EINVAL); 312119895Sanholt 313119895Sanholt DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_mem_t *)data, sizeof(agp)); 314119895Sanholt 315119895Sanholt if (!mmBlockInHeap(dev_priv->AGPHeap, (PMemBlock)agp.free)) 316119895Sanholt return DRM_ERR(EINVAL); 317119895Sanholt 318119895Sanholt mmFreeMem((PMemBlock)agp.free); 319119895Sanholt if (!del_alloc_set(agp.context, AGP_TYPE, agp.free)) 320119895Sanholt return DRM_ERR(EINVAL); 321119895Sanholt 322119895Sanholt DRM_DEBUG("free agp, free = 0x%lx\n", agp.free); 323119895Sanholt 324119895Sanholt return 0; 325119895Sanholt} 326119895Sanholt 327119895Sanholtint sis_init_context(int context) 328119895Sanholt{ 329119895Sanholt int i; 330119895Sanholt 331119895Sanholt for (i = 0; i < MAX_CONTEXT ; i++) { 332119895Sanholt if (global_ppriv[i].used && 333119895Sanholt (global_ppriv[i].context == context)) 334119895Sanholt break; 335119895Sanholt } 336119895Sanholt 337119895Sanholt if (i >= MAX_CONTEXT) { 338119895Sanholt for (i = 0; i < MAX_CONTEXT ; i++) { 339119895Sanholt if (!global_ppriv[i].used) { 340119895Sanholt global_ppriv[i].context = context; 341119895Sanholt global_ppriv[i].used = 1; 342119895Sanholt global_ppriv[i].sets[0] = setInit(); 343119895Sanholt global_ppriv[i].sets[1] = setInit(); 344119895Sanholt DRM_DEBUG("init allocation set, socket=%d, " 345119895Sanholt "context = %d\n", i, context); 346119895Sanholt break; 347119895Sanholt } 348119895Sanholt } 349119895Sanholt if ((i >= MAX_CONTEXT) || (global_ppriv[i].sets[0] == NULL) || 350119895Sanholt (global_ppriv[i].sets[1] == NULL)) 351119895Sanholt { 352119895Sanholt return 0; 353119895Sanholt } 354119895Sanholt } 355119895Sanholt 356119895Sanholt return 1; 357119895Sanholt} 358119895Sanholt 359119895Sanholtint sis_final_context(int context) 360119895Sanholt{ 361119895Sanholt int i; 362119895Sanholt 363119895Sanholt for (i=0; i<MAX_CONTEXT; i++) { 364119895Sanholt if (global_ppriv[i].used && 365119895Sanholt (global_ppriv[i].context == context)) 366119895Sanholt break; 367119895Sanholt } 368119895Sanholt 369119895Sanholt if (i < MAX_CONTEXT) { 370119895Sanholt set_t *set; 371119895Sanholt unsigned int item; 372119895Sanholt int retval; 373119895Sanholt 374119895Sanholt DRM_DEBUG("find socket %d, context = %d\n", i, context); 375119895Sanholt 376119895Sanholt /* Video Memory */ 377119895Sanholt set = global_ppriv[i].sets[0]; 378119895Sanholt retval = setFirst(set, &item); 379119895Sanholt while (retval) { 380119895Sanholt DRM_DEBUG("free video memory 0x%x\n", item); 381119895Sanholt#if defined(__linux__) && defined(CONFIG_FB_SIS) 382119895Sanholt sis_free(item); 383119895Sanholt#else 384119895Sanholt mmFreeMem((PMemBlock)item); 385119895Sanholt#endif 386119895Sanholt retval = setNext(set, &item); 387119895Sanholt } 388119895Sanholt setDestroy(set); 389119895Sanholt 390119895Sanholt /* AGP Memory */ 391119895Sanholt set = global_ppriv[i].sets[1]; 392119895Sanholt retval = setFirst(set, &item); 393119895Sanholt while (retval) { 394119895Sanholt DRM_DEBUG("free agp memory 0x%x\n", item); 395119895Sanholt mmFreeMem((PMemBlock)item); 396119895Sanholt retval = setNext(set, &item); 397119895Sanholt } 398119895Sanholt setDestroy(set); 399119895Sanholt 400119895Sanholt global_ppriv[i].used = 0; 401119895Sanholt } 402119895Sanholt 403119895Sanholt return 1; 404119895Sanholt} 405