aboutsummaryrefslogtreecommitdiff
path: root/graphics/dri-devel/files/patch-linuxcompat
blob: 3b6af5bf51791b6f5c957b62622c22eaeced465d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
Index: drm_drv.h
===================================================================
RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_drv.h,v
retrieving revision 1.3
diff -u -r1.3 programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_drv.h
--- programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_drv.h	5 Jul 2002 08:31:07 -0000	1.3
+++ programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_drv.h	21 Aug 2002 07:13:26 -0000
@@ -1221,27 +1221,83 @@
 }
 
 #if DRM_LINUX
+#define LINUX_IOCTL_DRM_MIN		0x6400
+#define LINUX_IOCTL_DRM_MAX		0x64ff
+
 static linux_ioctl_function_t DRM( linux_ioctl);
 static struct linux_ioctl_handler DRM( handler) = {DRM( linux_ioctl), LINUX_IOCTL_DRM_MIN, LINUX_IOCTL_DRM_MAX};
 SYSINIT  (DRM( register),   SI_SUB_KLD, SI_ORDER_MIDDLE, linux_ioctl_register_handler, &DRM( handler));
 SYSUNINIT(DRM( unregister), SI_SUB_KLD, SI_ORDER_MIDDLE, linux_ioctl_unregister_handler, &DRM( handler));
 
+#define LINUX_IOC_VOID	IOC_VOID
+#define LINUX_IOC_IN	IOC_OUT		/* Linux has the values the other way around */
+#define LINUX_IOC_OUT	IOC_IN
+
 /*
  * Linux emulation IOCTL
  */
 static int
 DRM(linux_ioctl)(DRM_STRUCTPROC *p, struct linux_ioctl_args* args)
 {
+	u_long		cmd = args->cmd;
+#define STK_PARAMS	128
+	union {
+	    char stkbuf[STK_PARAMS];
+	    long align;
+	} ubuf;
+	caddr_t		data=NULL, memp=NULL;
+	u_int		size = IOCPARM_LEN(cmd);
+	int		error;
+#if (__FreeBSD_version >= 500000)
+	struct file	*fp;
+#else
+	struct file	*fp = p->p_fd->fd_ofiles[args->fd];
+#endif
+	if ( size > STK_PARAMS ) {
+		if ( size > IOCPARM_MAX )
+			return EINVAL;
+		memp = malloc( (u_long)size, DRM(M_DRM), M_WAITOK );
+		data = memp;
+	} else {
+		data = ubuf.stkbuf;
+	}
+
+	if ( cmd & LINUX_IOC_IN ) {
+		if ( size ) {
+			error = copyin( (caddr_t)args->arg, data, (u_int)size );
+			if (error) {
+				if ( memp )
+					free( data, DRM(M_DRM) );
+				return error;
+			}
+		} else {
+			data = (caddr_t)args->arg;
+		}
+	} else if ( (cmd & LINUX_IOC_OUT) && size ) {
+		/*
+		 * Zero the buffer so the user always
+		 * gets back something deterministic.
+		 */
+		bzero( data, size );
+	} else if ( cmd & LINUX_IOC_VOID ) {
+		*(caddr_t *)data = (caddr_t)args->arg;
+	}
+
 #if (__FreeBSD_version >= 500000)
-    struct file		*fp = p->td_proc->p_fd->fd_ofiles[args->fd];
+	if ( (error = fget( p, args->fd, &fp )) != 0 ) {
+		if ( memp )
+			free( memp, DRM(M_DRM) );
+		return (error);
+	}
+	error = fo_ioctl( fp, cmd, data, p->td_ucred, p );
+	fdrop( fp, p );
 #else
-    struct file		*fp = p->p_fd->fd_ofiles[args->fd];
+	error = fo_ioctl( fp, cmd, data, p );
 #endif
-    u_long		cmd = args->cmd;
-    caddr_t             data = (caddr_t) args->arg;
-    /*
-     * Pass the ioctl off to our standard handler.
-     */
-    return(fo_ioctl(fp, cmd, data, p));
+	if ( error == 0 && (cmd & LINUX_IOC_OUT) && size )
+		error = copyout( data, (caddr_t)args->arg, (u_int)size );
+	if ( memp )
+		free( memp, DRM(M_DRM) );
+	return error;
 }
 #endif /* DRM_LINUX */
Index: drm_os_freebsd.h
===================================================================
RCS file: /cvsroot/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_os_freebsd.h,v
retrieving revision 1.3
diff -u -r1.3 programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_os_freebsd.h
--- programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_os_freebsd.h	5 Jul 2002 08:31:07 -0000	1.3
+++ programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_os_freebsd.h	21 Aug 2002 07:13:27 -0000
@@ -65,7 +65,6 @@
 #include <sys/proc.h>
 #include <machine/../linux/linux.h>
 #include <machine/../linux/linux_proto.h>
-#include "drm_linux.h"
 #endif
 
 #define DRM_TIME_SLICE	      (hz/20)  /* Time slice for GLXContexts	  */
@@ -140,14 +139,18 @@
 	}							\
 } while (0)
 
-#define DRM_COPY_TO_USER_IOCTL(arg1, arg2, arg3) \
-	*arg1 = arg2
-#define DRM_COPY_FROM_USER_IOCTL(arg1, arg2, arg3) \
-	arg1 = *arg2
-#define DRM_COPY_TO_USER(arg1, arg2, arg3) \
-	copyout(arg2, arg1, arg3)
-#define DRM_COPY_FROM_USER(arg1, arg2, arg3) \
-	copyin(arg2, arg1, arg3)
+#define DRM_COPY_TO_USER_IOCTL(user, kern, size)	\
+	if ( IOCPARM_LEN(cmd) != size)			\
+		return EINVAL;				\
+	*user = kern;
+#define DRM_COPY_FROM_USER_IOCTL(kern, user, size) \
+	if ( IOCPARM_LEN(cmd) != size)			\
+		return EINVAL;				\
+	kern = *user;
+#define DRM_COPY_TO_USER(user, kern, size) \
+	copyout(kern, user, size)
+#define DRM_COPY_FROM_USER(kern, user, size) \
+	copyin(user, kern, size)
 /* Macros for userspace access with checking readability once */
 /* FIXME: can't find equivalent functionality for nocheck yet.
  * It's be slower than linux, but should be correct.