patch-2.1.115 linux/arch/sparc64/kernel/ioctl32.c
Next file: linux/arch/sparc64/kernel/ioport.c
Previous file: linux/arch/sparc64/kernel/head.S
Back to the patch index
Back to the overall index
- Lines: 448
- Date:
Tue Aug 4 16:03:35 1998
- Orig file:
v2.1.114/linux/arch/sparc64/kernel/ioctl32.c
- Orig date:
Fri May 8 23:14:46 1998
diff -u --recursive --new-file v2.1.114/linux/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c
@@ -1,7 +1,8 @@
-/* $Id: ioctl32.c,v 1.37 1998/05/06 05:34:13 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.
@@ -30,6 +31,9 @@
#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. */
@@ -44,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.
@@ -392,7 +398,7 @@
}
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) ||
@@ -458,7 +464,162 @@
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();
@@ -1128,6 +1289,139 @@
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;
@@ -1200,6 +1494,10 @@
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;
@@ -1212,6 +1510,12 @@
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:
@@ -1263,7 +1567,21 @@
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...
*/
@@ -1315,6 +1633,17 @@
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:
@@ -1397,6 +1726,12 @@
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:
@@ -1438,9 +1773,11 @@
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:
@@ -1537,6 +1874,14 @@
/* 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:
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov