The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/drm/sis_mm.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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 <sys/cdefs.h>
   32 __FBSDID("$FreeBSD: releng/6.4/sys/dev/drm/sis_mm.c 158686 2006-05-17 07:40:12Z anholt $");
   33 
   34 #if defined(__linux__) && defined(CONFIG_FB_SIS)
   35 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
   36 #include <video/sisfb.h>
   37 #else
   38 #include <linux/sisfb.h>
   39 #endif
   40 #endif
   41 #include "dev/drm/drmP.h"
   42 #include "dev/drm/sis_drm.h"
   43 #include "dev/drm/sis_drv.h"
   44 #include "dev/drm/sis_ds.h"
   45 
   46 #define MAX_CONTEXT 100
   47 #define VIDEO_TYPE 0
   48 #define AGP_TYPE 1
   49 
   50 typedef struct {
   51         int used;
   52         int context;
   53         set_t *sets[2];         /* 0 for video, 1 for AGP */
   54 } sis_context_t;
   55 
   56 static sis_context_t global_ppriv[MAX_CONTEXT];
   57 
   58 static int add_alloc_set(int context, int type, unsigned int val)
   59 {
   60         int i, retval = 0;
   61 
   62         for (i = 0; i < MAX_CONTEXT; i++) {
   63                 if (global_ppriv[i].used && global_ppriv[i].context == context) {
   64                         retval = setAdd(global_ppriv[i].sets[type], val);
   65                         break;
   66                 }
   67         }
   68         return retval;
   69 }
   70 
   71 static int del_alloc_set(int context, int type, unsigned int val)
   72 {
   73         int i, retval = 0;
   74 
   75         for (i = 0; i < MAX_CONTEXT; i++) {
   76                 if (global_ppriv[i].used && global_ppriv[i].context == context) {
   77                         retval = setDel(global_ppriv[i].sets[type], val);
   78                         break;
   79                 }
   80         }
   81         return retval;
   82 }
   83 
   84 /* fb management via fb device */
   85 #if defined(__linux__) && defined(CONFIG_FB_SIS)
   86 
   87 static int sis_fb_init(DRM_IOCTL_ARGS)
   88 {
   89         return 0;
   90 }
   91 
   92 static int sis_fb_alloc(DRM_IOCTL_ARGS)
   93 {
   94         drm_sis_mem_t fb;
   95         struct sis_memreq req;
   96         drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *)data;
   97         int retval = 0;
   98 
   99         DRM_COPY_FROM_USER_IOCTL(fb, argp, sizeof(fb));
  100 
  101         req.size = fb.size;
  102         sis_malloc(&req);
  103         if (req.offset) {
  104                 /* TODO */
  105                 fb.offset = req.offset;
  106                 fb.free = req.offset;
  107                 if (!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)) {
  108                         DRM_DEBUG("adding to allocation set fails\n");
  109                         sis_free(req.offset);
  110                         retval = DRM_ERR(EINVAL);
  111                 }
  112         } else {
  113                 fb.offset = 0;
  114                 fb.size = 0;
  115                 fb.free = 0;
  116         }
  117 
  118         DRM_COPY_TO_USER_IOCTL(argp, fb, sizeof(fb));
  119 
  120         DRM_DEBUG("alloc fb, size = %d, offset = %ld\n", fb.size, req.offset);
  121 
  122         return retval;
  123 }
  124 
  125 static int sis_fb_free(DRM_IOCTL_ARGS)
  126 {
  127         drm_sis_mem_t fb;
  128         int retval = 0;
  129 
  130         DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t __user *) data, sizeof(fb));
  131 
  132         if (!fb.free)
  133                 return DRM_ERR(EINVAL);
  134 
  135         if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free))
  136                 retval = DRM_ERR(EINVAL);
  137         sis_free(fb.free);
  138 
  139         DRM_DEBUG("free fb, offset = 0x%lx\n", fb.free);
  140 
  141         return retval;
  142 }
  143 
  144 #else
  145 
  146 /* Called by the X Server to initialize the FB heap.  Allocations will fail
  147  * unless this is called.  Offset is the beginning of the heap from the
  148  * framebuffer offset (MaxXFBMem in XFree86).
  149  *
  150  * Memory layout according to Thomas Winischofer:
  151  * |------------------|DDDDDDDDDDDDDDDDDDDDDDDDDDDDD|HHHH|CCCCCCCCCCC|
  152  *
  153  *    X driver/sisfb                                  HW-   Command-
  154  *  framebuffer memory           DRI heap           Cursor   queue
  155  */
  156 static int sis_fb_init(DRM_IOCTL_ARGS)
  157 {
  158         DRM_DEVICE;
  159         drm_sis_private_t *dev_priv = dev->dev_private;
  160         drm_sis_fb_t fb;
  161 
  162         DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_fb_t __user *) data, sizeof(fb));
  163 
  164         if (dev_priv == NULL) {
  165                 dev->dev_private = drm_calloc(1, sizeof(drm_sis_private_t),
  166                                               DRM_MEM_DRIVER);
  167                 dev_priv = dev->dev_private;
  168                 if (dev_priv == NULL)
  169                         return ENOMEM;
  170         }
  171 
  172         if (dev_priv->FBHeap != NULL)
  173                 return DRM_ERR(EINVAL);
  174 
  175         dev_priv->FBHeap = mmInit(fb.offset, fb.size);
  176 
  177         DRM_DEBUG("offset = %u, size = %u", fb.offset, fb.size);
  178 
  179         return 0;
  180 }
  181 
  182 static int sis_fb_alloc(DRM_IOCTL_ARGS)
  183 {
  184         DRM_DEVICE;
  185         drm_sis_private_t *dev_priv = dev->dev_private;
  186         drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *)data;
  187         drm_sis_mem_t fb;
  188         PMemBlock block;
  189         int retval = 0;
  190 
  191         if (dev_priv == NULL || dev_priv->FBHeap == NULL)
  192                 return DRM_ERR(EINVAL);
  193 
  194         DRM_COPY_FROM_USER_IOCTL(fb, argp, sizeof(fb));
  195 
  196         block = mmAllocMem(dev_priv->FBHeap, fb.size, 0, 0);
  197         if (block) {
  198                 /* TODO */
  199                 fb.offset = block->ofs;
  200                 fb.free = (unsigned long)block;
  201                 if (!add_alloc_set(fb.context, VIDEO_TYPE, fb.free)) {
  202                         DRM_DEBUG("adding to allocation set fails\n");
  203                         mmFreeMem((PMemBlock) fb.free);
  204                         retval = DRM_ERR(EINVAL);
  205                 }
  206         } else {
  207                 fb.offset = 0;
  208                 fb.size = 0;
  209                 fb.free = 0;
  210         }
  211 
  212         DRM_COPY_TO_USER_IOCTL(argp, fb, sizeof(fb));
  213 
  214         DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, fb.offset);
  215 
  216         return retval;
  217 }
  218 
  219 static int sis_fb_free(DRM_IOCTL_ARGS)
  220 {
  221         DRM_DEVICE;
  222         drm_sis_private_t *dev_priv = dev->dev_private;
  223         drm_sis_mem_t fb;
  224 
  225         if (dev_priv == NULL || dev_priv->FBHeap == NULL)
  226                 return DRM_ERR(EINVAL);
  227 
  228         DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_mem_t __user *) data, sizeof(fb));
  229 
  230         if (!mmBlockInHeap(dev_priv->FBHeap, (PMemBlock) fb.free))
  231                 return DRM_ERR(EINVAL);
  232 
  233         if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free))
  234                 return DRM_ERR(EINVAL);
  235         mmFreeMem((PMemBlock) fb.free);
  236 
  237         DRM_DEBUG("free fb, free = 0x%lx\n", fb.free);
  238 
  239         return 0;
  240 }
  241 
  242 #endif
  243 
  244 /* agp memory management */
  245 
  246 static int sis_ioctl_agp_init(DRM_IOCTL_ARGS)
  247 {
  248         DRM_DEVICE;
  249         drm_sis_private_t *dev_priv = dev->dev_private;
  250         drm_sis_agp_t agp;
  251 
  252         if (dev_priv == NULL) {
  253                 dev->dev_private = drm_calloc(1, sizeof(drm_sis_private_t),
  254                                               DRM_MEM_DRIVER);
  255                 dev_priv = dev->dev_private;
  256                 if (dev_priv == NULL)
  257                         return ENOMEM;
  258         }
  259 
  260         if (dev_priv->AGPHeap != NULL)
  261                 return DRM_ERR(EINVAL);
  262 
  263         DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_agp_t __user *) data,
  264                                  sizeof(agp));
  265 
  266         dev_priv->AGPHeap = mmInit(agp.offset, agp.size);
  267 
  268         DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size);
  269 
  270         return 0;
  271 }
  272 
  273 static int sis_ioctl_agp_alloc(DRM_IOCTL_ARGS)
  274 {
  275         DRM_DEVICE;
  276         drm_sis_private_t *dev_priv = dev->dev_private;
  277         drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *)data;
  278         drm_sis_mem_t agp;
  279         PMemBlock block;
  280         int retval = 0;
  281 
  282         if (dev_priv == NULL || dev_priv->AGPHeap == NULL)
  283                 return DRM_ERR(EINVAL);
  284 
  285         DRM_COPY_FROM_USER_IOCTL(agp, argp, sizeof(agp));
  286 
  287         block = mmAllocMem(dev_priv->AGPHeap, agp.size, 0, 0);
  288         if (block) {
  289                 /* TODO */
  290                 agp.offset = block->ofs;
  291                 agp.free = (unsigned long)block;
  292                 if (!add_alloc_set(agp.context, AGP_TYPE, agp.free)) {
  293                         DRM_DEBUG("adding to allocation set fails\n");
  294                         mmFreeMem((PMemBlock) agp.free);
  295                         retval = -1;
  296                 }
  297         } else {
  298                 agp.offset = 0;
  299                 agp.size = 0;
  300                 agp.free = 0;
  301         }
  302 
  303         DRM_COPY_TO_USER_IOCTL(argp, agp, sizeof(agp));
  304 
  305         DRM_DEBUG("alloc agp, size = %d, offset = %d\n", agp.size, agp.offset);
  306 
  307         return retval;
  308 }
  309 
  310 static int sis_ioctl_agp_free(DRM_IOCTL_ARGS)
  311 {
  312         DRM_DEVICE;
  313         drm_sis_private_t *dev_priv = dev->dev_private;
  314         drm_sis_mem_t agp;
  315 
  316         if (dev_priv == NULL || dev_priv->AGPHeap == NULL)
  317                 return DRM_ERR(EINVAL);
  318 
  319         DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_mem_t __user *) data,
  320                                  sizeof(agp));
  321 
  322         if (!mmBlockInHeap(dev_priv->AGPHeap, (PMemBlock) agp.free))
  323                 return DRM_ERR(EINVAL);
  324 
  325         mmFreeMem((PMemBlock) agp.free);
  326         if (!del_alloc_set(agp.context, AGP_TYPE, agp.free))
  327                 return DRM_ERR(EINVAL);
  328 
  329         DRM_DEBUG("free agp, free = 0x%lx\n", agp.free);
  330 
  331         return 0;
  332 }
  333 
  334 int sis_init_context(struct drm_device *dev, int context)
  335 {
  336         int i;
  337 
  338         for (i = 0; i < MAX_CONTEXT; i++) {
  339                 if (global_ppriv[i].used &&
  340                     (global_ppriv[i].context == context))
  341                         break;
  342         }
  343 
  344         if (i >= MAX_CONTEXT) {
  345                 for (i = 0; i < MAX_CONTEXT; i++) {
  346                         if (!global_ppriv[i].used) {
  347                                 global_ppriv[i].context = context;
  348                                 global_ppriv[i].used = 1;
  349                                 global_ppriv[i].sets[0] = setInit();
  350                                 global_ppriv[i].sets[1] = setInit();
  351                                 DRM_DEBUG("init allocation set, socket=%d, "
  352                                           "context = %d\n", i, context);
  353                                 break;
  354                         }
  355                 }
  356                 if ((i >= MAX_CONTEXT) || (global_ppriv[i].sets[0] == NULL) ||
  357                     (global_ppriv[i].sets[1] == NULL)) {
  358                         return 0;
  359                 }
  360         }
  361 
  362         return 1;
  363 }
  364 
  365 int sis_final_context(struct drm_device *dev, int context)
  366 {
  367         int i;
  368 
  369         for (i = 0; i < MAX_CONTEXT; i++) {
  370                 if (global_ppriv[i].used &&
  371                     (global_ppriv[i].context == context))
  372                         break;
  373         }
  374 
  375         if (i < MAX_CONTEXT) {
  376                 set_t *set;
  377                 ITEM_TYPE item;
  378                 int retval;
  379 
  380                 DRM_DEBUG("find socket %d, context = %d\n", i, context);
  381 
  382                 /* Video Memory */
  383                 set = global_ppriv[i].sets[0];
  384                 retval = setFirst(set, &item);
  385                 while (retval) {
  386                         DRM_DEBUG("free video memory 0x%lx\n", item);
  387 #if defined(__linux__) && defined(CONFIG_FB_SIS)
  388                         sis_free(item);
  389 #else
  390                         mmFreeMem((PMemBlock) item);
  391 #endif
  392                         retval = setNext(set, &item);
  393                 }
  394                 setDestroy(set);
  395 
  396                 /* AGP Memory */
  397                 set = global_ppriv[i].sets[1];
  398                 retval = setFirst(set, &item);
  399                 while (retval) {
  400                         DRM_DEBUG("free agp memory 0x%lx\n", item);
  401                         mmFreeMem((PMemBlock) item);
  402                         retval = setNext(set, &item);
  403                 }
  404                 setDestroy(set);
  405 
  406                 global_ppriv[i].used = 0;
  407         }
  408 
  409         return 1;
  410 }
  411 
  412 drm_ioctl_desc_t sis_ioctls[] = {
  413         [DRM_IOCTL_NR(DRM_SIS_FB_ALLOC)] = {sis_fb_alloc, DRM_AUTH},
  414         [DRM_IOCTL_NR(DRM_SIS_FB_FREE)] = {sis_fb_free, DRM_AUTH},
  415         [DRM_IOCTL_NR(DRM_SIS_AGP_INIT)] = {sis_ioctl_agp_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
  416         [DRM_IOCTL_NR(DRM_SIS_AGP_ALLOC)] = {sis_ioctl_agp_alloc, DRM_AUTH},
  417         [DRM_IOCTL_NR(DRM_SIS_AGP_FREE)] = {sis_ioctl_agp_free, DRM_AUTH},
  418         [DRM_IOCTL_NR(DRM_SIS_FB_INIT)] = {sis_fb_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}
  419 };
  420 
  421 int sis_max_ioctl = DRM_ARRAY_SIZE(sis_ioctls);

Cache object: 56a8b69b46b59292fef9a183ddae0c4b


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.