linux/drivers/gpu/drm/drm_ioc32.c
<<
>>
Prefs
   1/**
   2 * \file drm_ioc32.c
   3 *
   4 * 32-bit ioctl compatibility routines for the DRM.
   5 *
   6 * \author Paul Mackerras <paulus@samba.org>
   7 *
   8 * Copyright (C) Paul Mackerras 2005.
   9 * All Rights Reserved.
  10 *
  11 * Permission is hereby granted, free of charge, to any person obtaining a
  12 * copy of this software and associated documentation files (the "Software"),
  13 * to deal in the Software without restriction, including without limitation
  14 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  15 * and/or sell copies of the Software, and to permit persons to whom the
  16 * Software is furnished to do so, subject to the following conditions:
  17 *
  18 * The above copyright notice and this permission notice (including the next
  19 * paragraph) shall be included in all copies or substantial portions of the
  20 * Software.
  21 *
  22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  25 * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  26 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  27 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  28 * IN THE SOFTWARE.
  29 */
  30#include <linux/compat.h>
  31#include <linux/ratelimit.h>
  32
  33#include "drmP.h"
  34#include "drm_core.h"
  35
  36#define DRM_IOCTL_VERSION32             DRM_IOWR(0x00, drm_version32_t)
  37#define DRM_IOCTL_GET_UNIQUE32          DRM_IOWR(0x01, drm_unique32_t)
  38#define DRM_IOCTL_GET_MAP32             DRM_IOWR(0x04, drm_map32_t)
  39#define DRM_IOCTL_GET_CLIENT32          DRM_IOWR(0x05, drm_client32_t)
  40#define DRM_IOCTL_GET_STATS32           DRM_IOR( 0x06, drm_stats32_t)
  41
  42#define DRM_IOCTL_SET_UNIQUE32          DRM_IOW( 0x10, drm_unique32_t)
  43#define DRM_IOCTL_ADD_MAP32             DRM_IOWR(0x15, drm_map32_t)
  44#define DRM_IOCTL_ADD_BUFS32            DRM_IOWR(0x16, drm_buf_desc32_t)
  45#define DRM_IOCTL_MARK_BUFS32           DRM_IOW( 0x17, drm_buf_desc32_t)
  46#define DRM_IOCTL_INFO_BUFS32           DRM_IOWR(0x18, drm_buf_info32_t)
  47#define DRM_IOCTL_MAP_BUFS32            DRM_IOWR(0x19, drm_buf_map32_t)
  48#define DRM_IOCTL_FREE_BUFS32           DRM_IOW( 0x1a, drm_buf_free32_t)
  49
  50#define DRM_IOCTL_RM_MAP32              DRM_IOW( 0x1b, drm_map32_t)
  51
  52#define DRM_IOCTL_SET_SAREA_CTX32       DRM_IOW( 0x1c, drm_ctx_priv_map32_t)
  53#define DRM_IOCTL_GET_SAREA_CTX32       DRM_IOWR(0x1d, drm_ctx_priv_map32_t)
  54
  55#define DRM_IOCTL_RES_CTX32             DRM_IOWR(0x26, drm_ctx_res32_t)
  56#define DRM_IOCTL_DMA32                 DRM_IOWR(0x29, drm_dma32_t)
  57
  58#define DRM_IOCTL_AGP_ENABLE32          DRM_IOW( 0x32, drm_agp_mode32_t)
  59#define DRM_IOCTL_AGP_INFO32            DRM_IOR( 0x33, drm_agp_info32_t)
  60#define DRM_IOCTL_AGP_ALLOC32           DRM_IOWR(0x34, drm_agp_buffer32_t)
  61#define DRM_IOCTL_AGP_FREE32            DRM_IOW( 0x35, drm_agp_buffer32_t)
  62#define DRM_IOCTL_AGP_BIND32            DRM_IOW( 0x36, drm_agp_binding32_t)
  63#define DRM_IOCTL_AGP_UNBIND32          DRM_IOW( 0x37, drm_agp_binding32_t)
  64
  65#define DRM_IOCTL_SG_ALLOC32            DRM_IOW( 0x38, drm_scatter_gather32_t)
  66#define DRM_IOCTL_SG_FREE32             DRM_IOW( 0x39, drm_scatter_gather32_t)
  67
  68#define DRM_IOCTL_UPDATE_DRAW32         DRM_IOW( 0x3f, drm_update_draw32_t)
  69
  70#define DRM_IOCTL_WAIT_VBLANK32         DRM_IOWR(0x3a, drm_wait_vblank32_t)
  71
  72typedef struct drm_version_32 {
  73        int version_major;        /**< Major version */
  74        int version_minor;        /**< Minor version */
  75        int version_patchlevel;    /**< Patch level */
  76        u32 name_len;             /**< Length of name buffer */
  77        u32 name;                 /**< Name of driver */
  78        u32 date_len;             /**< Length of date buffer */
  79        u32 date;                 /**< User-space buffer to hold date */
  80        u32 desc_len;             /**< Length of desc buffer */
  81        u32 desc;                 /**< User-space buffer to hold desc */
  82} drm_version32_t;
  83
  84static int compat_drm_version(struct file *file, unsigned int cmd,
  85                              unsigned long arg)
  86{
  87        drm_version32_t v32;
  88        struct drm_version __user *version;
  89        int err;
  90
  91        if (copy_from_user(&v32, (void __user *)arg, sizeof(v32)))
  92                return -EFAULT;
  93
  94        version = compat_alloc_user_space(sizeof(*version));
  95        if (!access_ok(VERIFY_WRITE, version, sizeof(*version)))
  96                return -EFAULT;
  97        if (__put_user(v32.name_len, &version->name_len)
  98            || __put_user((void __user *)(unsigned long)v32.name,
  99                          &version->name)
 100            || __put_user(v32.date_len, &version->date_len)
 101            || __put_user((void __user *)(unsigned long)v32.date,
 102                          &version->date)
 103            || __put_user(v32.desc_len, &version->desc_len)
 104            || __put_user((void __user *)(unsigned long)v32.desc,
 105                          &version->desc))
 106                return -EFAULT;
 107
 108        err = drm_ioctl(file,
 109                        DRM_IOCTL_VERSION, (unsigned long)version);
 110        if (err)
 111                return err;
 112
 113        if (__get_user(v32.version_major, &version->version_major)
 114            || __get_user(v32.version_minor, &version->version_minor)
 115            || __get_user(v32.version_patchlevel, &version->version_patchlevel)
 116            || __get_user(v32.name_len, &version->name_len)
 117            || __get_user(v32.date_len, &version->date_len)
 118            || __get_user(v32.desc_len, &version->desc_len))
 119                return -EFAULT;
 120
 121        if (copy_to_user((void __user *)arg, &v32, sizeof(v32)))
 122                return -EFAULT;
 123        return 0;
 124}
 125
 126typedef struct drm_unique32 {
 127        u32 unique_len; /**< Length of unique */
 128        u32 unique;     /**< Unique name for driver instantiation */
 129} drm_unique32_t;
 130
 131static int compat_drm_getunique(struct file *file, unsigned int cmd,
 132                                unsigned long arg)
 133{
 134        drm_unique32_t uq32;
 135        struct drm_unique __user *u;
 136        int err;
 137
 138        if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32)))
 139                return -EFAULT;
 140
 141        u = compat_alloc_user_space(sizeof(*u));
 142        if (!access_ok(VERIFY_WRITE, u, sizeof(*u)))
 143                return -EFAULT;
 144        if (__put_user(uq32.unique_len, &u->unique_len)
 145            || __put_user((void __user *)(unsigned long)uq32.unique,
 146                          &u->unique))
 147                return -EFAULT;
 148
 149        err = drm_ioctl(file, DRM_IOCTL_GET_UNIQUE, (unsigned long)u);
 150        if (err)
 151                return err;
 152
 153        if (__get_user(uq32.unique_len, &u->unique_len))
 154                return -EFAULT;
 155        if (copy_to_user((void __user *)arg, &uq32, sizeof(uq32)))
 156                return -EFAULT;
 157        return 0;
 158}
 159
 160static int compat_drm_setunique(struct file *file, unsigned int cmd,
 161                                unsigned long arg)
 162{
 163        drm_unique32_t uq32;
 164        struct drm_unique __user *u;
 165
 166        if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32)))
 167                return -EFAULT;
 168
 169        u = compat_alloc_user_space(sizeof(*u));
 170        if (!access_ok(VERIFY_WRITE, u, sizeof(*u)))
 171                return -EFAULT;
 172        if (__put_user(uq32.unique_len, &u->unique_len)
 173            || __put_user((void __user *)(unsigned long)uq32.unique,
 174                          &u->unique))
 175                return -EFAULT;
 176
 177        return drm_ioctl(file, DRM_IOCTL_SET_UNIQUE, (unsigned long)u);
 178}
 179
 180typedef struct drm_map32 {
 181        u32 offset;             /**< Requested physical address (0 for SAREA)*/
 182        u32 size;               /**< Requested physical size (bytes) */
 183        enum drm_map_type type; /**< Type of memory to map */
 184        enum drm_map_flags flags;       /**< Flags */
 185        u32 handle;             /**< User-space: "Handle" to pass to mmap() */
 186        int mtrr;               /**< MTRR slot used */
 187} drm_map32_t;
 188
 189static int compat_drm_getmap(struct file *file, unsigned int cmd,
 190                             unsigned long arg)
 191{
 192        drm_map32_t __user *argp = (void __user *)arg;
 193        drm_map32_t m32;
 194        struct drm_map __user *map;
 195        int idx, err;
 196        void *handle;
 197
 198        if (get_user(idx, &argp->offset))
 199                return -EFAULT;
 200
 201        map = compat_alloc_user_space(sizeof(*map));
 202        if (!access_ok(VERIFY_WRITE, map, sizeof(*map)))
 203                return -EFAULT;
 204        if (__put_user(idx, &map->offset))
 205                return -EFAULT;
 206
 207        err = drm_ioctl(file, DRM_IOCTL_GET_MAP, (unsigned long)map);
 208        if (err)
 209                return err;
 210
 211        if (__get_user(m32.offset, &map->offset)
 212            || __get_user(m32.size, &map->size)
 213            || __get_user(m32.type, &map->type)
 214            || __get_user(m32.flags, &map->flags)
 215            || __get_user(handle, &map->handle)
 216            || __get_user(m32.mtrr, &map->mtrr))
 217                return -EFAULT;
 218
 219        m32.handle = (unsigned long)handle;
 220        if (copy_to_user(argp, &m32, sizeof(m32)))
 221                return -EFAULT;
 222        return 0;
 223
 224}
 225
 226static int compat_drm_addmap(struct file *file, unsigned int cmd,
 227                             unsigned long arg)
 228{
 229        drm_map32_t __user *argp = (void __user *)arg;
 230        drm_map32_t m32;
 231        struct drm_map __user *map;
 232        int err;
 233        void *handle;
 234
 235        if (copy_from_user(&m32, argp, sizeof(m32)))
 236                return -EFAULT;
 237
 238        map = compat_alloc_user_space(sizeof(*map));
 239        if (!access_ok(VERIFY_WRITE, map, sizeof(*map)))
 240                return -EFAULT;
 241        if (__put_user(m32.offset, &map->offset)
 242            || __put_user(m32.size, &map->size)
 243            || __put_user(m32.type, &map->type)
 244            || __put_user(m32.flags, &map->flags))
 245                return -EFAULT;
 246
 247        err = drm_ioctl(file, DRM_IOCTL_ADD_MAP, (unsigned long)map);
 248        if (err)
 249                return err;
 250
 251        if (__get_user(m32.offset, &map->offset)
 252            || __get_user(m32.mtrr, &map->mtrr)
 253            || __get_user(handle, &map->handle))
 254                return -EFAULT;
 255
 256        m32.handle = (unsigned long)handle;
 257        if (m32.handle != (unsigned long)handle)
 258                printk_ratelimited(KERN_ERR "compat_drm_addmap truncated handle"
 259                                   " %p for type %d offset %x\n",
 260                                   handle, m32.type, m32.offset);
 261
 262        if (copy_to_user(argp, &m32, sizeof(m32)))
 263                return -EFAULT;
 264
 265        return 0;
 266}
 267
 268static int compat_drm_rmmap(struct file *file, unsigned int cmd,
 269                            unsigned long arg)
 270{
 271        drm_map32_t __user *argp = (void __user *)arg;
 272        struct drm_map __user *map;
 273        u32 handle;
 274
 275        if (get_user(handle, &argp->handle))
 276                return -EFAULT;
 277
 278        map = compat_alloc_user_space(sizeof(*map));
 279        if (!access_ok(VERIFY_WRITE, map, sizeof(*map)))
 280                return -EFAULT;
 281        if (__put_user((void *)(unsigned long)handle, &map->handle))
 282                return -EFAULT;
 283
 284        return drm_ioctl(file, DRM_IOCTL_RM_MAP, (unsigned long)map);
 285}
 286
 287typedef struct drm_client32 {
 288        int idx;        /**< Which client desired? */
 289        int auth;       /**< Is client authenticated? */
 290        u32 pid;        /**< Process ID */
 291        u32 uid;        /**< User ID */
 292        u32 magic;      /**< Magic */
 293        u32 iocs;       /**< Ioctl count */
 294} drm_client32_t;
 295
 296static int compat_drm_getclient(struct file *file, unsigned int cmd,
 297                                unsigned long arg)
 298{
 299        drm_client32_t c32;
 300        drm_client32_t __user *argp = (void __user *)arg;
 301        struct drm_client __user *client;
 302        int idx, err;
 303
 304        if (get_user(idx, &argp->idx))
 305                return -EFAULT;
 306
 307        client = compat_alloc_user_space(sizeof(*client));
 308        if (!access_ok(VERIFY_WRITE, client, sizeof(*client)))
 309                return -EFAULT;
 310        if (__put_user(idx, &client->idx))
 311                return -EFAULT;
 312
 313        err = drm_ioctl(file, DRM_IOCTL_GET_CLIENT, (unsigned long)client);
 314        if (err)
 315                return err;
 316
 317        if (__get_user(c32.auth, &client->auth)
 318            || __get_user(c32.pid, &client->pid)
 319            || __get_user(c32.uid, &client->uid)
 320            || __get_user(c32.magic, &client->magic)
 321            || __get_user(c32.iocs, &client->iocs))
 322                return -EFAULT;
 323
 324        if (copy_to_user(argp, &c32, sizeof(c32)))
 325                return -EFAULT;
 326        return 0;
 327}
 328
 329typedef struct drm_stats32 {
 330        u32 count;
 331        struct {
 332                u32 value;
 333                enum drm_stat_type type;
 334        } data[15];
 335} drm_stats32_t;
 336
 337static int compat_drm_getstats(struct file *file, unsigned int cmd,
 338                               unsigned long arg)
 339{
 340        drm_stats32_t s32;
 341        drm_stats32_t __user *argp = (void __user *)arg;
 342        struct drm_stats __user *stats;
 343        int i, err;
 344
 345        stats = compat_alloc_user_space(sizeof(*stats));
 346        if (!access_ok(VERIFY_WRITE, stats, sizeof(*stats)))
 347                return -EFAULT;
 348
 349        err = drm_ioctl(file, DRM_IOCTL_GET_STATS, (unsigned long)stats);
 350        if (err)
 351                return err;
 352
 353        if (__get_user(s32.count, &stats->count))
 354                return -EFAULT;
 355        for (i = 0; i < 15; ++i)
 356                if (__get_user(s32.data[i].value, &stats->data[i].value)
 357                    || __get_user(s32.data[i].type, &stats->data[i].type))
 358                        return -EFAULT;
 359
 360        if (copy_to_user(argp, &s32, sizeof(s32)))
 361                return -EFAULT;
 362        return 0;
 363}
 364
 365typedef struct drm_buf_desc32 {
 366        int count;               /**< Number of buffers of this size */
 367        int size;                /**< Size in bytes */
 368        int low_mark;            /**< Low water mark */
 369        int high_mark;           /**< High water mark */
 370        int flags;
 371        u32 agp_start;           /**< Start address in the AGP aperture */
 372} drm_buf_desc32_t;
 373
 374static int compat_drm_addbufs(struct file *file, unsigned int cmd,
 375                              unsigned long arg)
 376{
 377        drm_buf_desc32_t __user *argp = (void __user *)arg;
 378        struct drm_buf_desc __user *buf;
 379        int err;
 380        unsigned long agp_start;
 381
 382        buf = compat_alloc_user_space(sizeof(*buf));
 383        if (!access_ok(VERIFY_WRITE, buf, sizeof(*buf))
 384            || !access_ok(VERIFY_WRITE, argp, sizeof(*argp)))
 385                return -EFAULT;
 386
 387        if (__copy_in_user(buf, argp, offsetof(drm_buf_desc32_t, agp_start))
 388            || __get_user(agp_start, &argp->agp_start)
 389            || __put_user(agp_start, &buf->agp_start))
 390                return -EFAULT;
 391
 392        err = drm_ioctl(file, DRM_IOCTL_ADD_BUFS, (unsigned long)buf);
 393        if (err)
 394                return err;
 395
 396        if (__copy_in_user(argp, buf, offsetof(drm_buf_desc32_t, agp_start))
 397            || __get_user(agp_start, &buf->agp_start)
 398            || __put_user(agp_start, &argp->agp_start))
 399                return -EFAULT;
 400
 401        return 0;
 402}
 403
 404static int compat_drm_markbufs(struct file *file, unsigned int cmd,
 405                               unsigned long arg)
 406{
 407        drm_buf_desc32_t b32;
 408        drm_buf_desc32_t __user *argp = (void __user *)arg;
 409        struct drm_buf_desc __user *buf;
 410
 411        if (copy_from_user(&b32, argp, sizeof(b32)))
 412                return -EFAULT;
 413
 414        buf = compat_alloc_user_space(sizeof(*buf));
 415        if (!access_ok(VERIFY_WRITE, buf, sizeof(*buf)))
 416                return -EFAULT;
 417
 418        if (__put_user(b32.size, &buf->size)
 419            || __put_user(b32.low_mark, &buf->low_mark)
 420            || __put_user(b32.high_mark, &buf->high_mark))
 421                return -EFAULT;
 422
 423        return drm_ioctl(file, DRM_IOCTL_MARK_BUFS, (unsigned long)buf);
 424}
 425
 426typedef struct drm_buf_info32 {
 427        int count;              /**< Entries in list */
 428        u32 list;
 429} drm_buf_info32_t;
 430
 431static int compat_drm_infobufs(struct file *file, unsigned int cmd,
 432                               unsigned long arg)
 433{
 434        drm_buf_info32_t req32;
 435        drm_buf_info32_t __user *argp = (void __user *)arg;
 436        drm_buf_desc32_t __user *to;
 437        struct drm_buf_info __user *request;
 438        struct drm_buf_desc __user *list;
 439        size_t nbytes;
 440        int i, err;
 441        int count, actual;
 442
 443        if (copy_from_user(&req32, argp, sizeof(req32)))
 444                return -EFAULT;
 445
 446        count = req32.count;
 447        to = (drm_buf_desc32_t __user *) (unsigned long)req32.list;
 448        if (count < 0)
 449                count = 0;
 450        if (count > 0
 451            && !access_ok(VERIFY_WRITE, to, count * sizeof(drm_buf_desc32_t)))
 452                return -EFAULT;
 453
 454        nbytes = sizeof(*request) + count * sizeof(struct drm_buf_desc);
 455        request = compat_alloc_user_space(nbytes);
 456        if (!access_ok(VERIFY_WRITE, request, nbytes))
 457                return -EFAULT;
 458        list = (struct drm_buf_desc *) (request + 1);
 459
 460        if (__put_user(count, &request->count)
 461            || __put_user(list, &request->list))
 462                return -EFAULT;
 463
 464        err = drm_ioctl(file, DRM_IOCTL_INFO_BUFS, (unsigned long)request);
 465        if (err)
 466                return err;
 467
 468        if (__get_user(actual, &request->count))
 469                return -EFAULT;
 470        if (count >= actual)
 471                for (i = 0; i < actual; ++i)
 472                        if (__copy_in_user(&to[i], &list[i],
 473                                           offsetof(struct drm_buf_desc, flags)))
 474                                return -EFAULT;
 475
 476        if (__put_user(actual, &argp->count))
 477                return -EFAULT;
 478
 479        return 0;
 480}
 481
 482typedef struct drm_buf_pub32 {
 483        int idx;                /**< Index into the master buffer list */
 484        int total;              /**< Buffer size */
 485        int used;               /**< Amount of buffer in use (for DMA) */
 486        u32 address;            /**< Address of buffer */
 487} drm_buf_pub32_t;
 488
 489typedef struct drm_buf_map32 {
 490        int count;              /**< Length of the buffer list */
 491        u32 virtual;            /**< Mmap'd area in user-virtual */
 492        u32 list;               /**< Buffer information */
 493} drm_buf_map32_t;
 494
 495static int compat_drm_mapbufs(struct file *file, unsigned int cmd,
 496                              unsigned long arg)
 497{
 498        drm_buf_map32_t __user *argp = (void __user *)arg;
 499        drm_buf_map32_t req32;
 500        drm_buf_pub32_t __user *list32;
 501        struct drm_buf_map __user *request;
 502        struct drm_buf_pub __user *list;
 503        int i, err;
 504        int count, actual;
 505        size_t nbytes;
 506        void __user *addr;
 507
 508        if (copy_from_user(&req32, argp, sizeof(req32)))
 509                return -EFAULT;
 510        count = req32.count;
 511        list32 = (void __user *)(unsigned long)req32.list;
 512
 513        if (count < 0)
 514                return -EINVAL;
 515        nbytes = sizeof(*request) + count * sizeof(struct drm_buf_pub);
 516        request = compat_alloc_user_space(nbytes);
 517        if (!access_ok(VERIFY_WRITE, request, nbytes))
 518                return -EFAULT;
 519        list = (struct drm_buf_pub *) (request + 1);
 520
 521        if (__put_user(count, &request->count)
 522            || __put_user(list, &request->list))
 523                return -EFAULT;
 524
 525        err = drm_ioctl(file, DRM_IOCTL_MAP_BUFS, (unsigned long)request);
 526        if (err)
 527                return err;
 528
 529        if (__get_user(actual, &request->count))
 530                return -EFAULT;
 531        if (count >= actual)
 532                for (i = 0; i < actual; ++i)
 533                        if (__copy_in_user(&list32[i], &list[i],
 534                                           offsetof(struct drm_buf_pub, address))
 535                            || __get_user(addr, &list[i].address)
 536                            || __put_user((unsigned long)addr,
 537                                          &list32[i].address))
 538                                return -EFAULT;
 539
 540        if (__put_user(actual, &argp->count)
 541            || __get_user(addr, &request->virtual)
 542            || __put_user((unsigned long)addr, &argp->virtual))
 543                return -EFAULT;
 544
 545        return 0;
 546}
 547
 548typedef struct drm_buf_free32 {
 549        int count;
 550        u32 list;
 551} drm_buf_free32_t;
 552
 553static int compat_drm_freebufs(struct file *file, unsigned int cmd,
 554                               unsigned long arg)
 555{
 556        drm_buf_free32_t req32;
 557        struct drm_buf_free __user *request;
 558        drm_buf_free32_t __user *argp = (void __user *)arg;
 559
 560        if (copy_from_user(&req32, argp, sizeof(req32)))
 561                return -EFAULT;
 562
 563        request = compat_alloc_user_space(sizeof(*request));
 564        if (!access_ok(VERIFY_WRITE, request, sizeof(*request)))
 565                return -EFAULT;
 566        if (__put_user(req32.count, &request->count)
 567            || __put_user((int __user *)(unsigned long)req32.list,
 568                          &request->list))
 569                return -EFAULT;
 570
 571        return drm_ioctl(file, DRM_IOCTL_FREE_BUFS, (unsigned long)request);
 572}
 573
 574typedef struct drm_ctx_priv_map32 {
 575        unsigned int ctx_id;     /**< Context requesting private mapping */
 576        u32 handle;             /**< Handle of map */
 577} drm_ctx_priv_map32_t;
 578
 579static int compat_drm_setsareactx(struct file *file, unsigned int cmd,
 580                                  unsigned long arg)
 581{
 582        drm_ctx_priv_map32_t req32;
 583        struct drm_ctx_priv_map __user *request;
 584        drm_ctx_priv_map32_t __user *argp = (void __user *)arg;
 585
 586        if (copy_from_user(&req32, argp, sizeof(req32)))
 587                return -EFAULT;
 588
 589        request = compat_alloc_user_space(sizeof(*request));
 590        if (!access_ok(VERIFY_WRITE, request, sizeof(*request)))
 591                return -EFAULT;
 592        if (__put_user(req32.ctx_id, &request->ctx_id)
 593            || __put_user((void *)(unsigned long)req32.handle,
 594                          &request->handle))
 595                return -EFAULT;
 596
 597        return drm_ioctl(file, DRM_IOCTL_SET_SAREA_CTX, (unsigned long)request);
 598}
 599
 600static int compat_drm_getsareactx(struct file *file, unsigned int cmd,
 601                                  unsigned long arg)
 602{
 603        struct drm_ctx_priv_map __user *request;
 604        drm_ctx_priv_map32_t __user *argp = (void __user *)arg;
 605        int err;
 606        unsigned int ctx_id;
 607        void *handle;
 608
 609        if (!access_ok(VERIFY_WRITE, argp, sizeof(*argp))
 610            || __get_user(ctx_id, &argp->ctx_id))
 611                return -EFAULT;
 612
 613        request = compat_alloc_user_space(sizeof(*request));
 614        if (!access_ok(VERIFY_WRITE, request, sizeof(*request)))
 615                return -EFAULT;
 616        if (__put_user(ctx_id, &request->ctx_id))
 617                return -EFAULT;
 618
 619        err = drm_ioctl(file, DRM_IOCTL_GET_SAREA_CTX, (unsigned long)request);
 620        if (err)
 621                return err;
 622
 623        if (__get_user(handle, &request->handle)
 624            || __put_user((unsigned long)handle, &argp->handle))
 625                return -EFAULT;
 626
 627        return 0;
 628}
 629
 630typedef struct drm_ctx_res32 {
 631        int count;
 632        u32 contexts;
 633} drm_ctx_res32_t;
 634
 635static int compat_drm_resctx(struct file *file, unsigned int cmd,
 636                             unsigned long arg)
 637{
 638        drm_ctx_res32_t __user *argp = (void __user *)arg;
 639        drm_ctx_res32_t res32;
 640        struct drm_ctx_res __user *res;
 641        int err;
 642
 643        if (copy_from_user(&res32, argp, sizeof(res32)))
 644                return -EFAULT;
 645
 646        res = compat_alloc_user_space(sizeof(*res));
 647        if (!access_ok(VERIFY_WRITE, res, sizeof(*res)))
 648                return -EFAULT;
 649        if (__put_user(res32.count, &res->count)
 650            || __put_user((struct drm_ctx __user *) (unsigned long)res32.contexts,
 651                          &res->contexts))
 652                return -EFAULT;
 653
 654        err = drm_ioctl(file, DRM_IOCTL_RES_CTX, (unsigned long)res);
 655        if (err)
 656                return err;
 657
 658        if (__get_user(res32.count, &res->count)
 659            || __put_user(res32.count, &argp->count))
 660                return -EFAULT;
 661
 662        return 0;
 663}
 664
 665typedef struct drm_dma32 {
 666        int context;              /**< Context handle */
 667        int send_count;           /**< Number of buffers to send */
 668        u32 send_indices;         /**< List of handles to buffers */
 669        u32 send_sizes;           /**< Lengths of data to send */
 670        enum drm_dma_flags flags;                 /**< Flags */
 671        int request_count;        /**< Number of buffers requested */
 672        int request_size;         /**< Desired size for buffers */
 673        u32 request_indices;      /**< Buffer information */
 674        u32 request_sizes;
 675        int granted_count;        /**< Number of buffers granted */
 676} drm_dma32_t;
 677
 678static int compat_drm_dma(struct file *file, unsigned int cmd,
 679                          unsigned long arg)
 680{
 681        drm_dma32_t d32;
 682        drm_dma32_t __user *argp = (void __user *)arg;
 683        struct drm_dma __user *d;
 684        int err;
 685
 686        if (copy_from_user(&d32, argp, sizeof(d32)))
 687                return -EFAULT;
 688
 689        d = compat_alloc_user_space(sizeof(*d));
 690        if (!access_ok(VERIFY_WRITE, d, sizeof(*d)))
 691                return -EFAULT;
 692
 693        if (__put_user(d32.context, &d->context)
 694            || __put_user(d32.send_count, &d->send_count)
 695            || __put_user((int __user *)(unsigned long)d32.send_indices,
 696                          &d->send_indices)
 697            || __put_user((int __user *)(unsigned long)d32.send_sizes,
 698                          &d->send_sizes)
 699            || __put_user(d32.flags, &d->flags)
 700            || __put_user(d32.request_count, &d->request_count)
 701            || __put_user((int __user *)(unsigned long)d32.request_indices,
 702                          &d->request_indices)
 703            || __put_user((int __user *)(unsigned long)d32.request_sizes,
 704                          &d->request_sizes))
 705                return -EFAULT;
 706
 707        err = drm_ioctl(file, DRM_IOCTL_DMA, (unsigned long)d);
 708        if (err)
 709                return err;
 710
 711        if (__get_user(d32.request_size, &d->request_size)
 712            || __get_user(d32.granted_count, &d->granted_count)
 713            || __put_user(d32.request_size, &argp->request_size)
 714            || __put_user(d32.granted_count, &argp->granted_count))
 715                return -EFAULT;
 716
 717        return 0;
 718}
 719
 720#if __OS_HAS_AGP
 721typedef struct drm_agp_mode32 {
 722        u32 mode;       /**< AGP mode */
 723} drm_agp_mode32_t;
 724
 725static int compat_drm_agp_enable(struct file *file, unsigned int cmd,
 726                                 unsigned long arg)
 727{
 728        drm_agp_mode32_t __user *argp = (void __user *)arg;
 729        drm_agp_mode32_t m32;
 730        struct drm_agp_mode __user *mode;
 731
 732        if (get_user(m32.mode, &argp->mode))
 733                return -EFAULT;
 734
 735        mode = compat_alloc_user_space(sizeof(*mode));
 736        if (put_user(m32.mode, &mode->mode))
 737                return -EFAULT;
 738
 739        return drm_ioctl(file, DRM_IOCTL_AGP_ENABLE, (unsigned long)mode);
 740}
 741
 742typedef struct drm_agp_info32 {
 743        int agp_version_major;
 744        int agp_version_minor;
 745        u32 mode;
 746        u32 aperture_base;      /* physical address */
 747        u32 aperture_size;      /* bytes */
 748        u32 memory_allowed;     /* bytes */
 749        u32 memory_used;
 750
 751        /* PCI information */
 752        unsigned short id_vendor;
 753        unsigned short id_device;
 754} drm_agp_info32_t;
 755
 756static int compat_drm_agp_info(struct file *file, unsigned int cmd,
 757                               unsigned long arg)
 758{
 759        drm_agp_info32_t __user *argp = (void __user *)arg;
 760        drm_agp_info32_t i32;
 761        struct drm_agp_info __user *info;
 762        int err;
 763
 764        info = compat_alloc_user_space(sizeof(*info));
 765        if (!access_ok(VERIFY_WRITE, info, sizeof(*info)))
 766                return -EFAULT;
 767
 768        err = drm_ioctl(file, DRM_IOCTL_AGP_INFO, (unsigned long)info);
 769        if (err)
 770                return err;
 771
 772        if (__get_user(i32.agp_version_major, &info->agp_version_major)
 773            || __get_user(i32.agp_version_minor, &info->agp_version_minor)
 774            || __get_user(i32.mode, &info->mode)
 775            || __get_user(i32.aperture_base, &info->aperture_base)
 776            || __get_user(i32.aperture_size, &info->aperture_size)
 777            || __get_user(i32.memory_allowed, &info->memory_allowed)
 778            || __get_user(i32.memory_used, &info->memory_used)
 779            || __get_user(i32.id_vendor, &info->id_vendor)
 780            || __get_user(i32.id_device, &info->id_device))
 781                return -EFAULT;
 782
 783        if (copy_to_user(argp, &i32, sizeof(i32)))
 784                return -EFAULT;
 785
 786        return 0;
 787}
 788
 789typedef struct drm_agp_buffer32 {
 790        u32 size;       /**< In bytes -- will round to page boundary */
 791        u32 handle;     /**< Used for binding / unbinding */
 792        u32 type;       /**< Type of memory to allocate */
 793        u32 physical;   /**< Physical used by i810 */
 794} drm_agp_buffer32_t;
 795
 796static int compat_drm_agp_alloc(struct file *file, unsigned int cmd,
 797                                unsigned long arg)
 798{
 799        drm_agp_buffer32_t __user *argp = (void __user *)arg;
 800        drm_agp_buffer32_t req32;
 801        struct drm_agp_buffer __user *request;
 802        int err;
 803
 804        if (copy_from_user(&req32, argp, sizeof(req32)))
 805                return -EFAULT;
 806
 807        request = compat_alloc_user_space(sizeof(*request));
 808        if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
 809            || __put_user(req32.size, &request->size)
 810            || __put_user(req32.type, &request->type))
 811                return -EFAULT;
 812
 813        err = drm_ioctl(file, DRM_IOCTL_AGP_ALLOC, (unsigned long)request);
 814        if (err)
 815                return err;
 816
 817        if (__get_user(req32.handle, &request->handle)
 818            || __get_user(req32.physical, &request->physical)
 819            || copy_to_user(argp, &req32, sizeof(req32))) {
 820                drm_ioctl(file, DRM_IOCTL_AGP_FREE, (unsigned long)request);
 821                return -EFAULT;
 822        }
 823
 824        return 0;
 825}
 826
 827static int compat_drm_agp_free(struct file *file, unsigned int cmd,
 828                               unsigned long arg)
 829{
 830        drm_agp_buffer32_t __user *argp = (void __user *)arg;
 831        struct drm_agp_buffer __user *request;
 832        u32 handle;
 833
 834        request = compat_alloc_user_space(sizeof(*request));
 835        if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
 836            || get_user(handle, &argp->handle)
 837            || __put_user(handle, &request->handle))
 838                return -EFAULT;
 839
 840        return drm_ioctl(file, DRM_IOCTL_AGP_FREE, (unsigned long)request);
 841}
 842
 843typedef struct drm_agp_binding32 {
 844        u32 handle;     /**< From drm_agp_buffer */
 845        u32 offset;     /**< In bytes -- will round to page boundary */
 846} drm_agp_binding32_t;
 847
 848static int compat_drm_agp_bind(struct file *file, unsigned int cmd,
 849                               unsigned long arg)
 850{
 851        drm_agp_binding32_t __user *argp = (void __user *)arg;
 852        drm_agp_binding32_t req32;
 853        struct drm_agp_binding __user *request;
 854
 855        if (copy_from_user(&req32, argp, sizeof(req32)))
 856                return -EFAULT;
 857
 858        request = compat_alloc_user_space(sizeof(*request));
 859        if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
 860            || __put_user(req32.handle, &request->handle)
 861            || __put_user(req32.offset, &request->offset))
 862                return -EFAULT;
 863
 864        return drm_ioctl(file, DRM_IOCTL_AGP_BIND, (unsigned long)request);
 865}
 866
 867static int compat_drm_agp_unbind(struct file *file, unsigned int cmd,
 868                                 unsigned long arg)
 869{
 870        drm_agp_binding32_t __user *argp = (void __user *)arg;
 871        struct drm_agp_binding __user *request;
 872        u32 handle;
 873
 874        request = compat_alloc_user_space(sizeof(*request));
 875        if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
 876            || get_user(handle, &argp->handle)
 877            || __put_user(handle, &request->handle))
 878                return -EFAULT;
 879
 880        return drm_ioctl(file, DRM_IOCTL_AGP_UNBIND, (unsigned long)request);
 881}
 882#endif                          /* __OS_HAS_AGP */
 883
 884typedef struct drm_scatter_gather32 {
 885        u32 size;       /**< In bytes -- will round to page boundary */
 886        u32 handle;     /**< Used for mapping / unmapping */
 887} drm_scatter_gather32_t;
 888
 889static int compat_drm_sg_alloc(struct file *file, unsigned int cmd,
 890                               unsigned long arg)
 891{
 892        drm_scatter_gather32_t __user *argp = (void __user *)arg;
 893        struct drm_scatter_gather __user *request;
 894        int err;
 895        unsigned long x;
 896
 897        request = compat_alloc_user_space(sizeof(*request));
 898        if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
 899            || !access_ok(VERIFY_WRITE, argp, sizeof(*argp))
 900            || __get_user(x, &argp->size)
 901            || __put_user(x, &request->size))
 902                return -EFAULT;
 903
 904        err = drm_ioctl(file, DRM_IOCTL_SG_ALLOC, (unsigned long)request);
 905        if (err)
 906                return err;
 907
 908        /* XXX not sure about the handle conversion here... */
 909        if (__get_user(x, &request->handle)
 910            || __put_user(x >> PAGE_SHIFT, &argp->handle))
 911                return -EFAULT;
 912
 913        return 0;
 914}
 915
 916static int compat_drm_sg_free(struct file *file, unsigned int cmd,
 917                              unsigned long arg)
 918{
 919        drm_scatter_gather32_t __user *argp = (void __user *)arg;
 920        struct drm_scatter_gather __user *request;
 921        unsigned long x;
 922
 923        request = compat_alloc_user_space(sizeof(*request));
 924        if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
 925            || !access_ok(VERIFY_WRITE, argp, sizeof(*argp))
 926            || __get_user(x, &argp->handle)
 927            || __put_user(x << PAGE_SHIFT, &request->handle))
 928                return -EFAULT;
 929
 930        return drm_ioctl(file, DRM_IOCTL_SG_FREE, (unsigned long)request);
 931}
 932
 933#if defined(CONFIG_X86) || defined(CONFIG_IA64)
 934typedef struct drm_update_draw32 {
 935        drm_drawable_t handle;
 936        unsigned int type;
 937        unsigned int num;
 938        /* 64-bit version has a 32-bit pad here */
 939        u64 data;       /**< Pointer */
 940} __attribute__((packed)) drm_update_draw32_t;
 941
 942static int compat_drm_update_draw(struct file *file, unsigned int cmd,
 943                                  unsigned long arg)
 944{
 945        drm_update_draw32_t update32;
 946        struct drm_update_draw __user *request;
 947        int err;
 948
 949        if (copy_from_user(&update32, (void __user *)arg, sizeof(update32)))
 950                return -EFAULT;
 951
 952        request = compat_alloc_user_space(sizeof(*request));
 953        if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) ||
 954            __put_user(update32.handle, &request->handle) ||
 955            __put_user(update32.type, &request->type) ||
 956            __put_user(update32.num, &request->num) ||
 957            __put_user(update32.data, &request->data))
 958                return -EFAULT;
 959
 960        err = drm_ioctl(file, DRM_IOCTL_UPDATE_DRAW, (unsigned long)request);
 961        return err;
 962}
 963#endif
 964
 965struct drm_wait_vblank_request32 {
 966        enum drm_vblank_seq_type type;
 967        unsigned int sequence;
 968        u32 signal;
 969};
 970
 971struct drm_wait_vblank_reply32 {
 972        enum drm_vblank_seq_type type;
 973        unsigned int sequence;
 974        s32 tval_sec;
 975        s32 tval_usec;
 976};
 977
 978typedef union drm_wait_vblank32 {
 979        struct drm_wait_vblank_request32 request;
 980        struct drm_wait_vblank_reply32 reply;
 981} drm_wait_vblank32_t;
 982
 983static int compat_drm_wait_vblank(struct file *file, unsigned int cmd,
 984                                  unsigned long arg)
 985{
 986        drm_wait_vblank32_t __user *argp = (void __user *)arg;
 987        drm_wait_vblank32_t req32;
 988        union drm_wait_vblank __user *request;
 989        int err;
 990
 991        if (copy_from_user(&req32, argp, sizeof(req32)))
 992                return -EFAULT;
 993
 994        request = compat_alloc_user_space(sizeof(*request));
 995        if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
 996            || __put_user(req32.request.type, &request->request.type)
 997            || __put_user(req32.request.sequence, &request->request.sequence)
 998            || __put_user(req32.request.signal, &request->request.signal))
 999                return -EFAULT;
1000
1001        err = drm_ioctl(file, DRM_IOCTL_WAIT_VBLANK, (unsigned long)request);
1002        if (err)
1003                return err;
1004
1005        if (__get_user(req32.reply.type, &request->reply.type)
1006            || __get_user(req32.reply.sequence, &request->reply.sequence)
1007            || __get_user(req32.reply.tval_sec, &request->reply.tval_sec)
1008            || __get_user(req32.reply.tval_usec, &request->reply.tval_usec))
1009                return -EFAULT;
1010
1011        if (copy_to_user(argp, &req32, sizeof(req32)))
1012                return -EFAULT;
1013
1014        return 0;
1015}
1016
1017drm_ioctl_compat_t *drm_compat_ioctls[] = {
1018        [DRM_IOCTL_NR(DRM_IOCTL_VERSION32)] = compat_drm_version,
1019        [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE32)] = compat_drm_getunique,
1020        [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP32)] = compat_drm_getmap,
1021        [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT32)] = compat_drm_getclient,
1022        [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS32)] = compat_drm_getstats,
1023        [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE32)] = compat_drm_setunique,
1024        [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP32)] = compat_drm_addmap,
1025        [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS32)] = compat_drm_addbufs,
1026        [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS32)] = compat_drm_markbufs,
1027        [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS32)] = compat_drm_infobufs,
1028        [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS32)] = compat_drm_mapbufs,
1029        [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS32)] = compat_drm_freebufs,
1030        [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP32)] = compat_drm_rmmap,
1031        [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX32)] = compat_drm_setsareactx,
1032        [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX32)] = compat_drm_getsareactx,
1033        [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX32)] = compat_drm_resctx,
1034        [DRM_IOCTL_NR(DRM_IOCTL_DMA32)] = compat_drm_dma,
1035#if __OS_HAS_AGP
1036        [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE32)] = compat_drm_agp_enable,
1037        [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO32)] = compat_drm_agp_info,
1038        [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC32)] = compat_drm_agp_alloc,
1039        [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE32)] = compat_drm_agp_free,
1040        [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND32)] = compat_drm_agp_bind,
1041        [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND32)] = compat_drm_agp_unbind,
1042#endif
1043        [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC32)] = compat_drm_sg_alloc,
1044        [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE32)] = compat_drm_sg_free,
1045#if defined(CONFIG_X86) || defined(CONFIG_IA64)
1046        [DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW32)] = compat_drm_update_draw,
1047#endif
1048        [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK32)] = compat_drm_wait_vblank,
1049};
1050
1051/**
1052 * Called whenever a 32-bit process running under a 64-bit kernel
1053 * performs an ioctl on /dev/drm.
1054 *
1055 * \param file_priv DRM file private.
1056 * \param cmd command.
1057 * \param arg user argument.
1058 * \return zero on success or negative number on failure.
1059 */
1060long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
1061{
1062        unsigned int nr = DRM_IOCTL_NR(cmd);
1063        drm_ioctl_compat_t *fn;
1064        int ret;
1065
1066        /* Assume that ioctls without an explicit compat routine will just
1067         * work.  This may not always be a good assumption, but it's better
1068         * than always failing.
1069         */
1070        if (nr >= ARRAY_SIZE(drm_compat_ioctls))
1071                return drm_ioctl(filp, cmd, arg);
1072
1073        fn = drm_compat_ioctls[nr];
1074
1075        if (fn != NULL)
1076                ret = (*fn) (filp, cmd, arg);
1077        else
1078                ret = drm_ioctl(filp, cmd, arg);
1079
1080        return ret;
1081}
1082
1083EXPORT_SYMBOL(drm_compat_ioctl);
1084