[parisc-linux-cvs] ioctl32 changes

Paul Bame bame@fc.hp.com
Tue, 27 Mar 2001 12:24:21 -0700


This fixes the 64-bit kernel panic with mii-tool, removes some unusued
code, and activates some we'll need.

Note that the panic in copy_to_user() is eliminated, but it shouldn't
have been panic-ing because it wasn't called while set_fs(KERNEL_DS)
was in effect.

Index: ioctl32.c
===================================================================
RCS file: /home/cvs/parisc/linux/arch/parisc/kernel/ioctl32.c,v
retrieving revision 1.1
diff -u -r1.1 ioctl32.c
--- ioctl32.c	2001/03/02 00:48:47	1.1
+++ ioctl32.c	2001/03/27 19:13:45
@@ -66,17 +66,7 @@
 
 #include <asm/types.h>
 #include <asm/uaccess.h>
-#ifndef __hppa__
-#include <asm/fbio.h>
-#include <asm/kbio.h>
-#include <asm/vuid_event.h>
-#include <asm/rtc.h>
-#include <asm/openpromio.h>
-#include <asm/envctrl.h>
-#include <asm/audioio.h>
-#include <asm/ethtool.h>
-#include <asm/display7seg.h>
-#endif
+#include <linux/ethtool.h>
 #include <linux/soundcard.h>
 
 #include <linux/atm.h>
@@ -94,13 +84,6 @@
 /* Use this to get at 32-bit user passed pointers. 
    See sys_sparc32.c for description about these. */
 #define A(__x) ((unsigned long)(__x))
-#define AA(__x)				\
-({	unsigned long __ret;		\
-	__asm__ ("srl	%0, 0, %0"	\
-		 : "=r" (__ret)		\
-		 : "0" (__x));		\
-	__ret;				\
-})
 
 /* Aiee. Someone does not find a difference between int and long */
 #define EXT2_IOC32_GETFLAGS               _IOR('f', 1, int)
@@ -140,6 +123,13 @@
 	return err;
 }
 
+static int siocprivate(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	printk("ioctl(%d, 0x%x, %p) -- SIOCDEVPRIVATE-based cmd not supported\n",
+		fd, cmd, (void *)arg);
+	return -ENOSYS;
+}
+
 static int do_ext2_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	/* These are just misnamed, they actually get/put from/to user an int */
@@ -152,250 +142,6 @@
 	return sys_ioctl(fd, cmd, arg);
 }
  
-#if 0
-/* I'm too lazy to read all this right now -PB */
-struct video_tuner32 {
-	s32 tuner;
-	u8 name[32];
-	u32 rangelow, rangehigh;
-	u32 flags;
-	u16 mode, signal;
-};
-
-static int get_video_tuner32(struct video_tuner *kp, struct video_tuner32 *up)
-{
-	int i;
-
-	if(get_user(kp->tuner, &up->tuner))
-		return -EFAULT;
-	for(i = 0; i < 32; i++)
-		__get_user(kp->name[i], &up->name[i]);
-	__get_user(kp->rangelow, &up->rangelow);
-	__get_user(kp->rangehigh, &up->rangehigh);
-	__get_user(kp->flags, &up->flags);
-	__get_user(kp->mode, &up->mode);
-	__get_user(kp->signal, &up->signal);
-	return 0;
-}
-
-static int put_video_tuner32(struct video_tuner *kp, struct video_tuner32 *up)
-{
-	int i;
-
-	if(put_user(kp->tuner, &up->tuner))
-		return -EFAULT;
-	for(i = 0; i < 32; i++)
-		__put_user(kp->name[i], &up->name[i]);
-	__put_user(kp->rangelow, &up->rangelow);
-	__put_user(kp->rangehigh, &up->rangehigh);
-	__put_user(kp->flags, &up->flags);
-	__put_user(kp->mode, &up->mode);
-	__put_user(kp->signal, &up->signal);
-	return 0;
-}
-
-struct video_buffer32 {
-	/* void * */ u32 base;
-	s32 height, width, depth, bytesperline;
-};
-
-static int get_video_buffer32(struct video_buffer *kp, struct video_buffer32 *up)
-{
-	u32 tmp;
-
-	if(get_user(tmp, &up->base))
-		return -EFAULT;
-	kp->base = (void *) ((unsigned long)tmp);
-	__get_user(kp->height, &up->height);
-	__get_user(kp->width, &up->width);
-	__get_user(kp->depth, &up->depth);
-	__get_user(kp->bytesperline, &up->bytesperline);
-	return 0;
-}
-
-static int put_video_buffer32(struct video_buffer *kp, struct video_buffer32 *up)
-{
-	u32 tmp = (u32)((unsigned long)kp->base);
-
-	if(put_user(tmp, &up->base))
-		return -EFAULT;
-	__put_user(kp->height, &up->height);
-	__put_user(kp->width, &up->width);
-	__put_user(kp->depth, &up->depth);
-	__put_user(kp->bytesperline, &up->bytesperline);
-	return 0;
-}
-
-struct video_clip32 {
-	s32 x, y, width, height;
-	/* struct video_clip32 * */ u32 next;
-};
-
-struct video_window32 {
-	u32 x, y, width, height, chromakey, flags;
-	/* struct video_clip32 * */ u32 clips;
-	s32 clipcount;
-};
-
-static void free_kvideo_clips(struct video_window *kp)
-{
-	struct video_clip *cp;
-
-	cp = kp->clips;
-	if(cp != NULL)
-		kfree(cp);
-}
-
-static int get_video_window32(struct video_window *kp, struct video_window32 *up)
-{
-	struct video_clip32 *ucp;
-	struct video_clip *kcp;
-	int nclips, err, i;
-	u32 tmp;
-
-	if(get_user(kp->x, &up->x))
-		return -EFAULT;
-	__get_user(kp->y, &up->y);
-	__get_user(kp->width, &up->width);
-	__get_user(kp->height, &up->height);
-	__get_user(kp->chromakey, &up->chromakey);
-	__get_user(kp->flags, &up->flags);
-	__get_user(kp->clipcount, &up->clipcount);
-	__get_user(tmp, &up->clips);
-	ucp = (struct video_clip32 *)A(tmp);
-	kp->clips = NULL;
-
-	nclips = kp->clipcount;
-	if(nclips == 0)
-		return 0;
-
-	if(ucp == 0)
-		return -EINVAL;
-
-	/* Peculiar interface... */
-	if(nclips < 0)
-		nclips = VIDEO_CLIPMAP_SIZE;
-
-	kcp = kmalloc(nclips * sizeof(struct video_clip), GFP_KERNEL);
-	err = -ENOMEM;
-	if(kcp == NULL)
-		goto cleanup_and_err;
-
-	kp->clips = kcp;
-	for(i = 0; i < nclips; i++) {
-		__get_user(kcp[i].x, &ucp[i].x);
-		__get_user(kcp[i].y, &ucp[i].y);
-		__get_user(kcp[i].width, &ucp[i].width);
-		__get_user(kcp[i].height, &ucp[i].height);
-		kcp[nclips].next = NULL;
-	}
-
-	return 0;
-
-cleanup_and_err:
-	free_kvideo_clips(kp);
-	return err;
-}
-
-/* You get back everything except the clips... */
-static int put_video_window32(struct video_window *kp, struct video_window32 *up)
-{
-	if(put_user(kp->x, &up->x))
-		return -EFAULT;
-	__put_user(kp->y, &up->y);
-	__put_user(kp->width, &up->width);
-	__put_user(kp->height, &up->height);
-	__put_user(kp->chromakey, &up->chromakey);
-	__put_user(kp->flags, &up->flags);
-	__put_user(kp->clipcount, &up->clipcount);
-	return 0;
-}
-
-#define VIDIOCGTUNER32		_IOWR('v',4, struct video_tuner32)
-#define VIDIOCSTUNER32		_IOW('v',5, struct video_tuner32)
-#define VIDIOCGWIN32		_IOR('v',9, struct video_window32)
-#define VIDIOCSWIN32		_IOW('v',10, struct video_window32)
-#define VIDIOCGFBUF32		_IOR('v',11, struct video_buffer32)
-#define VIDIOCSFBUF32		_IOW('v',12, struct video_buffer32)
-#define VIDIOCGFREQ32		_IOR('v',14, u32)
-#define VIDIOCSFREQ32		_IOW('v',15, u32)
-
-static int do_video_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	union {
-		struct video_tuner vt;
-		struct video_buffer vb;
-		struct video_window vw;
-		unsigned long vx;
-	} karg;
-	mm_segment_t old_fs = get_fs();
-	void *up = (void *)arg;
-	int err = 0;
-
-	/* First, convert the command. */
-	switch(cmd) {
-	case VIDIOCGTUNER32: cmd = VIDIOCGTUNER; break;
-	case VIDIOCSTUNER32: cmd = VIDIOCSTUNER; break;
-	case VIDIOCGWIN32: cmd = VIDIOCGWIN; break;
-	case VIDIOCSWIN32: cmd = VIDIOCSWIN; break;
-	case VIDIOCGFBUF32: cmd = VIDIOCGFBUF; break;
-	case VIDIOCSFBUF32: cmd = VIDIOCSFBUF; break;
-	case VIDIOCGFREQ32: cmd = VIDIOCGFREQ; break;
-	case VIDIOCSFREQ32: cmd = VIDIOCSFREQ; break;
-	};
-
-	switch(cmd) {
-	case VIDIOCSTUNER:
-	case VIDIOCGTUNER:
-		err = get_video_tuner32(&karg.vt, up);
-		break;
-
-	case VIDIOCSWIN:
-		err = get_video_window32(&karg.vw, up);
-		break;
-
-	case VIDIOCSFBUF:
-		err = get_video_buffer32(&karg.vb, up);
-		break;
-
-	case VIDIOCSFREQ:
-		err = get_user(karg.vx, (u32 *)up);
-		break;
-	};
-	if(err)
-		goto out;
-
-	set_fs(KERNEL_DS);
-	err = sys_ioctl(fd, cmd, (unsigned long)&karg);
-	set_fs(old_fs);
-
-	if(cmd == VIDIOCSWIN)
-		free_kvideo_clips(&karg.vw);
-
-	if(err == 0) {
-		switch(cmd) {
-		case VIDIOCGTUNER:
-			err = put_video_tuner32(&karg.vt, up);
-			break;
-
-		case VIDIOCGWIN:
-			err = put_video_window32(&karg.vw, up);
-			break;
-
-		case VIDIOCGFBUF:
-			err = put_video_buffer32(&karg.vb, up);
-			break;
-
-		case VIDIOCGFREQ:
-			err = put_user(((u32)karg.vx), (u32 *)up);
-			break;
-		};
-	}
-out:
-	return err;
-}
-#endif /* 0 */
-
 static int do_siocgstamp(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	struct timeval32 *up = (struct timeval32 *)arg;
@@ -527,7 +273,7 @@
 	return err;
 }
 
-static inline int dev_ifsioc(unsigned int fd, unsigned int cmd, unsigned long arg)
+static int dev_ifsioc(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	struct ifreq ifr;
 	mm_segment_t old_fs;
@@ -548,15 +294,12 @@
 	case SIOCGPPPSTATS:
 	case SIOCGPPPCSTATS:
 	case SIOCGPPPVER:
-#ifndef __hppa__
 	case SIOCETHTOOL:
-#endif
 		if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32)))
 			return -EFAULT;
 		ifr.ifr_data = (__kernel_caddr_t)get_free_page(GFP_KERNEL);
 		if (!ifr.ifr_data)
 			return -EAGAIN;
-#ifndef __hppa__
 		if(cmd == SIOCETHTOOL) {
 			u32 data;
 
@@ -568,7 +311,6 @@
 				return -EFAULT;
 			}
 		}
-#endif
 		break;
 	default:
 		if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32)))
@@ -598,20 +340,14 @@
 		case SIOCGPPPSTATS:
 		case SIOCGPPPCSTATS:
 		case SIOCGPPPVER:
-#ifndef __hppa__
 		case SIOCETHTOOL:
-#endif
 		{
 			u32 data;
 			int len;
 
-#if 0
 			__get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data));
-#endif
-#ifndef __hppa__
 			if(cmd == SIOCETHTOOL)
 				len = sizeof(struct ethtool_cmd);
-#endif
 			if(cmd == SIOCGPPPVER)
 				len = strlen((char *)ifr.ifr_data) + 1;
 			else if(cmd == SIOCGPPPCSTATS)
@@ -3780,6 +3516,15 @@
 
 	if (!filp->f_op || !filp->f_op->ioctl) {
 		error = sys_ioctl (fd, cmd, arg);
+		goto out;
+	}
+
+	/* intercept private networking ioctl() calls here since it is
+	 * an onerous task to figure out which ones of the HANDLE_IOCTL
+	 * list map to these values.
+	 */
+	if (cmd >= SIOCDEVPRIVATE && cmd <= SIOCDEVPRIVATE + 0xf) {
+		error = siocprivate(fd, cmd, arg);
 		goto out;
 	}