summaryrefslogtreecommitdiffstats
path: root/arch/mips64/kernel/ioctl32.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-09-05 01:13:01 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-09-05 01:13:01 +0000
commitcd6236bd58e553626c20d99234566a4dbbf1734a (patch)
treebed55e8727f0fb9bb15d05bd30d7057f4abe49c7 /arch/mips64/kernel/ioctl32.c
parente0fc8c9572d7a4ddceb464dc8919591f6009da10 (diff)
Handle a ton more block device, IDE (yuck :-), partition handling and
tape ioctls. Dump support for ancient variants of uname(2) syscall; Nothing is using the since Linux/MIPS history started with glibc 2.0.
Diffstat (limited to 'arch/mips64/kernel/ioctl32.c')
-rw-r--r--arch/mips64/kernel/ioctl32.c264
1 files changed, 262 insertions, 2 deletions
diff --git a/arch/mips64/kernel/ioctl32.c b/arch/mips64/kernel/ioctl32.c
index 87174861f..95081b76d 100644
--- a/arch/mips64/kernel/ioctl32.c
+++ b/arch/mips64/kernel/ioctl32.c
@@ -12,12 +12,17 @@
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/mm.h>
+#include <linux/mtio.h>
#include <linux/init.h>
#include <linux/file.h>
#include <linux/vt.h>
#include <linux/kd.h>
#include <linux/netdevice.h>
#include <linux/route.h>
+#include <linux/hdreg.h>
+#include <linux/blkpg.h>
+#include <linux/blkdev.h>
+#include <linux/elevator.h>
#include <asm/types.h>
#include <asm/uaccess.h>
@@ -283,6 +288,210 @@ static int do_ext2_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
return sys_ioctl(fd, cmd, arg);
}
+struct hd_geometry32 {
+ unsigned char heads;
+ unsigned char sectors;
+ unsigned short cylinders;
+ u32 start;
+};
+
+static int hdio_getgeo(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+ mm_segment_t old_fs = get_fs();
+ struct hd_geometry geo;
+ int err;
+
+ set_fs (KERNEL_DS);
+ err = sys_ioctl(fd, HDIO_GETGEO, (unsigned long)&geo);
+ set_fs (old_fs);
+ if (!err) {
+ err = copy_to_user ((struct hd_geometry32 *)arg, &geo, 4);
+ err |= __put_user (geo.start, &(((struct hd_geometry32 *)arg)->start));
+ }
+
+ return err ? -EFAULT : 0;
+}
+
+static int hdio_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+ mm_segment_t old_fs = get_fs();
+ unsigned long kval;
+ unsigned int *uvp;
+ int error;
+
+ set_fs(KERNEL_DS);
+ error = sys_ioctl(fd, cmd, (long)&kval);
+ set_fs(old_fs);
+
+ if (error == 0) {
+ uvp = (unsigned int *)arg;
+ if (put_user(kval, uvp))
+ error = -EFAULT;
+ }
+
+ return error;
+}
+
+struct blkpg_ioctl_arg32 {
+ int op;
+ int flags;
+ int datalen;
+ u32 data;
+};
+
+static int blkpg_ioctl_trans(unsigned int fd, unsigned int cmd,
+ struct blkpg_ioctl_arg32 *arg)
+{
+ struct blkpg_ioctl_arg a;
+ struct blkpg_partition p;
+ int err;
+ mm_segment_t old_fs = get_fs();
+
+ err = get_user(a.op, &arg->op);
+ err |= __get_user(a.flags, &arg->flags);
+ err |= __get_user(a.datalen, &arg->datalen);
+ err |= __get_user((long)a.data, &arg->data);
+ if (err) return err;
+ switch (a.op) {
+ case BLKPG_ADD_PARTITION:
+ case BLKPG_DEL_PARTITION:
+ if (a.datalen < sizeof(struct blkpg_partition))
+ return -EINVAL;
+ if (copy_from_user(&p, a.data, sizeof(struct blkpg_partition)))
+ return -EFAULT;
+ a.data = &p;
+ set_fs (KERNEL_DS);
+ err = sys_ioctl(fd, cmd, (unsigned long)&a);
+ set_fs (old_fs);
+ default:
+ return -EINVAL;
+ }
+ 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, unsigned long 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;
+ err = __get_user(info.mt_type, &((struct mtconfiginfo32 *)arg)->mt_type);
+ err |= __get_user(info.ifc_type, &((struct mtconfiginfo32 *)arg)->ifc_type);
+ err |= __get_user(info.irqnr, &((struct mtconfiginfo32 *)arg)->irqnr);
+ err |= __get_user(info.dmanr, &((struct mtconfiginfo32 *)arg)->dmanr);
+ err |= __get_user(info.port, &((struct mtconfiginfo32 *)arg)->port);
+ err |= __get_user(info.debug, &((struct mtconfiginfo32 *)arg)->debug);
+ err |= __copy_from_user((char *)&info.debug + sizeof(info.debug),
+ (char *)&((struct mtconfiginfo32 *)arg)->debug
+ + sizeof(((struct mtconfiginfo32 *)arg)->debug), sizeof(__u32));
+ if (err)
+ return -EFAULT;
+ break;
+ default:
+ do {
+ static int count = 0;
+ if (++count <= 20)
+ printk("mt_ioctl: Unknown cmd fd(%d) "
+ "cmd(%08x) arg(%08x)\n",
+ (int)fd, (unsigned int)cmd, (unsigned int)arg);
+ } while(0);
+ 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:
+ err = __put_user(pos.mt_blkno, &((struct mtpos32 *)arg)->mt_blkno);
+ break;
+ case MTIOCGET32:
+ err = __put_user(get.mt_type, &((struct mtget32 *)arg)->mt_type);
+ err |= __put_user(get.mt_resid, &((struct mtget32 *)arg)->mt_resid);
+ err |= __put_user(get.mt_dsreg, &((struct mtget32 *)arg)->mt_dsreg);
+ err |= __put_user(get.mt_gstat, &((struct mtget32 *)arg)->mt_gstat);
+ err |= __put_user(get.mt_erreg, &((struct mtget32 *)arg)->mt_erreg);
+ err |= __put_user(get.mt_fileno, &((struct mtget32 *)arg)->mt_fileno);
+ err |= __put_user(get.mt_blkno, &((struct mtget32 *)arg)->mt_blkno);
+ break;
+ case MTIOCGETCONFIG32:
+ err = __put_user(info.mt_type, &((struct mtconfiginfo32 *)arg)->mt_type);
+ err |= __put_user(info.ifc_type, &((struct mtconfiginfo32 *)arg)->ifc_type);
+ err |= __put_user(info.irqnr, &((struct mtconfiginfo32 *)arg)->irqnr);
+ err |= __put_user(info.dmanr, &((struct mtconfiginfo32 *)arg)->dmanr);
+ err |= __put_user(info.port, &((struct mtconfiginfo32 *)arg)->port);
+ err |= __put_user(info.debug, &((struct mtconfiginfo32 *)arg)->debug);
+ err |= __copy_to_user((char *)&((struct mtconfiginfo32 *)arg)->debug
+ + sizeof(((struct mtconfiginfo32 *)arg)->debug),
+ (char *)&info.debug + sizeof(info.debug), sizeof(__u32));
+ break;
+ case MTIOCSETCONFIG32:
+ break;
+ }
+ return err ? -EFAULT: 0;
+}
+
static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg)
{
mm_segment_t old_fs = get_fs();
@@ -437,8 +646,59 @@ static struct ioctl32_list ioctl32_handler_table[] = {
IOCTL32_HANDLER(EXT2_IOC32_GETVERSION, do_ext2_ioctl),
IOCTL32_HANDLER(EXT2_IOC32_SETVERSION, do_ext2_ioctl),
- IOCTL32_HANDLER(BLKGETSIZE, w_long)
-
+ IOCTL32_HANDLER(HDIO_GETGEO, hdio_getgeo), /* hdreg.h ioctls */
+ IOCTL32_HANDLER(HDIO_GET_UNMASKINTR, hdio_ioctl_trans),
+ IOCTL32_HANDLER(HDIO_GET_MULTCOUNT, hdio_ioctl_trans),
+ // HDIO_OBSOLETE_IDENTITY
+ IOCTL32_HANDLER(HDIO_GET_KEEPSETTINGS, hdio_ioctl_trans),
+ IOCTL32_HANDLER(HDIO_GET_32BIT, hdio_ioctl_trans),
+ IOCTL32_HANDLER(HDIO_GET_NOWERR, hdio_ioctl_trans),
+ IOCTL32_HANDLER(HDIO_GET_DMA, hdio_ioctl_trans),
+ IOCTL32_HANDLER(HDIO_GET_NICE, hdio_ioctl_trans),
+ IOCTL32_DEFAULT(HDIO_GET_IDENTITY),
+ IOCTL32_DEFAULT(HDIO_DRIVE_RESET),
+ // HDIO_TRISTATE_HWIF /* not implemented */
+ // HDIO_DRIVE_TASK /* To do, need specs */
+ IOCTL32_DEFAULT(HDIO_DRIVE_CMD),
+ IOCTL32_DEFAULT(HDIO_SET_MULTCOUNT),
+ IOCTL32_DEFAULT(HDIO_SET_UNMASKINTR),
+ IOCTL32_DEFAULT(HDIO_SET_KEEPSETTINGS),
+ IOCTL32_DEFAULT(HDIO_SET_32BIT),
+ IOCTL32_DEFAULT(HDIO_SET_NOWERR),
+ IOCTL32_DEFAULT(HDIO_SET_DMA),
+ IOCTL32_DEFAULT(HDIO_SET_PIO_MODE),
+ IOCTL32_DEFAULT(HDIO_SCAN_HWIF),
+ IOCTL32_DEFAULT(HDIO_SET_NICE),
+ //HDIO_UNREGISTER_HWIF
+
+ IOCTL32_DEFAULT(BLKROSET), /* fs.h ioctls */
+ IOCTL32_DEFAULT(BLKROGET),
+ IOCTL32_DEFAULT(BLKRRPART),
+ IOCTL32_HANDLER(BLKGETSIZE, w_long),
+
+ IOCTL32_DEFAULT(BLKFLSBUF),
+ IOCTL32_DEFAULT(BLKRASET),
+ IOCTL32_HANDLER(BLKRAGET, w_long),
+ IOCTL32_DEFAULT(BLKFRASET),
+ IOCTL32_HANDLER(BLKFRAGET, w_long),
+ IOCTL32_DEFAULT(BLKSECTSET),
+ IOCTL32_HANDLER(BLKSECTGET, w_long),
+ IOCTL32_DEFAULT(BLKSSZGET),
+ IOCTL32_HANDLER(BLKPG, blkpg_ioctl_trans),
+ IOCTL32_DEFAULT(BLKELVGET),
+ IOCTL32_DEFAULT(BLKELVSET),
+
+ IOCTL32_DEFAULT(MTIOCTOP), /* mtio.h ioctls */
+ IOCTL32_HANDLER(MTIOCGET32, mt_ioctl_trans),
+ IOCTL32_HANDLER(MTIOCPOS32, mt_ioctl_trans),
+ IOCTL32_HANDLER(MTIOCGETCONFIG32, mt_ioctl_trans),
+ IOCTL32_HANDLER(MTIOCSETCONFIG32, mt_ioctl_trans)
+ // MTIOCRDFTSEG
+ // MTIOCWRFTSEG
+ // MTIOCVOLINFO
+ // MTIOCGETSIZE
+ // MTIOCFTFORMAT
+ // MTIOCFTCMD
};
#define NR_IOCTL32_HANDLERS (sizeof(ioctl32_handler_table) / \