diff options
Diffstat (limited to 'drivers/ide')
-rw-r--r-- | drivers/ide/ide-cd.c | 2 | ||||
-rw-r--r-- | drivers/ide/ide-disk.c | 81 | ||||
-rw-r--r-- | drivers/ide/ide-floppy.c | 10 | ||||
-rw-r--r-- | drivers/ide/ide-tape.c | 30 | ||||
-rw-r--r-- | drivers/ide/ide.c | 176 |
5 files changed, 193 insertions, 106 deletions
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index c3a0079789fd..29408cfd9869 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c | |||
@@ -3061,7 +3061,7 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive) | |||
3061 | 3061 | ||
3062 | static void ide_cdrom_add_settings(ide_drive_t *drive) | 3062 | static void ide_cdrom_add_settings(ide_drive_t *drive) |
3063 | { | 3063 | { |
3064 | ide_add_setting(drive, "dsc_overlap", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL); | 3064 | ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL); |
3065 | } | 3065 | } |
3066 | 3066 | ||
3067 | /* | 3067 | /* |
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) |
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 84d398f71e0f..38fe45cf4019 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c | |||
@@ -1816,12 +1816,12 @@ static void idefloppy_add_settings(ide_drive_t *drive) | |||
1816 | idefloppy_floppy_t *floppy = drive->driver_data; | 1816 | idefloppy_floppy_t *floppy = drive->driver_data; |
1817 | 1817 | ||
1818 | /* | 1818 | /* |
1819 | * drive setting name read/write ioctl ioctl data type min max mul_factor div_factor data pointer set function | 1819 | * drive setting name read/write data type min max mul_factor div_factor data pointer set function |
1820 | */ | 1820 | */ |
1821 | ide_add_setting(drive, "bios_cyl", SETTING_RW, -1, -1, TYPE_INT, 0, 1023, 1, 1, &drive->bios_cyl, NULL); | 1821 | ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 1023, 1, 1, &drive->bios_cyl, NULL); |
1822 | ide_add_setting(drive, "bios_head", SETTING_RW, -1, -1, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); | 1822 | ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); |
1823 | ide_add_setting(drive, "bios_sect", SETTING_RW, -1, -1, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); | 1823 | ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); |
1824 | ide_add_setting(drive, "ticks", SETTING_RW, -1, -1, TYPE_BYTE, 0, 255, 1, 1, &floppy->ticks, NULL); | 1824 | ide_add_setting(drive, "ticks", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, &floppy->ticks, NULL); |
1825 | } | 1825 | } |
1826 | 1826 | ||
1827 | /* | 1827 | /* |
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index ad306ae24e24..fa0d22de37a7 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c | |||
@@ -4566,22 +4566,22 @@ static void idetape_add_settings (ide_drive_t *drive) | |||
4566 | idetape_tape_t *tape = drive->driver_data; | 4566 | idetape_tape_t *tape = drive->driver_data; |
4567 | 4567 | ||
4568 | /* | 4568 | /* |
4569 | * drive setting name read/write ioctl ioctl data type min max mul_factor div_factor data pointer set function | 4569 | * drive setting name read/write data type min max mul_factor div_factor data pointer set function |
4570 | */ | 4570 | */ |
4571 | ide_add_setting(drive, "buffer", SETTING_READ, -1, -1, TYPE_SHORT, 0, 0xffff, 1, 2, &tape->capabilities.buffer_size, NULL); | 4571 | ide_add_setting(drive, "buffer", SETTING_READ, TYPE_SHORT, 0, 0xffff, 1, 2, &tape->capabilities.buffer_size, NULL); |
4572 | ide_add_setting(drive, "pipeline_min", SETTING_RW, -1, -1, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->min_pipeline, NULL); | 4572 | ide_add_setting(drive, "pipeline_min", SETTING_RW, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->min_pipeline, NULL); |
4573 | ide_add_setting(drive, "pipeline", SETTING_RW, -1, -1, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->max_stages, NULL); | 4573 | ide_add_setting(drive, "pipeline", SETTING_RW, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->max_stages, NULL); |
4574 | ide_add_setting(drive, "pipeline_max", SETTING_RW, -1, -1, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->max_pipeline, NULL); | 4574 | ide_add_setting(drive, "pipeline_max", SETTING_RW, TYPE_INT, 1, 0xffff, tape->stage_size / 1024, 1, &tape->max_pipeline, NULL); |
4575 | ide_add_setting(drive, "pipeline_used",SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, tape->stage_size / 1024, 1, &tape->nr_stages, NULL); | 4575 | ide_add_setting(drive, "pipeline_used", SETTING_READ, TYPE_INT, 0, 0xffff, tape->stage_size / 1024, 1, &tape->nr_stages, NULL); |
4576 | ide_add_setting(drive, "pipeline_pending",SETTING_READ,-1, -1, TYPE_INT, 0, 0xffff, tape->stage_size / 1024, 1, &tape->nr_pending_stages, NULL); | 4576 | ide_add_setting(drive, "pipeline_pending", SETTING_READ, TYPE_INT, 0, 0xffff, tape->stage_size / 1024, 1, &tape->nr_pending_stages, NULL); |
4577 | ide_add_setting(drive, "speed", SETTING_READ, -1, -1, TYPE_SHORT, 0, 0xffff, 1, 1, &tape->capabilities.speed, NULL); | 4577 | ide_add_setting(drive, "speed", SETTING_READ, TYPE_SHORT, 0, 0xffff, 1, 1, &tape->capabilities.speed, NULL); |
4578 | ide_add_setting(drive, "stage", SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1024, &tape->stage_size, NULL); | 4578 | ide_add_setting(drive, "stage", SETTING_READ, TYPE_INT, 0, 0xffff, 1, 1024, &tape->stage_size, NULL); |
4579 | ide_add_setting(drive, "tdsc", SETTING_RW, -1, -1, TYPE_INT, IDETAPE_DSC_RW_MIN, IDETAPE_DSC_RW_MAX, 1000, HZ, &tape->best_dsc_rw_frequency, NULL); | 4579 | ide_add_setting(drive, "tdsc", SETTING_RW, TYPE_INT, IDETAPE_DSC_RW_MIN, IDETAPE_DSC_RW_MAX, 1000, HZ, &tape->best_dsc_rw_frequency, NULL); |
4580 | ide_add_setting(drive, "dsc_overlap", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL); | 4580 | ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->dsc_overlap, NULL); |
4581 | ide_add_setting(drive, "pipeline_head_speed_c",SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->controlled_pipeline_head_speed, NULL); | 4581 | ide_add_setting(drive, "pipeline_head_speed_c",SETTING_READ, TYPE_INT, 0, 0xffff, 1, 1, &tape->controlled_pipeline_head_speed, NULL); |
4582 | ide_add_setting(drive, "pipeline_head_speed_u",SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->uncontrolled_pipeline_head_speed, NULL); | 4582 | ide_add_setting(drive, "pipeline_head_speed_u",SETTING_READ, TYPE_INT, 0, 0xffff, 1, 1, &tape->uncontrolled_pipeline_head_speed,NULL); |
4583 | ide_add_setting(drive, "avg_speed", SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->avg_speed, NULL); | 4583 | ide_add_setting(drive, "avg_speed", SETTING_READ, TYPE_INT, 0, 0xffff, 1, 1, &tape->avg_speed, NULL); |
4584 | ide_add_setting(drive, "debug_level",SETTING_RW, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->debug_level, NULL); | 4584 | ide_add_setting(drive, "debug_level", SETTING_RW, TYPE_INT, 0, 0xffff, 1, 1, &tape->debug_level, NULL); |
4585 | } | 4585 | } |
4586 | 4586 | ||
4587 | /* | 4587 | /* |
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 7a96f6f07494..8793a960210c 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c | |||
@@ -823,13 +823,13 @@ EXPORT_SYMBOL(ide_register_hw); | |||
823 | 823 | ||
824 | DECLARE_MUTEX(ide_setting_sem); | 824 | DECLARE_MUTEX(ide_setting_sem); |
825 | 825 | ||
826 | EXPORT_SYMBOL_GPL(ide_setting_sem); | ||
827 | |||
826 | /** | 828 | /** |
827 | * __ide_add_setting - add an ide setting option | 829 | * __ide_add_setting - add an ide setting option |
828 | * @drive: drive to use | 830 | * @drive: drive to use |
829 | * @name: setting name | 831 | * @name: setting name |
830 | * @rw: true if the function is read write | 832 | * @rw: true if the function is read write |
831 | * @read_ioctl: function to call on read | ||
832 | * @write_ioctl: function to call on write | ||
833 | * @data_type: type of data | 833 | * @data_type: type of data |
834 | * @min: range minimum | 834 | * @min: range minimum |
835 | * @max: range maximum | 835 | * @max: range maximum |
@@ -850,7 +850,7 @@ DECLARE_MUTEX(ide_setting_sem); | |||
850 | * remove. | 850 | * remove. |
851 | */ | 851 | */ |
852 | 852 | ||
853 | static int __ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set, int auto_remove) | 853 | static int __ide_add_setting(ide_drive_t *drive, const char *name, int rw, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set, int auto_remove) |
854 | { | 854 | { |
855 | ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL; | 855 | ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL; |
856 | 856 | ||
@@ -863,8 +863,6 @@ static int __ide_add_setting(ide_drive_t *drive, const char *name, int rw, int r | |||
863 | goto abort; | 863 | goto abort; |
864 | strcpy(setting->name, name); | 864 | strcpy(setting->name, name); |
865 | setting->rw = rw; | 865 | setting->rw = rw; |
866 | setting->read_ioctl = read_ioctl; | ||
867 | setting->write_ioctl = write_ioctl; | ||
868 | setting->data_type = data_type; | 866 | setting->data_type = data_type; |
869 | setting->min = min; | 867 | setting->min = min; |
870 | setting->max = max; | 868 | setting->max = max; |
@@ -885,9 +883,9 @@ abort: | |||
885 | return -1; | 883 | return -1; |
886 | } | 884 | } |
887 | 885 | ||
888 | int ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set) | 886 | int ide_add_setting(ide_drive_t *drive, const char *name, int rw, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set) |
889 | { | 887 | { |
890 | return __ide_add_setting(drive, name, rw, read_ioctl, write_ioctl, data_type, min, max, mul_factor, div_factor, data, set, 1); | 888 | return __ide_add_setting(drive, name, rw, data_type, min, max, mul_factor, div_factor, data, set, 1); |
891 | } | 889 | } |
892 | 890 | ||
893 | EXPORT_SYMBOL(ide_add_setting); | 891 | EXPORT_SYMBOL(ide_add_setting); |
@@ -919,29 +917,6 @@ static void __ide_remove_setting (ide_drive_t *drive, char *name) | |||
919 | } | 917 | } |
920 | 918 | ||
921 | /** | 919 | /** |
922 | * ide_find_setting_by_ioctl - find a drive specific ioctl | ||
923 | * @drive: drive to scan | ||
924 | * @cmd: ioctl command to handle | ||
925 | * | ||
926 | * Scan's the device setting table for a matching entry and returns | ||
927 | * this or NULL if no entry is found. The caller must hold the | ||
928 | * setting semaphore | ||
929 | */ | ||
930 | |||
931 | static ide_settings_t *ide_find_setting_by_ioctl (ide_drive_t *drive, int cmd) | ||
932 | { | ||
933 | ide_settings_t *setting = drive->settings; | ||
934 | |||
935 | while (setting) { | ||
936 | if (setting->read_ioctl == cmd || setting->write_ioctl == cmd) | ||
937 | break; | ||
938 | setting = setting->next; | ||
939 | } | ||
940 | |||
941 | return setting; | ||
942 | } | ||
943 | |||
944 | /** | ||
945 | * ide_find_setting_by_name - find a drive specific setting | 920 | * ide_find_setting_by_name - find a drive specific setting |
946 | * @drive: drive to scan | 921 | * @drive: drive to scan |
947 | * @name: setting name | 922 | * @name: setting name |
@@ -1014,7 +989,6 @@ int ide_read_setting (ide_drive_t *drive, ide_settings_t *setting) | |||
1014 | val = *((u16 *) setting->data); | 989 | val = *((u16 *) setting->data); |
1015 | break; | 990 | break; |
1016 | case TYPE_INT: | 991 | case TYPE_INT: |
1017 | case TYPE_INTA: | ||
1018 | val = *((u32 *) setting->data); | 992 | val = *((u32 *) setting->data); |
1019 | break; | 993 | break; |
1020 | } | 994 | } |
@@ -1076,17 +1050,14 @@ EXPORT_SYMBOL(ide_spin_wait_hwgroup); | |||
1076 | 1050 | ||
1077 | int ide_write_setting (ide_drive_t *drive, ide_settings_t *setting, int val) | 1051 | int ide_write_setting (ide_drive_t *drive, ide_settings_t *setting, int val) |
1078 | { | 1052 | { |
1079 | int i; | ||
1080 | u32 *p; | ||
1081 | |||
1082 | if (!capable(CAP_SYS_ADMIN)) | 1053 | if (!capable(CAP_SYS_ADMIN)) |
1083 | return -EACCES; | 1054 | return -EACCES; |
1055 | if (setting->set) | ||
1056 | return setting->set(drive, val); | ||
1084 | if (!(setting->rw & SETTING_WRITE)) | 1057 | if (!(setting->rw & SETTING_WRITE)) |
1085 | return -EPERM; | 1058 | return -EPERM; |
1086 | if (val < setting->min || val > setting->max) | 1059 | if (val < setting->min || val > setting->max) |
1087 | return -EINVAL; | 1060 | return -EINVAL; |
1088 | if (setting->set) | ||
1089 | return setting->set(drive, val); | ||
1090 | if (ide_spin_wait_hwgroup(drive)) | 1061 | if (ide_spin_wait_hwgroup(drive)) |
1091 | return -EBUSY; | 1062 | return -EBUSY; |
1092 | switch (setting->data_type) { | 1063 | switch (setting->data_type) { |
@@ -1099,11 +1070,6 @@ int ide_write_setting (ide_drive_t *drive, ide_settings_t *setting, int val) | |||
1099 | case TYPE_INT: | 1070 | case TYPE_INT: |
1100 | *((u32 *) setting->data) = val; | 1071 | *((u32 *) setting->data) = val; |
1101 | break; | 1072 | break; |
1102 | case TYPE_INTA: | ||
1103 | p = (u32 *) setting->data; | ||
1104 | for (i = 0; i < 1 << PARTN_BITS; i++, p++) | ||
1105 | *p = val; | ||
1106 | break; | ||
1107 | } | 1073 | } |
1108 | spin_unlock_irq(&ide_lock); | 1074 | spin_unlock_irq(&ide_lock); |
1109 | return 0; | 1075 | return 0; |
@@ -1111,6 +1077,12 @@ int ide_write_setting (ide_drive_t *drive, ide_settings_t *setting, int val) | |||
1111 | 1077 | ||
1112 | static int set_io_32bit(ide_drive_t *drive, int arg) | 1078 | static int set_io_32bit(ide_drive_t *drive, int arg) |
1113 | { | 1079 | { |
1080 | if (drive->no_io_32bit) | ||
1081 | return -EPERM; | ||
1082 | |||
1083 | if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1)) | ||
1084 | return -EINVAL; | ||
1085 | |||
1114 | drive->io_32bit = arg; | 1086 | drive->io_32bit = arg; |
1115 | #ifdef CONFIG_BLK_DEV_DTC2278 | 1087 | #ifdef CONFIG_BLK_DEV_DTC2278 |
1116 | if (HWIF(drive)->chipset == ide_dtc2278) | 1088 | if (HWIF(drive)->chipset == ide_dtc2278) |
@@ -1119,12 +1091,28 @@ static int set_io_32bit(ide_drive_t *drive, int arg) | |||
1119 | return 0; | 1091 | return 0; |
1120 | } | 1092 | } |
1121 | 1093 | ||
1094 | static int set_ksettings(ide_drive_t *drive, int arg) | ||
1095 | { | ||
1096 | if (arg < 0 || arg > 1) | ||
1097 | return -EINVAL; | ||
1098 | |||
1099 | if (ide_spin_wait_hwgroup(drive)) | ||
1100 | return -EBUSY; | ||
1101 | drive->keep_settings = arg; | ||
1102 | spin_unlock_irq(&ide_lock); | ||
1103 | |||
1104 | return 0; | ||
1105 | } | ||
1106 | |||
1122 | static int set_using_dma (ide_drive_t *drive, int arg) | 1107 | static int set_using_dma (ide_drive_t *drive, int arg) |
1123 | { | 1108 | { |
1124 | #ifdef CONFIG_BLK_DEV_IDEDMA | 1109 | #ifdef CONFIG_BLK_DEV_IDEDMA |
1125 | ide_hwif_t *hwif = drive->hwif; | 1110 | ide_hwif_t *hwif = drive->hwif; |
1126 | int err = -EPERM; | 1111 | int err = -EPERM; |
1127 | 1112 | ||
1113 | if (arg < 0 || arg > 1) | ||
1114 | return -EINVAL; | ||
1115 | |||
1128 | if (!drive->id || !(drive->id->capability & 1)) | 1116 | if (!drive->id || !(drive->id->capability & 1)) |
1129 | goto out; | 1117 | goto out; |
1130 | 1118 | ||
@@ -1157,6 +1145,9 @@ static int set_using_dma (ide_drive_t *drive, int arg) | |||
1157 | out: | 1145 | out: |
1158 | return err; | 1146 | return err; |
1159 | #else | 1147 | #else |
1148 | if (arg < 0 || arg > 1) | ||
1149 | return -EINVAL; | ||
1150 | |||
1160 | return -EPERM; | 1151 | return -EPERM; |
1161 | #endif | 1152 | #endif |
1162 | } | 1153 | } |
@@ -1165,6 +1156,9 @@ static int set_pio_mode (ide_drive_t *drive, int arg) | |||
1165 | { | 1156 | { |
1166 | struct request rq; | 1157 | struct request rq; |
1167 | 1158 | ||
1159 | if (arg < 0 || arg > 255) | ||
1160 | return -EINVAL; | ||
1161 | |||
1168 | if (!HWIF(drive)->tuneproc) | 1162 | if (!HWIF(drive)->tuneproc) |
1169 | return -ENOSYS; | 1163 | return -ENOSYS; |
1170 | if (drive->special.b.set_tune) | 1164 | if (drive->special.b.set_tune) |
@@ -1176,9 +1170,30 @@ static int set_pio_mode (ide_drive_t *drive, int arg) | |||
1176 | return 0; | 1170 | return 0; |
1177 | } | 1171 | } |
1178 | 1172 | ||
1173 | static int set_unmaskirq(ide_drive_t *drive, int arg) | ||
1174 | { | ||
1175 | if (drive->no_unmask) | ||
1176 | return -EPERM; | ||
1177 | |||
1178 | if (arg < 0 || arg > 1) | ||
1179 | return -EINVAL; | ||
1180 | |||
1181 | if (ide_spin_wait_hwgroup(drive)) | ||
1182 | return -EBUSY; | ||
1183 | drive->unmask = arg; | ||
1184 | spin_unlock_irq(&ide_lock); | ||
1185 | |||
1186 | return 0; | ||
1187 | } | ||
1188 | |||
1179 | static int set_xfer_rate (ide_drive_t *drive, int arg) | 1189 | static int set_xfer_rate (ide_drive_t *drive, int arg) |
1180 | { | 1190 | { |
1181 | int err = ide_wait_cmd(drive, | 1191 | int err; |
1192 | |||
1193 | if (arg < 0 || arg > 70) | ||
1194 | return -EINVAL; | ||
1195 | |||
1196 | err = ide_wait_cmd(drive, | ||
1182 | WIN_SETFEATURES, (u8) arg, | 1197 | WIN_SETFEATURES, (u8) arg, |
1183 | SETFEATURES_XFER, 0, NULL); | 1198 | SETFEATURES_XFER, 0, NULL); |
1184 | 1199 | ||
@@ -1193,25 +1208,24 @@ static int set_xfer_rate (ide_drive_t *drive, int arg) | |||
1193 | * ide_add_generic_settings - generic ide settings | 1208 | * ide_add_generic_settings - generic ide settings |
1194 | * @drive: drive being configured | 1209 | * @drive: drive being configured |
1195 | * | 1210 | * |
1196 | * Add the generic parts of the system settings to the /proc files and | 1211 | * Add the generic parts of the system settings to the /proc files. |
1197 | * ioctls for this IDE device. The caller must not be holding the | 1212 | * The caller must not be holding the ide_setting_sem. |
1198 | * ide_setting_sem. | ||
1199 | */ | 1213 | */ |
1200 | 1214 | ||
1201 | void ide_add_generic_settings (ide_drive_t *drive) | 1215 | void ide_add_generic_settings (ide_drive_t *drive) |
1202 | { | 1216 | { |
1203 | /* | 1217 | /* |
1204 | * drive setting name read/write access read ioctl write ioctl data type min max mul_factor div_factor data pointer set function | 1218 | * drive setting name read/write access data type min max mul_factor div_factor data pointer set function |
1205 | */ | 1219 | */ |
1206 | __ide_add_setting(drive, "io_32bit", drive->no_io_32bit ? SETTING_READ : SETTING_RW, HDIO_GET_32BIT, HDIO_SET_32BIT, TYPE_BYTE, 0, 1 + (SUPPORT_VLB_SYNC << 1), 1, 1, &drive->io_32bit, set_io_32bit, 0); | 1220 | __ide_add_setting(drive, "io_32bit", drive->no_io_32bit ? SETTING_READ : SETTING_RW, TYPE_BYTE, 0, 1 + (SUPPORT_VLB_SYNC << 1), 1, 1, &drive->io_32bit, set_io_32bit, 0); |
1207 | __ide_add_setting(drive, "keepsettings", SETTING_RW, HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS, TYPE_BYTE, 0, 1, 1, 1, &drive->keep_settings, NULL, 0); | 1221 | __ide_add_setting(drive, "keepsettings", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->keep_settings, NULL, 0); |
1208 | __ide_add_setting(drive, "nice1", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->nice1, NULL, 0); | 1222 | __ide_add_setting(drive, "nice1", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->nice1, NULL, 0); |
1209 | __ide_add_setting(drive, "pio_mode", SETTING_WRITE, -1, HDIO_SET_PIO_MODE, TYPE_BYTE, 0, 255, 1, 1, NULL, set_pio_mode, 0); | 1223 | __ide_add_setting(drive, "pio_mode", SETTING_WRITE, TYPE_BYTE, 0, 255, 1, 1, NULL, set_pio_mode, 0); |
1210 | __ide_add_setting(drive, "unmaskirq", drive->no_unmask ? SETTING_READ : SETTING_RW, HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, NULL, 0); | 1224 | __ide_add_setting(drive, "unmaskirq", drive->no_unmask ? SETTING_READ : SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, NULL, 0); |
1211 | __ide_add_setting(drive, "using_dma", SETTING_RW, HDIO_GET_DMA, HDIO_SET_DMA, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma, 0); | 1225 | __ide_add_setting(drive, "using_dma", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma, 0); |
1212 | __ide_add_setting(drive, "init_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->init_speed, NULL, 0); | 1226 | __ide_add_setting(drive, "init_speed", SETTING_RW, TYPE_BYTE, 0, 70, 1, 1, &drive->init_speed, NULL, 0); |
1213 | __ide_add_setting(drive, "current_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->current_speed, set_xfer_rate, 0); | 1227 | __ide_add_setting(drive, "current_speed", SETTING_RW, TYPE_BYTE, 0, 70, 1, 1, &drive->current_speed, set_xfer_rate, 0); |
1214 | __ide_add_setting(drive, "number", SETTING_RW, -1, -1, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL, 0); | 1228 | __ide_add_setting(drive, "number", SETTING_RW, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL, 0); |
1215 | } | 1229 | } |
1216 | 1230 | ||
1217 | /** | 1231 | /** |
@@ -1283,27 +1297,23 @@ static int generic_ide_resume(struct device *dev) | |||
1283 | int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev, | 1297 | int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev, |
1284 | unsigned int cmd, unsigned long arg) | 1298 | unsigned int cmd, unsigned long arg) |
1285 | { | 1299 | { |
1286 | ide_settings_t *setting; | 1300 | unsigned long flags; |
1287 | ide_driver_t *drv; | 1301 | ide_driver_t *drv; |
1288 | int err = 0; | ||
1289 | void __user *p = (void __user *)arg; | 1302 | void __user *p = (void __user *)arg; |
1303 | int err = 0, (*setfunc)(ide_drive_t *, int); | ||
1304 | u8 *val; | ||
1290 | 1305 | ||
1291 | down(&ide_setting_sem); | 1306 | switch (cmd) { |
1292 | if ((setting = ide_find_setting_by_ioctl(drive, cmd)) != NULL) { | 1307 | case HDIO_GET_32BIT: val = &drive->io_32bit; goto read_val; |
1293 | if (cmd == setting->read_ioctl) { | 1308 | case HDIO_GET_KEEPSETTINGS: val = &drive->keep_settings; goto read_val; |
1294 | err = ide_read_setting(drive, setting); | 1309 | case HDIO_GET_UNMASKINTR: val = &drive->unmask; goto read_val; |
1295 | up(&ide_setting_sem); | 1310 | case HDIO_GET_DMA: val = &drive->using_dma; goto read_val; |
1296 | return err >= 0 ? put_user(err, (long __user *)arg) : err; | 1311 | case HDIO_SET_32BIT: setfunc = set_io_32bit; goto set_val; |
1297 | } else { | 1312 | case HDIO_SET_KEEPSETTINGS: setfunc = set_ksettings; goto set_val; |
1298 | if (bdev != bdev->bd_contains) | 1313 | case HDIO_SET_PIO_MODE: setfunc = set_pio_mode; goto set_val; |
1299 | err = -EINVAL; | 1314 | case HDIO_SET_UNMASKINTR: setfunc = set_unmaskirq; goto set_val; |
1300 | else | 1315 | case HDIO_SET_DMA: setfunc = set_using_dma; goto set_val; |
1301 | err = ide_write_setting(drive, setting, arg); | ||
1302 | up(&ide_setting_sem); | ||
1303 | return err; | ||
1304 | } | ||
1305 | } | 1316 | } |
1306 | up(&ide_setting_sem); | ||
1307 | 1317 | ||
1308 | switch (cmd) { | 1318 | switch (cmd) { |
1309 | case HDIO_OBSOLETE_IDENTITY: | 1319 | case HDIO_OBSOLETE_IDENTITY: |
@@ -1432,6 +1442,28 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device | |||
1432 | default: | 1442 | default: |
1433 | return -EINVAL; | 1443 | return -EINVAL; |
1434 | } | 1444 | } |
1445 | |||
1446 | read_val: | ||
1447 | down(&ide_setting_sem); | ||
1448 | spin_lock_irqsave(&ide_lock, flags); | ||
1449 | err = *val; | ||
1450 | spin_unlock_irqrestore(&ide_lock, flags); | ||
1451 | up(&ide_setting_sem); | ||
1452 | return err >= 0 ? put_user(err, (long __user *)arg) : err; | ||
1453 | |||
1454 | set_val: | ||
1455 | if (bdev != bdev->bd_contains) | ||
1456 | err = -EINVAL; | ||
1457 | else { | ||
1458 | if (!capable(CAP_SYS_ADMIN)) | ||
1459 | err = -EACCES; | ||
1460 | else { | ||
1461 | down(&ide_setting_sem); | ||
1462 | err = setfunc(drive, arg); | ||
1463 | up(&ide_setting_sem); | ||
1464 | } | ||
1465 | } | ||
1466 | return err; | ||
1435 | } | 1467 | } |
1436 | 1468 | ||
1437 | EXPORT_SYMBOL(generic_ide_ioctl); | 1469 | EXPORT_SYMBOL(generic_ide_ioctl); |