aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/ide.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ide/ide.c')
-rw-r--r--drivers/ide/ide.c176
1 files changed, 104 insertions, 72 deletions
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);