aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2007-05-09 18:01:10 -0400
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2007-05-09 18:01:10 -0400
commit1497943ee692aa7519fa972d0e3a339649bf3a96 (patch)
treedc70ee9731f66dd323ddb397380b62c0c2977add
parentecfd80e4a514123070b4cfb674b817ba75055df2 (diff)
ide: split off ioctl handling from IDE settings (v2)
* do write permission and min/max checks in ide_procset_t functions * ide-disk.c: drive->id is always available so cleanup "multcount" setting accordingly * ide-disk.c: "address" setting was incorrectly defined as type TYPE_INTA, fix it by using type TYPE_BYTE and updating ide_drive_t->adressing field, the bug didn't trigger because this IDE setting uses custom ->set function * ide.c: add set_ksettings() for handling HDIO_SET_KEEPSETTINGS ioctl * ide.c: add set_unmaskirq() for handling HDIO_SET_UNMASKINTR ioctl * handle ioctls directly in generic_ide_ioclt() and idedisk_ioctl() instead of using IDE settings to deal with them * remove no longer needed ide_find_setting_by_ioctl() and {read,write}_ioctl fields from ide_settings_t, also remove now unused TYPE_INTA handling v2: * add missing EXPORT_SYMBOL_GPL(ide_setting_sem) needed now for ide-disk Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
-rw-r--r--drivers/ide/ide-cd.c2
-rw-r--r--drivers/ide/ide-disk.c81
-rw-r--r--drivers/ide/ide-floppy.c10
-rw-r--r--drivers/ide/ide-tape.c30
-rw-r--r--drivers/ide/ide.c176
-rw-r--r--drivers/scsi/ide-scsi.c12
-rw-r--r--include/linux/ide.h16
7 files changed, 203 insertions, 124 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
3062static void ide_cdrom_add_settings(ide_drive_t *drive) 3062static 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
750static int set_nowerr(ide_drive_t *drive, int arg) 753static 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 */
856static int set_lba_addressing(ide_drive_t *drive, int arg) 868static 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
887static void idedisk_setup (ide_drive_t *drive) 902static void idedisk_setup (ide_drive_t *drive)
@@ -1140,9 +1155,49 @@ static int idedisk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
1140static int idedisk_ioctl(struct inode *inode, struct file *file, 1155static 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
1180read_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
1188set_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
1148static int idedisk_media_changed(struct gendisk *disk) 1203static 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
824DECLARE_MUTEX(ide_setting_sem); 824DECLARE_MUTEX(ide_setting_sem);
825 825
826EXPORT_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
853static 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) 853static 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
888int 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) 886int 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
893EXPORT_SYMBOL(ide_add_setting); 891EXPORT_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
931static 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
1077int ide_write_setting (ide_drive_t *drive, ide_settings_t *setting, int val) 1051int 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
1112static int set_io_32bit(ide_drive_t *drive, int arg) 1078static 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
1094static 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
1122static int set_using_dma (ide_drive_t *drive, int arg) 1107static 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)
1157out: 1145out:
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
1173static 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
1179static int set_xfer_rate (ide_drive_t *drive, int arg) 1189static 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
1201void ide_add_generic_settings (ide_drive_t *drive) 1215void 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)
1283int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev, 1297int 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
1446read_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
1454set_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
1437EXPORT_SYMBOL(generic_ide_ioctl); 1469EXPORT_SYMBOL(generic_ide_ioctl);
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index 531df3a29c47..4388b8ab69a1 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -726,13 +726,13 @@ static void idescsi_add_settings(ide_drive_t *drive)
726 idescsi_scsi_t *scsi = drive_to_idescsi(drive); 726 idescsi_scsi_t *scsi = drive_to_idescsi(drive);
727 727
728/* 728/*
729 * drive setting name read/write ioctl ioctl data type min max mul_factor div_factor data pointer set function 729 * drive setting name read/write data type min max mul_factor div_factor data pointer set function
730 */ 730 */
731 ide_add_setting(drive, "bios_cyl", SETTING_RW, -1, -1, TYPE_INT, 0, 1023, 1, 1, &drive->bios_cyl, NULL); 731 ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 1023, 1, 1, &drive->bios_cyl, NULL);
732 ide_add_setting(drive, "bios_head", SETTING_RW, -1, -1, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); 732 ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL);
733 ide_add_setting(drive, "bios_sect", SETTING_RW, -1, -1, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); 733 ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL);
734 ide_add_setting(drive, "transform", SETTING_RW, -1, -1, TYPE_INT, 0, 3, 1, 1, &scsi->transform, NULL); 734 ide_add_setting(drive, "transform", SETTING_RW, TYPE_INT, 0, 3, 1, 1, &scsi->transform, NULL);
735 ide_add_setting(drive, "log", SETTING_RW, -1, -1, TYPE_INT, 0, 1, 1, 1, &scsi->log, NULL); 735 ide_add_setting(drive, "log", SETTING_RW, TYPE_INT, 0, 1, 1, 1, &scsi->log, NULL);
736} 736}
737 737
738/* 738/*
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 697c39dd66a1..591a0b55e31c 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -601,16 +601,11 @@ typedef struct ide_drive_s {
601 unsigned remap_0_to_1 : 1; /* 0=noremap, 1=remap 0->1 (for EZDrive) */ 601 unsigned remap_0_to_1 : 1; /* 0=noremap, 1=remap 0->1 (for EZDrive) */
602 unsigned blocked : 1; /* 1=powermanagment told us not to do anything, so sleep nicely */ 602 unsigned blocked : 1; /* 1=powermanagment told us not to do anything, so sleep nicely */
603 unsigned vdma : 1; /* 1=doing PIO over DMA 0=doing normal DMA */ 603 unsigned vdma : 1; /* 1=doing PIO over DMA 0=doing normal DMA */
604 unsigned addressing; /* : 3;
605 * 0=28-bit
606 * 1=48-bit
607 * 2=48-bit doing 28-bit
608 * 3=64-bit
609 */
610 unsigned scsi : 1; /* 0=default, 1=ide-scsi emulation */ 604 unsigned scsi : 1; /* 0=default, 1=ide-scsi emulation */
611 unsigned sleeping : 1; /* 1=sleeping & sleep field valid */ 605 unsigned sleeping : 1; /* 1=sleeping & sleep field valid */
612 unsigned post_reset : 1; 606 unsigned post_reset : 1;
613 607
608 u8 addressing; /* 0=28-bit, 1=48-bit, 2=48-bit doing 28-bit */
614 u8 quirk_list; /* considered quirky, set for a specific host */ 609 u8 quirk_list; /* considered quirky, set for a specific host */
615 u8 init_speed; /* transfer rate set at boot */ 610 u8 init_speed; /* transfer rate set at boot */
616 u8 current_speed; /* current transfer rate set */ 611 u8 current_speed; /* current transfer rate set */
@@ -870,9 +865,8 @@ typedef struct hwgroup_s {
870 */ 865 */
871 866
872#define TYPE_INT 0 867#define TYPE_INT 0
873#define TYPE_INTA 1 868#define TYPE_BYTE 1
874#define TYPE_BYTE 2 869#define TYPE_SHORT 2
875#define TYPE_SHORT 3
876 870
877#define SETTING_READ (1 << 0) 871#define SETTING_READ (1 << 0)
878#define SETTING_WRITE (1 << 1) 872#define SETTING_WRITE (1 << 1)
@@ -882,8 +876,6 @@ typedef int (ide_procset_t)(ide_drive_t *, int);
882typedef struct ide_settings_s { 876typedef struct ide_settings_s {
883 char *name; 877 char *name;
884 int rw; 878 int rw;
885 int read_ioctl;
886 int write_ioctl;
887 int data_type; 879 int data_type;
888 int min; 880 int min;
889 int max; 881 int max;
@@ -896,7 +888,7 @@ typedef struct ide_settings_s {
896} ide_settings_t; 888} ide_settings_t;
897 889
898extern struct semaphore ide_setting_sem; 890extern struct semaphore ide_setting_sem;
899extern 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); 891int ide_add_setting(ide_drive_t *, const char *, int, int, int, int, int, int, void *, ide_procset_t *set);
900extern ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name); 892extern ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name);
901extern int ide_read_setting(ide_drive_t *t, ide_settings_t *setting); 893extern int ide_read_setting(ide_drive_t *t, ide_settings_t *setting);
902extern int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val); 894extern int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val);