diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-09-05 01:13:01 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-09-05 01:13:01 +0000 |
commit | cd6236bd58e553626c20d99234566a4dbbf1734a (patch) | |
tree | bed55e8727f0fb9bb15d05bd30d7057f4abe49c7 /arch/mips64/kernel/ioctl32.c | |
parent | e0fc8c9572d7a4ddceb464dc8919591f6009da10 (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.c | 264 |
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) / \ |