aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2008-10-10 16:39:28 -0400
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2008-10-10 16:39:28 -0400
commit8185d5aa93e0a5c111adc4952a5b87193a68ae5b (patch)
tree431aeb09a448b7b07a353e12f4fe931ebb8555cd
parent263138a0ad6e38de7f6526b7de037ed4511308ef (diff)
ide: /proc/ide/hd*/settings rework
* Add struct ide_devset, S_* flags, *DEVSET() & ide*_devset_*() macros. * Add 'const struct ide_devset **settings' to ide_driver_t. * Use 'const struct ide_devset **settings' in ide_drive_t instead of 'struct ide_settings_s *settings'. Then convert core code and device drivers to use struct ide_devset and co.: - device settings are no longer allocated dynamically for each device but instead there is an unique struct ide_devset instance per setting - device driver keeps the pointer to the table of pointers to its settings in ide_driver_t.settings - generic settings are kept in ide_generic_setting[] - ide_proc_[un]register_driver(), ide_find_setting_by_name(), ide_{read,write}_setting() and proc_ide_{read,write}_settings() are updated accordingly - ide*_add_settings() are removed * Remove no longer used __ide_add_setting(), ide_add_setting(), __ide_remove_setting() and auto_remove_settings(). * Remove no longer used TYPE_*, SETTING_*, ide_procset_t and ide_settings_t. * ->keep_settings, ->using_dma, ->unmask, ->noflush, ->dsc_overlap, ->nice1, ->addressing, ->wcache and ->nowerr ide_drive_t fields can now be bitfield flags. While at it: * Rename ide_find_setting_by_name() to ide_find_setting(). * Rename write_wcache() to set_wcache(). There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
-rw-r--r--drivers/ide/ide-cd.c15
-rw-r--r--drivers/ide/ide-disk.c87
-rw-r--r--drivers/ide/ide-floppy.c35
-rw-r--r--drivers/ide/ide-probe.c2
-rw-r--r--drivers/ide/ide-proc.c279
-rw-r--r--drivers/ide/ide-tape.c74
-rw-r--r--drivers/ide/ide.c21
-rw-r--r--drivers/scsi/ide-scsi.c52
-rw-r--r--include/linux/ide.h110
9 files changed, 340 insertions, 335 deletions
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 34a1aeaa15dd..1f5652326489 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -1809,13 +1809,12 @@ static ide_proc_entry_t idecd_proc[] = {
1809 { NULL, 0, NULL, NULL } 1809 { NULL, 0, NULL, NULL }
1810}; 1810};
1811 1811
1812static void ide_cdrom_add_settings(ide_drive_t *drive) 1812ide_devset_rw(dsc_overlap, 0, 1, dsc_overlap);
1813{ 1813
1814 ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, 1814static const struct ide_devset *idecd_settings[] = {
1815 &drive->dsc_overlap, NULL); 1815 &ide_devset_dsc_overlap,
1816} 1816 NULL
1817#else 1817};
1818static inline void ide_cdrom_add_settings(ide_drive_t *drive) { ; }
1819#endif 1818#endif
1820 1819
1821static const struct cd_list_entry ide_cd_quirks_list[] = { 1820static const struct cd_list_entry ide_cd_quirks_list[] = {
@@ -1926,7 +1925,6 @@ static int ide_cdrom_setup(ide_drive_t *drive)
1926 } 1925 }
1927 1926
1928 ide_proc_register_driver(drive, cd->driver); 1927 ide_proc_register_driver(drive, cd->driver);
1929 ide_cdrom_add_settings(drive);
1930 return 0; 1928 return 0;
1931} 1929}
1932 1930
@@ -1977,6 +1975,7 @@ static ide_driver_t ide_cdrom_driver = {
1977 .error = __ide_error, 1975 .error = __ide_error,
1978#ifdef CONFIG_IDE_PROC_FS 1976#ifdef CONFIG_IDE_PROC_FS
1979 .proc = idecd_proc, 1977 .proc = idecd_proc,
1978 .settings = idecd_settings,
1980#endif 1979#endif
1981}; 1980};
1982 1981
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 7a15907dce1d..2e43ae15fb1b 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -599,6 +599,8 @@ static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
599 rq->special = task; 599 rq->special = task;
600} 600}
601 601
602ide_devset_get(multcount, mult_count);
603
602/* 604/*
603 * This is tightly woven into the driver->do_special can not touch. 605 * This is tightly woven into the driver->do_special can not touch.
604 * DON'T do it again until a total personality rewrite is committed. 606 * DON'T do it again until a total personality rewrite is committed.
@@ -625,6 +627,8 @@ static int set_multcount(ide_drive_t *drive, int arg)
625 return (drive->mult_count == arg) ? 0 : -EIO; 627 return (drive->mult_count == arg) ? 0 : -EIO;
626} 628}
627 629
630ide_devset_get(nowerr, nowerr);
631
628static int set_nowerr(ide_drive_t *drive, int arg) 632static int set_nowerr(ide_drive_t *drive, int arg)
629{ 633{
630 if (arg < 0 || arg > 1) 634 if (arg < 0 || arg > 1)
@@ -673,7 +677,9 @@ static void update_ordered(ide_drive_t *drive)
673 blk_queue_ordered(drive->queue, ordered, prep_fn); 677 blk_queue_ordered(drive->queue, ordered, prep_fn);
674} 678}
675 679
676static int write_cache(ide_drive_t *drive, int arg) 680ide_devset_get(wcache, wcache);
681
682static int set_wcache(ide_drive_t *drive, int arg)
677{ 683{
678 ide_task_t args; 684 ide_task_t args;
679 int err = 1; 685 int err = 1;
@@ -710,6 +716,8 @@ static int do_idedisk_flushcache(ide_drive_t *drive)
710 return ide_no_data_taskfile(drive, &args); 716 return ide_no_data_taskfile(drive, &args);
711} 717}
712 718
719ide_devset_get(acoustic, acoustic);
720
713static int set_acoustic(ide_drive_t *drive, int arg) 721static int set_acoustic(ide_drive_t *drive, int arg)
714{ 722{
715 ide_task_t args; 723 ide_task_t args;
@@ -727,6 +735,8 @@ static int set_acoustic(ide_drive_t *drive, int arg)
727 return 0; 735 return 0;
728} 736}
729 737
738ide_devset_get(lba_addressing, addressing);
739
730/* 740/*
731 * drive->addressing: 741 * drive->addressing:
732 * 0: 28-bit 742 * 0: 28-bit
@@ -750,33 +760,33 @@ static int set_lba_addressing(ide_drive_t *drive, int arg)
750} 760}
751 761
752#ifdef CONFIG_IDE_PROC_FS 762#ifdef CONFIG_IDE_PROC_FS
753static void idedisk_add_settings(ide_drive_t *drive) 763ide_devset_rw_nolock(acoustic, 0, 254, acoustic);
754{ 764ide_devset_rw_nolock(address, 0, 2, lba_addressing);
755 ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, 765ide_devset_rw_nolock(multcount, 0, 16, multcount);
756 &drive->bios_cyl, NULL); 766ide_devset_rw_nolock(nowerr, 0, 1, nowerr);
757 ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, 767ide_devset_rw_nolock(wcache, 0, 1, wcache);
758 &drive->bios_head, NULL); 768
759 ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1, 769ide_devset_rw(bios_cyl, 0, 65535, bios_cyl);
760 &drive->bios_sect, NULL); 770ide_devset_rw(bios_head, 0, 255, bios_head);
761 ide_add_setting(drive, "address", SETTING_RW, TYPE_BYTE, 0, 2, 1, 1, 771ide_devset_rw(bios_sect, 0, 63, bios_sect);
762 &drive->addressing, set_lba_addressing); 772ide_devset_rw(failures, 0, 65535, failures);
763 ide_add_setting(drive, "multcount", SETTING_RW, TYPE_BYTE, 0, 16, 1, 1, 773ide_devset_rw(lun, 0, 7, lun);
764 &drive->mult_count, set_multcount); 774ide_devset_rw(max_failures, 0, 65535, max_failures);
765 ide_add_setting(drive, "nowerr", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, 775
766 &drive->nowerr, set_nowerr); 776static const struct ide_devset *idedisk_settings[] = {
767 ide_add_setting(drive, "lun", SETTING_RW, TYPE_INT, 0, 7, 1, 1, 777 &ide_devset_acoustic,
768 &drive->lun, NULL); 778 &ide_devset_address,
769 ide_add_setting(drive, "wcache", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, 779 &ide_devset_bios_cyl,
770 &drive->wcache, write_cache); 780 &ide_devset_bios_head,
771 ide_add_setting(drive, "acoustic", SETTING_RW, TYPE_BYTE, 0, 254, 1, 1, 781 &ide_devset_bios_sect,
772 &drive->acoustic, set_acoustic); 782 &ide_devset_failures,
773 ide_add_setting(drive, "failures", SETTING_RW, TYPE_INT, 0, 65535, 1, 1, 783 &ide_devset_lun,
774 &drive->failures, NULL); 784 &ide_devset_max_failures,
775 ide_add_setting(drive, "max_failures", SETTING_RW, TYPE_INT, 0, 65535, 785 &ide_devset_multcount,
776 1, 1, &drive->max_failures, NULL); 786 &ide_devset_nowerr,
777} 787 &ide_devset_wcache,
778#else 788 NULL
779static inline void idedisk_add_settings(ide_drive_t *drive) { ; } 789};
780#endif 790#endif
781 791
782static void idedisk_setup(ide_drive_t *drive) 792static void idedisk_setup(ide_drive_t *drive)
@@ -788,7 +798,6 @@ static void idedisk_setup(ide_drive_t *drive)
788 unsigned long long capacity; 798 unsigned long long capacity;
789 799
790 ide_proc_register_driver(drive, idkp->driver); 800 ide_proc_register_driver(drive, idkp->driver);
791 idedisk_add_settings(drive);
792 801
793 if (drive->id_read == 0) 802 if (drive->id_read == 0)
794 return; 803 return;
@@ -880,7 +889,7 @@ static void idedisk_setup(ide_drive_t *drive)
880 if ((id[ATA_ID_CSFO] & 1) || ata_id_wcache_enabled(id)) 889 if ((id[ATA_ID_CSFO] & 1) || ata_id_wcache_enabled(id))
881 drive->wcache = 1; 890 drive->wcache = 1;
882 891
883 write_cache(drive, 1); 892 set_wcache(drive, 1);
884} 893}
885 894
886static void ide_cacheflush_p(ide_drive_t *drive) 895static void ide_cacheflush_p(ide_drive_t *drive)
@@ -976,6 +985,7 @@ static ide_driver_t idedisk_driver = {
976 .error = __ide_error, 985 .error = __ide_error,
977#ifdef CONFIG_IDE_PROC_FS 986#ifdef CONFIG_IDE_PROC_FS
978 .proc = idedisk_proc, 987 .proc = idedisk_proc,
988 .settings = idedisk_settings,
979#endif 989#endif
980}; 990};
981 991
@@ -1056,19 +1066,18 @@ static int idedisk_ioctl(struct inode *inode, struct file *file,
1056 struct block_device *bdev = inode->i_bdev; 1066 struct block_device *bdev = inode->i_bdev;
1057 struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk); 1067 struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
1058 ide_drive_t *drive = idkp->drive; 1068 ide_drive_t *drive = idkp->drive;
1059 int err, (*setfunc)(ide_drive_t *, int); 1069 int err, (*getfunc)(ide_drive_t *), (*setfunc)(ide_drive_t *, int);
1060 u8 *val;
1061 1070
1062 switch (cmd) { 1071 switch (cmd) {
1063 case HDIO_GET_ADDRESS: val = &drive->addressing; goto read_val; 1072 case HDIO_GET_ADDRESS: getfunc = get_lba_addressing; goto read_val;
1064 case HDIO_GET_MULTCOUNT: val = &drive->mult_count; goto read_val; 1073 case HDIO_GET_MULTCOUNT: getfunc = get_multcount; goto read_val;
1065 case HDIO_GET_NOWERR: val = &drive->nowerr; goto read_val; 1074 case HDIO_GET_NOWERR: getfunc = get_nowerr; goto read_val;
1066 case HDIO_GET_WCACHE: val = &drive->wcache; goto read_val; 1075 case HDIO_GET_WCACHE: getfunc = get_wcache; goto read_val;
1067 case HDIO_GET_ACOUSTIC: val = &drive->acoustic; goto read_val; 1076 case HDIO_GET_ACOUSTIC: getfunc = get_acoustic; goto read_val;
1068 case HDIO_SET_ADDRESS: setfunc = set_lba_addressing; goto set_val; 1077 case HDIO_SET_ADDRESS: setfunc = set_lba_addressing; goto set_val;
1069 case HDIO_SET_MULTCOUNT: setfunc = set_multcount; goto set_val; 1078 case HDIO_SET_MULTCOUNT: setfunc = set_multcount; goto set_val;
1070 case HDIO_SET_NOWERR: setfunc = set_nowerr; goto set_val; 1079 case HDIO_SET_NOWERR: setfunc = set_nowerr; goto set_val;
1071 case HDIO_SET_WCACHE: setfunc = write_cache; goto set_val; 1080 case HDIO_SET_WCACHE: setfunc = set_wcache; goto set_val;
1072 case HDIO_SET_ACOUSTIC: setfunc = set_acoustic; goto set_val; 1081 case HDIO_SET_ACOUSTIC: setfunc = set_acoustic; goto set_val;
1073 } 1082 }
1074 1083
@@ -1077,7 +1086,7 @@ static int idedisk_ioctl(struct inode *inode, struct file *file,
1077read_val: 1086read_val:
1078 mutex_lock(&ide_setting_mtx); 1087 mutex_lock(&ide_setting_mtx);
1079 spin_lock_irqsave(&ide_lock, flags); 1088 spin_lock_irqsave(&ide_lock, flags);
1080 err = *val; 1089 err = getfunc(drive);
1081 spin_unlock_irqrestore(&ide_lock, flags); 1090 spin_unlock_irqrestore(&ide_lock, flags);
1082 mutex_unlock(&ide_setting_mtx); 1091 mutex_unlock(&ide_setting_mtx);
1083 return err >= 0 ? put_user(err, (long __user *)arg) : err; 1092 return err >= 0 ? put_user(err, (long __user *)arg) : err;
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index 597459c81d5f..673644fdb6f2 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -1007,21 +1007,32 @@ static int idefloppy_identify_device(ide_drive_t *drive, u16 *id)
1007} 1007}
1008 1008
1009#ifdef CONFIG_IDE_PROC_FS 1009#ifdef CONFIG_IDE_PROC_FS
1010static void idefloppy_add_settings(ide_drive_t *drive) 1010ide_devset_rw(bios_cyl, 0, 1023, bios_cyl);
1011ide_devset_rw(bios_head, 0, 255, bios_head);
1012ide_devset_rw(bios_sect, 0, 63, bios_sect);
1013
1014static int get_ticks(ide_drive_t *drive)
1011{ 1015{
1012 idefloppy_floppy_t *floppy = drive->driver_data; 1016 idefloppy_floppy_t *floppy = drive->driver_data;
1017 return floppy->ticks;
1018}
1013 1019
1014 ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 1023, 1, 1, 1020static int set_ticks(ide_drive_t *drive, int arg)
1015 &drive->bios_cyl, NULL); 1021{
1016 ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, 1022 idefloppy_floppy_t *floppy = drive->driver_data;
1017 &drive->bios_head, NULL); 1023 floppy->ticks = arg;
1018 ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1, 1024 return 0;
1019 &drive->bios_sect, NULL);
1020 ide_add_setting(drive, "ticks", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1,
1021 &floppy->ticks, NULL);
1022} 1025}
1023#else 1026
1024static inline void idefloppy_add_settings(ide_drive_t *drive) { ; } 1027IDE_DEVSET(ticks, S_RW, 0, 255, get_ticks, set_ticks);
1028
1029static const struct ide_devset *idefloppy_settings[] = {
1030 &ide_devset_bios_cyl,
1031 &ide_devset_bios_head,
1032 &ide_devset_bios_sect,
1033 &ide_devset_ticks,
1034 NULL
1035};
1025#endif 1036#endif
1026 1037
1027static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy) 1038static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy)
@@ -1063,7 +1074,6 @@ static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy)
1063 (void) ide_floppy_get_capacity(drive); 1074 (void) ide_floppy_get_capacity(drive);
1064 1075
1065 ide_proc_register_driver(drive, floppy->driver); 1076 ide_proc_register_driver(drive, floppy->driver);
1066 idefloppy_add_settings(drive);
1067} 1077}
1068 1078
1069static void ide_floppy_remove(ide_drive_t *drive) 1079static void ide_floppy_remove(ide_drive_t *drive)
@@ -1126,6 +1136,7 @@ static ide_driver_t idefloppy_driver = {
1126 .error = __ide_error, 1136 .error = __ide_error,
1127#ifdef CONFIG_IDE_PROC_FS 1137#ifdef CONFIG_IDE_PROC_FS
1128 .proc = idefloppy_proc, 1138 .proc = idefloppy_proc,
1139 .settings = idefloppy_settings,
1129#endif 1140#endif
1130}; 1141};
1131 1142
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 9926e12783bb..62f7e1ef10c1 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -1332,8 +1332,6 @@ static void hwif_register_devices(ide_hwif_t *hwif)
1332 if (!drive->present) 1332 if (!drive->present)
1333 continue; 1333 continue;
1334 1334
1335 ide_add_generic_settings(drive);
1336
1337 snprintf(dev->bus_id, BUS_ID_SIZE, "%u.%u", hwif->index, i); 1335 snprintf(dev->bus_id, BUS_ID_SIZE, "%u.%u", hwif->index, i);
1338 dev->parent = &hwif->gendev; 1336 dev->parent = &hwif->gendev;
1339 dev->bus = &ide_bus_type; 1337 dev->bus = &ide_bus_type;
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index 7a64aedfa648..5634b3971d21 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -114,140 +114,24 @@ static int proc_ide_read_identify
114} 114}
115 115
116/** 116/**
117 * __ide_add_setting - add an ide setting option 117 * ide_find_setting - find a specific setting
118 * @drive: drive to use 118 * @st: setting table pointer
119 * @name: setting name 119 * @name: setting name
120 * @rw: true if the function is read write
121 * @data_type: type of data
122 * @min: range minimum
123 * @max: range maximum
124 * @mul_factor: multiplication scale
125 * @div_factor: divison scale
126 * @data: private data field
127 * @set: setting
128 * @auto_remove: setting auto removal flag
129 * 120 *
130 * Removes the setting named from the device if it is present. 121 * Scan's the setting table for a matching entry and returns
131 * The function takes the settings_lock to protect against
132 * parallel changes. This function must not be called from IRQ
133 * context. Returns 0 on success or -1 on failure.
134 *
135 * BUGS: This code is seriously over-engineered. There is also
136 * magic about how the driver specific features are setup. If
137 * a driver is attached we assume the driver settings are auto
138 * remove.
139 */
140
141static 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)
142{
143 ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL;
144
145 mutex_lock(&ide_setting_mtx);
146 while ((*p) && strcmp((*p)->name, name) < 0)
147 p = &((*p)->next);
148 if ((setting = kzalloc(sizeof(*setting), GFP_KERNEL)) == NULL)
149 goto abort;
150 if ((setting->name = kmalloc(strlen(name) + 1, GFP_KERNEL)) == NULL)
151 goto abort;
152 strcpy(setting->name, name);
153 setting->rw = rw;
154 setting->data_type = data_type;
155 setting->min = min;
156 setting->max = max;
157 setting->mul_factor = mul_factor;
158 setting->div_factor = div_factor;
159 setting->data = data;
160 setting->set = set;
161
162 setting->next = *p;
163 if (auto_remove)
164 setting->auto_remove = 1;
165 *p = setting;
166 mutex_unlock(&ide_setting_mtx);
167 return 0;
168abort:
169 mutex_unlock(&ide_setting_mtx);
170 kfree(setting);
171 return -1;
172}
173
174int 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)
175{
176 return __ide_add_setting(drive, name, rw, data_type, min, max, mul_factor, div_factor, data, set, 1);
177}
178
179EXPORT_SYMBOL(ide_add_setting);
180
181/**
182 * __ide_remove_setting - remove an ide setting option
183 * @drive: drive to use
184 * @name: setting name
185 *
186 * Removes the setting named from the device if it is present.
187 * The caller must hold the setting semaphore.
188 */
189
190static void __ide_remove_setting(ide_drive_t *drive, char *name)
191{
192 ide_settings_t **p, *setting;
193
194 p = (ide_settings_t **) &drive->settings;
195
196 while ((*p) && strcmp((*p)->name, name))
197 p = &((*p)->next);
198 setting = (*p);
199 if (setting == NULL)
200 return;
201
202 (*p) = setting->next;
203
204 kfree(setting->name);
205 kfree(setting);
206}
207
208/**
209 * auto_remove_settings - remove driver specific settings
210 * @drive: drive
211 *
212 * Automatically remove all the driver specific settings for this
213 * drive. This function may not be called from IRQ context. The
214 * caller must hold ide_setting_mtx.
215 */
216
217static void auto_remove_settings(ide_drive_t *drive)
218{
219 ide_settings_t *setting;
220repeat:
221 setting = drive->settings;
222 while (setting) {
223 if (setting->auto_remove) {
224 __ide_remove_setting(drive, setting->name);
225 goto repeat;
226 }
227 setting = setting->next;
228 }
229}
230
231/**
232 * ide_find_setting_by_name - find a drive specific setting
233 * @drive: drive to scan
234 * @name: setting name
235 *
236 * Scan's the device setting table for a matching entry and returns
237 * this or NULL if no entry is found. The caller must hold the 122 * this or NULL if no entry is found. The caller must hold the
238 * setting semaphore 123 * setting semaphore
239 */ 124 */
240 125
241static ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name) 126static const struct ide_devset *ide_find_setting(const struct ide_devset **st,
127 char *name)
242{ 128{
243 ide_settings_t *setting = drive->settings; 129 while (*st) {
244 130 if (strcmp((*st)->name, name) == 0)
245 while (setting) {
246 if (strcmp(setting->name, name) == 0)
247 break; 131 break;
248 setting = setting->next; 132 st++;
249 } 133 }
250 return setting; 134 return *st;
251} 135}
252 136
253/** 137/**
@@ -263,26 +147,19 @@ static ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name)
263 * be told apart 147 * be told apart
264 */ 148 */
265 149
266static int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting) 150static int ide_read_setting(ide_drive_t *drive,
151 const struct ide_devset *setting)
267{ 152{
268 int val = -EINVAL; 153 int val = -EINVAL;
269 unsigned long flags; 154
155 if ((setting->flags & S_READ)) {
156 unsigned long flags;
270 157
271 if ((setting->rw & SETTING_READ)) {
272 spin_lock_irqsave(&ide_lock, flags); 158 spin_lock_irqsave(&ide_lock, flags);
273 switch (setting->data_type) { 159 val = setting->get(drive);
274 case TYPE_BYTE:
275 val = *((u8 *) setting->data);
276 break;
277 case TYPE_SHORT:
278 val = *((u16 *) setting->data);
279 break;
280 case TYPE_INT:
281 val = *((u32 *) setting->data);
282 break;
283 }
284 spin_unlock_irqrestore(&ide_lock, flags); 160 spin_unlock_irqrestore(&ide_lock, flags);
285 } 161 }
162
286 return val; 163 return val;
287} 164}
288 165
@@ -304,33 +181,26 @@ static int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting)
304 * The current scheme of polling is kludgy, though safe enough. 181 * The current scheme of polling is kludgy, though safe enough.
305 */ 182 */
306 183
307static int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val) 184static int ide_write_setting(ide_drive_t *drive,
185 const struct ide_devset *setting, int val)
308{ 186{
309 if (!capable(CAP_SYS_ADMIN)) 187 if (!capable(CAP_SYS_ADMIN))
310 return -EACCES; 188 return -EACCES;
311 if (setting->set) 189 if (setting->set && (setting->flags & S_NOLOCK))
312 return setting->set(drive, val); 190 return setting->set(drive, val);
313 if (!(setting->rw & SETTING_WRITE)) 191 if (!(setting->flags & S_WRITE))
314 return -EPERM; 192 return -EPERM;
315 if (val < setting->min || val > setting->max) 193 if (val < setting->min || val > setting->max)
316 return -EINVAL; 194 return -EINVAL;
317 if (ide_spin_wait_hwgroup(drive)) 195 if (ide_spin_wait_hwgroup(drive))
318 return -EBUSY; 196 return -EBUSY;
319 switch (setting->data_type) { 197 setting->set(drive, val);
320 case TYPE_BYTE:
321 *((u8 *) setting->data) = val;
322 break;
323 case TYPE_SHORT:
324 *((u16 *) setting->data) = val;
325 break;
326 case TYPE_INT:
327 *((u32 *) setting->data) = val;
328 break;
329 }
330 spin_unlock_irq(&ide_lock); 198 spin_unlock_irq(&ide_lock);
331 return 0; 199 return 0;
332} 200}
333 201
202static ide_devset_get(xfer_rate, current_speed);
203
334static int set_xfer_rate (ide_drive_t *drive, int arg) 204static int set_xfer_rate (ide_drive_t *drive, int arg)
335{ 205{
336 ide_task_t task; 206 ide_task_t task;
@@ -355,29 +225,30 @@ static int set_xfer_rate (ide_drive_t *drive, int arg)
355 return err; 225 return err;
356} 226}
357 227
358/** 228ide_devset_rw_nolock(current_speed, 0, 70, xfer_rate);
359 * ide_add_generic_settings - generic ide settings 229ide_devset_rw_nolock(io_32bit, 0, 1 + (SUPPORT_VLB_SYNC << 1), io_32bit);
360 * @drive: drive being configured 230ide_devset_rw_nolock(keepsettings, 0, 1, ksettings);
361 * 231ide_devset_rw_nolock(unmaskirq, 0, 1, unmaskirq);
362 * Add the generic parts of the system settings to the /proc files. 232ide_devset_rw_nolock(using_dma, 0, 1, using_dma);
363 * The caller must not be holding the ide_setting_mtx. 233
364 */ 234ide_devset_w_nolock(pio_mode, 0, 255, pio_mode);
365 235
366void ide_add_generic_settings (ide_drive_t *drive) 236ide_devset_rw(init_speed, 0, 70, init_speed);
367{ 237ide_devset_rw(nice1, 0, 1, nice1);
368/* 238ide_devset_rw(number, 0, 3, dn);
369 * drive setting name read/write access data type min max mul_factor div_factor data pointer set function 239
370 */ 240static const struct ide_devset *ide_generic_settings[] = {
371 __ide_add_setting(drive, "io_32bit", SETTING_RW, TYPE_BYTE, 0, 1 + (SUPPORT_VLB_SYNC << 1), 1, 1, &drive->io_32bit, set_io_32bit, 0); 241 &ide_devset_current_speed,
372 __ide_add_setting(drive, "keepsettings", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->keep_settings, set_ksettings, 0); 242 &ide_devset_init_speed,
373 __ide_add_setting(drive, "nice1", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->nice1, NULL, 0); 243 &ide_devset_io_32bit,
374 __ide_add_setting(drive, "pio_mode", SETTING_WRITE, TYPE_BYTE, 0, 255, 1, 1, NULL, set_pio_mode, 0); 244 &ide_devset_keepsettings,
375 __ide_add_setting(drive, "unmaskirq", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, set_unmaskirq, 0); 245 &ide_devset_nice1,
376 __ide_add_setting(drive, "using_dma", SETTING_RW, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma, 0); 246 &ide_devset_number,
377 __ide_add_setting(drive, "init_speed", SETTING_RW, TYPE_BYTE, 0, 70, 1, 1, &drive->init_speed, NULL, 0); 247 &ide_devset_pio_mode,
378 __ide_add_setting(drive, "current_speed", SETTING_RW, TYPE_BYTE, 0, 70, 1, 1, &drive->current_speed, set_xfer_rate, 0); 248 &ide_devset_unmaskirq,
379 __ide_add_setting(drive, "number", SETTING_RW, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL, 0); 249 &ide_devset_using_dma,
380} 250 NULL
251};
381 252
382static void proc_ide_settings_warn(void) 253static void proc_ide_settings_warn(void)
383{ 254{
@@ -394,19 +265,31 @@ static void proc_ide_settings_warn(void)
394static int proc_ide_read_settings 265static int proc_ide_read_settings
395 (char *page, char **start, off_t off, int count, int *eof, void *data) 266 (char *page, char **start, off_t off, int count, int *eof, void *data)
396{ 267{
268 const struct ide_devset *setting, **g, **d;
397 ide_drive_t *drive = (ide_drive_t *) data; 269 ide_drive_t *drive = (ide_drive_t *) data;
398 ide_settings_t *setting = (ide_settings_t *) drive->settings;
399 char *out = page; 270 char *out = page;
400 int len, rc, mul_factor, div_factor; 271 int len, rc, mul_factor, div_factor;
401 272
402 proc_ide_settings_warn(); 273 proc_ide_settings_warn();
403 274
404 mutex_lock(&ide_setting_mtx); 275 mutex_lock(&ide_setting_mtx);
276 g = ide_generic_settings;
277 d = drive->settings;
405 out += sprintf(out, "name\t\t\tvalue\t\tmin\t\tmax\t\tmode\n"); 278 out += sprintf(out, "name\t\t\tvalue\t\tmin\t\tmax\t\tmode\n");
406 out += sprintf(out, "----\t\t\t-----\t\t---\t\t---\t\t----\n"); 279 out += sprintf(out, "----\t\t\t-----\t\t---\t\t---\t\t----\n");
407 while (setting) { 280 while (*g || (d && *d)) {
408 mul_factor = setting->mul_factor; 281 /* read settings in the alphabetical order */
409 div_factor = setting->div_factor; 282 if (*g && d && *d) {
283 if (strcmp((*d)->name, (*g)->name) < 0)
284 setting = *d++;
285 else
286 setting = *g++;
287 } else if (d && *d) {
288 setting = *d++;
289 } else
290 setting = *g++;
291 mul_factor = setting->mulf ? setting->mulf(drive) : 1;
292 div_factor = setting->divf ? setting->divf(drive) : 1;
410 out += sprintf(out, "%-24s", setting->name); 293 out += sprintf(out, "%-24s", setting->name);
411 rc = ide_read_setting(drive, setting); 294 rc = ide_read_setting(drive, setting);
412 if (rc >= 0) 295 if (rc >= 0)
@@ -414,12 +297,11 @@ static int proc_ide_read_settings
414 else 297 else
415 out += sprintf(out, "%-16s", "write-only"); 298 out += sprintf(out, "%-16s", "write-only");
416 out += sprintf(out, "%-16d%-16d", (setting->min * mul_factor + div_factor - 1) / div_factor, setting->max * mul_factor / div_factor); 299 out += sprintf(out, "%-16d%-16d", (setting->min * mul_factor + div_factor - 1) / div_factor, setting->max * mul_factor / div_factor);
417 if (setting->rw & SETTING_READ) 300 if (setting->flags & S_READ)
418 out += sprintf(out, "r"); 301 out += sprintf(out, "r");
419 if (setting->rw & SETTING_WRITE) 302 if (setting->flags & S_WRITE)
420 out += sprintf(out, "w"); 303 out += sprintf(out, "w");
421 out += sprintf(out, "\n"); 304 out += sprintf(out, "\n");
422 setting = setting->next;
423 } 305 }
424 len = out - page; 306 len = out - page;
425 mutex_unlock(&ide_setting_mtx); 307 mutex_unlock(&ide_setting_mtx);
@@ -433,9 +315,10 @@ static int proc_ide_write_settings(struct file *file, const char __user *buffer,
433{ 315{
434 ide_drive_t *drive = (ide_drive_t *) data; 316 ide_drive_t *drive = (ide_drive_t *) data;
435 char name[MAX_LEN + 1]; 317 char name[MAX_LEN + 1];
436 int for_real = 0; 318 int for_real = 0, mul_factor, div_factor;
437 unsigned long n; 319 unsigned long n;
438 ide_settings_t *setting; 320
321 const struct ide_devset *setting;
439 char *buf, *s; 322 char *buf, *s;
440 323
441 if (!capable(CAP_SYS_ADMIN)) 324 if (!capable(CAP_SYS_ADMIN))
@@ -503,13 +386,21 @@ static int proc_ide_write_settings(struct file *file, const char __user *buffer,
503 } 386 }
504 387
505 mutex_lock(&ide_setting_mtx); 388 mutex_lock(&ide_setting_mtx);
506 setting = ide_find_setting_by_name(drive, name); 389 /* generic settings first, then driver specific ones */
390 setting = ide_find_setting(ide_generic_settings, name);
507 if (!setting) { 391 if (!setting) {
508 mutex_unlock(&ide_setting_mtx); 392 if (drive->settings)
509 goto parse_error; 393 setting = ide_find_setting(drive->settings, name);
394 if (!setting) {
395 mutex_unlock(&ide_setting_mtx);
396 goto parse_error;
397 }
398 }
399 if (for_real) {
400 mul_factor = setting->mulf ? setting->mulf(drive) : 1;
401 div_factor = setting->divf ? setting->divf(drive) : 1;
402 ide_write_setting(drive, setting, val * div_factor / mul_factor);
510 } 403 }
511 if (for_real)
512 ide_write_setting(drive, setting, val * setting->div_factor / setting->mul_factor);
513 mutex_unlock(&ide_setting_mtx); 404 mutex_unlock(&ide_setting_mtx);
514 } 405 }
515 } while (!for_real++); 406 } while (!for_real++);
@@ -680,6 +571,10 @@ static void ide_remove_proc_entries(struct proc_dir_entry *dir, ide_proc_entry_t
680 571
681void ide_proc_register_driver(ide_drive_t *drive, ide_driver_t *driver) 572void ide_proc_register_driver(ide_drive_t *drive, ide_driver_t *driver)
682{ 573{
574 mutex_lock(&ide_setting_mtx);
575 drive->settings = driver->settings;
576 mutex_unlock(&ide_setting_mtx);
577
683 ide_add_proc_entries(drive->proc, driver->proc, drive); 578 ide_add_proc_entries(drive->proc, driver->proc, drive);
684} 579}
685 580
@@ -716,7 +611,7 @@ void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver)
716 * OTOH both ide_{read,write}_setting are only ever used under 611 * OTOH both ide_{read,write}_setting are only ever used under
717 * ide_setting_mtx. 612 * ide_setting_mtx.
718 */ 613 */
719 auto_remove_settings(drive); 614 drive->settings = NULL;
720 spin_unlock_irqrestore(&ide_lock, flags); 615 spin_unlock_irqrestore(&ide_lock, flags);
721 mutex_unlock(&ide_setting_mtx); 616 mutex_unlock(&ide_setting_mtx);
722} 617}
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index f41983e4a4e4..7037accb0589 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -2410,28 +2410,56 @@ static void idetape_get_mode_sense_results(ide_drive_t *drive)
2410} 2410}
2411 2411
2412#ifdef CONFIG_IDE_PROC_FS 2412#ifdef CONFIG_IDE_PROC_FS
2413static void idetape_add_settings(ide_drive_t *drive) 2413#define ide_tape_devset_get(name, field) \
2414{ 2414static int get_##name(ide_drive_t *drive) \
2415 idetape_tape_t *tape = drive->driver_data; 2415{ \
2416 2416 idetape_tape_t *tape = drive->driver_data; \
2417 ide_add_setting(drive, "buffer", SETTING_READ, TYPE_SHORT, 0, 0xffff, 2417 return tape->field; \
2418 1, 2, (u16 *)&tape->caps[16], NULL); 2418}
2419 ide_add_setting(drive, "speed", SETTING_READ, TYPE_SHORT, 0, 0xffff, 2419
2420 1, 1, (u16 *)&tape->caps[14], NULL); 2420#define ide_tape_devset_set(name, field) \
2421 ide_add_setting(drive, "buffer_size", SETTING_READ, TYPE_INT, 0, 0xffff, 2421static int set_##name(ide_drive_t *drive, int arg) \
2422 1, 1024, &tape->buffer_size, NULL); 2422{ \
2423 ide_add_setting(drive, "tdsc", SETTING_RW, TYPE_INT, IDETAPE_DSC_RW_MIN, 2423 idetape_tape_t *tape = drive->driver_data; \
2424 IDETAPE_DSC_RW_MAX, 1000, HZ, &tape->best_dsc_rw_freq, 2424 tape->field = arg; \
2425 NULL); 2425 return 0; \
2426 ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1, 2426}
2427 1, &drive->dsc_overlap, NULL); 2427
2428 ide_add_setting(drive, "avg_speed", SETTING_READ, TYPE_INT, 0, 0xffff, 2428#define ide_tape_devset_rw(_name, _min, _max, _field, _mulf, _divf) \
2429 1, 1, &tape->avg_speed, NULL); 2429ide_tape_devset_get(_name, _field) \
2430 ide_add_setting(drive, "debug_mask", SETTING_RW, TYPE_INT, 0, 0xffff, 1, 2430ide_tape_devset_set(_name, _field) \
2431 1, &tape->debug_mask, NULL); 2431__IDE_DEVSET(_name, S_RW, _min, _max, get_##_name, set_##_name, _mulf, _divf)
2432} 2432
2433#else 2433#define ide_tape_devset_r(_name, _min, _max, _field, _mulf, _divf) \
2434static inline void idetape_add_settings(ide_drive_t *drive) { ; } 2434ide_tape_devset_get(_name, _field) \
2435__IDE_DEVSET(_name, S_READ, _min, _max, get_##_name, NULL, _mulf, _divf)
2436
2437static int mulf_tdsc(ide_drive_t *drive) { return 1000; }
2438static int divf_tdsc(ide_drive_t *drive) { return HZ; }
2439static int divf_buffer(ide_drive_t *drive) { return 2; }
2440static int divf_buffer_size(ide_drive_t *drive) { return 1024; }
2441
2442ide_devset_rw(dsc_overlap, 0, 1, dsc_overlap);
2443
2444ide_tape_devset_rw(debug_mask, 0, 0xffff, debug_mask, NULL, NULL);
2445ide_tape_devset_rw(tdsc, IDETAPE_DSC_RW_MIN, IDETAPE_DSC_RW_MAX,
2446 best_dsc_rw_freq, mulf_tdsc, divf_tdsc);
2447
2448ide_tape_devset_r(avg_speed, 0, 0xffff, avg_speed, NULL, NULL);
2449ide_tape_devset_r(speed, 0, 0xffff, caps[14], NULL, NULL);
2450ide_tape_devset_r(buffer, 0, 0xffff, caps[16], NULL, divf_buffer);
2451ide_tape_devset_r(buffer_size, 0, 0xffff, buffer_size, NULL, divf_buffer_size);
2452
2453static const struct ide_devset *idetape_settings[] = {
2454 &ide_devset_avg_speed,
2455 &ide_devset_buffer,
2456 &ide_devset_buffer_size,
2457 &ide_devset_debug_mask,
2458 &ide_devset_dsc_overlap,
2459 &ide_devset_speed,
2460 &ide_devset_tdsc,
2461 NULL
2462};
2435#endif 2463#endif
2436 2464
2437/* 2465/*
@@ -2515,7 +2543,6 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
2515 drive->using_dma ? ", DMA":""); 2543 drive->using_dma ? ", DMA":"");
2516 2544
2517 ide_proc_register_driver(drive, tape->driver); 2545 ide_proc_register_driver(drive, tape->driver);
2518 idetape_add_settings(drive);
2519} 2546}
2520 2547
2521static void ide_tape_remove(ide_drive_t *drive) 2548static void ide_tape_remove(ide_drive_t *drive)
@@ -2586,6 +2613,7 @@ static ide_driver_t idetape_driver = {
2586 .error = __ide_error, 2613 .error = __ide_error,
2587#ifdef CONFIG_IDE_PROC_FS 2614#ifdef CONFIG_IDE_PROC_FS
2588 .proc = idetape_proc, 2615 .proc = idetape_proc,
2616 .settings = idetape_settings,
2589#endif 2617#endif
2590}; 2618};
2591 2619
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 8e0c9f27ae4a..eb64e942f58b 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -287,6 +287,8 @@ int ide_spin_wait_hwgroup (ide_drive_t *drive)
287 287
288EXPORT_SYMBOL(ide_spin_wait_hwgroup); 288EXPORT_SYMBOL(ide_spin_wait_hwgroup);
289 289
290ide_devset_get(io_32bit, io_32bit);
291
290int set_io_32bit(ide_drive_t *drive, int arg) 292int set_io_32bit(ide_drive_t *drive, int arg)
291{ 293{
292 if (drive->no_io_32bit) 294 if (drive->no_io_32bit)
@@ -305,6 +307,8 @@ int set_io_32bit(ide_drive_t *drive, int arg)
305 return 0; 307 return 0;
306} 308}
307 309
310ide_devset_get(ksettings, keep_settings);
311
308int set_ksettings(ide_drive_t *drive, int arg) 312int set_ksettings(ide_drive_t *drive, int arg)
309{ 313{
310 if (arg < 0 || arg > 1) 314 if (arg < 0 || arg > 1)
@@ -318,6 +322,8 @@ int set_ksettings(ide_drive_t *drive, int arg)
318 return 0; 322 return 0;
319} 323}
320 324
325ide_devset_get(using_dma, using_dma);
326
321int set_using_dma(ide_drive_t *drive, int arg) 327int set_using_dma(ide_drive_t *drive, int arg)
322{ 328{
323#ifdef CONFIG_BLK_DEV_IDEDMA 329#ifdef CONFIG_BLK_DEV_IDEDMA
@@ -394,6 +400,8 @@ int set_pio_mode(ide_drive_t *drive, int arg)
394 return 0; 400 return 0;
395} 401}
396 402
403ide_devset_get(unmaskirq, unmask);
404
397int set_unmaskirq(ide_drive_t *drive, int arg) 405int set_unmaskirq(ide_drive_t *drive, int arg)
398{ 406{
399 if (drive->no_unmask) 407 if (drive->no_unmask)
@@ -555,14 +563,13 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
555{ 563{
556 unsigned long flags; 564 unsigned long flags;
557 ide_driver_t *drv; 565 ide_driver_t *drv;
558 int err = 0, (*setfunc)(ide_drive_t *, int); 566 int err = 0, (*getfunc)(ide_drive_t *), (*setfunc)(ide_drive_t *, int);
559 u8 *val;
560 567
561 switch (cmd) { 568 switch (cmd) {
562 case HDIO_GET_32BIT: val = &drive->io_32bit; goto read_val; 569 case HDIO_GET_32BIT: getfunc = get_io_32bit; goto read_val;
563 case HDIO_GET_KEEPSETTINGS: val = &drive->keep_settings; goto read_val; 570 case HDIO_GET_KEEPSETTINGS: getfunc = get_ksettings; goto read_val;
564 case HDIO_GET_UNMASKINTR: val = &drive->unmask; goto read_val; 571 case HDIO_GET_UNMASKINTR: getfunc = get_unmaskirq; goto read_val;
565 case HDIO_GET_DMA: val = &drive->using_dma; goto read_val; 572 case HDIO_GET_DMA: getfunc = get_using_dma; goto read_val;
566 case HDIO_SET_32BIT: setfunc = set_io_32bit; goto set_val; 573 case HDIO_SET_32BIT: setfunc = set_io_32bit; goto set_val;
567 case HDIO_SET_KEEPSETTINGS: setfunc = set_ksettings; goto set_val; 574 case HDIO_SET_KEEPSETTINGS: setfunc = set_ksettings; goto set_val;
568 case HDIO_SET_PIO_MODE: setfunc = set_pio_mode; goto set_val; 575 case HDIO_SET_PIO_MODE: setfunc = set_pio_mode; goto set_val;
@@ -638,7 +645,7 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
638read_val: 645read_val:
639 mutex_lock(&ide_setting_mtx); 646 mutex_lock(&ide_setting_mtx);
640 spin_lock_irqsave(&ide_lock, flags); 647 spin_lock_irqsave(&ide_lock, flags);
641 err = *val; 648 err = getfunc(drive);
642 spin_unlock_irqrestore(&ide_lock, flags); 649 spin_unlock_irqrestore(&ide_lock, flags);
643 mutex_unlock(&ide_setting_mtx); 650 mutex_unlock(&ide_setting_mtx);
644 return err >= 0 ? put_user(err, (long __user *)arg) : err; 651 return err >= 0 ? put_user(err, (long __user *)arg) : err;
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index 02bd5c487d1f..65cf84b222c5 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -429,21 +429,41 @@ static ide_startstop_t idescsi_do_request (ide_drive_t *drive, struct request *r
429} 429}
430 430
431#ifdef CONFIG_IDE_PROC_FS 431#ifdef CONFIG_IDE_PROC_FS
432static void idescsi_add_settings(ide_drive_t *drive) 432#define ide_scsi_devset_get(name, field) \
433{ 433static int get_##name(ide_drive_t *drive) \
434 idescsi_scsi_t *scsi = drive_to_idescsi(drive); 434{ \
435 435 idescsi_scsi_t *scsi = drive_to_idescsi(drive); \
436/* 436 return scsi->field; \
437 * drive setting name read/write data type min max mul_factor div_factor data pointer set function 437}
438 */ 438
439 ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 1023, 1, 1, &drive->bios_cyl, NULL); 439#define ide_scsi_devset_set(name, field) \
440 ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1, &drive->bios_head, NULL); 440static int set_##name(ide_drive_t *drive, int arg) \
441 ide_add_setting(drive, "bios_sect", SETTING_RW, TYPE_BYTE, 0, 63, 1, 1, &drive->bios_sect, NULL); 441{ \
442 ide_add_setting(drive, "transform", SETTING_RW, TYPE_INT, 0, 3, 1, 1, &scsi->transform, NULL); 442 idescsi_scsi_t *scsi = drive_to_idescsi(drive); \
443 ide_add_setting(drive, "log", SETTING_RW, TYPE_INT, 0, 1, 1, 1, &scsi->log, NULL); 443 scsi->field = arg; \
444} 444 return 0; \
445#else 445}
446static inline void idescsi_add_settings(ide_drive_t *drive) { ; } 446
447#define ide_scsi_devset_rw(_name, _min, _max, _field) \
448ide_scsi_devset_get(_name, _field); \
449ide_scsi_devset_set(_name, _field); \
450IDE_DEVSET(_name, S_RW, _min, _max, get_##_name, set_##_name)
451
452ide_devset_rw(bios_cyl, 0, 1023, bios_cyl);
453ide_devset_rw(bios_head, 0, 255, bios_head);
454ide_devset_rw(bios_sect, 0, 63, bios_sect);
455
456ide_scsi_devset_rw(transform, 0, 3, transform);
457ide_scsi_devset_rw(log, 0, 1, log);
458
459static const struct ide_devset *idescsi_settings[] = {
460 &ide_devset_bios_cyl,
461 &ide_devset_bios_head,
462 &ide_devset_bios_sect,
463 &ide_devset_log,
464 &ide_devset_transform,
465 NULL
466};
447#endif 467#endif
448 468
449/* 469/*
@@ -461,7 +481,6 @@ static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi)
461 drive->pc_callback = ide_scsi_callback; 481 drive->pc_callback = ide_scsi_callback;
462 482
463 ide_proc_register_driver(drive, scsi->driver); 483 ide_proc_register_driver(drive, scsi->driver);
464 idescsi_add_settings(drive);
465} 484}
466 485
467static void ide_scsi_remove(ide_drive_t *drive) 486static void ide_scsi_remove(ide_drive_t *drive)
@@ -509,6 +528,7 @@ static ide_driver_t idescsi_driver = {
509 .error = idescsi_atapi_error, 528 .error = idescsi_atapi_error,
510#ifdef CONFIG_IDE_PROC_FS 529#ifdef CONFIG_IDE_PROC_FS
511 .proc = idescsi_proc, 530 .proc = idescsi_proc,
531 .settings = idescsi_settings,
512#endif 532#endif
513}; 533};
514 534
diff --git a/include/linux/ide.h b/include/linux/ide.h
index ad09e7c81ae9..4667ec8aeebb 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -304,8 +304,8 @@ typedef enum {
304 ide_started, /* a drive operation was started, handler was set */ 304 ide_started, /* a drive operation was started, handler was set */
305} ide_startstop_t; 305} ide_startstop_t;
306 306
307struct ide_devset;
307struct ide_driver_s; 308struct ide_driver_s;
308struct ide_settings_s;
309 309
310#ifdef CONFIG_BLK_DEV_IDEACPI 310#ifdef CONFIG_BLK_DEV_IDEACPI
311struct ide_acpi_drive_link; 311struct ide_acpi_drive_link;
@@ -384,7 +384,7 @@ struct ide_drive_s {
384 u16 *id; /* identification info */ 384 u16 *id; /* identification info */
385#ifdef CONFIG_IDE_PROC_FS 385#ifdef CONFIG_IDE_PROC_FS
386 struct proc_dir_entry *proc; /* /proc/ide/ directory entry */ 386 struct proc_dir_entry *proc; /* /proc/ide/ directory entry */
387 struct ide_settings_s *settings;/* /proc/ide/ drive settings */ 387 const struct ide_devset **settings; /* /proc/ide/ drive settings */
388#endif 388#endif
389 struct hwif_s *hwif; /* actually (ide_hwif_t *) */ 389 struct hwif_s *hwif; /* actually (ide_hwif_t *) */
390 390
@@ -396,16 +396,16 @@ struct ide_drive_s {
396 special_t special; /* special action flags */ 396 special_t special; /* special action flags */
397 select_t select; /* basic drive/head select reg value */ 397 select_t select; /* basic drive/head select reg value */
398 398
399 u8 keep_settings; /* restore settings after drive reset */
400 u8 using_dma; /* disk is using dma for read/write */
401 u8 retry_pio; /* retrying dma capable host in pio */ 399 u8 retry_pio; /* retrying dma capable host in pio */
402 u8 state; /* retry state */ 400 u8 state; /* retry state */
403 u8 waiting_for_dma; /* dma currently in progress */ 401 u8 waiting_for_dma; /* dma currently in progress */
404 u8 unmask; /* okay to unmask other irqs */
405 u8 noflush; /* don't attempt flushes */
406 u8 dsc_overlap; /* DSC overlap */
407 u8 nice1; /* give potential excess bandwidth */
408 402
403 unsigned keep_settings : 1; /* restore settings after drive reset */
404 unsigned using_dma : 1; /* disk is using dma for read/write */
405 unsigned unmask : 1; /* okay to unmask other irqs */
406 unsigned noflush : 1; /* don't attempt flushes */
407 unsigned dsc_overlap : 1; /* DSC overlap */
408 unsigned nice1 : 1; /* give potential excess bandwidth */
409 unsigned present : 1; /* drive is physically present */ 409 unsigned present : 1; /* drive is physically present */
410 unsigned dead : 1; /* device ejected hint */ 410 unsigned dead : 1; /* device ejected hint */
411 unsigned id_read : 1; /* 1=id read from disk 0 = synthetic */ 411 unsigned id_read : 1; /* 1=id read from disk 0 = synthetic */
@@ -423,14 +423,15 @@ struct ide_drive_s {
423 unsigned sleeping : 1; /* 1=sleeping & sleep field valid */ 423 unsigned sleeping : 1; /* 1=sleeping & sleep field valid */
424 unsigned post_reset : 1; 424 unsigned post_reset : 1;
425 unsigned udma33_warned : 1; 425 unsigned udma33_warned : 1;
426 unsigned addressing : 2; /* 0=28-bit, 1=48-bit, 2=48-bit doing 28-bit */
427 unsigned wcache : 1; /* status of write cache */
428 unsigned nowerr : 1; /* used for ignoring ATA_DF */
426 429
427 u8 addressing; /* 0=28-bit, 1=48-bit, 2=48-bit doing 28-bit */
428 u8 quirk_list; /* considered quirky, set for a specific host */ 430 u8 quirk_list; /* considered quirky, set for a specific host */
429 u8 init_speed; /* transfer rate set at boot */ 431 u8 init_speed; /* transfer rate set at boot */
430 u8 current_speed; /* current transfer rate set */ 432 u8 current_speed; /* current transfer rate set */
431 u8 desired_speed; /* desired transfer rate set */ 433 u8 desired_speed; /* desired transfer rate set */
432 u8 dn; /* now wide spread use */ 434 u8 dn; /* now wide spread use */
433 u8 wcache; /* status of write cache */
434 u8 acoustic; /* acoustic management */ 435 u8 acoustic; /* acoustic management */
435 u8 media; /* disk, cdrom, tape, floppy, ... */ 436 u8 media; /* disk, cdrom, tape, floppy, ... */
436 u8 ready_stat; /* min status value for drive ready */ 437 u8 ready_stat; /* min status value for drive ready */
@@ -439,7 +440,6 @@ struct ide_drive_s {
439 u8 tune_req; /* requested drive tuning setting */ 440 u8 tune_req; /* requested drive tuning setting */
440 u8 io_32bit; /* 0=16-bit, 1=32-bit, 2/3=32bit+sync */ 441 u8 io_32bit; /* 0=16-bit, 1=32-bit, 2/3=32bit+sync */
441 u8 bad_wstat; /* used for ignoring ATA_DF */ 442 u8 bad_wstat; /* used for ignoring ATA_DF */
442 u8 nowerr; /* used for ignoring ATA_DF */
443 u8 head; /* "real" number of heads */ 443 u8 head; /* "real" number of heads */
444 u8 sect; /* "real" sectors per track */ 444 u8 sect; /* "real" sectors per track */
445 u8 bios_head; /* BIOS/fdisk/LILO number of heads */ 445 u8 bios_head; /* BIOS/fdisk/LILO number of heads */
@@ -687,12 +687,29 @@ typedef struct ide_driver_s ide_driver_t;
687 687
688extern struct mutex ide_setting_mtx; 688extern struct mutex ide_setting_mtx;
689 689
690int get_io_32bit(ide_drive_t *);
690int set_io_32bit(ide_drive_t *, int); 691int set_io_32bit(ide_drive_t *, int);
692int get_ksettings(ide_drive_t *);
691int set_ksettings(ide_drive_t *, int); 693int set_ksettings(ide_drive_t *, int);
692int set_pio_mode(ide_drive_t *, int); 694int set_pio_mode(ide_drive_t *, int);
695int get_unmaskirq(ide_drive_t *);
693int set_unmaskirq(ide_drive_t *, int); 696int set_unmaskirq(ide_drive_t *, int);
697int get_using_dma(ide_drive_t *);
694int set_using_dma(ide_drive_t *, int); 698int set_using_dma(ide_drive_t *, int);
695 699
700#define ide_devset_get(name, field) \
701int get_##name(ide_drive_t *drive) \
702{ \
703 return drive->field; \
704}
705
706#define ide_devset_set(name, field) \
707int set_##name(ide_drive_t *drive, int arg) \
708{ \
709 drive->field = arg; \
710 return 0; \
711}
712
696/* ATAPI packet command flags */ 713/* ATAPI packet command flags */
697enum { 714enum {
698 /* set when an error is considered normal - no retry (ide-tape) */ 715 /* set when an error is considered normal - no retry (ide-tape) */
@@ -757,30 +774,53 @@ struct ide_atapi_pc {
757 * configurable drive settings 774 * configurable drive settings
758 */ 775 */
759 776
760#define TYPE_INT 0 777#define S_READ (1 << 0)
761#define TYPE_BYTE 1 778#define S_WRITE (1 << 1)
762#define TYPE_SHORT 2 779#define S_RW (S_READ | S_WRITE)
780#define S_NOLOCK (1 << 2)
763 781
764#define SETTING_READ (1 << 0) 782struct ide_devset {
765#define SETTING_WRITE (1 << 1) 783 const char *name;
766#define SETTING_RW (SETTING_READ | SETTING_WRITE) 784 unsigned int flags;
785 int min, max;
786 int (*get)(ide_drive_t *);
787 int (*set)(ide_drive_t *, int);
788 int (*mulf)(ide_drive_t *);
789 int (*divf)(ide_drive_t *);
790};
767 791
768typedef int (ide_procset_t)(ide_drive_t *, int); 792#define __DEVSET(_name, _flags, _min, _max, _get, _set, _mulf, _divf) { \
769typedef struct ide_settings_s { 793 .name = __stringify(_name), \
770 char *name; 794 .flags = _flags, \
771 int rw; 795 .min = _min, \
772 int data_type; 796 .max = _max, \
773 int min; 797 .get = _get, \
774 int max; 798 .set = _set, \
775 int mul_factor; 799 .mulf = _mulf, \
776 int div_factor; 800 .divf = _divf, \
777 void *data; 801}
778 ide_procset_t *set; 802
779 int auto_remove; 803#define __IDE_DEVSET(_name, _flags, _min, _max, _get, _set, _mulf, _divf) \
780 struct ide_settings_s *next; 804static const struct ide_devset ide_devset_##_name = \
781} ide_settings_t; 805 __DEVSET(_name, _flags, _min, _max, _get, _set, _mulf, _divf)
782 806
783int ide_add_setting(ide_drive_t *, const char *, int, int, int, int, int, int, void *, ide_procset_t *set); 807#define IDE_DEVSET(_name, _flags, _min, _max, _get, _set) \
808__IDE_DEVSET(_name, _flags, _min, _max, _get, _set, NULL, NULL)
809
810#define ide_devset_rw_nolock(_name, _min, _max, _func) \
811IDE_DEVSET(_name, S_RW | S_NOLOCK, _min, _max, get_##_func, set_##_func)
812
813#define ide_devset_w_nolock(_name, _min, _max, _func) \
814IDE_DEVSET(_name, S_WRITE | S_NOLOCK, _min, _max, NULL, set_##_func)
815
816#define ide_devset_rw(_name, _min, _max, _field) \
817static ide_devset_get(_name, _field); \
818static ide_devset_set(_name, _field); \
819IDE_DEVSET(_name, S_RW, _min, _max, get_##_name, set_##_name)
820
821#define ide_devset_r(_name, _min, _max, _field) \
822ide_devset_get(_name, _field) \
823IDE_DEVSET(_name, S_READ, _min, _max, get_##_name, NULL)
784 824
785/* 825/*
786 * /proc/ide interface 826 * /proc/ide interface
@@ -801,8 +841,6 @@ void ide_proc_unregister_port(ide_hwif_t *);
801void ide_proc_register_driver(ide_drive_t *, ide_driver_t *); 841void ide_proc_register_driver(ide_drive_t *, ide_driver_t *);
802void ide_proc_unregister_driver(ide_drive_t *, ide_driver_t *); 842void ide_proc_unregister_driver(ide_drive_t *, ide_driver_t *);
803 843
804void ide_add_generic_settings(ide_drive_t *);
805
806read_proc_t proc_ide_read_capacity; 844read_proc_t proc_ide_read_capacity;
807read_proc_t proc_ide_read_geometry; 845read_proc_t proc_ide_read_geometry;
808 846
@@ -830,7 +868,6 @@ static inline void ide_proc_unregister_device(ide_drive_t *drive) { ; }
830static inline void ide_proc_unregister_port(ide_hwif_t *hwif) { ; } 868static inline void ide_proc_unregister_port(ide_hwif_t *hwif) { ; }
831static inline void ide_proc_register_driver(ide_drive_t *drive, ide_driver_t *driver) { ; } 869static inline void ide_proc_register_driver(ide_drive_t *drive, ide_driver_t *driver) { ; }
832static inline void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver) { ; } 870static inline void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver) { ; }
833static inline void ide_add_generic_settings(ide_drive_t *drive) { ; }
834#define PROC_IDE_READ_RETURN(page,start,off,count,eof,len) return 0; 871#define PROC_IDE_READ_RETURN(page,start,off,count,eof,len) return 0;
835#endif 872#endif
836 873
@@ -887,6 +924,7 @@ struct ide_driver_s {
887 void (*shutdown)(ide_drive_t *); 924 void (*shutdown)(ide_drive_t *);
888#ifdef CONFIG_IDE_PROC_FS 925#ifdef CONFIG_IDE_PROC_FS
889 ide_proc_entry_t *proc; 926 ide_proc_entry_t *proc;
927 const struct ide_devset **settings;
890#endif 928#endif
891}; 929};
892 930