patch-2.1.79 linux/arch/sparc64/kernel/ioctl32.c

Next file: linux/arch/sparc64/kernel/irq.c
Previous file: linux/arch/sparc64/kernel/etrap.S
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.78/linux/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c
@@ -1,4 +1,4 @@
-/* $Id: ioctl32.c,v 1.18 1997/09/06 02:25:13 davem Exp $
+/* $Id: ioctl32.c,v 1.26 1997/12/15 15:11:02 jj Exp $
  * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
  *
  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -19,11 +19,19 @@
 #include <linux/md.h>
 #include <linux/kd.h>
 #include <linux/route.h>
+#include <linux/skbuff.h>
 #include <linux/netlink.h>
 #include <linux/vt.h>
 #include <linux/fs.h>
 #include <linux/fd.h>
 #include <linux/if_ppp.h>
+#include <linux/mtio.h>
+
+#include <scsi/scsi.h>
+/* Ugly hack. */
+#undef __KERNEL__
+#include <scsi/scsi_ioctl.h>
+#define __KERNEL__
 
 #include <asm/types.h>
 #include <asm/uaccess.h>
@@ -44,7 +52,7 @@
 
 static int w_long(unsigned int fd, unsigned int cmd, u32 arg)
 {
-	unsigned long old_fs = get_fs();
+	mm_segment_t old_fs = get_fs();
 	int err;
 	unsigned long val;
 	
@@ -97,16 +105,24 @@
 	struct ifconf ifc;
 	struct ifreq32 *ifr32;
 	struct ifreq *ifr;
-	unsigned long old_fs;
+	mm_segment_t old_fs;
 	unsigned int i, j;
 	int err;
 
 	if (copy_from_user(&ifc32, (struct ifconf32 *)A(arg), sizeof(struct ifconf32)))
 		return -EFAULT;
 
-	ifc.ifc_len = ((ifc32.ifc_len / sizeof (struct ifreq32)) + 1) * sizeof (struct ifreq);
-	ifc.ifc_buf = kmalloc (ifc.ifc_len, GFP_KERNEL);
-	if (!ifc.ifc_buf) return -ENOMEM;
+	if(ifc32.ifcbuf == 0) {
+		ifc32.ifc_len = 0;
+		ifc.ifc_len = 0;
+		ifc.ifc_buf = NULL;
+	} else {
+		ifc.ifc_len = ((ifc32.ifc_len / sizeof (struct ifreq32)) + 1) *
+			sizeof (struct ifreq);
+		ifc.ifc_buf = kmalloc (ifc.ifc_len, GFP_KERNEL);
+		if (!ifc.ifc_buf)
+			return -ENOMEM;
+	}
 	ifr = ifc.ifc_req;
 	ifr32 = (struct ifreq32 *)A(ifc32.ifcbuf);
 	for (i = 0; i < ifc32.ifc_len; i += sizeof (struct ifreq32)) {
@@ -137,14 +153,15 @@
 				err = -EFAULT;
 		}
 	}
-	kfree (ifc.ifc_buf);
+	if(ifc.ifc_buf != NULL)
+		kfree (ifc.ifc_buf);
 	return err;
 }
 
 static inline int dev_ifsioc(unsigned int fd, unsigned int cmd, u32 arg)
 {
 	struct ifreq ifr;
-	unsigned long old_fs;
+	mm_segment_t old_fs;
 	int err;
 	
 	switch (cmd) {
@@ -183,7 +200,7 @@
 		case SIOCGIFMTU:
 		case SIOCGIFMEM:
 		case SIOCGIFHWADDR:
-		case SIOGIFINDEX:
+		case SIOCGIFINDEX:
 		case SIOCGIFADDR:
 		case SIOCGIFBRDADDR:
 		case SIOCGIFDSTADDR:
@@ -250,16 +267,10 @@
 	char devname[16];
 	u32 rtdev;
 	int ret;
-	unsigned long old_fs = get_fs();
+	mm_segment_t old_fs = get_fs();
 	
-	if (get_user (r.rt_pad1, &(((struct rtentry32 *)A(arg))->rt_pad1)) ||
-	    copy_from_user (&r.rt_dst, &(((struct rtentry32 *)A(arg))->rt_dst), 3 * sizeof(struct sockaddr)) ||
+	if (copy_from_user (&r.rt_dst, &(((struct rtentry32 *)A(arg))->rt_dst), 3 * sizeof(struct sockaddr)) ||
 	    __get_user (r.rt_flags, &(((struct rtentry32 *)A(arg))->rt_flags)) ||
-	    __get_user (r.rt_pad2, &(((struct rtentry32 *)A(arg))->rt_pad2)) ||
-	    __get_user (r.rt_pad3, &(((struct rtentry32 *)A(arg))->rt_pad3)) ||
-	    __get_user (r.rt_tos, &(((struct rtentry32 *)A(arg))->rt_tos)) ||
-	    __get_user (r.rt_class, &(((struct rtentry32 *)A(arg))->rt_class)) ||
-	    __get_user (r.rt_pad4, &(((struct rtentry32 *)A(arg))->rt_pad4)) ||
 	    __get_user (r.rt_metric, &(((struct rtentry32 *)A(arg))->rt_metric)) ||
 	    __get_user (r.rt_mtu, &(((struct rtentry32 *)A(arg))->rt_mtu)) ||
 	    __get_user (r.rt_window, &(((struct rtentry32 *)A(arg))->rt_window)) ||
@@ -277,116 +288,6 @@
 	return ret;
 }
 
-struct nlmsghdr32 {
-        u32   		nlmsg_len;      /* Length of message including header */
-        u32   		nlmsg_type;     /* Message type */
-        u32   		nlmsg_seq;      /* Sequence number */
-        u32   		nlmsg_pid;      /* Sending process PID */
-        unsigned char   nlmsg_data[0];
-};
-
-struct in_rtmsg32 {
-        struct in_addr  rtmsg_prefix;
-        struct in_addr  rtmsg_gateway;
-        unsigned        rtmsg_flags;
-        u32   		rtmsg_mtu;
-        u32   		rtmsg_window;
-        unsigned short  rtmsg_rtt;
-        short           rtmsg_metric;
-        unsigned char   rtmsg_tos;
-        unsigned char   rtmsg_class;
-        unsigned char   rtmsg_prefixlen;
-        unsigned char   rtmsg_reserved;
-        int             rtmsg_ifindex;
-};
-
-struct in_ifmsg32 {
-        struct sockaddr ifmsg_lladdr;
-        struct in_addr  ifmsg_prefix;
-        struct in_addr  ifmsg_brd;
-        unsigned        ifmsg_flags;
-        u32   		ifmsg_mtu;
-        short           ifmsg_metric;
-        unsigned char   ifmsg_prefixlen;
-        unsigned char   ifmsg_reserved;
-        int             ifmsg_index;
-        char            ifmsg_name[16];
-};
-
-static inline int rtmsg_ioctl(unsigned int fd, u32 arg)
-{
-	struct {
-		struct nlmsghdr n;
-		union {
-			struct in_rtmsg rt;
-			struct in_ifmsg iff;
-			struct in_rtctlmsg ctl;
-			struct in_rtrulemsg rule;
-		} u;
-	} nn;
-	char *p;
-	int ret;
-	unsigned long old_fs = get_fs();
-	
-	if (get_user (nn.n.nlmsg_len, &(((struct nlmsghdr32 *)A(arg))->nlmsg_len)) ||
-	    __get_user (nn.n.nlmsg_type, &(((struct nlmsghdr32 *)A(arg))->nlmsg_type)) ||
-	    __get_user (nn.n.nlmsg_seq, &(((struct nlmsghdr32 *)A(arg))->nlmsg_seq)) ||
-	    __get_user (nn.n.nlmsg_pid, &(((struct nlmsghdr32 *)A(arg))->nlmsg_pid)) ||
-	    __get_user (nn.n.nlmsg_data[0], &(((struct nlmsghdr32 *)A(arg))->nlmsg_data[0])))
-		return -EFAULT;
-	p = ((char *)(&nn.n)) + sizeof(struct nlmsghdr);
-	arg += sizeof(struct nlmsghdr32);
-	switch (nn.n.nlmsg_type) {
-	case RTMSG_NEWRULE:
-	case RTMSG_DELRULE:
-		if (nn.n.nlmsg_len < sizeof(struct nlmsghdr32) + sizeof(struct in_rtrulemsg)
-		    - sizeof(struct in_rtmsg) + sizeof(struct in_rtmsg32))
-			return -EINVAL;
-		if (copy_from_user (p, (struct in_rtrulemsg *)A(arg), sizeof(struct in_rtrulemsg) - sizeof(struct in_rtmsg)))
-			return -EFAULT;
-		nn.n.nlmsg_len = sizeof(struct nlmsghdr) + sizeof(struct in_rtrulemsg);
-		p += sizeof (struct in_rtrulemsg) - sizeof(struct in_rtmsg);
-		arg += sizeof (struct in_rtrulemsg) - sizeof(struct in_rtmsg);
-		goto newroute;
-	case RTMSG_NEWROUTE:
-	case RTMSG_DELROUTE:
-		if (nn.n.nlmsg_len < sizeof(struct nlmsghdr32) + sizeof(struct in_rtmsg))
-			return -EINVAL;
-		nn.n.nlmsg_len = sizeof(struct nlmsghdr) + sizeof(struct in_rtmsg);
-newroute:
-		if (copy_from_user (p, (struct in_rtmsg32 *)A(arg), 2*sizeof(struct in_addr) + sizeof(unsigned)) ||
-	    	    __get_user (((struct in_rtmsg *)p)->rtmsg_mtu, &((struct in_rtmsg32 *)A(arg))->rtmsg_mtu) ||
-	    	    __get_user (((struct in_rtmsg *)p)->rtmsg_window, &((struct in_rtmsg32 *)A(arg))->rtmsg_window) ||
-		    copy_from_user (&(((struct in_rtmsg *)p)->rtmsg_rtt), &((struct in_rtmsg32 *)A(arg))->rtmsg_rtt, 
-			2 * sizeof(short) + 4 + sizeof(int)))
-			return -EFAULT;
-		break;
-	case RTMSG_NEWDEVICE:
-	case RTMSG_DELDEVICE:
-		if (nn.n.nlmsg_len < sizeof(struct nlmsghdr32) + sizeof(struct in_ifmsg))
-			return -EINVAL;
-		nn.n.nlmsg_len = sizeof(struct nlmsghdr) + sizeof(struct in_ifmsg);
-		if (copy_from_user (p, (struct in_ifmsg32 *)A(arg), 
-			sizeof(struct sockaddr) + 2*sizeof(struct in_addr) + sizeof(unsigned)) ||
-	    	    __get_user (((struct in_ifmsg *)p)->ifmsg_mtu, &((struct in_ifmsg32 *)A(arg))->ifmsg_mtu) ||
-		    copy_from_user (&(((struct in_ifmsg *)p)->ifmsg_metric), &((struct in_ifmsg32 *)A(arg))->ifmsg_metric, 
-			sizeof(short) + 2 + sizeof(int) + 16))
-			return -EFAULT;
-		break;
-	case RTMSG_CONTROL:
-		if (nn.n.nlmsg_len < sizeof(struct nlmsghdr32) + sizeof(struct in_rtctlmsg))
-			return -EINVAL;
-		nn.n.nlmsg_len = sizeof(struct nlmsghdr) + sizeof(struct in_rtctlmsg);
-		if (copy_from_user (p, (struct in_rtctlmsg *)A(arg), sizeof(struct in_rtctlmsg)))
-			return -EFAULT;
-		break;
-	}
-	set_fs (KERNEL_DS);
-	ret = sys_ioctl (fd, SIOCRTMSG, (long)&(nn.n));
-	set_fs (old_fs);
-	return ret;
-}
-
 struct hd_geometry32 {
 	unsigned char heads;
 	unsigned char sectors;
@@ -396,7 +297,7 @@
                         
 static inline int hdio_getgeo(unsigned int fd, u32 arg)
 {
-	unsigned long old_fs = get_fs();
+	mm_segment_t old_fs = get_fs();
 	struct hd_geometry geo;
 	int err;
 	
@@ -428,7 +329,7 @@
 	int ret;
 	char red[256], green[256], blue[256];
 	u32 r, g, b;
-	unsigned long old_fs = get_fs();
+	mm_segment_t old_fs = get_fs();
 	
 	if (get_user(f.index, &(((struct fbcmap32 *)A(arg))->index)) ||
 	    __get_user(f.count, &(((struct fbcmap32 *)A(arg))->count)) ||
@@ -480,7 +381,7 @@
 	char image[128], mask[128];
 	u32 r, g, b;
 	u32 m, i;
-	unsigned long old_fs = get_fs();
+	mm_segment_t old_fs = get_fs();
 	
 	if (copy_from_user (&f, (struct fbcursor32 *)A(arg), 2 * sizeof (short) + 2 * sizeof(struct fbcurpos)) ||
 	    __get_user(f.size.fbx, &(((struct fbcursor32 *)A(arg))->size.fbx)) ||
@@ -516,7 +417,7 @@
 	
 static int hdio_ioctl_trans(unsigned int fd, unsigned int cmd, u32 arg)
 {
-	unsigned long old_fs = get_fs();
+	mm_segment_t old_fs = get_fs();
 	unsigned long kval;
 	unsigned int *uvp;
 	int error;
@@ -533,6 +434,328 @@
 	return error;
 }
 
+struct floppy_struct32 {
+	unsigned int	size;
+	unsigned int	sect;
+	unsigned int	head;
+	unsigned int	track;
+	unsigned int	stretch;
+	unsigned char	gap;
+	unsigned char	rate;
+	unsigned char	spec1;
+	unsigned char	fmt_gap;
+	const __kernel_caddr_t32 name;
+};
+
+struct floppy_drive_params32 {
+	char		cmos;
+	u32		max_dtr;
+	u32		hlt;
+	u32		hut;
+	u32		srt;
+	u32		spinup;
+	u32		spindown;
+	unsigned char	spindown_offset;
+	unsigned char	select_delay;
+	unsigned char	rps;
+	unsigned char	tracks;
+	u32		timeout;
+	unsigned char	interleave_sect;
+	struct floppy_max_errors max_errors;
+	char		flags;
+	char		read_track;
+	short		autodetect[8];
+	int		checkfreq;
+	int		native_format;
+};
+
+struct floppy_drive_struct32 {
+	signed char	flags;
+	u32		spinup_date;
+	u32		select_date;
+	u32		first_read_date;
+	short		probed_format;
+	short		track;
+	short		maxblock;
+	short		maxtrack;
+	int		generation;
+	int		keep_data;
+	int		fd_ref;
+	int		fd_device;
+	int		last_checked;
+	__kernel_caddr_t32 dmabuf;
+	int		bufblocks;
+};
+
+struct floppy_fdc_state32 {
+	int		spec1;
+	int		spec2;
+	int		dtr;
+	unsigned char	version;
+	unsigned char	dor;
+	u32		address;
+	unsigned int	rawcmd:2;
+	unsigned int	reset:1;
+	unsigned int	need_configure:1;
+	unsigned int	perp_mode:2;
+	unsigned int	has_fifo:1;
+	unsigned int	driver_version;
+	unsigned char	track[4];
+};
+
+struct floppy_write_errors32 {
+	unsigned int	write_errors;
+	u32		first_error_sector;
+	int		first_error_generation;
+	u32		last_error_sector;
+	int		last_error_generation;
+	unsigned int	badness;
+};
+
+#define FDSETPRM32 _IOW(2, 0x42, struct floppy_struct32) 
+#define FDDEFPRM32 _IOW(2, 0x43, struct floppy_struct32) 
+#define FDGETPRM32 _IOR(2, 0x04, struct floppy_struct32)
+#define FDSETDRVPRM32 _IOW(2, 0x90, struct floppy_drive_params32)
+#define FDGETDRVPRM32 _IOR(2, 0x11, struct floppy_drive_params32)
+#define FDGETDRVSTAT32 _IOR(2, 0x12, struct floppy_drive_struct32)
+#define FDPOLLDRVSTAT32 _IOR(2, 0x13, struct floppy_drive_struct32)
+#define FDGETFDCSTAT32 _IOR(2, 0x15, struct floppy_fdc_state32)
+#define FDWERRORGET32  _IOR(2, 0x17, struct floppy_write_errors32)
+
+static struct {
+	unsigned int	cmd32;
+	unsigned int	cmd;
+} fd_ioctl_trans_table[] = {
+	{ FDSETPRM32, FDSETPRM },
+	{ FDDEFPRM32, FDDEFPRM },
+	{ FDGETPRM32, FDGETPRM },
+	{ FDSETDRVPRM32, FDSETDRVPRM },
+	{ FDGETDRVPRM32, FDGETDRVPRM },
+	{ FDGETDRVSTAT32, FDGETDRVSTAT },
+	{ FDPOLLDRVSTAT32, FDPOLLDRVSTAT },
+	{ FDGETFDCSTAT32, FDGETFDCSTAT },
+	{ FDWERRORGET32, FDWERRORGET }
+};
+
+#define NR_FD_IOCTL_TRANS (sizeof(fd_ioctl_trans_table)/sizeof(fd_ioctl_trans_table[0]))
+
+static int fd_ioctl_trans(unsigned int fd, unsigned int cmd, u32 arg)
+{
+	mm_segment_t old_fs = get_fs();
+	void *karg;
+	unsigned int kcmd = 0;
+	int i, err;
+
+	for (i = 0; i < NR_FD_IOCTL_TRANS; i++)
+		if (cmd == fd_ioctl_trans_table[i].cmd32) {
+			kcmd = fd_ioctl_trans_table[i].cmd;
+			break;
+		}
+	if (!kcmd)
+		return -EINVAL;
+
+	switch (cmd) {
+		case FDSETPRM32:
+		case FDDEFPRM32:
+		case FDGETPRM32:
+		{
+			struct floppy_struct *f;
+
+			f = karg = kmalloc(GFP_KERNEL, sizeof(struct floppy_struct));
+			if (!karg)
+				return -ENOMEM;
+			if (cmd == FDGETPRM32)
+				break;
+			if (__get_user(f->size, &((struct floppy_struct32 *)A(arg))->size) ||
+			    __get_user(f->sect, &((struct floppy_struct32 *)A(arg))->sect) ||
+			    __get_user(f->head, &((struct floppy_struct32 *)A(arg))->head) ||
+			    __get_user(f->track, &((struct floppy_struct32 *)A(arg))->track) ||
+			    __get_user(f->stretch, &((struct floppy_struct32 *)A(arg))->stretch) ||
+			    __get_user(f->gap, &((struct floppy_struct32 *)A(arg))->gap) ||
+			    __get_user(f->rate, &((struct floppy_struct32 *)A(arg))->rate) ||
+			    __get_user(f->spec1, &((struct floppy_struct32 *)A(arg))->spec1) ||
+			    __get_user(f->fmt_gap, &((struct floppy_struct32 *)A(arg))->fmt_gap) ||
+			    __get_user((u64)f->name, &((struct floppy_struct32 *)A(arg))->name)) {
+				kfree(karg);
+				return -EFAULT;
+			}
+			break;
+		}
+		case FDSETDRVPRM32:
+		case FDGETDRVPRM32:
+		{
+			struct floppy_drive_params *f;
+
+			f = karg = kmalloc(GFP_KERNEL, sizeof(struct floppy_drive_params));
+			if (!karg)
+				return -ENOMEM;
+			if (cmd == FDGETDRVPRM32)
+				break;
+			if (__get_user(f->cmos, &((struct floppy_drive_params32 *)A(arg))->cmos) ||
+			    __get_user(f->max_dtr, &((struct floppy_drive_params32 *)A(arg))->max_dtr) ||
+			    __get_user(f->hlt, &((struct floppy_drive_params32 *)A(arg))->hlt) ||
+			    __get_user(f->hut, &((struct floppy_drive_params32 *)A(arg))->hut) ||
+			    __get_user(f->srt, &((struct floppy_drive_params32 *)A(arg))->srt) ||
+			    __get_user(f->spinup, &((struct floppy_drive_params32 *)A(arg))->spinup) ||
+			    __get_user(f->spindown, &((struct floppy_drive_params32 *)A(arg))->spindown) ||
+			    __get_user(f->spindown_offset, &((struct floppy_drive_params32 *)A(arg))->spindown_offset) ||
+			    __get_user(f->select_delay, &((struct floppy_drive_params32 *)A(arg))->select_delay) ||
+			    __get_user(f->rps, &((struct floppy_drive_params32 *)A(arg))->rps) ||
+			    __get_user(f->tracks, &((struct floppy_drive_params32 *)A(arg))->tracks) ||
+			    __get_user(f->timeout, &((struct floppy_drive_params32 *)A(arg))->timeout) ||
+			    __get_user(f->interleave_sect, &((struct floppy_drive_params32 *)A(arg))->interleave_sect) ||
+			    __copy_from_user(&f->max_errors, &((struct floppy_drive_params32 *)A(arg))->max_errors, sizeof(f->max_errors)) ||
+			    __get_user(f->flags, &((struct floppy_drive_params32 *)A(arg))->flags) ||
+			    __get_user(f->read_track, &((struct floppy_drive_params32 *)A(arg))->read_track) ||
+			    __copy_from_user(f->autodetect, ((struct floppy_drive_params32 *)A(arg))->autodetect, sizeof(f->autodetect)) ||
+			    __get_user(f->checkfreq, &((struct floppy_drive_params32 *)A(arg))->checkfreq) ||
+			    __get_user(f->native_format, &((struct floppy_drive_params32 *)A(arg))->native_format)) {
+				kfree(karg);
+				return -EFAULT;
+			}
+			break;
+		}
+		case FDGETDRVSTAT32:
+		case FDPOLLDRVSTAT32:
+			karg = kmalloc(GFP_KERNEL, sizeof(struct floppy_drive_struct));
+			if (!karg)
+				return -ENOMEM;
+			break;
+		case FDGETFDCSTAT32:
+			karg = kmalloc(GFP_KERNEL, sizeof(struct floppy_fdc_state));
+			if (!karg)
+				return -ENOMEM;
+			break;
+		case FDWERRORGET32:
+			karg = kmalloc(GFP_KERNEL, sizeof(struct floppy_write_errors));
+			if (!karg)
+				return -ENOMEM;
+			break;
+		default:
+			return -EINVAL;
+	}
+	set_fs (KERNEL_DS);
+	err = sys_ioctl (fd, kcmd, (unsigned long)karg);
+	set_fs (old_fs);
+	if (err) {
+		kfree(karg);
+		return err;
+	}
+	switch (cmd) {
+		case FDGETPRM32:
+		{
+			struct floppy_struct *f = karg;
+
+			if (__put_user(f->size, &((struct floppy_struct32 *)A(arg))->size) ||
+			    __put_user(f->sect, &((struct floppy_struct32 *)A(arg))->sect) ||
+			    __put_user(f->head, &((struct floppy_struct32 *)A(arg))->head) ||
+			    __put_user(f->track, &((struct floppy_struct32 *)A(arg))->track) ||
+			    __put_user(f->stretch, &((struct floppy_struct32 *)A(arg))->stretch) ||
+			    __put_user(f->gap, &((struct floppy_struct32 *)A(arg))->gap) ||
+			    __put_user(f->rate, &((struct floppy_struct32 *)A(arg))->rate) ||
+			    __put_user(f->spec1, &((struct floppy_struct32 *)A(arg))->spec1) ||
+			    __put_user(f->fmt_gap, &((struct floppy_struct32 *)A(arg))->fmt_gap) ||
+			    __put_user((u64)f->name, &((struct floppy_struct32 *)A(arg))->name)) {
+				kfree(karg);
+				return -EFAULT;
+			}
+			break;
+		}
+		case FDGETDRVPRM32:
+		{
+			struct floppy_drive_params *f = karg;
+
+			if (__put_user(f->cmos, &((struct floppy_drive_params32 *)A(arg))->cmos) ||
+			    __put_user(f->max_dtr, &((struct floppy_drive_params32 *)A(arg))->max_dtr) ||
+			    __put_user(f->hlt, &((struct floppy_drive_params32 *)A(arg))->hlt) ||
+			    __put_user(f->hut, &((struct floppy_drive_params32 *)A(arg))->hut) ||
+			    __put_user(f->srt, &((struct floppy_drive_params32 *)A(arg))->srt) ||
+			    __put_user(f->spinup, &((struct floppy_drive_params32 *)A(arg))->spinup) ||
+			    __put_user(f->spindown, &((struct floppy_drive_params32 *)A(arg))->spindown) ||
+			    __put_user(f->spindown_offset, &((struct floppy_drive_params32 *)A(arg))->spindown_offset) ||
+			    __put_user(f->select_delay, &((struct floppy_drive_params32 *)A(arg))->select_delay) ||
+			    __put_user(f->rps, &((struct floppy_drive_params32 *)A(arg))->rps) ||
+			    __put_user(f->tracks, &((struct floppy_drive_params32 *)A(arg))->tracks) ||
+			    __put_user(f->timeout, &((struct floppy_drive_params32 *)A(arg))->timeout) ||
+			    __put_user(f->interleave_sect, &((struct floppy_drive_params32 *)A(arg))->interleave_sect) ||
+			    __copy_to_user(&((struct floppy_drive_params32 *)A(arg))->max_errors, &f->max_errors, sizeof(f->max_errors)) ||
+			    __put_user(f->flags, &((struct floppy_drive_params32 *)A(arg))->flags) ||
+			    __put_user(f->read_track, &((struct floppy_drive_params32 *)A(arg))->read_track) ||
+			    __copy_to_user(((struct floppy_drive_params32 *)A(arg))->autodetect, f->autodetect, sizeof(f->autodetect)) ||
+			    __put_user(f->checkfreq, &((struct floppy_drive_params32 *)A(arg))->checkfreq) ||
+			    __put_user(f->native_format, &((struct floppy_drive_params32 *)A(arg))->native_format)) {
+				kfree(karg);
+				return -EFAULT;
+			}
+			break;
+		}
+		case FDGETDRVSTAT32:
+		case FDPOLLDRVSTAT32:
+		{
+			struct floppy_drive_struct *f = karg;
+
+			if (__put_user(f->flags, &((struct floppy_drive_struct32 *)A(arg))->flags) ||
+			    __put_user(f->spinup_date, &((struct floppy_drive_struct32 *)A(arg))->spinup_date) ||
+			    __put_user(f->select_date, &((struct floppy_drive_struct32 *)A(arg))->select_date) ||
+			    __put_user(f->first_read_date, &((struct floppy_drive_struct32 *)A(arg))->first_read_date) ||
+			    __put_user(f->probed_format, &((struct floppy_drive_struct32 *)A(arg))->probed_format) ||
+			    __put_user(f->track, &((struct floppy_drive_struct32 *)A(arg))->track) ||
+			    __put_user(f->maxblock, &((struct floppy_drive_struct32 *)A(arg))->maxblock) ||
+			    __put_user(f->maxtrack, &((struct floppy_drive_struct32 *)A(arg))->maxtrack) ||
+			    __put_user(f->generation, &((struct floppy_drive_struct32 *)A(arg))->generation) ||
+			    __put_user(f->keep_data, &((struct floppy_drive_struct32 *)A(arg))->keep_data) ||
+			    __put_user(f->fd_ref, &((struct floppy_drive_struct32 *)A(arg))->fd_ref) ||
+			    __put_user(f->fd_device, &((struct floppy_drive_struct32 *)A(arg))->fd_device) ||
+			    __put_user(f->last_checked, &((struct floppy_drive_struct32 *)A(arg))->last_checked) ||
+			    __put_user((u64)f->dmabuf, &((struct floppy_drive_struct32 *)A(arg))->dmabuf) ||
+			    __put_user((u64)f->bufblocks, &((struct floppy_drive_struct32 *)A(arg))->bufblocks)) {
+				kfree(karg);
+				return -EFAULT;
+			}
+			break;
+		}
+		case FDGETFDCSTAT32:
+		{
+			struct floppy_fdc_state *f = karg;
+
+			if (__put_user(f->spec1, &((struct floppy_fdc_state32 *)A(arg))->spec1) ||
+			    __put_user(f->spec2, &((struct floppy_fdc_state32 *)A(arg))->spec2) ||
+			    __put_user(f->dtr, &((struct floppy_fdc_state32 *)A(arg))->dtr) ||
+			    __put_user(f->version, &((struct floppy_fdc_state32 *)A(arg))->version) ||
+			    __put_user(f->dor, &((struct floppy_fdc_state32 *)A(arg))->dor) ||
+			    __put_user(f->address, &((struct floppy_fdc_state32 *)A(arg))->address) ||
+			    __copy_to_user((char *)&((struct floppy_fdc_state32 *)A(arg))->address
+			    		   + sizeof(((struct floppy_fdc_state32 *)A(arg))->address),
+					   (char *)&f->address + sizeof(f->address), sizeof(int)) ||
+			    __put_user(f->driver_version, &((struct floppy_fdc_state32 *)A(arg))->driver_version) ||
+			    __copy_to_user(((struct floppy_fdc_state32 *)A(arg))->track, f->track, sizeof(f->track))) {
+				kfree(karg);
+				return -EFAULT;
+			}
+			break;
+		}
+		case FDWERRORGET32:
+		{
+			struct floppy_write_errors *f = karg;
+
+			if (__put_user(f->write_errors, &((struct floppy_write_errors32 *)A(arg))->write_errors) ||
+			    __put_user(f->first_error_sector, &((struct floppy_write_errors32 *)A(arg))->first_error_sector) ||
+			    __put_user(f->first_error_generation, &((struct floppy_write_errors32 *)A(arg))->first_error_generation) ||
+			    __put_user(f->last_error_sector, &((struct floppy_write_errors32 *)A(arg))->last_error_sector) ||
+			    __put_user(f->last_error_generation, &((struct floppy_write_errors32 *)A(arg))->last_error_generation) ||
+			    __put_user(f->badness, &((struct floppy_write_errors32 *)A(arg))->badness)) {
+				kfree(karg);
+				return -EFAULT;
+			}
+			break;
+		}
+		default:
+			break;
+	}
+	kfree(karg);
+	return 0;
+}
+
 struct ppp_option_data32 {
 	__kernel_caddr_t32	ptr;
 	__u32			length;
@@ -540,14 +763,28 @@
 };
 #define PPPIOCSCOMPRESS32	_IOW('t', 77, struct ppp_option_data32)
 
-static int ppp_ioctl(unsigned int fd, unsigned int cmd, u32 arg)
+struct ppp_idle32 {
+	__kernel_time_t32 xmit_idle;
+	__kernel_time_t32 recv_idle;
+};
+#define PPPIOCGIDLE32		_IOR('t', 63, struct ppp_idle32)
+
+static int ppp_ioctl_trans(unsigned int fd, unsigned int cmd, u32 arg)
 {
-	unsigned long old_fs = get_fs();
+	mm_segment_t old_fs = get_fs();
 	struct ppp_option_data32 data32;
 	struct ppp_option_data data;
-	int err;
+	struct ppp_idle32 idle32;
+	struct ppp_idle idle;
+	unsigned int kcmd;
+	void *karg;
+	int err = 0;
 
 	switch (cmd) {
+	case PPPIOCGIDLE32:
+		kcmd = PPPIOCGIDLE;
+		karg = &idle;
+		break;
 	case PPPIOCSCOMPRESS32:
 		if (copy_from_user(&data32, (struct ppp_option_data32 *)A(arg), sizeof(struct ppp_option_data32)))
 			return -EFAULT;
@@ -555,33 +792,163 @@
 		if (!data.ptr)
 			return -ENOMEM;
 		if (copy_from_user(data.ptr, (__u8 *)A(data32.ptr), data32.length)) {
-			err = -EFAULT;
-			goto out;
+			kfree(data.ptr);
+			return -EFAULT;
 		}
 		data.length = data32.length;
 		data.transmit = data32.transmit;
+		kcmd = PPPIOCSCOMPRESS;
+		karg = &data;
 		break;
 	default:
 		printk("ppp_ioctl: Unknown cmd fd(%d) cmd(%08x) arg(%08x)\n",
 		       (int)fd, (unsigned int)cmd, (unsigned int)arg);
 		return -EINVAL;
 	}
-	old_fs = get_fs();
 	set_fs (KERNEL_DS);
-	err = sys_ioctl (fd, cmd, (unsigned long)&data);
+	err = sys_ioctl (fd, kcmd, (unsigned long)karg);
 	set_fs (old_fs);
-	if (err)
-		goto out;
 	switch (cmd) {
+	case PPPIOCGIDLE32:
+		if (err)
+			return err;
+		idle32.xmit_idle = idle.xmit_idle;
+		idle32.recv_idle = idle.recv_idle;
+		if (copy_to_user((struct ppp_idle32 *)A(arg), &idle32, sizeof(struct ppp_idle32)))
+			return -EFAULT;
+		break;
 	case PPPIOCSCOMPRESS32:
+		kfree(data.ptr);
+		break;
 	default:
 		break;
 	}
-out:
-	kfree(data.ptr);
 	return err;
 }
 
+
+struct mtget32 {
+	__u32	mt_type;
+	__u32	mt_resid;
+	__u32	mt_dsreg;
+	__u32	mt_gstat;
+	__u32	mt_erreg;
+	__kernel_daddr_t32	mt_fileno;
+	__kernel_daddr_t32	mt_blkno;
+};
+#define MTIOCGET32	_IOR('m', 2, struct mtget32)
+
+struct mtpos32 {
+	__u32	mt_blkno;
+};
+#define MTIOCPOS32	_IOR('m', 3, struct mtpos32)
+
+struct mtconfiginfo32 {
+	__u32	mt_type;
+	__u32	ifc_type;
+	__u16	irqnr;
+	__u16	dmanr;
+	__u16	port;
+	__u32	debug;
+	__u32	have_dens:1;
+	__u32	have_bsf:1;
+	__u32	have_fsr:1;
+	__u32	have_bsr:1;
+	__u32	have_eod:1;
+	__u32	have_seek:1;
+	__u32	have_tell:1;
+	__u32	have_ras1:1;
+	__u32	have_ras2:1;
+	__u32	have_ras3:1;
+	__u32	have_qfa:1;
+	__u32	pad1:5;
+	char	reserved[10];
+};
+#define	MTIOCGETCONFIG32	_IOR('m', 4, struct mtconfiginfo32)
+#define	MTIOCSETCONFIG32	_IOW('m', 5, struct mtconfiginfo32)
+
+static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, u32 arg)
+{
+	mm_segment_t old_fs = get_fs();
+	struct mtconfiginfo info;
+	struct mtget get;
+	struct mtpos pos;
+	unsigned long kcmd;
+	void *karg;
+	int err = 0;
+
+	switch(cmd) {
+	case MTIOCPOS32:
+		kcmd = MTIOCPOS;
+		karg = &pos;
+		break;
+	case MTIOCGET32:
+		kcmd = MTIOCGET;
+		karg = &get;
+		break;
+	case MTIOCGETCONFIG32:
+		kcmd = MTIOCGETCONFIG;
+		karg = &info;
+		break;
+	case MTIOCSETCONFIG32:
+		kcmd = MTIOCSETCONFIG;
+		karg = &info;
+		if (__get_user(info.mt_type, &((struct mtconfiginfo32 *)A(arg))->mt_type) ||
+		    __get_user(info.ifc_type, &((struct mtconfiginfo32 *)A(arg))->ifc_type) ||
+		    __get_user(info.irqnr, &((struct mtconfiginfo32 *)A(arg))->irqnr) ||
+		    __get_user(info.dmanr, &((struct mtconfiginfo32 *)A(arg))->dmanr) ||
+		    __get_user(info.port, &((struct mtconfiginfo32 *)A(arg))->port) ||
+		    __get_user(info.debug, &((struct mtconfiginfo32 *)A(arg))->debug) ||
+		    __copy_from_user((char *)&info.debug + sizeof(info.debug),
+				     (char *)&((struct mtconfiginfo32 *)A(arg))->debug
+			    		     + sizeof(((struct mtconfiginfo32 *)A(arg))->debug),
+				     sizeof(__u32)))
+			return -EFAULT;
+		break;
+	default:
+		printk("mt_ioctl: Unknown cmd fd(%d) cmd(%08x) arg(%08x)\n",
+		       (int)fd, (unsigned int)cmd, (unsigned int)arg);
+		return -EINVAL;
+	}
+	set_fs (KERNEL_DS);
+	err = sys_ioctl (fd, kcmd, (unsigned long)karg);
+	set_fs (old_fs);
+	if (err)
+		return err;
+	switch (cmd) {
+	case MTIOCPOS32:
+		if (__put_user(pos.mt_blkno, &((struct mtpos32 *)A(arg))->mt_blkno))
+			return -EFAULT;
+		break;
+	case MTIOCGET32:
+		if (__put_user(get.mt_type, &((struct mtget32 *)A(arg))->mt_type) ||
+		    __put_user(get.mt_resid, &((struct mtget32 *)A(arg))->mt_resid) ||
+		    __put_user(get.mt_dsreg, &((struct mtget32 *)A(arg))->mt_dsreg) ||
+		    __put_user(get.mt_gstat, &((struct mtget32 *)A(arg))->mt_gstat) ||
+		    __put_user(get.mt_erreg, &((struct mtget32 *)A(arg))->mt_erreg) ||
+		    __put_user(get.mt_fileno, &((struct mtget32 *)A(arg))->mt_fileno) ||
+		    __put_user(get.mt_blkno, &((struct mtget32 *)A(arg))->mt_blkno))
+			return -EFAULT;
+		break;
+	case MTIOCGETCONFIG32:
+		if (__put_user(info.mt_type, &((struct mtconfiginfo32 *)A(arg))->mt_type) ||
+		    __put_user(info.ifc_type, &((struct mtconfiginfo32 *)A(arg))->ifc_type) ||
+		    __put_user(info.irqnr, &((struct mtconfiginfo32 *)A(arg))->irqnr) ||
+		    __put_user(info.dmanr, &((struct mtconfiginfo32 *)A(arg))->dmanr) ||
+		    __put_user(info.port, &((struct mtconfiginfo32 *)A(arg))->port) ||
+		    __put_user(info.debug, &((struct mtconfiginfo32 *)A(arg))->debug) ||
+		    __copy_to_user((char *)&((struct mtconfiginfo32 *)A(arg))->debug
+			    		   + sizeof(((struct mtconfiginfo32 *)A(arg))->debug),
+					   (char *)&info.debug + sizeof(info.debug), sizeof(__u32)))
+			return -EFAULT;
+		break;
+	case MTIOCSETCONFIG32:
+		break;
+	}
+	return 0;
+}
+
+
 asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, u32 arg)
 {
 	struct file * filp;
@@ -617,7 +984,7 @@
 	case SIOCSIFHWADDR:
 	case SIOCADDMULTI:
 	case SIOCDELMULTI:
-	case SIOGIFINDEX:
+	case SIOCGIFINDEX:
 	case SIOCGIFMAP:
 	case SIOCSIFMAP:
 	case SIOCGIFADDR:
@@ -628,6 +995,8 @@
 	case SIOCSIFDSTADDR:
 	case SIOCGIFNETMASK:
 	case SIOCSIFNETMASK:
+	case SIOCSIFPFLAGS:
+	case SIOCGIFPFLAGS:
 	case SIOCGPPPSTATS:
 	case SIOCGPPPCSTATS:
 	case SIOCGPPPVER:
@@ -639,10 +1008,12 @@
 		error = routing_ioctl(fd, cmd, arg);
 		goto out;
 
-	case SIOCRTMSG:
-		error = rtmsg_ioctl(fd, arg);
+	case SIOCRTMSG: /* Note SIOCRTMSG is no longer, so this is safe and
+			 * the user would have seen just an -EINVAL anyways.
+			 */
+		error = -EINVAL;
 		goto out;
-		
+
 	case HDIO_GETGEO:
 		error = hdio_getgeo(fd, arg);
 		goto out;
@@ -671,6 +1042,30 @@
 		error = hdio_ioctl_trans(fd, cmd, arg);
 		goto out;
 
+	case FDSETPRM32:
+	case FDDEFPRM32:
+	case FDGETPRM32:
+	case FDSETDRVPRM32:
+	case FDGETDRVPRM32:
+	case FDGETDRVSTAT32:
+	case FDPOLLDRVSTAT32:
+	case FDGETFDCSTAT32:
+	case FDWERRORGET32:
+		error = fd_ioctl_trans(fd, cmd, (unsigned long)arg);
+		goto out;
+
+	case PPPIOCGIDLE32:
+	case PPPIOCSCOMPRESS32:
+		error = ppp_ioctl_trans(fd, cmd, arg);
+		goto out;
+
+	case MTIOCGET32:
+	case MTIOCPOS32:
+	case MTIOCGETCONFIG32:
+	case MTIOCSETCONFIG32:
+		error = mt_ioctl_trans(fd, cmd, arg);
+		goto out;
+
 	/* List here exlicitly which ioctl's are known to have
 	 * compatable types passed or none at all...
 	 */
@@ -751,13 +1146,22 @@
 	case BLKROGET:
 
 	/* 0x02 -- Floppy ioctls */
+	case FDMSGON:
+	case FDMSGOFF:
 	case FDSETEMSGTRESH:
 	case FDFLUSH:
+	case FDWERRORCLR:
 	case FDSETMAXERRS:
 	case FDGETMAXERRS:
 	case FDGETDRVTYP:
 	case FDEJECT:
-	/* XXX The rest need struct floppy_* translations. */
+	case FDCLRPRM:
+	case FDFMTBEG:
+	case FDFMTEND:
+	case FDRESET:
+	case FDTWADDLE:
+	case FDFMTTRK:
+	case FDRAWCMD:
 
 	/* 0x12 */
 	case BLKRRPART:
@@ -807,6 +1211,15 @@
 	case KIOCSRATE:
 	case KIOCGRATE:
 	
+	/* Big S */
+	case SCSI_IOCTL_GET_IDLUN:
+	case SCSI_IOCTL_DOORLOCK:
+	case SCSI_IOCTL_DOORUNLOCK:
+	case SCSI_IOCTL_TEST_UNIT_READY:
+	case SCSI_IOCTL_TAGGED_ENABLE:
+	case SCSI_IOCTL_TAGGED_DISABLE:
+	case SCSI_IOCTL_GET_BUS_NUMBER:
+	
 	/* Big V */
 	case VT_SETMODE:
 	case VT_GETMODE:
@@ -829,6 +1242,9 @@
 	case RTCGET:
 	case RTCSET:
 
+	/* Little m */
+	case MTIOCTOP:
+
 	/* OPENPROMIO, SunOS/Solaris only, the NetBSD one's have
 	 * embedded pointers in the arg which we'd need to clean up...
 	 */
@@ -860,9 +1276,11 @@
 	case SIOCSARP:
 	case SIOCGARP:
 	case SIOCDARP:
+#if 0 /* XXX No longer exist in new routing code. XXX */
 	case OLD_SIOCSARP:
 	case OLD_SIOCGARP:
 	case OLD_SIOCDARP:
+#endif
 	case SIOCSRARP:
 	case SIOCGRARP:
 	case SIOCDRARP:
@@ -887,12 +1305,7 @@
 	case PPPIOCSNPMODE:
 	case PPPIOCGDEBUG:
 	case PPPIOCSDEBUG:
-	case PPPIOCGIDLE:
 		error = sys_ioctl (fd, cmd, (unsigned long)arg);
-		goto out;
-
-	case PPPIOCSCOMPRESS32:
-		error = ppp_ioctl (fd, cmd, (unsigned long)arg);
 		goto out;
 
 	default:

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov