compat_ioctl.c revision 3b3a1814d1703027f9867d0f5cbbfaf6c7482474
1f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann#include <linux/blkdev.h> 2f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann#include <linux/blkpg.h> 3f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann#include <linux/blktrace_api.h> 4f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann#include <linux/cdrom.h> 5f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann#include <linux/compat.h> 6f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann#include <linux/elevator.h> 7f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann#include <linux/fd.h> 8f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann#include <linux/hdreg.h> 95a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 10f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann#include <linux/syscalls.h> 11f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann#include <linux/types.h> 12f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann#include <linux/uaccess.h> 13f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann 14f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmannstatic int compat_put_ushort(unsigned long arg, unsigned short val) 15f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann{ 16f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann return put_user(val, (unsigned short __user *)compat_ptr(arg)); 17f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann} 18f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann 19f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmannstatic int compat_put_int(unsigned long arg, int val) 20f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann{ 21f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann return put_user(val, (compat_int_t __user *)compat_ptr(arg)); 22f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann} 23f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann 24ac481c20ef8f6c6f2be75d581863f40c43874ef7Martin K. Petersenstatic int compat_put_uint(unsigned long arg, unsigned int val) 25ac481c20ef8f6c6f2be75d581863f40c43874ef7Martin K. Petersen{ 26ac481c20ef8f6c6f2be75d581863f40c43874ef7Martin K. Petersen return put_user(val, (compat_uint_t __user *)compat_ptr(arg)); 27ac481c20ef8f6c6f2be75d581863f40c43874ef7Martin K. Petersen} 28ac481c20ef8f6c6f2be75d581863f40c43874ef7Martin K. Petersen 29f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmannstatic int compat_put_long(unsigned long arg, long val) 30f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann{ 31f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann return put_user(val, (compat_long_t __user *)compat_ptr(arg)); 32f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann} 33f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann 34f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmannstatic int compat_put_ulong(unsigned long arg, compat_ulong_t val) 35f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann{ 36f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann return put_user(val, (compat_ulong_t __user *)compat_ptr(arg)); 37f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann} 38f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann 39f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmannstatic int compat_put_u64(unsigned long arg, u64 val) 40f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann{ 41f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann return put_user(val, (compat_u64 __user *)compat_ptr(arg)); 42f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann} 43f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann 449617db085c119879cd371e3212806a15596e121aArnd Bergmannstruct compat_hd_geometry { 459617db085c119879cd371e3212806a15596e121aArnd Bergmann unsigned char heads; 469617db085c119879cd371e3212806a15596e121aArnd Bergmann unsigned char sectors; 479617db085c119879cd371e3212806a15596e121aArnd Bergmann unsigned short cylinders; 489617db085c119879cd371e3212806a15596e121aArnd Bergmann u32 start; 499617db085c119879cd371e3212806a15596e121aArnd Bergmann}; 509617db085c119879cd371e3212806a15596e121aArnd Bergmann 519617db085c119879cd371e3212806a15596e121aArnd Bergmannstatic int compat_hdio_getgeo(struct gendisk *disk, struct block_device *bdev, 529617db085c119879cd371e3212806a15596e121aArnd Bergmann struct compat_hd_geometry __user *ugeo) 539617db085c119879cd371e3212806a15596e121aArnd Bergmann{ 549617db085c119879cd371e3212806a15596e121aArnd Bergmann struct hd_geometry geo; 559617db085c119879cd371e3212806a15596e121aArnd Bergmann int ret; 569617db085c119879cd371e3212806a15596e121aArnd Bergmann 579617db085c119879cd371e3212806a15596e121aArnd Bergmann if (!ugeo) 589617db085c119879cd371e3212806a15596e121aArnd Bergmann return -EINVAL; 599617db085c119879cd371e3212806a15596e121aArnd Bergmann if (!disk->fops->getgeo) 609617db085c119879cd371e3212806a15596e121aArnd Bergmann return -ENOTTY; 619617db085c119879cd371e3212806a15596e121aArnd Bergmann 628b0d77f13192678019f07cbc6b3338d6d91f1cf4Cong Wang memset(&geo, 0, sizeof(geo)); 639617db085c119879cd371e3212806a15596e121aArnd Bergmann /* 649617db085c119879cd371e3212806a15596e121aArnd Bergmann * We need to set the startsect first, the driver may 659617db085c119879cd371e3212806a15596e121aArnd Bergmann * want to override it. 669617db085c119879cd371e3212806a15596e121aArnd Bergmann */ 679617db085c119879cd371e3212806a15596e121aArnd Bergmann geo.start = get_start_sect(bdev); 689617db085c119879cd371e3212806a15596e121aArnd Bergmann ret = disk->fops->getgeo(bdev, &geo); 699617db085c119879cd371e3212806a15596e121aArnd Bergmann if (ret) 709617db085c119879cd371e3212806a15596e121aArnd Bergmann return ret; 719617db085c119879cd371e3212806a15596e121aArnd Bergmann 729617db085c119879cd371e3212806a15596e121aArnd Bergmann ret = copy_to_user(ugeo, &geo, 4); 733ddc5b46a8e90f3c9251338b60191d0a804b0d92Mathieu Desnoyers ret |= put_user(geo.start, &ugeo->start); 749617db085c119879cd371e3212806a15596e121aArnd Bergmann if (ret) 759617db085c119879cd371e3212806a15596e121aArnd Bergmann ret = -EFAULT; 769617db085c119879cd371e3212806a15596e121aArnd Bergmann 779617db085c119879cd371e3212806a15596e121aArnd Bergmann return ret; 789617db085c119879cd371e3212806a15596e121aArnd Bergmann} 799617db085c119879cd371e3212806a15596e121aArnd Bergmann 8033c2dca4957bd0da3e1af7b96d0758d97e708ef6Al Virostatic int compat_hdio_ioctl(struct block_device *bdev, fmode_t mode, 8133c2dca4957bd0da3e1af7b96d0758d97e708ef6Al Viro unsigned int cmd, unsigned long arg) 829617db085c119879cd371e3212806a15596e121aArnd Bergmann{ 839617db085c119879cd371e3212806a15596e121aArnd Bergmann mm_segment_t old_fs = get_fs(); 849617db085c119879cd371e3212806a15596e121aArnd Bergmann unsigned long kval; 859617db085c119879cd371e3212806a15596e121aArnd Bergmann unsigned int __user *uvp; 869617db085c119879cd371e3212806a15596e121aArnd Bergmann int error; 879617db085c119879cd371e3212806a15596e121aArnd Bergmann 889617db085c119879cd371e3212806a15596e121aArnd Bergmann set_fs(KERNEL_DS); 8933c2dca4957bd0da3e1af7b96d0758d97e708ef6Al Viro error = __blkdev_driver_ioctl(bdev, mode, 909617db085c119879cd371e3212806a15596e121aArnd Bergmann cmd, (unsigned long)(&kval)); 919617db085c119879cd371e3212806a15596e121aArnd Bergmann set_fs(old_fs); 929617db085c119879cd371e3212806a15596e121aArnd Bergmann 939617db085c119879cd371e3212806a15596e121aArnd Bergmann if (error == 0) { 949617db085c119879cd371e3212806a15596e121aArnd Bergmann uvp = compat_ptr(arg); 959617db085c119879cd371e3212806a15596e121aArnd Bergmann if (put_user(kval, uvp)) 969617db085c119879cd371e3212806a15596e121aArnd Bergmann error = -EFAULT; 979617db085c119879cd371e3212806a15596e121aArnd Bergmann } 989617db085c119879cd371e3212806a15596e121aArnd Bergmann return error; 999617db085c119879cd371e3212806a15596e121aArnd Bergmann} 1009617db085c119879cd371e3212806a15596e121aArnd Bergmann 101b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmannstruct compat_cdrom_read_audio { 102b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann union cdrom_addr addr; 103b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann u8 addr_format; 104b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann compat_int_t nframes; 105b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann compat_caddr_t buf; 106b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann}; 107b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann 108b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmannstruct compat_cdrom_generic_command { 109b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann unsigned char cmd[CDROM_PACKET_SIZE]; 110b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann compat_caddr_t buffer; 111b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann compat_uint_t buflen; 112b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann compat_int_t stat; 113b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann compat_caddr_t sense; 114b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann unsigned char data_direction; 115b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann compat_int_t quiet; 116b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann compat_int_t timeout; 117b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann compat_caddr_t reserved[1]; 118b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann}; 119b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann 12033c2dca4957bd0da3e1af7b96d0758d97e708ef6Al Virostatic int compat_cdrom_read_audio(struct block_device *bdev, fmode_t mode, 12133c2dca4957bd0da3e1af7b96d0758d97e708ef6Al Viro unsigned int cmd, unsigned long arg) 122b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann{ 123b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann struct cdrom_read_audio __user *cdread_audio; 124b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann struct compat_cdrom_read_audio __user *cdread_audio32; 125b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann __u32 data; 126b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann void __user *datap; 127b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann 128b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann cdread_audio = compat_alloc_user_space(sizeof(*cdread_audio)); 129b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann cdread_audio32 = compat_ptr(arg); 130b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann 131b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann if (copy_in_user(&cdread_audio->addr, 132b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann &cdread_audio32->addr, 133b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann (sizeof(*cdread_audio32) - 134b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann sizeof(compat_caddr_t)))) 135b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann return -EFAULT; 136b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann 137b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann if (get_user(data, &cdread_audio32->buf)) 138b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann return -EFAULT; 139b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann datap = compat_ptr(data); 140b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann if (put_user(datap, &cdread_audio->buf)) 141b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann return -EFAULT; 142b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann 14333c2dca4957bd0da3e1af7b96d0758d97e708ef6Al Viro return __blkdev_driver_ioctl(bdev, mode, cmd, 144b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann (unsigned long)cdread_audio); 145b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann} 146b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann 14733c2dca4957bd0da3e1af7b96d0758d97e708ef6Al Virostatic int compat_cdrom_generic_command(struct block_device *bdev, fmode_t mode, 14833c2dca4957bd0da3e1af7b96d0758d97e708ef6Al Viro unsigned int cmd, unsigned long arg) 149b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann{ 150b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann struct cdrom_generic_command __user *cgc; 151b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann struct compat_cdrom_generic_command __user *cgc32; 152b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann u32 data; 153b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann unsigned char dir; 154b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann int itmp; 155b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann 156b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann cgc = compat_alloc_user_space(sizeof(*cgc)); 157b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann cgc32 = compat_ptr(arg); 158b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann 159b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann if (copy_in_user(&cgc->cmd, &cgc32->cmd, sizeof(cgc->cmd)) || 160b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann get_user(data, &cgc32->buffer) || 161b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann put_user(compat_ptr(data), &cgc->buffer) || 162b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann copy_in_user(&cgc->buflen, &cgc32->buflen, 163b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann (sizeof(unsigned int) + sizeof(int))) || 164b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann get_user(data, &cgc32->sense) || 165b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann put_user(compat_ptr(data), &cgc->sense) || 166b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann get_user(dir, &cgc32->data_direction) || 167b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann put_user(dir, &cgc->data_direction) || 168b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann get_user(itmp, &cgc32->quiet) || 169b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann put_user(itmp, &cgc->quiet) || 170b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann get_user(itmp, &cgc32->timeout) || 171b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann put_user(itmp, &cgc->timeout) || 172b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann get_user(data, &cgc32->reserved[0]) || 173b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann put_user(compat_ptr(data), &cgc->reserved[0])) 174b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann return -EFAULT; 175b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann 17633c2dca4957bd0da3e1af7b96d0758d97e708ef6Al Viro return __blkdev_driver_ioctl(bdev, mode, cmd, (unsigned long)cgc); 177b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann} 178b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann 17918cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmannstruct compat_blkpg_ioctl_arg { 18018cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann compat_int_t op; 18118cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann compat_int_t flags; 18218cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann compat_int_t datalen; 18318cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann compat_caddr_t data; 18418cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann}; 18518cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann 18656b26add02b4bdea81d5e0ebda60db1fe3311ad4Al Virostatic int compat_blkpg_ioctl(struct block_device *bdev, fmode_t mode, 18718cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann unsigned int cmd, struct compat_blkpg_ioctl_arg __user *ua32) 18818cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann{ 18918cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann struct blkpg_ioctl_arg __user *a = compat_alloc_user_space(sizeof(*a)); 19018cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann compat_caddr_t udata; 19118cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann compat_int_t n; 19218cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann int err; 19318cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann 19418cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann err = get_user(n, &ua32->op); 19518cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann err |= put_user(n, &a->op); 19618cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann err |= get_user(n, &ua32->flags); 19718cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann err |= put_user(n, &a->flags); 19818cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann err |= get_user(n, &ua32->datalen); 19918cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann err |= put_user(n, &a->datalen); 20018cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann err |= get_user(udata, &ua32->data); 20118cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann err |= put_user(compat_ptr(udata), &a->data); 20218cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann if (err) 20318cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann return err; 20418cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann 20556b26add02b4bdea81d5e0ebda60db1fe3311ad4Al Viro return blkdev_ioctl(bdev, mode, cmd, (unsigned long)a); 20618cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann} 20718cf7f8723d913ce02bea43e468bebdd07bc880cArnd Bergmann 208f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann#define BLKBSZGET_32 _IOR(0x12, 112, int) 209f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann#define BLKBSZSET_32 _IOW(0x12, 113, int) 210f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann#define BLKGETSIZE64_32 _IOR(0x12, 114, int) 211f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann 2121ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmannstruct compat_floppy_drive_params { 2131ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann char cmos; 2141ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann compat_ulong_t max_dtr; 2151ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann compat_ulong_t hlt; 2161ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann compat_ulong_t hut; 2171ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann compat_ulong_t srt; 2181ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann compat_ulong_t spinup; 2191ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann compat_ulong_t spindown; 2201ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann unsigned char spindown_offset; 2211ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann unsigned char select_delay; 2221ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann unsigned char rps; 2231ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann unsigned char tracks; 2241ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann compat_ulong_t timeout; 2251ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann unsigned char interleave_sect; 2261ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann struct floppy_max_errors max_errors; 2271ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann char flags; 2281ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann char read_track; 2291ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann short autodetect[8]; 2301ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann compat_int_t checkfreq; 2311ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann compat_int_t native_format; 2321ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann}; 2331ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann 2341ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmannstruct compat_floppy_drive_struct { 2351ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann signed char flags; 2361ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann compat_ulong_t spinup_date; 2371ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann compat_ulong_t select_date; 2381ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann compat_ulong_t first_read_date; 2391ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann short probed_format; 2401ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann short track; 2411ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann short maxblock; 2421ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann short maxtrack; 2431ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann compat_int_t generation; 2441ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann compat_int_t keep_data; 2451ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann compat_int_t fd_ref; 2461ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann compat_int_t fd_device; 2471ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann compat_int_t last_checked; 2481ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann compat_caddr_t dmabuf; 2491ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann compat_int_t bufblocks; 2501ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann}; 2511ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann 2521ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmannstruct compat_floppy_fdc_state { 2531ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann compat_int_t spec1; 2541ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann compat_int_t spec2; 2551ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann compat_int_t dtr; 2561ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann unsigned char version; 2571ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann unsigned char dor; 2581ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann compat_ulong_t address; 2591ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann unsigned int rawcmd:2; 2601ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann unsigned int reset:1; 2611ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann unsigned int need_configure:1; 2621ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann unsigned int perp_mode:2; 2631ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann unsigned int has_fifo:1; 2641ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann unsigned int driver_version; 2651ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann unsigned char track[4]; 2661ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann}; 2671ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann 2681ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmannstruct compat_floppy_write_errors { 2691ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann unsigned int write_errors; 2701ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann compat_ulong_t first_error_sector; 2711ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann compat_int_t first_error_generation; 2721ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann compat_ulong_t last_error_sector; 2731ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann compat_int_t last_error_generation; 2741ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann compat_uint_t badness; 2751ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann}; 2761ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann 2771ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann#define FDSETPRM32 _IOW(2, 0x42, struct compat_floppy_struct) 2781ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann#define FDDEFPRM32 _IOW(2, 0x43, struct compat_floppy_struct) 2791ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann#define FDSETDRVPRM32 _IOW(2, 0x90, struct compat_floppy_drive_params) 2801ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann#define FDGETDRVPRM32 _IOR(2, 0x11, struct compat_floppy_drive_params) 2811ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann#define FDGETDRVSTAT32 _IOR(2, 0x12, struct compat_floppy_drive_struct) 2821ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann#define FDPOLLDRVSTAT32 _IOR(2, 0x13, struct compat_floppy_drive_struct) 2831ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann#define FDGETFDCSTAT32 _IOR(2, 0x15, struct compat_floppy_fdc_state) 2841ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann#define FDWERRORGET32 _IOR(2, 0x17, struct compat_floppy_write_errors) 2851ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann 2861ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmannstatic struct { 2871ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann unsigned int cmd32; 2881ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann unsigned int cmd; 2891ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann} fd_ioctl_trans_table[] = { 2901ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann { FDSETPRM32, FDSETPRM }, 2911ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann { FDDEFPRM32, FDDEFPRM }, 2921ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann { FDGETPRM32, FDGETPRM }, 2931ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann { FDSETDRVPRM32, FDSETDRVPRM }, 2941ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann { FDGETDRVPRM32, FDGETDRVPRM }, 2951ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann { FDGETDRVSTAT32, FDGETDRVSTAT }, 2961ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann { FDPOLLDRVSTAT32, FDPOLLDRVSTAT }, 2971ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann { FDGETFDCSTAT32, FDGETFDCSTAT }, 2981ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann { FDWERRORGET32, FDWERRORGET } 2991ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann}; 3001ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann 3011ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann#define NR_FD_IOCTL_TRANS ARRAY_SIZE(fd_ioctl_trans_table) 3021ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann 30333c2dca4957bd0da3e1af7b96d0758d97e708ef6Al Virostatic int compat_fd_ioctl(struct block_device *bdev, fmode_t mode, 30433c2dca4957bd0da3e1af7b96d0758d97e708ef6Al Viro unsigned int cmd, unsigned long arg) 3051ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann{ 3061ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann mm_segment_t old_fs = get_fs(); 3071ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann void *karg = NULL; 3081ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann unsigned int kcmd = 0; 3091ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann int i, err; 3101ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann 3111ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann for (i = 0; i < NR_FD_IOCTL_TRANS; i++) 3121ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann if (cmd == fd_ioctl_trans_table[i].cmd32) { 3131ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann kcmd = fd_ioctl_trans_table[i].cmd; 3141ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann break; 3151ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann } 3161ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann if (!kcmd) 3171ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann return -EINVAL; 3181ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann 3191ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann switch (cmd) { 3201ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann case FDSETPRM32: 3211ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann case FDDEFPRM32: 3221ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann case FDGETPRM32: 3231ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann { 3241ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann compat_uptr_t name; 3251ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann struct compat_floppy_struct __user *uf; 3261ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann struct floppy_struct *f; 3271ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann 3281ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann uf = compat_ptr(arg); 3291ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann f = karg = kmalloc(sizeof(struct floppy_struct), GFP_KERNEL); 3301ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann if (!karg) 3311ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann return -ENOMEM; 3321ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann if (cmd == FDGETPRM32) 3331ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann break; 3341ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err = __get_user(f->size, &uf->size); 3351ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __get_user(f->sect, &uf->sect); 3361ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __get_user(f->head, &uf->head); 3371ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __get_user(f->track, &uf->track); 3381ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __get_user(f->stretch, &uf->stretch); 3391ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __get_user(f->gap, &uf->gap); 3401ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __get_user(f->rate, &uf->rate); 3411ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __get_user(f->spec1, &uf->spec1); 3421ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __get_user(f->fmt_gap, &uf->fmt_gap); 3431ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __get_user(name, &uf->name); 3441ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann f->name = compat_ptr(name); 3451ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann if (err) { 3461ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err = -EFAULT; 3471ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann goto out; 3481ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann } 3491ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann break; 3501ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann } 3511ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann case FDSETDRVPRM32: 3521ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann case FDGETDRVPRM32: 3531ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann { 3541ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann struct compat_floppy_drive_params __user *uf; 3551ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann struct floppy_drive_params *f; 3561ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann 3571ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann uf = compat_ptr(arg); 3581ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann f = karg = kmalloc(sizeof(struct floppy_drive_params), GFP_KERNEL); 3591ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann if (!karg) 3601ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann return -ENOMEM; 3611ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann if (cmd == FDGETDRVPRM32) 3621ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann break; 3631ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err = __get_user(f->cmos, &uf->cmos); 3641ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __get_user(f->max_dtr, &uf->max_dtr); 3651ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __get_user(f->hlt, &uf->hlt); 3661ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __get_user(f->hut, &uf->hut); 3671ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __get_user(f->srt, &uf->srt); 3681ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __get_user(f->spinup, &uf->spinup); 3691ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __get_user(f->spindown, &uf->spindown); 3701ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __get_user(f->spindown_offset, &uf->spindown_offset); 3711ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __get_user(f->select_delay, &uf->select_delay); 3721ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __get_user(f->rps, &uf->rps); 3731ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __get_user(f->tracks, &uf->tracks); 3741ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __get_user(f->timeout, &uf->timeout); 3751ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __get_user(f->interleave_sect, &uf->interleave_sect); 3761ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __copy_from_user(&f->max_errors, &uf->max_errors, sizeof(f->max_errors)); 3771ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __get_user(f->flags, &uf->flags); 3781ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __get_user(f->read_track, &uf->read_track); 3791ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __copy_from_user(f->autodetect, uf->autodetect, sizeof(f->autodetect)); 3801ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __get_user(f->checkfreq, &uf->checkfreq); 3811ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __get_user(f->native_format, &uf->native_format); 3821ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann if (err) { 3831ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err = -EFAULT; 3841ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann goto out; 3851ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann } 3861ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann break; 3871ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann } 3881ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann case FDGETDRVSTAT32: 3891ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann case FDPOLLDRVSTAT32: 3901ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann karg = kmalloc(sizeof(struct floppy_drive_struct), GFP_KERNEL); 3911ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann if (!karg) 3921ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann return -ENOMEM; 3931ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann break; 3941ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann case FDGETFDCSTAT32: 3951ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann karg = kmalloc(sizeof(struct floppy_fdc_state), GFP_KERNEL); 3961ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann if (!karg) 3971ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann return -ENOMEM; 3981ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann break; 3991ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann case FDWERRORGET32: 4001ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann karg = kmalloc(sizeof(struct floppy_write_errors), GFP_KERNEL); 4011ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann if (!karg) 4021ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann return -ENOMEM; 4031ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann break; 4041ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann default: 4051ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann return -EINVAL; 4061ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann } 4071ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann set_fs(KERNEL_DS); 40833c2dca4957bd0da3e1af7b96d0758d97e708ef6Al Viro err = __blkdev_driver_ioctl(bdev, mode, kcmd, (unsigned long)karg); 4091ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann set_fs(old_fs); 4101ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann if (err) 4111ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann goto out; 4121ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann switch (cmd) { 4131ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann case FDGETPRM32: 4141ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann { 4151ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann struct floppy_struct *f = karg; 4161ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann struct compat_floppy_struct __user *uf = compat_ptr(arg); 4171ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann 4181ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err = __put_user(f->size, &uf->size); 4191ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->sect, &uf->sect); 4201ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->head, &uf->head); 4211ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->track, &uf->track); 4221ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->stretch, &uf->stretch); 4231ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->gap, &uf->gap); 4241ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->rate, &uf->rate); 4251ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->spec1, &uf->spec1); 4261ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->fmt_gap, &uf->fmt_gap); 4271ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user((u64)f->name, (compat_caddr_t __user *)&uf->name); 4281ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann break; 4291ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann } 4301ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann case FDGETDRVPRM32: 4311ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann { 4321ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann struct compat_floppy_drive_params __user *uf; 4331ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann struct floppy_drive_params *f = karg; 4341ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann 4351ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann uf = compat_ptr(arg); 4361ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err = __put_user(f->cmos, &uf->cmos); 4371ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->max_dtr, &uf->max_dtr); 4381ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->hlt, &uf->hlt); 4391ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->hut, &uf->hut); 4401ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->srt, &uf->srt); 4411ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->spinup, &uf->spinup); 4421ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->spindown, &uf->spindown); 4431ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->spindown_offset, &uf->spindown_offset); 4441ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->select_delay, &uf->select_delay); 4451ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->rps, &uf->rps); 4461ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->tracks, &uf->tracks); 4471ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->timeout, &uf->timeout); 4481ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->interleave_sect, &uf->interleave_sect); 4491ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __copy_to_user(&uf->max_errors, &f->max_errors, sizeof(f->max_errors)); 4501ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->flags, &uf->flags); 4511ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->read_track, &uf->read_track); 4521ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __copy_to_user(uf->autodetect, f->autodetect, sizeof(f->autodetect)); 4531ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->checkfreq, &uf->checkfreq); 4541ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->native_format, &uf->native_format); 4551ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann break; 4561ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann } 4571ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann case FDGETDRVSTAT32: 4581ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann case FDPOLLDRVSTAT32: 4591ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann { 4601ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann struct compat_floppy_drive_struct __user *uf; 4611ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann struct floppy_drive_struct *f = karg; 4621ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann 4631ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann uf = compat_ptr(arg); 4641ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err = __put_user(f->flags, &uf->flags); 4651ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->spinup_date, &uf->spinup_date); 4661ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->select_date, &uf->select_date); 4671ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->first_read_date, &uf->first_read_date); 4681ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->probed_format, &uf->probed_format); 4691ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->track, &uf->track); 4701ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->maxblock, &uf->maxblock); 4711ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->maxtrack, &uf->maxtrack); 4721ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->generation, &uf->generation); 4731ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->keep_data, &uf->keep_data); 4741ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->fd_ref, &uf->fd_ref); 4751ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->fd_device, &uf->fd_device); 4761ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->last_checked, &uf->last_checked); 4771ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user((u64)f->dmabuf, &uf->dmabuf); 4781ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user((u64)f->bufblocks, &uf->bufblocks); 4791ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann break; 4801ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann } 4811ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann case FDGETFDCSTAT32: 4821ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann { 4831ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann struct compat_floppy_fdc_state __user *uf; 4841ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann struct floppy_fdc_state *f = karg; 4851ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann 4861ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann uf = compat_ptr(arg); 4871ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err = __put_user(f->spec1, &uf->spec1); 4881ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->spec2, &uf->spec2); 4891ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->dtr, &uf->dtr); 4901ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->version, &uf->version); 4911ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->dor, &uf->dor); 4921ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->address, &uf->address); 4931ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __copy_to_user((char __user *)&uf->address + sizeof(uf->address), 4941ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann (char *)&f->address + sizeof(f->address), sizeof(int)); 4951ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->driver_version, &uf->driver_version); 4961ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __copy_to_user(uf->track, f->track, sizeof(f->track)); 4971ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann break; 4981ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann } 4991ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann case FDWERRORGET32: 5001ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann { 5011ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann struct compat_floppy_write_errors __user *uf; 5021ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann struct floppy_write_errors *f = karg; 5031ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann 5041ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann uf = compat_ptr(arg); 5051ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err = __put_user(f->write_errors, &uf->write_errors); 5061ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->first_error_sector, &uf->first_error_sector); 5071ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->first_error_generation, &uf->first_error_generation); 5081ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->last_error_sector, &uf->last_error_sector); 5091ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->last_error_generation, &uf->last_error_generation); 5101ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err |= __put_user(f->badness, &uf->badness); 5111ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann break; 5121ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann } 5131ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann default: 5141ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann break; 5151ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann } 5161ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann if (err) 5171ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann err = -EFAULT; 5181ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann 5191ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmannout: 5201ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann kfree(karg); 5211ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann return err; 5221ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann} 5231ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann 52433c2dca4957bd0da3e1af7b96d0758d97e708ef6Al Virostatic int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode, 52533c2dca4957bd0da3e1af7b96d0758d97e708ef6Al Viro unsigned cmd, unsigned long arg) 5267199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann{ 52733013a881104304fcffe817f17f22a1588908037Philip Langdale switch (cmd) { 5289617db085c119879cd371e3212806a15596e121aArnd Bergmann case HDIO_GET_UNMASKINTR: 5299617db085c119879cd371e3212806a15596e121aArnd Bergmann case HDIO_GET_MULTCOUNT: 5309617db085c119879cd371e3212806a15596e121aArnd Bergmann case HDIO_GET_KEEPSETTINGS: 5319617db085c119879cd371e3212806a15596e121aArnd Bergmann case HDIO_GET_32BIT: 5329617db085c119879cd371e3212806a15596e121aArnd Bergmann case HDIO_GET_NOWERR: 5339617db085c119879cd371e3212806a15596e121aArnd Bergmann case HDIO_GET_DMA: 5349617db085c119879cd371e3212806a15596e121aArnd Bergmann case HDIO_GET_NICE: 5359617db085c119879cd371e3212806a15596e121aArnd Bergmann case HDIO_GET_WCACHE: 5369617db085c119879cd371e3212806a15596e121aArnd Bergmann case HDIO_GET_ACOUSTIC: 5379617db085c119879cd371e3212806a15596e121aArnd Bergmann case HDIO_GET_ADDRESS: 5389617db085c119879cd371e3212806a15596e121aArnd Bergmann case HDIO_GET_BUSSTATE: 53933c2dca4957bd0da3e1af7b96d0758d97e708ef6Al Viro return compat_hdio_ioctl(bdev, mode, cmd, arg); 5401ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann case FDSETPRM32: 5411ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann case FDDEFPRM32: 5421ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann case FDGETPRM32: 5431ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann case FDSETDRVPRM32: 5441ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann case FDGETDRVPRM32: 5451ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann case FDGETDRVSTAT32: 5461ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann case FDPOLLDRVSTAT32: 5471ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann case FDGETFDCSTAT32: 5481ca91cd0336b05b91c51b403c9ed9d297813533fArnd Bergmann case FDWERRORGET32: 54933c2dca4957bd0da3e1af7b96d0758d97e708ef6Al Viro return compat_fd_ioctl(bdev, mode, cmd, arg); 550b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann case CDROMREADAUDIO: 55133c2dca4957bd0da3e1af7b96d0758d97e708ef6Al Viro return compat_cdrom_read_audio(bdev, mode, cmd, arg); 552b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann case CDROM_SEND_PACKET: 55333c2dca4957bd0da3e1af7b96d0758d97e708ef6Al Viro return compat_cdrom_generic_command(bdev, mode, cmd, arg); 554b3087cc4f31a66c8c7b63419e913ed9d34145f10Arnd Bergmann 5557199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann /* 5567199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann * No handler required for the ones below, we just need to 5577199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann * convert arg to a 64 bit pointer. 5587199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann */ 5597199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case BLKSECTSET: 5607199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann /* 5617199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann * 0x03 -- HD/IDE ioctl's used by hdparm and friends. 5627199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann * Some need translations, these do not. 5637199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann */ 5647199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case HDIO_GET_IDENTITY: 5657199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case HDIO_DRIVE_TASK: 5667199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case HDIO_DRIVE_CMD: 5677199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann /* 0x330 is reserved -- it used to be HDIO_GETGEO_BIG */ 5687199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case 0x330: 5697199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann /* 0x02 -- Floppy ioctls */ 5707199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case FDMSGON: 5717199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case FDMSGOFF: 5727199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case FDSETEMSGTRESH: 5737199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case FDFLUSH: 5747199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case FDWERRORCLR: 5757199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case FDSETMAXERRS: 5767199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case FDGETMAXERRS: 5777199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case FDGETDRVTYP: 5787199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case FDEJECT: 5797199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case FDCLRPRM: 5807199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case FDFMTBEG: 5817199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case FDFMTEND: 5827199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case FDRESET: 5837199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case FDTWADDLE: 5847199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case FDFMTTRK: 5857199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case FDRAWCMD: 5867199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann /* CDROM stuff */ 5877199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case CDROMPAUSE: 5887199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case CDROMRESUME: 5897199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case CDROMPLAYMSF: 5907199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case CDROMPLAYTRKIND: 5917199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case CDROMREADTOCHDR: 5927199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case CDROMREADTOCENTRY: 5937199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case CDROMSTOP: 5947199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case CDROMSTART: 5957199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case CDROMEJECT: 5967199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case CDROMVOLCTRL: 5977199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case CDROMSUBCHNL: 5987199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case CDROMMULTISESSION: 5997199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case CDROM_GET_MCN: 6007199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case CDROMRESET: 6017199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case CDROMVOLREAD: 6027199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case CDROMSEEK: 6037199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case CDROMPLAYBLK: 6047199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case CDROMCLOSETRAY: 6057199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case CDROM_DISC_STATUS: 6067199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case CDROM_CHANGER_NSLOTS: 6077199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case CDROM_GET_CAPABILITY: 6087199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann /* Ignore cdrom.h about these next 5 ioctls, they absolutely do 6097199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann * not take a struct cdrom_read, instead they take a struct cdrom_msf 6107199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann * which is compatible. 6117199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann */ 6127199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case CDROMREADMODE2: 6137199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case CDROMREADMODE1: 6147199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case CDROMREADRAW: 6157199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case CDROMREADCOOKED: 6167199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case CDROMREADALL: 6177199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann /* DVD ioctls */ 6187199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case DVD_READ_STRUCT: 6197199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case DVD_WRITE_STRUCT: 6207199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann case DVD_AUTH: 6217199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann arg = (unsigned long)compat_ptr(arg); 6221c925604e1038c7c65b91a92d14dc972b3a70a97Andreas Schwab /* These intepret arg as an unsigned long, not as a pointer, 6231c925604e1038c7c65b91a92d14dc972b3a70a97Andreas Schwab * so we must not do compat_ptr() conversion. */ 6241c925604e1038c7c65b91a92d14dc972b3a70a97Andreas Schwab case HDIO_SET_MULTCOUNT: 6251c925604e1038c7c65b91a92d14dc972b3a70a97Andreas Schwab case HDIO_SET_UNMASKINTR: 6261c925604e1038c7c65b91a92d14dc972b3a70a97Andreas Schwab case HDIO_SET_KEEPSETTINGS: 6271c925604e1038c7c65b91a92d14dc972b3a70a97Andreas Schwab case HDIO_SET_32BIT: 6281c925604e1038c7c65b91a92d14dc972b3a70a97Andreas Schwab case HDIO_SET_NOWERR: 6291c925604e1038c7c65b91a92d14dc972b3a70a97Andreas Schwab case HDIO_SET_DMA: 6301c925604e1038c7c65b91a92d14dc972b3a70a97Andreas Schwab case HDIO_SET_PIO_MODE: 6311c925604e1038c7c65b91a92d14dc972b3a70a97Andreas Schwab case HDIO_SET_NICE: 6321c925604e1038c7c65b91a92d14dc972b3a70a97Andreas Schwab case HDIO_SET_WCACHE: 6331c925604e1038c7c65b91a92d14dc972b3a70a97Andreas Schwab case HDIO_SET_ACOUSTIC: 6341c925604e1038c7c65b91a92d14dc972b3a70a97Andreas Schwab case HDIO_SET_BUSSTATE: 6351c925604e1038c7c65b91a92d14dc972b3a70a97Andreas Schwab case HDIO_SET_ADDRESS: 6361c925604e1038c7c65b91a92d14dc972b3a70a97Andreas Schwab case CDROMEJECT_SW: 6371c925604e1038c7c65b91a92d14dc972b3a70a97Andreas Schwab case CDROM_SET_OPTIONS: 6381c925604e1038c7c65b91a92d14dc972b3a70a97Andreas Schwab case CDROM_CLEAR_OPTIONS: 6391c925604e1038c7c65b91a92d14dc972b3a70a97Andreas Schwab case CDROM_SELECT_SPEED: 6401c925604e1038c7c65b91a92d14dc972b3a70a97Andreas Schwab case CDROM_SELECT_DISC: 6411c925604e1038c7c65b91a92d14dc972b3a70a97Andreas Schwab case CDROM_MEDIA_CHANGED: 6421c925604e1038c7c65b91a92d14dc972b3a70a97Andreas Schwab case CDROM_DRIVE_STATUS: 6431c925604e1038c7c65b91a92d14dc972b3a70a97Andreas Schwab case CDROM_LOCKDOOR: 6441c925604e1038c7c65b91a92d14dc972b3a70a97Andreas Schwab case CDROM_DEBUG: 6457199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann break; 6467199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann default: 6477199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann /* unknown ioctl number */ 6487199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann return -ENOIOCTLCMD; 6497199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann } 6507199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann 65133c2dca4957bd0da3e1af7b96d0758d97e708ef6Al Viro return __blkdev_driver_ioctl(bdev, mode, cmd, arg); 6527199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann} 6537199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann 65445048d0961cdbf7ddfba906797ad8cb42489e070Al Viro/* Most of the generic ioctls are handled in the normal fallback path. 65545048d0961cdbf7ddfba906797ad8cb42489e070Al Viro This assumes the blkdev's low level compat_ioctl always returns 65645048d0961cdbf7ddfba906797ad8cb42489e070Al Viro ENOIOCTLCMD for unknown ioctls. */ 65745048d0961cdbf7ddfba906797ad8cb42489e070Al Virolong compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) 658f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann{ 65945048d0961cdbf7ddfba906797ad8cb42489e070Al Viro int ret = -ENOIOCTLCMD; 66045048d0961cdbf7ddfba906797ad8cb42489e070Al Viro struct inode *inode = file->f_mapping->host; 66145048d0961cdbf7ddfba906797ad8cb42489e070Al Viro struct block_device *bdev = inode->i_bdev; 66245048d0961cdbf7ddfba906797ad8cb42489e070Al Viro struct gendisk *disk = bdev->bd_disk; 66345048d0961cdbf7ddfba906797ad8cb42489e070Al Viro fmode_t mode = file->f_mode; 664f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann struct backing_dev_info *bdi; 66545048d0961cdbf7ddfba906797ad8cb42489e070Al Viro loff_t size; 66645048d0961cdbf7ddfba906797ad8cb42489e070Al Viro 667fd4ce1acd0f8558033b1a6968001552bd7671e6dChristoph Hellwig /* 668fd4ce1acd0f8558033b1a6968001552bd7671e6dChristoph Hellwig * O_NDELAY can be altered using fcntl(.., F_SETFL, ..), so we have 669fd4ce1acd0f8558033b1a6968001552bd7671e6dChristoph Hellwig * to updated it before every ioctl. 670fd4ce1acd0f8558033b1a6968001552bd7671e6dChristoph Hellwig */ 67145048d0961cdbf7ddfba906797ad8cb42489e070Al Viro if (file->f_flags & O_NDELAY) 672fd4ce1acd0f8558033b1a6968001552bd7671e6dChristoph Hellwig mode |= FMODE_NDELAY; 673fd4ce1acd0f8558033b1a6968001552bd7671e6dChristoph Hellwig else 674fd4ce1acd0f8558033b1a6968001552bd7671e6dChristoph Hellwig mode &= ~FMODE_NDELAY; 675f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann 676f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann switch (cmd) { 67745048d0961cdbf7ddfba906797ad8cb42489e070Al Viro case HDIO_GETGEO: 67845048d0961cdbf7ddfba906797ad8cb42489e070Al Viro return compat_hdio_getgeo(disk, bdev, compat_ptr(arg)); 679ac481c20ef8f6c6f2be75d581863f40c43874ef7Martin K. Petersen case BLKPBSZGET: 680ac481c20ef8f6c6f2be75d581863f40c43874ef7Martin K. Petersen return compat_put_uint(arg, bdev_physical_block_size(bdev)); 681ac481c20ef8f6c6f2be75d581863f40c43874ef7Martin K. Petersen case BLKIOMIN: 682ac481c20ef8f6c6f2be75d581863f40c43874ef7Martin K. Petersen return compat_put_uint(arg, bdev_io_min(bdev)); 683ac481c20ef8f6c6f2be75d581863f40c43874ef7Martin K. Petersen case BLKIOOPT: 684ac481c20ef8f6c6f2be75d581863f40c43874ef7Martin K. Petersen return compat_put_uint(arg, bdev_io_opt(bdev)); 685ac481c20ef8f6c6f2be75d581863f40c43874ef7Martin K. Petersen case BLKALIGNOFF: 686ac481c20ef8f6c6f2be75d581863f40c43874ef7Martin K. Petersen return compat_put_int(arg, bdev_alignment_offset(bdev)); 68798262f2762f0067375f83824d81ea929e37e6bfeMartin K. Petersen case BLKDISCARDZEROES: 68898262f2762f0067375f83824d81ea929e37e6bfeMartin K. Petersen return compat_put_uint(arg, bdev_discard_zeroes_data(bdev)); 68945048d0961cdbf7ddfba906797ad8cb42489e070Al Viro case BLKFLSBUF: 69045048d0961cdbf7ddfba906797ad8cb42489e070Al Viro case BLKROSET: 69145048d0961cdbf7ddfba906797ad8cb42489e070Al Viro case BLKDISCARD: 6928d57a98ccd0b4489003473979da8f5a1363ba7a3Adrian Hunter case BLKSECDISCARD: 6933b3a1814d1703027f9867d0f5cbbfaf6c7482474Mikulas Patocka case BLKZEROOUT: 69445048d0961cdbf7ddfba906797ad8cb42489e070Al Viro /* 69545048d0961cdbf7ddfba906797ad8cb42489e070Al Viro * the ones below are implemented in blkdev_locked_ioctl, 69645048d0961cdbf7ddfba906797ad8cb42489e070Al Viro * but we call blkdev_ioctl, which gets the lock for us 69745048d0961cdbf7ddfba906797ad8cb42489e070Al Viro */ 69845048d0961cdbf7ddfba906797ad8cb42489e070Al Viro case BLKRRPART: 69956b26add02b4bdea81d5e0ebda60db1fe3311ad4Al Viro return blkdev_ioctl(bdev, mode, cmd, 70045048d0961cdbf7ddfba906797ad8cb42489e070Al Viro (unsigned long)compat_ptr(arg)); 70145048d0961cdbf7ddfba906797ad8cb42489e070Al Viro case BLKBSZSET_32: 70256b26add02b4bdea81d5e0ebda60db1fe3311ad4Al Viro return blkdev_ioctl(bdev, mode, BLKBSZSET, 70345048d0961cdbf7ddfba906797ad8cb42489e070Al Viro (unsigned long)compat_ptr(arg)); 70445048d0961cdbf7ddfba906797ad8cb42489e070Al Viro case BLKPG: 70556b26add02b4bdea81d5e0ebda60db1fe3311ad4Al Viro return compat_blkpg_ioctl(bdev, mode, cmd, compat_ptr(arg)); 706f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann case BLKRAGET: 707f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann case BLKFRAGET: 708f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann if (!arg) 709f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann return -EINVAL; 710f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann bdi = blk_get_backing_dev_info(bdev); 711f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann if (bdi == NULL) 712f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann return -ENOTTY; 713f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann return compat_put_long(arg, 714f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann (bdi->ra_pages * PAGE_CACHE_SIZE) / 512); 715f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann case BLKROGET: /* compatible */ 716f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann return compat_put_int(arg, bdev_read_only(bdev) != 0); 717f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann case BLKBSZGET_32: /* get the logical block size (cf. BLKSSZGET) */ 718f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann return compat_put_int(arg, block_size(bdev)); 719f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann case BLKSSZGET: /* get block device hardware sector size */ 720e1defc4ff0cf57aca6c5e3ff99fa503f5943c1f1Martin K. Petersen return compat_put_int(arg, bdev_logical_block_size(bdev)); 721f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann case BLKSECTGET: 722f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann return compat_put_ushort(arg, 723ae03bf639a5027d27270123f5f6e3ee6a412781dMartin K. Petersen queue_max_sectors(bdev_get_queue(bdev))); 724ef00f59c95fe6e002e7c6e3663cdea65e253f4ccMartin K. Petersen case BLKROTATIONAL: 725ef00f59c95fe6e002e7c6e3663cdea65e253f4ccMartin K. Petersen return compat_put_ushort(arg, 726ef00f59c95fe6e002e7c6e3663cdea65e253f4ccMartin K. Petersen !blk_queue_nonrot(bdev_get_queue(bdev))); 727f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann case BLKRASET: /* compatible, but no compat_ptr (!) */ 728f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann case BLKFRASET: 729f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann if (!capable(CAP_SYS_ADMIN)) 730f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann return -EACCES; 731f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann bdi = blk_get_backing_dev_info(bdev); 732f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann if (bdi == NULL) 733f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann return -ENOTTY; 734f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann bdi->ra_pages = (arg * 512) / PAGE_CACHE_SIZE; 735f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann return 0; 736f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann case BLKGETSIZE: 73777304d2abac6101f7249754ffdd4421258877ab0Mike Snitzer size = i_size_read(bdev->bd_inode); 73845048d0961cdbf7ddfba906797ad8cb42489e070Al Viro if ((size >> 9) > ~0UL) 739f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann return -EFBIG; 74045048d0961cdbf7ddfba906797ad8cb42489e070Al Viro return compat_put_ulong(arg, size >> 9); 741f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann 742f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann case BLKGETSIZE64_32: 74377304d2abac6101f7249754ffdd4421258877ab0Mike Snitzer return compat_put_u64(arg, i_size_read(bdev->bd_inode)); 744171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann 745171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann case BLKTRACESETUP32: 746171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann case BLKTRACESTART: /* compatible */ 747171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann case BLKTRACESTOP: /* compatible */ 748171044d449611c6e5040b37210ff6aba47f33ee4Arnd Bergmann case BLKTRACETEARDOWN: /* compatible */ 74945048d0961cdbf7ddfba906797ad8cb42489e070Al Viro ret = blk_trace_ioctl(bdev, cmd, compat_ptr(arg)); 7507199d4cdd8485f802df3e1bc131245c69009b9a4Arnd Bergmann return ret; 75145048d0961cdbf7ddfba906797ad8cb42489e070Al Viro default: 75245048d0961cdbf7ddfba906797ad8cb42489e070Al Viro if (disk->fops->compat_ioctl) 75345048d0961cdbf7ddfba906797ad8cb42489e070Al Viro ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg); 75445048d0961cdbf7ddfba906797ad8cb42489e070Al Viro if (ret == -ENOIOCTLCMD) 75545048d0961cdbf7ddfba906797ad8cb42489e070Al Viro ret = compat_blkdev_driver_ioctl(bdev, mode, cmd, arg); 75645048d0961cdbf7ddfba906797ad8cb42489e070Al Viro return ret; 75745048d0961cdbf7ddfba906797ad8cb42489e070Al Viro } 758f58c4c0a17e500e767473598b3deafaa1d64051dArnd Bergmann} 759