diff options
Diffstat (limited to 'drivers/ide/ide-disk.c')
-rw-r--r-- | drivers/ide/ide-disk.c | 81 |
1 files changed, 68 insertions, 13 deletions
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index e7bc4d35c40c..fb162cb3ebf5 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c | |||
@@ -737,6 +737,9 @@ static int set_multcount(ide_drive_t *drive, int arg) | |||
737 | { | 737 | { |
738 | struct request rq; | 738 | struct request rq; |
739 | 739 | ||
740 | if (arg < 0 || arg > drive->id->max_multsect) | ||
741 | return -EINVAL; | ||
742 | |||
740 | if (drive->special.b.set_multmode) | 743 | if (drive->special.b.set_multmode) |
741 | return -EBUSY; | 744 | return -EBUSY; |
742 | ide_init_drive_cmd (&rq); | 745 | ide_init_drive_cmd (&rq); |
@@ -749,6 +752,9 @@ static int set_multcount(ide_drive_t *drive, int arg) | |||
749 | 752 | ||
750 | static int set_nowerr(ide_drive_t *drive, int arg) | 753 | static int set_nowerr(ide_drive_t *drive, int arg) |
751 | { | 754 | { |
755 | if (arg < 0 || arg > 1) | ||
756 | return -EINVAL; | ||
757 | |||
752 | if (ide_spin_wait_hwgroup(drive)) | 758 | if (ide_spin_wait_hwgroup(drive)) |
753 | return -EBUSY; | 759 | return -EBUSY; |
754 | drive->nowerr = arg; | 760 | drive->nowerr = arg; |
@@ -800,6 +806,9 @@ static int write_cache(ide_drive_t *drive, int arg) | |||
800 | ide_task_t args; | 806 | ide_task_t args; |
801 | int err = 1; | 807 | int err = 1; |
802 | 808 | ||
809 | if (arg < 0 || arg > 1) | ||
810 | return -EINVAL; | ||
811 | |||
803 | if (ide_id_has_flush_cache(drive->id)) { | 812 | if (ide_id_has_flush_cache(drive->id)) { |
804 | memset(&args, 0, sizeof(ide_task_t)); | 813 | memset(&args, 0, sizeof(ide_task_t)); |
805 | args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ? | 814 | args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ? |
@@ -835,6 +844,9 @@ static int set_acoustic (ide_drive_t *drive, int arg) | |||
835 | { | 844 | { |
836 | ide_task_t args; | 845 | ide_task_t args; |
837 | 846 | ||
847 | if (arg < 0 || arg > 254) | ||
848 | return -EINVAL; | ||
849 | |||
838 | memset(&args, 0, sizeof(ide_task_t)); | 850 | memset(&args, 0, sizeof(ide_task_t)); |
839 | args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ? SETFEATURES_EN_AAM : | 851 | args.tfRegister[IDE_FEATURE_OFFSET] = (arg) ? SETFEATURES_EN_AAM : |
840 | SETFEATURES_DIS_AAM; | 852 | SETFEATURES_DIS_AAM; |
@@ -855,6 +867,9 @@ static int set_acoustic (ide_drive_t *drive, int arg) | |||
855 | */ | 867 | */ |
856 | static int set_lba_addressing(ide_drive_t *drive, int arg) | 868 | static int set_lba_addressing(ide_drive_t *drive, int arg) |
857 | { | 869 | { |
870 | if (arg < 0 || arg > 2) | ||
871 | return -EINVAL; | ||
872 | |||
858 | drive->addressing = 0; | 873 | drive->addressing = 0; |
859 | 874 | ||
860 | if (HWIF(drive)->no_lba48) | 875 | if (HWIF(drive)->no_lba48) |
@@ -870,18 +885,18 @@ static void idedisk_add_settings(ide_drive_t *drive) | |||
870 | { | 885 | { |
871 | struct hd_driveid *id = drive->id; | 886 | struct hd_driveid *id = drive->id; |
872 | 887 | ||
873 | ide_add_setting(drive, "bios_cyl", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->bios_cyl, NULL); | 888 | ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, &drive->bios_cyl, NULL); |
874 | ide_add_setting(drive, "bios_head", SETTING_RW, -1, -1, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); | 889 | ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); |
875 | ide_add_setting(drive, "bios_sect", SETTING_RW, -1, -1, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); | 890 | ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); |
876 | ide_add_setting(drive, "address", SETTING_RW, HDIO_GET_ADDRESS, HDIO_SET_ADDRESS, TYPE_INTA, 0, 2, 1, 1, &drive->addressing, set_lba_addressing); | 891 | ide_add_setting(drive, "address", SETTING_RW, TYPE_BYTE, 0, 2, 1, 1, &drive->addressing, set_lba_addressing); |
877 | ide_add_setting(drive, "bswap", SETTING_READ, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->bswap, NULL); | 892 | ide_add_setting(drive, "bswap", SETTING_READ, TYPE_BYTE, 0, 1, 1, 1, &drive->bswap, NULL); |
878 | ide_add_setting(drive, "multcount", id ? SETTING_RW : SETTING_READ, HDIO_GET_MULTCOUNT, HDIO_SET_MULTCOUNT, TYPE_BYTE, 0, id ? id->max_multsect : 0, 1, 1, &drive->mult_count, set_multcount); | 893 | ide_add_setting(drive, "multcount", SETTING_RW, TYPE_BYTE, 0, id->max_multsect, 1, 1, &drive->mult_count, set_multcount); |
879 | ide_add_setting(drive, "nowerr", SETTING_RW, HDIO_GET_NOWERR, HDIO_SET_NOWERR, TYPE_BYTE, 0, 1, 1, 1, &drive->nowerr, set_nowerr); | 894 | ide_add_setting(drive, "nowerr", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->nowerr, set_nowerr); |
880 | ide_add_setting(drive, "lun", SETTING_RW, -1, -1, TYPE_INT, 0, 7, 1, 1, &drive->lun, NULL); | 895 | ide_add_setting(drive, "lun", SETTING_RW, TYPE_INT, 0, 7, 1, 1, &drive->lun, NULL); |
881 | ide_add_setting(drive, "wcache", SETTING_RW, HDIO_GET_WCACHE, HDIO_SET_WCACHE, TYPE_BYTE, 0, 1, 1, 1, &drive->wcache, write_cache); | 896 | ide_add_setting(drive, "wcache", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->wcache, write_cache); |
882 | ide_add_setting(drive, "acoustic", SETTING_RW, HDIO_GET_ACOUSTIC, HDIO_SET_ACOUSTIC, TYPE_BYTE, 0, 254, 1, 1, &drive->acoustic, set_acoustic); | 897 | ide_add_setting(drive, "acoustic", SETTING_RW, TYPE_BYTE, 0, 254, 1, 1, &drive->acoustic, set_acoustic); |
883 | ide_add_setting(drive, "failures", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->failures, NULL); | 898 | ide_add_setting(drive, "failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, &drive->failures, NULL); |
884 | ide_add_setting(drive, "max_failures", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->max_failures, NULL); | 899 | ide_add_setting(drive, "max_failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, &drive->max_failures, NULL); |
885 | } | 900 | } |
886 | 901 | ||
887 | static void idedisk_setup (ide_drive_t *drive) | 902 | static void idedisk_setup (ide_drive_t *drive) |
@@ -1140,9 +1155,49 @@ static int idedisk_getgeo(struct block_device *bdev, struct hd_geometry *geo) | |||
1140 | static int idedisk_ioctl(struct inode *inode, struct file *file, | 1155 | static int idedisk_ioctl(struct inode *inode, struct file *file, |
1141 | unsigned int cmd, unsigned long arg) | 1156 | unsigned int cmd, unsigned long arg) |
1142 | { | 1157 | { |
1158 | unsigned long flags; | ||
1143 | struct block_device *bdev = inode->i_bdev; | 1159 | struct block_device *bdev = inode->i_bdev; |
1144 | struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk); | 1160 | struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk); |
1145 | return generic_ide_ioctl(idkp->drive, file, bdev, cmd, arg); | 1161 | ide_drive_t *drive = idkp->drive; |
1162 | int err, (*setfunc)(ide_drive_t *, int); | ||
1163 | u8 *val; | ||
1164 | |||
1165 | switch (cmd) { | ||
1166 | case HDIO_GET_ADDRESS: val = &drive->addressing; goto read_val; | ||
1167 | case HDIO_GET_MULTCOUNT: val = &drive->mult_count; goto read_val; | ||
1168 | case HDIO_GET_NOWERR: val = &drive->nowerr; goto read_val; | ||
1169 | case HDIO_GET_WCACHE: val = &drive->wcache; goto read_val; | ||
1170 | case HDIO_GET_ACOUSTIC: val = &drive->acoustic; goto read_val; | ||
1171 | case HDIO_SET_ADDRESS: setfunc = set_lba_addressing; goto set_val; | ||
1172 | case HDIO_SET_MULTCOUNT: setfunc = set_multcount; goto set_val; | ||
1173 | case HDIO_SET_NOWERR: setfunc = set_nowerr; goto set_val; | ||
1174 | case HDIO_SET_WCACHE: setfunc = write_cache; goto set_val; | ||
1175 | case HDIO_SET_ACOUSTIC: setfunc = set_acoustic; goto set_val; | ||
1176 | } | ||
1177 | |||
1178 | return generic_ide_ioctl(drive, file, bdev, cmd, arg); | ||
1179 | |||
1180 | read_val: | ||
1181 | down(&ide_setting_sem); | ||
1182 | spin_lock_irqsave(&ide_lock, flags); | ||
1183 | err = *val; | ||
1184 | spin_unlock_irqrestore(&ide_lock, flags); | ||
1185 | up(&ide_setting_sem); | ||
1186 | return err >= 0 ? put_user(err, (long __user *)arg) : err; | ||
1187 | |||
1188 | set_val: | ||
1189 | if (bdev != bdev->bd_contains) | ||
1190 | err = -EINVAL; | ||
1191 | else { | ||
1192 | if (!capable(CAP_SYS_ADMIN)) | ||
1193 | err = -EACCES; | ||
1194 | else { | ||
1195 | down(&ide_setting_sem); | ||
1196 | err = setfunc(drive, arg); | ||
1197 | up(&ide_setting_sem); | ||
1198 | } | ||
1199 | } | ||
1200 | return err; | ||
1146 | } | 1201 | } |
1147 | 1202 | ||
1148 | static int idedisk_media_changed(struct gendisk *disk) | 1203 | static int idedisk_media_changed(struct gendisk *disk) |