summaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/ioctl32.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64/kernel/ioctl32.c')
-rw-r--r--arch/sparc64/kernel/ioctl32.c444
1 files changed, 439 insertions, 5 deletions
diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c
index 17e904f25..51fbd6ce5 100644
--- a/arch/sparc64/kernel/ioctl32.c
+++ b/arch/sparc64/kernel/ioctl32.c
@@ -1,7 +1,8 @@
-/* $Id: ioctl32.c,v 1.35 1998/04/10 02:01:46 davem Exp $
+/* $Id: ioctl32.c,v 1.48 1998/08/03 23:58:04 davem Exp $
* ioctl32.c: Conversion between 32bit and 64bit native ioctls.
*
- * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
*
* These routines maintain argument size conversion between 32bit and 64bit
* ioctls.
@@ -28,6 +29,11 @@
#include <linux/if_ppp.h>
#include <linux/mtio.h>
#include <linux/cdrom.h>
+#include <linux/loop.h>
+#include <linux/auto_fs.h>
+#include <linux/tty.h>
+#include <linux/vt_kern.h>
+#include <linux/fb.h>
#include <scsi/scsi.h>
/* Ugly hack. */
@@ -42,6 +48,8 @@
#include <asm/vuid_event.h>
#include <asm/rtc.h>
#include <asm/openpromio.h>
+#include <asm/envctrl.h>
+#include <asm/audioio.h>
/* As gcc will warn about casting u32 to some ptr, we have to cast it to
* unsigned long first, and that's what is A() for.
@@ -66,6 +74,22 @@ static int w_long(unsigned int fd, unsigned int cmd, u32 arg)
return err;
}
+static int rw_long(unsigned int fd, unsigned int cmd, u32 arg)
+{
+ mm_segment_t old_fs = get_fs();
+ int err;
+ unsigned long val;
+
+ if(get_user(val, (u32 *)A(arg)))
+ return -EFAULT;
+ set_fs (KERNEL_DS);
+ err = sys_ioctl(fd, cmd, (unsigned long)&val);
+ set_fs (old_fs);
+ if (!err && put_user(val, (u32 *)A(arg)))
+ return -EFAULT;
+ return err;
+}
+
struct timeval32 {
int tv_sec;
int tv_usec;
@@ -374,7 +398,7 @@ static inline int fbiogetputcmap(unsigned int fd, unsigned int cmd, u32 arg)
}
f.red = red; f.green = green; f.blue = blue;
set_fs (KERNEL_DS);
- ret = sys_ioctl (fd, (cmd == FBIOPUTCMAP32) ? FBIOPUTCMAP : FBIOGETCMAP, (long)&f);
+ ret = sys_ioctl (fd, (cmd == FBIOPUTCMAP32) ? FBIOPUTCMAP_SPARC : FBIOGETCMAP_SPARC, (long)&f);
set_fs (old_fs);
if (!ret && cmd == FBIOGETCMAP32) {
if (copy_to_user ((char *)A(r), red, f.count) ||
@@ -440,7 +464,162 @@ static inline int fbiogscursor(unsigned int fd, unsigned int cmd, u32 arg)
set_fs (old_fs);
return ret;
}
-
+
+struct fb_fix_screeninfo32 {
+ char id[16];
+ __kernel_caddr_t32 smem_start;
+ __u32 smem_len;
+ __u32 type;
+ __u32 type_aux;
+ __u32 visual;
+ __u16 xpanstep;
+ __u16 ypanstep;
+ __u16 ywrapstep;
+ __u32 line_length;
+ __kernel_caddr_t32 mmio_start;
+ __u32 mmio_len;
+ __u32 accel;
+ __u16 reserved[3];
+};
+
+struct fb_cmap32 {
+ __u32 start;
+ __u32 len;
+ __kernel_caddr_t32 red;
+ __kernel_caddr_t32 green;
+ __kernel_caddr_t32 blue;
+ __kernel_caddr_t32 transp;
+};
+
+static int fb_ioctl_trans(unsigned int fd, unsigned int cmd, u32 arg)
+{
+ mm_segment_t old_fs = get_fs();
+ u32 red = 0, green = 0, blue = 0, transp = 0;
+ struct fb_fix_screeninfo fix;
+ struct fb_cmap cmap;
+ void *karg;
+ int err = 0;
+
+ switch (cmd) {
+ case FBIOGET_FSCREENINFO:
+ karg = &fix;
+ break;
+ case FBIOGETCMAP:
+ case FBIOPUTCMAP:
+ karg = &cmap;
+ if (__get_user(cmap.start, &((struct fb_cmap32 *)A(arg))->start) ||
+ __get_user(cmap.len, &((struct fb_cmap32 *)A(arg))->len) ||
+ __get_user(red, &((struct fb_cmap32 *)A(arg))->red) ||
+ __get_user(green, &((struct fb_cmap32 *)A(arg))->green) ||
+ __get_user(blue, &((struct fb_cmap32 *)A(arg))->blue) ||
+ __get_user(transp, &((struct fb_cmap32 *)A(arg))->transp))
+ return -EFAULT;
+ cmap.red = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
+ if (!cmap.red)
+ return -ENOMEM;
+ cmap.green = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
+ if (!cmap.green) {
+ kfree(cmap.red);
+ return -ENOMEM;
+ }
+ cmap.blue = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
+ if (!cmap.blue) {
+ kfree(cmap.red);
+ kfree(cmap.green);
+ return -ENOMEM;
+ }
+ if (transp) {
+ cmap.transp = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
+ if (!cmap.transp) {
+ kfree(cmap.red);
+ kfree(cmap.green);
+ kfree(cmap.blue);
+ return -ENOMEM;
+ }
+ } else {
+ cmap.transp = NULL;
+ }
+ if (cmd == FBIOGETCMAP)
+ break;
+
+ if (__copy_from_user(cmap.red, (char *)A(((struct fb_cmap32 *)A(arg))->red),
+ cmap.len * sizeof(__u16)) ||
+ __copy_from_user(cmap.green, (char *)A(((struct fb_cmap32 *)A(arg))->green),
+ cmap.len * sizeof(__u16)) ||
+ __copy_from_user(cmap.blue, (char *)A(((struct fb_cmap32 *)A(arg))->blue),
+ cmap.len * sizeof(__u16)) ||
+ (cmap.transp &&
+ __copy_from_user(cmap.transp, (char *)A(((struct fb_cmap32 *)A(arg))->transp),
+ cmap.len * sizeof(__u16)))) {
+ kfree(cmap.red);
+ kfree(cmap.green);
+ kfree(cmap.blue);
+ if (cmap.transp)
+ kfree(cmap.transp);
+ return -EFAULT;
+ }
+ break;
+ default:
+ printk("%s: Unknown fb ioctl cmd fd(%d) cmd(%08x) arg(%08x)\n",
+ __FUNCTION__, fd, cmd, arg);
+ return -ENOSYS;
+ }
+ set_fs(KERNEL_DS);
+ err = sys_ioctl(fd, cmd, (unsigned long)karg);
+ set_fs(old_fs);
+ if (err)
+ return err;
+ switch (cmd) {
+ case FBIOGET_FSCREENINFO:
+ if (__copy_to_user((char *)((struct fb_fix_screeninfo32 *)A(arg))->id,
+ (char *)fix.id, sizeof(fix.id)) ||
+ __put_user((__u32)(unsigned long)fix.smem_start,
+ &((struct fb_fix_screeninfo32 *)A(arg))->smem_start) ||
+ __put_user(fix.smem_len, &((struct fb_fix_screeninfo32 *)A(arg))->smem_len) ||
+ __put_user(fix.type, &((struct fb_fix_screeninfo32 *)A(arg))->type) ||
+ __put_user(fix.type_aux, &((struct fb_fix_screeninfo32 *)A(arg))->type_aux) ||
+ __put_user(fix.visual, &((struct fb_fix_screeninfo32 *)A(arg))->visual) ||
+ __put_user(fix.xpanstep, &((struct fb_fix_screeninfo32 *)A(arg))->xpanstep) ||
+ __put_user(fix.ypanstep, &((struct fb_fix_screeninfo32 *)A(arg))->ypanstep) ||
+ __put_user(fix.ywrapstep, &((struct fb_fix_screeninfo32 *)A(arg))->ywrapstep) ||
+ __put_user(fix.line_length, &((struct fb_fix_screeninfo32 *)A(arg))->line_length) ||
+ __put_user((__u32)(unsigned long)fix.mmio_start,
+ &((struct fb_fix_screeninfo32 *)A(arg))->mmio_start) ||
+ __put_user(fix.mmio_len, &((struct fb_fix_screeninfo32 *)A(arg))->mmio_len) ||
+ __put_user(fix.accel, &((struct fb_fix_screeninfo32 *)A(arg))->accel) ||
+ __copy_to_user((char *)((struct fb_fix_screeninfo32 *)A(arg))->reserved,
+ (char *)fix.reserved, sizeof(fix.reserved)))
+ return -EFAULT;
+ break;
+ case FBIOGETCMAP:
+ if (__copy_to_user((char *)A(((struct fb_cmap32 *)A(arg))->red), cmap.red,
+ cmap.len * sizeof(__u16)) ||
+ __copy_to_user((char *)A(((struct fb_cmap32 *)A(arg))->green), cmap.blue,
+ cmap.len * sizeof(__u16)) ||
+ __copy_to_user((char *)A(((struct fb_cmap32 *)A(arg))->blue), cmap.blue,
+ cmap.len * sizeof(__u16)) ||
+ (cmap.transp &&
+ __copy_to_user((char *)A(((struct fb_cmap32 *)A(arg))->transp), cmap.transp,
+ cmap.len * sizeof(__u16)))) {
+ kfree(cmap.red);
+ kfree(cmap.green);
+ kfree(cmap.blue);
+ if (cmap.transp)
+ kfree(cmap.transp);
+ return -EFAULT;
+ }
+ /* fall through */
+ case FBIOPUTCMAP:
+ kfree(cmap.red);
+ kfree(cmap.green);
+ kfree(cmap.blue);
+ if (cmap.transp)
+ kfree(cmap.transp);
+ break;
+ }
+ return 0;
+}
+
static int hdio_ioctl_trans(unsigned int fd, unsigned int cmd, u32 arg)
{
mm_segment_t old_fs = get_fs();
@@ -1059,6 +1238,190 @@ static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, u32 arg)
return 0;
}
+struct loop_info32 {
+ int lo_number; /* ioctl r/o */
+ __kernel_dev_t32 lo_device; /* ioctl r/o */
+ unsigned int lo_inode; /* ioctl r/o */
+ __kernel_dev_t32 lo_rdevice; /* ioctl r/o */
+ int lo_offset;
+ int lo_encrypt_type;
+ int lo_encrypt_key_size; /* ioctl w/o */
+ int lo_flags; /* ioctl r/o */
+ char lo_name[LO_NAME_SIZE];
+ unsigned char lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */
+ unsigned int lo_init[2];
+ char reserved[4];
+};
+
+static int loop_status(unsigned int fd, unsigned int cmd, u32 arg)
+{
+ mm_segment_t old_fs = get_fs();
+ struct loop_info l;
+ int err = 0;
+
+ switch(cmd) {
+ case LOOP_SET_STATUS:
+ if ((get_user(l.lo_number, &((struct loop_info32 *)A(arg))->lo_number) ||
+ __get_user(l.lo_device, &((struct loop_info32 *)A(arg))->lo_device) ||
+ __get_user(l.lo_inode, &((struct loop_info32 *)A(arg))->lo_inode) ||
+ __get_user(l.lo_rdevice, &((struct loop_info32 *)A(arg))->lo_rdevice) ||
+ __copy_from_user((char *)&l.lo_offset, (char *)&((struct loop_info32 *)A(arg))->lo_offset,
+ 8 + (unsigned long)l.lo_init - (unsigned long)&l.lo_offset)))
+ return -EFAULT;
+ set_fs (KERNEL_DS);
+ err = sys_ioctl (fd, cmd, (unsigned long)&l);
+ set_fs (old_fs);
+ break;
+ case LOOP_GET_STATUS:
+ set_fs (KERNEL_DS);
+ err = sys_ioctl (fd, cmd, (unsigned long)&l);
+ set_fs (old_fs);
+ if (!err &&
+ (put_user(l.lo_number, &((struct loop_info32 *)A(arg))->lo_number) ||
+ __put_user(l.lo_device, &((struct loop_info32 *)A(arg))->lo_device) ||
+ __put_user(l.lo_inode, &((struct loop_info32 *)A(arg))->lo_inode) ||
+ __put_user(l.lo_rdevice, &((struct loop_info32 *)A(arg))->lo_rdevice) ||
+ __copy_to_user((char *)&((struct loop_info32 *)A(arg))->lo_offset,
+ (char *)&l.lo_offset, (unsigned long)l.lo_init - (unsigned long)&l.lo_offset)))
+ err = -EFAULT;
+ break;
+ }
+ return err;
+}
+
+extern int tty_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg);
+
+static int vt_check(struct file *file)
+{
+ struct tty_struct *tty;
+ struct inode *inode = file->f_dentry->d_inode;
+
+ if (file->f_op->ioctl != tty_ioctl)
+ return -EINVAL;
+
+ tty = (struct tty_struct *)file->private_data;
+ if (tty_paranoia_check(tty, inode->i_rdev, "tty_ioctl"))
+ return -EINVAL;
+
+ if (tty->driver.ioctl != vt_ioctl)
+ return -EINVAL;
+
+ /*
+ * To have permissions to do most of the vt ioctls, we either have
+ * to be the owner of the tty, or super-user.
+ */
+ if (current->tty == tty || suser())
+ return 1;
+ return 0;
+}
+
+struct consolefontdesc32 {
+ unsigned short charcount; /* characters in font (256 or 512) */
+ unsigned short charheight; /* scan lines per character (1-32) */
+ u32 chardata; /* font data in expanded form */
+};
+
+static int do_fontx_ioctl(struct file *file, int cmd, struct consolefontdesc32 *user_cfd)
+{
+ struct consolefontdesc cfdarg;
+ struct console_font_op op;
+ int i, perm;
+
+ perm = vt_check(file);
+ if (perm < 0) return perm;
+
+ if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc32)))
+ return -EFAULT;
+
+ cfdarg.chardata = (unsigned char *)A(((struct consolefontdesc32 *)&cfdarg)->chardata);
+
+ switch (cmd) {
+ case PIO_FONTX:
+ if (!perm)
+ return -EPERM;
+ op.op = KD_FONT_OP_SET;
+ op.flags = 0;
+ op.width = 8;
+ op.height = cfdarg.charheight;
+ op.charcount = cfdarg.charcount;
+ op.data = cfdarg.chardata;
+ return con_font_op(fg_console, &op);
+ case GIO_FONTX:
+ if (!cfdarg.chardata)
+ return 0;
+ op.op = KD_FONT_OP_GET;
+ op.flags = 0;
+ op.width = 8;
+ op.height = cfdarg.charheight;
+ op.charcount = cfdarg.charcount;
+ op.data = cfdarg.chardata;
+ i = con_font_op(fg_console, &op);
+ if (i)
+ return i;
+ cfdarg.charheight = op.height;
+ cfdarg.charcount = op.charcount;
+ ((struct consolefontdesc32 *)&cfdarg)->chardata = (unsigned long)cfdarg.chardata;
+ if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc32)))
+ return -EFAULT;
+ return 0;
+ }
+ return -EINVAL;
+}
+
+struct console_font_op32 {
+ unsigned int op; /* operation code KD_FONT_OP_* */
+ unsigned int flags; /* KD_FONT_FLAG_* */
+ unsigned int width, height; /* font size */
+ unsigned int charcount;
+ u32 data; /* font data with height fixed to 32 */
+};
+
+static int do_kdfontop_ioctl(struct file *file, struct console_font_op32 *fontop)
+{
+ struct console_font_op op;
+ int perm = vt_check(file), i;
+ struct vt_struct *vt;
+
+ if (perm < 0) return perm;
+
+ if (copy_from_user(&op, (void *) fontop, sizeof(struct console_font_op32)))
+ return -EFAULT;
+ if (!perm && op.op != KD_FONT_OP_GET)
+ return -EPERM;
+ op.data = (unsigned char *)A(((struct console_font_op32 *)&op)->data);
+ op.flags |= KD_FONT_FLAG_OLD;
+ vt = (struct vt_struct *)((struct tty_struct *)file->private_data)->driver_data;
+ i = con_font_op(vt->vc_num, &op);
+ if (i) return i;
+ ((struct console_font_op32 *)&op)->data = (unsigned long)op.data;
+ if (copy_to_user((void *) fontop, &op, sizeof(struct console_font_op32)))
+ return -EFAULT;
+ return 0;
+}
+
+struct unimapdesc32 {
+ unsigned short entry_ct;
+ u32 entries;
+};
+
+static int do_unimap_ioctl(struct file *file, int cmd, struct unimapdesc32 *user_ud)
+{
+ struct unimapdesc32 tmp;
+ int perm = vt_check(file);
+
+ if (perm < 0) return perm;
+ if (copy_from_user(&tmp, user_ud, sizeof tmp))
+ return -EFAULT;
+ switch (cmd) {
+ case PIO_UNIMAP:
+ if (!perm) return -EPERM;
+ return con_set_unimap(fg_console, tmp.entry_ct, (struct unipair *)A(tmp.entries));
+ case GIO_UNIMAP:
+ return con_get_unimap(fg_console, tmp.entry_ct, &(user_ud->entry_ct), (struct unipair *)A(tmp.entries));
+ }
+ return 0;
+}
+
asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, u32 arg)
{
struct file * filp;
@@ -1131,6 +1494,10 @@ asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, u32 arg)
case BLKRAGET:
case BLKGETSIZE:
+ case 0x1260:
+ /* The mkswap binary hard codes it to Intel value :-((( */
+ if(cmd == 0x1260)
+ cmd = BLKGETSIZE;
error = w_long(fd, cmd, arg);
goto out;
@@ -1143,6 +1510,12 @@ asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, u32 arg)
error = fbiogscursor(fd, cmd, arg);
goto out;
+ case FBIOGET_FSCREENINFO:
+ case FBIOGETCMAP:
+ case FBIOPUTCMAP:
+ error = fb_ioctl_trans(fd, cmd, arg);
+ goto out;
+
case HDIO_GET_KEEPSETTINGS:
case HDIO_GET_UNMASKINTR:
case HDIO_GET_DMA:
@@ -1185,7 +1558,30 @@ asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, u32 arg)
case CDROMREADALL:
error = cdrom_ioctl_trans(fd, cmd, arg);
goto out;
+
+ case LOOP_SET_STATUS:
+ case LOOP_GET_STATUS:
+ error = loop_status(fd, cmd, arg);
+ goto out;
+
+ case AUTOFS_IOC_SETTIMEOUT:
+ error = rw_long(fd, cmd, arg);
+ goto out;
+
+ case PIO_FONTX:
+ case GIO_FONTX:
+ error = do_fontx_ioctl(filp, cmd, (struct consolefontdesc32 *)A(arg));
+ goto out;
+
+ case PIO_UNIMAP:
+ case GIO_UNIMAP:
+ error = do_unimap_ioctl(filp, cmd, (struct unimapdesc32 *)A(arg));
+ goto out;
+ case KDFONTOP:
+ error = do_kdfontop_ioctl(filp, (struct console_font_op32 *)A(arg));
+ goto out;
+
/* List here exlicitly which ioctl's are known to have
* compatable types passed or none at all...
*/
@@ -1237,6 +1633,17 @@ asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, u32 arg)
case FBIOGCURPOS:
case FBIOGCURMAX:
+ case FBIOGET_VSCREENINFO:
+ case FBIOPUT_VSCREENINFO:
+ case FBIOPAN_DISPLAY:
+ case FBIOGET_FCURSORINFO:
+ case FBIOGET_VCURSORINFO:
+ case FBIOPUT_VCURSORINFO:
+ case FBIOGET_CURSORSTATE:
+ case FBIOPUT_CURSORSTATE:
+ case FBIOGET_CON2FBMAP:
+ case FBIOPUT_CON2FBMAP:
+
/* Little f */
case FIOCLEX:
case FIONCLEX:
@@ -1319,6 +1726,12 @@ asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, u32 arg)
case KDSKBLED:
case KDGETLED:
case KDSETLED:
+ case GIO_SCRNMAP:
+ case PIO_SCRNMAP:
+ case GIO_UNISCRNMAP:
+ case PIO_UNISCRNMAP:
+ case PIO_FONTRESET:
+ case PIO_UNIMAPCLR:
/* Little k */
case KIOCTYPE:
@@ -1360,9 +1773,11 @@ asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, u32 arg)
case VUIDSFORMAT:
case VUIDGFORMAT:
- /* Little p (/dev/rtc etc.) */
+ /* Little p (/dev/rtc, /dev/envctrl, etc.) */
case RTCGET:
case RTCSET:
+ case I2CIOCSADR:
+ case I2CIOCGADR:
/* Little m */
case MTIOCTOP:
@@ -1455,6 +1870,25 @@ asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, u32 arg)
case CDROM_DRIVE_STATUS:
case CDROM_DISC_STATUS:
case CDROM_CHANGER_NSLOTS:
+
+ /* Big L */
+ case LOOP_SET_FD:
+ case LOOP_CLR_FD:
+
+ /* Big A */
+ case AUDIO_GETINFO:
+ case AUDIO_SETINFO:
+ case AUDIO_DRAIN:
+ case AUDIO_GETDEV:
+ case AUDIO_GETDEV_SUNOS:
+ case AUDIO_FLUSH:
+
+ /* AUTOFS */
+ case AUTOFS_IOC_READY:
+ case AUTOFS_IOC_FAIL:
+ case AUTOFS_IOC_CATATONIC:
+ case AUTOFS_IOC_PROTOVER:
+ case AUTOFS_IOC_EXPIRE:
error = sys_ioctl (fd, cmd, (unsigned long)arg);
goto out;