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/9.0/sys/dev/drm/sis_mm.c 182080 2008-08-23 20:59:12Z rnoland $");
   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(struct drm_device *dev, void *data, struct drm_file *file_priv)
   88 {
   89         return 0;
   90 }
   91 
   92 static int sis_fb_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv)
   93 {
   94         drm_sis_mem_t *fb = data;
   95         struct sis_memreq req;
   96         int retval = 0;
   97 
   98         req.size = fb->size;
   99         sis_malloc(&req);
  100         if (req.offset) {
  101                 /* TODO */
  102                 fb->offset = req.offset;
  103                 fb->free = req.offset;
  104                 if (!add_alloc_set(fb->context, VIDEO_TYPE, fb->free)) {
  105                         DRM_DEBUG("adding to allocation set fails\n");
  106                         sis_free(req.offset);
  107                         retval = -EINVAL;
  108                 }
  109         } else {
  110                 fb->offset = 0;
  111                 fb->size = 0;
  112                 fb->free = 0;
  113         }
  114 
  115         DRM_DEBUG("alloc fb, size = %d, offset = %ld\n", fb->size, req.offset);
  116 
  117         return retval;
  118 }
  119 
  120 static int sis_fb_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
  121 {
  122         drm_sis_mem_t fb;
  123         int retval = 0;
  124 
  125         if (!fb->free)
  126                 return -EINVAL;
  127 
  128         if (!del_alloc_set(fb->context, VIDEO_TYPE, fb->free))
  129                 retval = -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  */
  149 static int sis_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
  150 {
  151         drm_sis_private_t *dev_priv = dev->dev_private;
  152         drm_sis_fb_t *fb = data;
  153 
  154         if (dev_priv == NULL) {
  155                 dev->dev_private = drm_calloc(1, sizeof(drm_sis_private_t),
  156                                               DRM_MEM_DRIVER);
  157                 dev_priv = dev->dev_private;
  158                 if (dev_priv == NULL)
  159                         return ENOMEM;
  160         }
  161 
  162         if (dev_priv->FBHeap != NULL)
  163                 return -EINVAL;
  164 
  165         dev_priv->FBHeap = mmInit(fb->offset, fb->size);
  166 
  167         DRM_DEBUG("offset = %u, size = %u", fb->offset, fb->size);
  168 
  169         return 0;
  170 }
  171 
  172 static int sis_fb_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv)
  173 {
  174         drm_sis_private_t *dev_priv = dev->dev_private;
  175         drm_sis_mem_t *fb = data;
  176         PMemBlock block;
  177         int retval = 0;
  178 
  179         if (dev_priv == NULL || dev_priv->FBHeap == NULL)
  180                 return -EINVAL;
  181 
  182         block = mmAllocMem(dev_priv->FBHeap, fb->size, 0, 0);
  183         if (block) {
  184                 /* TODO */
  185                 fb->offset = block->ofs;
  186                 fb->free = (unsigned long)block;
  187                 if (!add_alloc_set(fb->context, VIDEO_TYPE, fb->free)) {
  188                         DRM_DEBUG("adding to allocation set fails\n");
  189                         mmFreeMem((PMemBlock) fb->free);
  190                         retval = -EINVAL;
  191                 }
  192         } else {
  193                 fb->offset = 0;
  194                 fb->size = 0;
  195                 fb->free = 0;
  196         }
  197 
  198         DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb->size, fb->offset);
  199 
  200         return retval;
  201 }
  202 
  203 static int sis_fb_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
  204 {
  205         drm_sis_private_t *dev_priv = dev->dev_private;
  206         drm_sis_mem_t *fb = data;
  207 
  208         if (dev_priv == NULL || dev_priv->FBHeap == NULL)
  209                 return -EINVAL;
  210 
  211         if (!mmBlockInHeap(dev_priv->FBHeap, (PMemBlock) fb->free))
  212                 return -EINVAL;
  213 
  214         if (!del_alloc_set(fb->context, VIDEO_TYPE, fb->free))
  215                 return -EINVAL;
  216         mmFreeMem((PMemBlock) fb->free);
  217 
  218         DRM_DEBUG("free fb, free = 0x%lx\n", fb->free);
  219 
  220         return 0;
  221 }
  222 
  223 #endif
  224 
  225 /* agp memory management */
  226 
  227 static int sis_ioctl_agp_init(struct drm_device *dev, void *data, struct drm_file *file_priv)
  228 {
  229         drm_sis_private_t *dev_priv = dev->dev_private;
  230         drm_sis_agp_t *agp = data;
  231 
  232         if (dev_priv == NULL) {
  233                 dev->dev_private = drm_calloc(1, sizeof(drm_sis_private_t),
  234                                               DRM_MEM_DRIVER);
  235                 dev_priv = dev->dev_private;
  236                 if (dev_priv == NULL)
  237                         return ENOMEM;
  238         }
  239 
  240         if (dev_priv->AGPHeap != NULL)
  241                 return -EINVAL;
  242 
  243         dev_priv->AGPHeap = mmInit(agp->offset, agp->size);
  244 
  245         DRM_DEBUG("offset = %u, size = %u", agp->offset, agp->size);
  246 
  247         return 0;
  248 }
  249 
  250 static int sis_ioctl_agp_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv)
  251 {
  252         drm_sis_private_t *dev_priv = dev->dev_private;
  253         drm_sis_mem_t *agp = data;
  254         PMemBlock block;
  255         int retval = 0;
  256 
  257         if (dev_priv == NULL || dev_priv->AGPHeap == NULL)
  258                 return -EINVAL;
  259 
  260         block = mmAllocMem(dev_priv->AGPHeap, agp->size, 0, 0);
  261         if (block) {
  262                 /* TODO */
  263                 agp->offset = block->ofs;
  264                 agp->free = (unsigned long)block;
  265                 if (!add_alloc_set(agp->context, AGP_TYPE, agp->free)) {
  266                         DRM_DEBUG("adding to allocation set fails\n");
  267                         mmFreeMem((PMemBlock) agp->free);
  268                         retval = -1;
  269                 }
  270         } else {
  271                 agp->offset = 0;
  272                 agp->size = 0;
  273                 agp->free = 0;
  274         }
  275 
  276         DRM_DEBUG("alloc agp, size = %d, offset = %d\n", agp->size,
  277             agp->offset);
  278 
  279         return retval;
  280 }
  281 
  282 static int sis_ioctl_agp_free(struct drm_device *dev, void *data, struct drm_file *file_priv)
  283 {
  284         drm_sis_private_t *dev_priv = dev->dev_private;
  285         drm_sis_mem_t *agp = data;
  286 
  287         if (dev_priv == NULL || dev_priv->AGPHeap == NULL)
  288                 return -EINVAL;
  289 
  290         if (!mmBlockInHeap(dev_priv->AGPHeap, (PMemBlock) agp->free))
  291                 return -EINVAL;
  292 
  293         mmFreeMem((PMemBlock) agp->free);
  294         if (!del_alloc_set(agp->context, AGP_TYPE, agp->free))
  295                 return -EINVAL;
  296 
  297         DRM_DEBUG("free agp, free = 0x%lx\n", agp->free);
  298 
  299         return 0;
  300 }
  301 
  302 int sis_init_context(struct drm_device *dev, int context)
  303 {
  304         int i;
  305 
  306         for (i = 0; i < MAX_CONTEXT; i++) {
  307                 if (global_ppriv[i].used &&
  308                     (global_ppriv[i].context == context))
  309                         break;
  310         }
  311 
  312         if (i >= MAX_CONTEXT) {
  313                 for (i = 0; i < MAX_CONTEXT; i++) {
  314                         if (!global_ppriv[i].used) {
  315                                 global_ppriv[i].context = context;
  316                                 global_ppriv[i].used = 1;
  317                                 global_ppriv[i].sets[0] = setInit();
  318                                 global_ppriv[i].sets[1] = setInit();
  319                                 DRM_DEBUG("init allocation set, socket=%d, "
  320                                           "context = %d\n", i, context);
  321                                 break;
  322                         }
  323                 }
  324                 if ((i >= MAX_CONTEXT) || (global_ppriv[i].sets[0] == NULL) ||
  325                     (global_ppriv[i].sets[1] == NULL)) {
  326                         return 0;
  327                 }
  328         }
  329 
  330         return 1;
  331 }
  332 
  333 int sis_final_context(struct drm_device *dev, int context)
  334 {
  335         int i;
  336 
  337         for (i = 0; i < MAX_CONTEXT; i++) {
  338                 if (global_ppriv[i].used &&
  339                     (global_ppriv[i].context == context))
  340                         break;
  341         }
  342 
  343         if (i < MAX_CONTEXT) {
  344                 set_t *set;
  345                 ITEM_TYPE item;
  346                 int retval;
  347 
  348                 DRM_DEBUG("find socket %d, context = %d\n", i, context);
  349 
  350                 /* Video Memory */
  351                 set = global_ppriv[i].sets[0];
  352                 retval = setFirst(set, &item);
  353                 while (retval) {
  354                         DRM_DEBUG("free video memory 0x%lx\n", item);
  355 #if defined(__linux__) && defined(CONFIG_FB_SIS)
  356                         sis_free(item);
  357 #else
  358                         mmFreeMem((PMemBlock) item);
  359 #endif
  360                         retval = setNext(set, &item);
  361                 }
  362                 setDestroy(set);
  363 
  364                 /* AGP Memory */
  365                 set = global_ppriv[i].sets[1];
  366                 retval = setFirst(set, &item);
  367                 while (retval) {
  368                         DRM_DEBUG("free agp memory 0x%lx\n", item);
  369                         mmFreeMem((PMemBlock) item);
  370                         retval = setNext(set, &item);
  371                 }
  372                 setDestroy(set);
  373 
  374                 global_ppriv[i].used = 0;
  375         }
  376 
  377         return 1;
  378 }
  379 
  380 drm_ioctl_desc_t sis_ioctls[] = {
  381         DRM_IOCTL_DEF(DRM_SIS_FB_ALLOC, sis_fb_alloc, DRM_AUTH),
  382         DRM_IOCTL_DEF(DRM_SIS_FB_FREE, sis_fb_free, DRM_AUTH),
  383         DRM_IOCTL_DEF(DRM_SIS_AGP_INIT, sis_ioctl_agp_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
  384         DRM_IOCTL_DEF(DRM_SIS_AGP_ALLOC, sis_ioctl_agp_alloc, DRM_AUTH),
  385         DRM_IOCTL_DEF(DRM_SIS_AGP_FREE, sis_ioctl_agp_free, DRM_AUTH),
  386         DRM_IOCTL_DEF(DRM_SIS_FB_INIT, sis_fb_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY)
  387 };
  388 
  389 int sis_max_ioctl = DRM_ARRAY_SIZE(sis_ioctls);

Cache object: 2d9de30ae874c9329e20c78575403098


[ 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.