linux/drivers/gpu/drm/mga/mga_ioc32.c
<<
>>
Prefs
   1/**
   2 * \file mga_ioc32.c
   3 *
   4 * 32-bit ioctl compatibility routines for the MGA DRM.
   5 *
   6 * \author Dave Airlie <airlied@linux.ie> with code from patches by Egbert Eich
   7 *
   8 *
   9 * Copyright (C) Paul Mackerras 2005
  10 * Copyright (C) Egbert Eich 2003,2004
  11 * Copyright (C) Dave Airlie 2005
  12 * All Rights Reserved.
  13 *
  14 * Permission is hereby granted, free of charge, to any person obtaining a
  15 * copy of this software and associated documentation files (the "Software"),
  16 * to deal in the Software without restriction, including without limitation
  17 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  18 * and/or sell copies of the Software, and to permit persons to whom the
  19 * Software is furnished to do so, subject to the following conditions:
  20 *
  21 * The above copyright notice and this permission notice (including the next
  22 * paragraph) shall be included in all copies or substantial portions of the
  23 * Software.
  24 *
  25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  26 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  27 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  28 * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  29 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  30 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  31 * IN THE SOFTWARE.
  32 */
  33#include <linux/compat.h>
  34
  35#include <drm/drmP.h>
  36#include <drm/mga_drm.h>
  37#include "mga_drv.h"
  38
  39typedef struct drm32_mga_init {
  40        int func;
  41        u32 sarea_priv_offset;
  42        int chipset;
  43        int sgram;
  44        unsigned int maccess;
  45        unsigned int fb_cpp;
  46        unsigned int front_offset, front_pitch;
  47        unsigned int back_offset, back_pitch;
  48        unsigned int depth_cpp;
  49        unsigned int depth_offset, depth_pitch;
  50        unsigned int texture_offset[MGA_NR_TEX_HEAPS];
  51        unsigned int texture_size[MGA_NR_TEX_HEAPS];
  52        u32 fb_offset;
  53        u32 mmio_offset;
  54        u32 status_offset;
  55        u32 warp_offset;
  56        u32 primary_offset;
  57        u32 buffers_offset;
  58} drm_mga_init32_t;
  59
  60static int compat_mga_init(struct file *file, unsigned int cmd,
  61                           unsigned long arg)
  62{
  63        drm_mga_init32_t init32;
  64        drm_mga_init_t __user *init;
  65        int err = 0, i;
  66
  67        if (copy_from_user(&init32, (void __user *)arg, sizeof(init32)))
  68                return -EFAULT;
  69
  70        init = compat_alloc_user_space(sizeof(*init));
  71        if (!access_ok(VERIFY_WRITE, init, sizeof(*init))
  72            || __put_user(init32.func, &init->func)
  73            || __put_user(init32.sarea_priv_offset, &init->sarea_priv_offset)
  74            || __put_user(init32.chipset, &init->chipset)
  75            || __put_user(init32.sgram, &init->sgram)
  76            || __put_user(init32.maccess, &init->maccess)
  77            || __put_user(init32.fb_cpp, &init->fb_cpp)
  78            || __put_user(init32.front_offset, &init->front_offset)
  79            || __put_user(init32.front_pitch, &init->front_pitch)
  80            || __put_user(init32.back_offset, &init->back_offset)
  81            || __put_user(init32.back_pitch, &init->back_pitch)
  82            || __put_user(init32.depth_cpp, &init->depth_cpp)
  83            || __put_user(init32.depth_offset, &init->depth_offset)
  84            || __put_user(init32.depth_pitch, &init->depth_pitch)
  85            || __put_user(init32.fb_offset, &init->fb_offset)
  86            || __put_user(init32.mmio_offset, &init->mmio_offset)
  87            || __put_user(init32.status_offset, &init->status_offset)
  88            || __put_user(init32.warp_offset, &init->warp_offset)
  89            || __put_user(init32.primary_offset, &init->primary_offset)
  90            || __put_user(init32.buffers_offset, &init->buffers_offset))
  91                return -EFAULT;
  92
  93        for (i = 0; i < MGA_NR_TEX_HEAPS; i++) {
  94                err |=
  95                    __put_user(init32.texture_offset[i],
  96                               &init->texture_offset[i]);
  97                err |=
  98                    __put_user(init32.texture_size[i], &init->texture_size[i]);
  99        }
 100        if (err)
 101                return -EFAULT;
 102
 103        return drm_ioctl(file, DRM_IOCTL_MGA_INIT, (unsigned long)init);
 104}
 105
 106typedef struct drm_mga_getparam32 {
 107        int param;
 108        u32 value;
 109} drm_mga_getparam32_t;
 110
 111static int compat_mga_getparam(struct file *file, unsigned int cmd,
 112                               unsigned long arg)
 113{
 114        drm_mga_getparam32_t getparam32;
 115        drm_mga_getparam_t __user *getparam;
 116
 117        if (copy_from_user(&getparam32, (void __user *)arg, sizeof(getparam32)))
 118                return -EFAULT;
 119
 120        getparam = compat_alloc_user_space(sizeof(*getparam));
 121        if (!access_ok(VERIFY_WRITE, getparam, sizeof(*getparam))
 122            || __put_user(getparam32.param, &getparam->param)
 123            || __put_user((void __user *)(unsigned long)getparam32.value,
 124                          &getparam->value))
 125                return -EFAULT;
 126
 127        return drm_ioctl(file, DRM_IOCTL_MGA_GETPARAM, (unsigned long)getparam);
 128}
 129
 130typedef struct drm_mga_drm_bootstrap32 {
 131        u32 texture_handle;
 132        u32 texture_size;
 133        u32 primary_size;
 134        u32 secondary_bin_count;
 135        u32 secondary_bin_size;
 136        u32 agp_mode;
 137        u8 agp_size;
 138} drm_mga_dma_bootstrap32_t;
 139
 140static int compat_mga_dma_bootstrap(struct file *file, unsigned int cmd,
 141                                    unsigned long arg)
 142{
 143        drm_mga_dma_bootstrap32_t dma_bootstrap32;
 144        drm_mga_dma_bootstrap_t __user *dma_bootstrap;
 145        int err;
 146
 147        if (copy_from_user(&dma_bootstrap32, (void __user *)arg,
 148                           sizeof(dma_bootstrap32)))
 149                return -EFAULT;
 150
 151        dma_bootstrap = compat_alloc_user_space(sizeof(*dma_bootstrap));
 152        if (!access_ok(VERIFY_WRITE, dma_bootstrap, sizeof(*dma_bootstrap))
 153            || __put_user(dma_bootstrap32.texture_handle,
 154                          &dma_bootstrap->texture_handle)
 155            || __put_user(dma_bootstrap32.texture_size,
 156                          &dma_bootstrap->texture_size)
 157            || __put_user(dma_bootstrap32.primary_size,
 158                          &dma_bootstrap->primary_size)
 159            || __put_user(dma_bootstrap32.secondary_bin_count,
 160                          &dma_bootstrap->secondary_bin_count)
 161            || __put_user(dma_bootstrap32.secondary_bin_size,
 162                          &dma_bootstrap->secondary_bin_size)
 163            || __put_user(dma_bootstrap32.agp_mode, &dma_bootstrap->agp_mode)
 164            || __put_user(dma_bootstrap32.agp_size, &dma_bootstrap->agp_size))
 165                return -EFAULT;
 166
 167        err = drm_ioctl(file, DRM_IOCTL_MGA_DMA_BOOTSTRAP,
 168                        (unsigned long)dma_bootstrap);
 169        if (err)
 170                return err;
 171
 172        if (__get_user(dma_bootstrap32.texture_handle,
 173                       &dma_bootstrap->texture_handle)
 174            || __get_user(dma_bootstrap32.texture_size,
 175                          &dma_bootstrap->texture_size)
 176            || __get_user(dma_bootstrap32.primary_size,
 177                          &dma_bootstrap->primary_size)
 178            || __get_user(dma_bootstrap32.secondary_bin_count,
 179                          &dma_bootstrap->secondary_bin_count)
 180            || __get_user(dma_bootstrap32.secondary_bin_size,
 181                          &dma_bootstrap->secondary_bin_size)
 182            || __get_user(dma_bootstrap32.agp_mode, &dma_bootstrap->agp_mode)
 183            || __get_user(dma_bootstrap32.agp_size, &dma_bootstrap->agp_size))
 184                return -EFAULT;
 185
 186        if (copy_to_user((void __user *)arg, &dma_bootstrap32,
 187                         sizeof(dma_bootstrap32)))
 188                return -EFAULT;
 189
 190        return 0;
 191}
 192
 193drm_ioctl_compat_t *mga_compat_ioctls[] = {
 194        [DRM_MGA_INIT] = compat_mga_init,
 195        [DRM_MGA_GETPARAM] = compat_mga_getparam,
 196        [DRM_MGA_DMA_BOOTSTRAP] = compat_mga_dma_bootstrap,
 197};
 198
 199/**
 200 * Called whenever a 32-bit process running under a 64-bit kernel
 201 * performs an ioctl on /dev/dri/card<n>.
 202 *
 203 * \param filp file pointer.
 204 * \param cmd command.
 205 * \param arg user argument.
 206 * \return zero on success or negative number on failure.
 207 */
 208long mga_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 209{
 210        unsigned int nr = DRM_IOCTL_NR(cmd);
 211        drm_ioctl_compat_t *fn = NULL;
 212        int ret;
 213
 214        if (nr < DRM_COMMAND_BASE)
 215                return drm_compat_ioctl(filp, cmd, arg);
 216
 217        if (nr < DRM_COMMAND_BASE + ARRAY_SIZE(mga_compat_ioctls))
 218                fn = mga_compat_ioctls[nr - DRM_COMMAND_BASE];
 219
 220        if (fn != NULL)
 221                ret = (*fn) (filp, cmd, arg);
 222        else
 223                ret = drm_ioctl(filp, cmd, arg);
 224
 225        return ret;
 226}
 227