ioctl32.c

来自「Linux Kernel 2.6.9 for OMAP1710」· 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 + -
显示快捷键?