[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;
}