ioctl32.c
来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 626 行 · 第 1/2 页
C
626 行
/* $Id: ioctl32.c,v 1.5 2002/10/18 00:21:43 varenet Exp $ * ioctl32.c: Conversion between 32bit and 64bit native ioctls. * * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) * * These routines maintain argument size conversion between 32bit and 64bit * ioctls. */#include <linux/syscalls.h>#define INCLUDES#include "compat_ioctl.c"#include <asm/perf.h>#include <asm/ioctls.h>#define CODE#include "compat_ioctl.c"/* Use this to get at 32-bit user passed pointers. See sys_sparc32.c for description about these. */#define A(__x) ((unsigned long)(__x))/* The same for use with copy_from_user() and copy_to_user(). */#define B(__x) ((void *)(unsigned long)(__x))#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE)/* This really belongs in include/linux/drm.h -DaveM */#include "../../../drivers/char/drm/drm.h"typedef struct drm32_version { int version_major; /* Major version */ int version_minor; /* Minor version */ int version_patchlevel;/* Patch level */ int name_len; /* Length of name buffer */ u32 name; /* Name of driver */ int date_len; /* Length of date buffer */ u32 date; /* User-space buffer to hold date */ int desc_len; /* Length of desc buffer */ u32 desc; /* User-space buffer to hold desc */} drm32_version_t;#define DRM32_IOCTL_VERSION DRM_IOWR(0x00, drm32_version_t)static int drm32_version(unsigned int fd, unsigned int cmd, unsigned long arg){ drm32_version_t *uversion = (drm32_version_t *)arg; char *name_ptr, *date_ptr, *desc_ptr; u32 tmp1, tmp2, tmp3; drm_version_t kversion; mm_segment_t old_fs; int ret; memset(&kversion, 0, sizeof(kversion)); if (get_user(kversion.name_len, &uversion->name_len) || get_user(kversion.date_len, &uversion->date_len) || get_user(kversion.desc_len, &uversion->desc_len) || get_user(tmp1, &uversion->name) || get_user(tmp2, &uversion->date) || get_user(tmp3, &uversion->desc)) return -EFAULT; name_ptr = (char *) A(tmp1); date_ptr = (char *) A(tmp2); desc_ptr = (char *) A(tmp3); ret = -ENOMEM; if (kversion.name_len && name_ptr) { kversion.name = kmalloc(kversion.name_len, GFP_KERNEL); if (!kversion.name) goto out; } if (kversion.date_len && date_ptr) { kversion.date = kmalloc(kversion.date_len, GFP_KERNEL); if (!kversion.date) goto out; } if (kversion.desc_len && desc_ptr) { kversion.desc = kmalloc(kversion.desc_len, GFP_KERNEL); if (!kversion.desc) goto out; } old_fs = get_fs(); set_fs(KERNEL_DS); ret = sys_ioctl (fd, DRM_IOCTL_VERSION, (unsigned long)&kversion); set_fs(old_fs); if (!ret) { if ((kversion.name && copy_to_user(name_ptr, kversion.name, kversion.name_len)) || (kversion.date && copy_to_user(date_ptr, kversion.date, kversion.date_len)) || (kversion.desc && copy_to_user(desc_ptr, kversion.desc, kversion.desc_len))) ret = -EFAULT; if (put_user(kversion.version_major, &uversion->version_major) || put_user(kversion.version_minor, &uversion->version_minor) || put_user(kversion.version_patchlevel, &uversion->version_patchlevel) || put_user(kversion.name_len, &uversion->name_len) || put_user(kversion.date_len, &uversion->date_len) || put_user(kversion.desc_len, &uversion->desc_len)) ret = -EFAULT; }out: if (kversion.name) kfree(kversion.name); if (kversion.date) kfree(kversion.date); if (kversion.desc) kfree(kversion.desc); return ret;}typedef struct drm32_unique { int unique_len; /* Length of unique */ u32 unique; /* Unique name for driver instantiation */} drm32_unique_t;#define DRM32_IOCTL_GET_UNIQUE DRM_IOWR(0x01, drm32_unique_t)#define DRM32_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm32_unique_t)static int drm32_getsetunique(unsigned int fd, unsigned int cmd, unsigned long arg){ drm32_unique_t *uarg = (drm32_unique_t *)arg; drm_unique_t karg; mm_segment_t old_fs; char *uptr; u32 tmp; int ret; if (get_user(karg.unique_len, &uarg->unique_len)) return -EFAULT; karg.unique = NULL; if (get_user(tmp, &uarg->unique)) return -EFAULT; uptr = (char *) A(tmp); if (uptr) { karg.unique = kmalloc(karg.unique_len, GFP_KERNEL); if (!karg.unique) return -ENOMEM; if (cmd == DRM32_IOCTL_SET_UNIQUE && copy_from_user(karg.unique, uptr, karg.unique_len)) { kfree(karg.unique); return -EFAULT; } } old_fs = get_fs(); set_fs(KERNEL_DS); if (cmd == DRM32_IOCTL_GET_UNIQUE) ret = sys_ioctl (fd, DRM_IOCTL_GET_UNIQUE, (unsigned long)&karg); else ret = sys_ioctl (fd, DRM_IOCTL_SET_UNIQUE, (unsigned long)&karg); set_fs(old_fs); if (!ret) { if (cmd == DRM32_IOCTL_GET_UNIQUE && uptr != NULL && copy_to_user(uptr, karg.unique, karg.unique_len)) ret = -EFAULT; if (put_user(karg.unique_len, &uarg->unique_len)) ret = -EFAULT; } if (karg.unique != NULL) kfree(karg.unique); return ret;}typedef struct drm32_map { u32 offset; /* Requested physical address (0 for SAREA)*/ u32 size; /* Requested physical size (bytes) */ drm_map_type_t type; /* Type of memory to map */ drm_map_flags_t flags; /* Flags */ u32 handle; /* User-space: "Handle" to pass to mmap */ /* Kernel-space: kernel-virtual address */ int mtrr; /* MTRR slot used */ /* Private data */} drm32_map_t;#define DRM32_IOCTL_ADD_MAP DRM_IOWR(0x15, drm32_map_t)static int drm32_addmap(unsigned int fd, unsigned int cmd, unsigned long arg){ drm32_map_t *uarg = (drm32_map_t *) arg; drm_map_t karg; mm_segment_t old_fs; u32 tmp; int ret; ret = get_user(karg.offset, &uarg->offset); ret |= get_user(karg.size, &uarg->size); ret |= get_user(karg.type, &uarg->type); ret |= get_user(karg.flags, &uarg->flags); ret |= get_user(tmp, &uarg->handle); ret |= get_user(karg.mtrr, &uarg->mtrr); if (ret) return -EFAULT; karg.handle = (void *) A(tmp); old_fs = get_fs(); set_fs(KERNEL_DS); ret = sys_ioctl(fd, DRM_IOCTL_ADD_MAP, (unsigned long) &karg); set_fs(old_fs); if (!ret) { ret = put_user(karg.offset, &uarg->offset); ret |= put_user(karg.size, &uarg->size); ret |= put_user(karg.type, &uarg->type); ret |= put_user(karg.flags, &uarg->flags); tmp = (u32) (long)karg.handle; ret |= put_user(tmp, &uarg->handle); ret |= put_user(karg.mtrr, &uarg->mtrr); if (ret) ret = -EFAULT; } return ret;}typedef struct drm32_buf_info { int count; /* Entries in list */ u32 list; /* (drm_buf_desc_t *) */ } drm32_buf_info_t;#define DRM32_IOCTL_INFO_BUFS DRM_IOWR(0x18, drm32_buf_info_t)static int drm32_info_bufs(unsigned int fd, unsigned int cmd, unsigned long arg){ drm32_buf_info_t *uarg = (drm32_buf_info_t *)arg; drm_buf_desc_t *ulist; drm_buf_info_t karg; mm_segment_t old_fs; int orig_count, ret; u32 tmp; if (get_user(karg.count, &uarg->count) || get_user(tmp, &uarg->list)) return -EFAULT; ulist = (drm_buf_desc_t *) A(tmp); orig_count = karg.count; karg.list = kmalloc(karg.count * sizeof(drm_buf_desc_t), GFP_KERNEL); if (!karg.list) return -EFAULT; old_fs = get_fs(); set_fs(KERNEL_DS); ret = sys_ioctl(fd, DRM_IOCTL_INFO_BUFS, (unsigned long) &karg); set_fs(old_fs); if (!ret) { if (karg.count <= orig_count && (copy_to_user(ulist, karg.list, karg.count * sizeof(drm_buf_desc_t)))) ret = -EFAULT; if (put_user(karg.count, &uarg->count)) ret = -EFAULT; } kfree(karg.list); return ret;}typedef struct drm32_buf_free { int count; u32 list; /* (int *) */} drm32_buf_free_t;#define DRM32_IOCTL_FREE_BUFS DRM_IOW( 0x1a, drm32_buf_free_t)static int drm32_free_bufs(unsigned int fd, unsigned int cmd, unsigned long arg){ drm32_buf_free_t *uarg = (drm32_buf_free_t *)arg; drm_buf_free_t karg; mm_segment_t old_fs; int *ulist; int ret; u32 tmp; if (get_user(karg.count, &uarg->count) || get_user(tmp, &uarg->list)) return -EFAULT; ulist = (int *) A(tmp); karg.list = kmalloc(karg.count * sizeof(int), GFP_KERNEL); if (!karg.list) return -ENOMEM; ret = -EFAULT; if (copy_from_user(karg.list, ulist, (karg.count * sizeof(int)))) goto out; old_fs = get_fs(); set_fs(KERNEL_DS); ret = sys_ioctl(fd, DRM_IOCTL_FREE_BUFS, (unsigned long) &karg); set_fs(old_fs);out: kfree(karg.list); return ret;}typedef struct drm32_buf_pub { int idx; /* Index into master buflist */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?