diff options
author | Elias Oltmanns <eo@nebensachen.de> | 2008-10-10 16:39:40 -0400 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-10-10 16:39:40 -0400 |
commit | 92f1f8fd8040e7b50a67a850a935509bb01201bb (patch) | |
tree | df27468982bc64f0a6fdc54f05153e382ca63a1b | |
parent | d6e2955a6b82d2312b5ff885ce13c8ab54d59d96 (diff) |
ide: Remove ide_spin_wait_hwgroup() and use special requests instead
Use a special request for serialisation purposes and get rid of the
awkward ide_spin_wait_hwgroup(). This also involves converting the
ide_devset structure so it can be shared by the /proc and the ioctl code.
Signed-off-by: Elias Oltmanns <eo@nebensachen.de>
[bart: use rq->cmd[] directly]
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
-rw-r--r-- | drivers/ide/ide-cd.c | 8 | ||||
-rw-r--r-- | drivers/ide/ide-disk.c | 66 | ||||
-rw-r--r-- | drivers/ide/ide-floppy.c | 20 | ||||
-rw-r--r-- | drivers/ide/ide-io.c | 40 | ||||
-rw-r--r-- | drivers/ide/ide-ioctls.c | 21 | ||||
-rw-r--r-- | drivers/ide/ide-proc.c | 102 | ||||
-rw-r--r-- | drivers/ide/ide-tape.c | 48 | ||||
-rw-r--r-- | drivers/ide/ide.c | 81 | ||||
-rw-r--r-- | drivers/scsi/ide-scsi.c | 34 | ||||
-rw-r--r-- | include/linux/ide.h | 138 |
10 files changed, 274 insertions, 284 deletions
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 7ea90de55058..465a92ca0179 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c | |||
@@ -1809,11 +1809,11 @@ static ide_proc_entry_t idecd_proc[] = { | |||
1809 | { NULL, 0, NULL, NULL } | 1809 | { NULL, 0, NULL, NULL } |
1810 | }; | 1810 | }; |
1811 | 1811 | ||
1812 | ide_devset_rw(dsc_overlap, 0, 1, dsc_overlap); | 1812 | ide_devset_rw_field(dsc_overlap, dsc_overlap); |
1813 | 1813 | ||
1814 | static const struct ide_devset *idecd_settings[] = { | 1814 | static const struct ide_proc_devset idecd_settings[] = { |
1815 | &ide_devset_dsc_overlap, | 1815 | IDE_PROC_DEVSET(dsc_overlap, 0, 1), |
1816 | NULL | 1816 | { 0 }, |
1817 | }; | 1817 | }; |
1818 | #endif | 1818 | #endif |
1819 | 1819 | ||
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 119063470820..01846f244b40 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c | |||
@@ -575,11 +575,8 @@ static int set_nowerr(ide_drive_t *drive, int arg) | |||
575 | if (arg < 0 || arg > 1) | 575 | if (arg < 0 || arg > 1) |
576 | return -EINVAL; | 576 | return -EINVAL; |
577 | 577 | ||
578 | if (ide_spin_wait_hwgroup(drive)) | ||
579 | return -EBUSY; | ||
580 | drive->nowerr = arg; | 578 | drive->nowerr = arg; |
581 | drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT; | 579 | drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT; |
582 | spin_unlock_irq(&ide_lock); | ||
583 | return 0; | 580 | return 0; |
584 | } | 581 | } |
585 | 582 | ||
@@ -702,33 +699,34 @@ static int set_addressing(ide_drive_t *drive, int arg) | |||
702 | return 0; | 699 | return 0; |
703 | } | 700 | } |
704 | 701 | ||
702 | ide_devset_rw(acoustic, acoustic); | ||
703 | ide_devset_rw(address, addressing); | ||
704 | ide_devset_rw(multcount, multcount); | ||
705 | ide_devset_rw(wcache, wcache); | ||
706 | |||
707 | ide_devset_rw_sync(nowerr, nowerr); | ||
708 | |||
705 | #ifdef CONFIG_IDE_PROC_FS | 709 | #ifdef CONFIG_IDE_PROC_FS |
706 | ide_devset_rw_nolock(acoustic, 0, 254, acoustic); | 710 | ide_devset_rw_field(bios_cyl, bios_cyl); |
707 | ide_devset_rw_nolock(address, 0, 2, addressing); | 711 | ide_devset_rw_field(bios_head, bios_head); |
708 | ide_devset_rw_nolock(multcount, 0, 16, multcount); | 712 | ide_devset_rw_field(bios_sect, bios_sect); |
709 | ide_devset_rw_nolock(nowerr, 0, 1, nowerr); | 713 | ide_devset_rw_field(failures, failures); |
710 | ide_devset_rw_nolock(wcache, 0, 1, wcache); | 714 | ide_devset_rw_field(lun, lun); |
711 | 715 | ide_devset_rw_field(max_failures, max_failures); | |
712 | ide_devset_rw(bios_cyl, 0, 65535, bios_cyl); | 716 | |
713 | ide_devset_rw(bios_head, 0, 255, bios_head); | 717 | static const struct ide_proc_devset idedisk_settings[] = { |
714 | ide_devset_rw(bios_sect, 0, 63, bios_sect); | 718 | IDE_PROC_DEVSET(acoustic, 0, 254), |
715 | ide_devset_rw(failures, 0, 65535, failures); | 719 | IDE_PROC_DEVSET(address, 0, 2), |
716 | ide_devset_rw(lun, 0, 7, lun); | 720 | IDE_PROC_DEVSET(bios_cyl, 0, 65535), |
717 | ide_devset_rw(max_failures, 0, 65535, max_failures); | 721 | IDE_PROC_DEVSET(bios_head, 0, 255), |
718 | 722 | IDE_PROC_DEVSET(bios_sect, 0, 63), | |
719 | static const struct ide_devset *idedisk_settings[] = { | 723 | IDE_PROC_DEVSET(failures, 0, 65535), |
720 | &ide_devset_acoustic, | 724 | IDE_PROC_DEVSET(lun, 0, 7), |
721 | &ide_devset_address, | 725 | IDE_PROC_DEVSET(max_failures, 0, 65535), |
722 | &ide_devset_bios_cyl, | 726 | IDE_PROC_DEVSET(multcount, 0, 16), |
723 | &ide_devset_bios_head, | 727 | IDE_PROC_DEVSET(nowerr, 0, 1), |
724 | &ide_devset_bios_sect, | 728 | IDE_PROC_DEVSET(wcache, 0, 1), |
725 | &ide_devset_failures, | 729 | { 0 }, |
726 | &ide_devset_lun, | ||
727 | &ide_devset_max_failures, | ||
728 | &ide_devset_multcount, | ||
729 | &ide_devset_nowerr, | ||
730 | &ide_devset_wcache, | ||
731 | NULL | ||
732 | }; | 730 | }; |
733 | #endif | 731 | #endif |
734 | 732 | ||
@@ -1001,11 +999,11 @@ static int idedisk_getgeo(struct block_device *bdev, struct hd_geometry *geo) | |||
1001 | } | 999 | } |
1002 | 1000 | ||
1003 | static const struct ide_ioctl_devset ide_disk_ioctl_settings[] = { | 1001 | static const struct ide_ioctl_devset ide_disk_ioctl_settings[] = { |
1004 | { HDIO_GET_ADDRESS, HDIO_SET_ADDRESS, get_addressing, set_addressing }, | 1002 | { HDIO_GET_ADDRESS, HDIO_SET_ADDRESS, &ide_devset_address }, |
1005 | { HDIO_GET_MULTCOUNT, HDIO_SET_MULTCOUNT, get_multcount, set_multcount }, | 1003 | { HDIO_GET_MULTCOUNT, HDIO_SET_MULTCOUNT, &ide_devset_multcount }, |
1006 | { HDIO_GET_NOWERR, HDIO_SET_NOWERR, get_nowerr, set_nowerr }, | 1004 | { HDIO_GET_NOWERR, HDIO_SET_NOWERR, &ide_devset_nowerr }, |
1007 | { HDIO_GET_WCACHE, HDIO_SET_WCACHE, get_wcache, set_wcache }, | 1005 | { HDIO_GET_WCACHE, HDIO_SET_WCACHE, &ide_devset_wcache }, |
1008 | { HDIO_GET_ACOUSTIC, HDIO_SET_ACOUSTIC, get_acoustic, set_acoustic }, | 1006 | { HDIO_GET_ACOUSTIC, HDIO_SET_ACOUSTIC, &ide_devset_acoustic }, |
1009 | { 0 } | 1007 | { 0 } |
1010 | }; | 1008 | }; |
1011 | 1009 | ||
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index a63aba2c8265..d36f155470a4 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c | |||
@@ -629,9 +629,9 @@ static sector_t idefloppy_capacity(ide_drive_t *drive) | |||
629 | } | 629 | } |
630 | 630 | ||
631 | #ifdef CONFIG_IDE_PROC_FS | 631 | #ifdef CONFIG_IDE_PROC_FS |
632 | ide_devset_rw(bios_cyl, 0, 1023, bios_cyl); | 632 | ide_devset_rw_field(bios_cyl, bios_cyl); |
633 | ide_devset_rw(bios_head, 0, 255, bios_head); | 633 | ide_devset_rw_field(bios_head, bios_head); |
634 | ide_devset_rw(bios_sect, 0, 63, bios_sect); | 634 | ide_devset_rw_field(bios_sect, bios_sect); |
635 | 635 | ||
636 | static int get_ticks(ide_drive_t *drive) | 636 | static int get_ticks(ide_drive_t *drive) |
637 | { | 637 | { |
@@ -646,14 +646,14 @@ static int set_ticks(ide_drive_t *drive, int arg) | |||
646 | return 0; | 646 | return 0; |
647 | } | 647 | } |
648 | 648 | ||
649 | IDE_DEVSET(ticks, S_RW, 0, 255, get_ticks, set_ticks); | 649 | IDE_DEVSET(ticks, DS_SYNC, get_ticks, set_ticks); |
650 | 650 | ||
651 | static const struct ide_devset *idefloppy_settings[] = { | 651 | static const struct ide_proc_devset idefloppy_settings[] = { |
652 | &ide_devset_bios_cyl, | 652 | IDE_PROC_DEVSET(bios_cyl, 0, 1023), |
653 | &ide_devset_bios_head, | 653 | IDE_PROC_DEVSET(bios_head, 0, 255), |
654 | &ide_devset_bios_sect, | 654 | IDE_PROC_DEVSET(bios_sect, 0, 63), |
655 | &ide_devset_ticks, | 655 | IDE_PROC_DEVSET(ticks, 0, 255), |
656 | NULL | 656 | { 0 }, |
657 | }; | 657 | }; |
658 | #endif | 658 | #endif |
659 | 659 | ||
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index ec6664b0d3a9..1c51949833be 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c | |||
@@ -716,9 +716,49 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive, | |||
716 | return ide_stopped; | 716 | return ide_stopped; |
717 | } | 717 | } |
718 | 718 | ||
719 | int ide_devset_execute(ide_drive_t *drive, const struct ide_devset *setting, | ||
720 | int arg) | ||
721 | { | ||
722 | struct request_queue *q = drive->queue; | ||
723 | struct request *rq; | ||
724 | int ret = 0; | ||
725 | |||
726 | if (!(setting->flags & DS_SYNC)) | ||
727 | return setting->set(drive, arg); | ||
728 | |||
729 | rq = blk_get_request(q, READ, GFP_KERNEL); | ||
730 | if (!rq) | ||
731 | return -ENOMEM; | ||
732 | |||
733 | rq->cmd_type = REQ_TYPE_SPECIAL; | ||
734 | rq->cmd_len = 5; | ||
735 | rq->cmd[0] = REQ_DEVSET_EXEC; | ||
736 | *(int *)&rq->cmd[1] = arg; | ||
737 | rq->special = setting->set; | ||
738 | |||
739 | if (blk_execute_rq(q, NULL, rq, 0)) | ||
740 | ret = rq->errors; | ||
741 | blk_put_request(rq); | ||
742 | |||
743 | return ret; | ||
744 | } | ||
745 | EXPORT_SYMBOL_GPL(ide_devset_execute); | ||
746 | |||
719 | static ide_startstop_t ide_special_rq(ide_drive_t *drive, struct request *rq) | 747 | static ide_startstop_t ide_special_rq(ide_drive_t *drive, struct request *rq) |
720 | { | 748 | { |
721 | switch (rq->cmd[0]) { | 749 | switch (rq->cmd[0]) { |
750 | case REQ_DEVSET_EXEC: | ||
751 | { | ||
752 | int err, (*setfunc)(ide_drive_t *, int) = rq->special; | ||
753 | |||
754 | err = setfunc(drive, *(int *)&rq->cmd[1]); | ||
755 | if (err) | ||
756 | rq->errors = err; | ||
757 | else | ||
758 | err = 1; | ||
759 | ide_end_request(drive, err, 0); | ||
760 | return ide_stopped; | ||
761 | } | ||
722 | case REQ_DRIVE_RESET: | 762 | case REQ_DRIVE_RESET: |
723 | return ide_do_reset(drive); | 763 | return ide_do_reset(drive); |
724 | default: | 764 | default: |
diff --git a/drivers/ide/ide-ioctls.c b/drivers/ide/ide-ioctls.c index 7a0d62e7286b..cf01564901af 100644 --- a/drivers/ide/ide-ioctls.c +++ b/drivers/ide/ide-ioctls.c | |||
@@ -6,11 +6,11 @@ | |||
6 | #include <linux/ide.h> | 6 | #include <linux/ide.h> |
7 | 7 | ||
8 | static const struct ide_ioctl_devset ide_ioctl_settings[] = { | 8 | static const struct ide_ioctl_devset ide_ioctl_settings[] = { |
9 | { HDIO_GET_32BIT, HDIO_SET_32BIT, get_io_32bit, set_io_32bit }, | 9 | { HDIO_GET_32BIT, HDIO_SET_32BIT, &ide_devset_io_32bit }, |
10 | { HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS, get_ksettings, set_ksettings }, | 10 | { HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS, &ide_devset_keepsettings }, |
11 | { HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, get_unmaskirq, set_unmaskirq }, | 11 | { HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, &ide_devset_unmaskirq }, |
12 | { HDIO_GET_DMA, HDIO_SET_DMA, get_using_dma, set_using_dma }, | 12 | { HDIO_GET_DMA, HDIO_SET_DMA, &ide_devset_using_dma }, |
13 | { -1, HDIO_SET_PIO_MODE, NULL, set_pio_mode }, | 13 | { -1, HDIO_SET_PIO_MODE, &ide_devset_pio_mode }, |
14 | { 0 } | 14 | { 0 } |
15 | }; | 15 | }; |
16 | 16 | ||
@@ -18,13 +18,14 @@ int ide_setting_ioctl(ide_drive_t *drive, struct block_device *bdev, | |||
18 | unsigned int cmd, unsigned long arg, | 18 | unsigned int cmd, unsigned long arg, |
19 | const struct ide_ioctl_devset *s) | 19 | const struct ide_ioctl_devset *s) |
20 | { | 20 | { |
21 | const struct ide_devset *ds; | ||
21 | unsigned long flags; | 22 | unsigned long flags; |
22 | int err = -EOPNOTSUPP; | 23 | int err = -EOPNOTSUPP; |
23 | 24 | ||
24 | for (; s->get_ioctl; s++) { | 25 | for (; (ds = s->setting); s++) { |
25 | if (s->get && s->get_ioctl == cmd) | 26 | if (ds->get && s->get_ioctl == cmd) |
26 | goto read_val; | 27 | goto read_val; |
27 | else if (s->set && s->set_ioctl == cmd) | 28 | else if (ds->set && s->set_ioctl == cmd) |
28 | goto set_val; | 29 | goto set_val; |
29 | } | 30 | } |
30 | 31 | ||
@@ -33,7 +34,7 @@ int ide_setting_ioctl(ide_drive_t *drive, struct block_device *bdev, | |||
33 | read_val: | 34 | read_val: |
34 | mutex_lock(&ide_setting_mtx); | 35 | mutex_lock(&ide_setting_mtx); |
35 | spin_lock_irqsave(&ide_lock, flags); | 36 | spin_lock_irqsave(&ide_lock, flags); |
36 | err = s->get(drive); | 37 | err = ds->get(drive); |
37 | spin_unlock_irqrestore(&ide_lock, flags); | 38 | spin_unlock_irqrestore(&ide_lock, flags); |
38 | mutex_unlock(&ide_setting_mtx); | 39 | mutex_unlock(&ide_setting_mtx); |
39 | return err >= 0 ? put_user(err, (long __user *)arg) : err; | 40 | return err >= 0 ? put_user(err, (long __user *)arg) : err; |
@@ -46,7 +47,7 @@ set_val: | |||
46 | err = -EACCES; | 47 | err = -EACCES; |
47 | else { | 48 | else { |
48 | mutex_lock(&ide_setting_mtx); | 49 | mutex_lock(&ide_setting_mtx); |
49 | err = s->set(drive, arg); | 50 | err = ide_devset_execute(drive, ds, arg); |
50 | mutex_unlock(&ide_setting_mtx); | 51 | mutex_unlock(&ide_setting_mtx); |
51 | } | 52 | } |
52 | } | 53 | } |
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index 6489c647be82..e7030a491463 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c | |||
@@ -124,15 +124,16 @@ static int proc_ide_read_identify | |||
124 | * setting semaphore | 124 | * setting semaphore |
125 | */ | 125 | */ |
126 | 126 | ||
127 | static const struct ide_devset *ide_find_setting(const struct ide_devset **st, | 127 | static |
128 | char *name) | 128 | const struct ide_proc_devset *ide_find_setting(const struct ide_proc_devset *st, |
129 | char *name) | ||
129 | { | 130 | { |
130 | while (*st) { | 131 | while (st->name) { |
131 | if (strcmp((*st)->name, name) == 0) | 132 | if (strcmp(st->name, name) == 0) |
132 | break; | 133 | break; |
133 | st++; | 134 | st++; |
134 | } | 135 | } |
135 | return *st; | 136 | return st->name ? st : NULL; |
136 | } | 137 | } |
137 | 138 | ||
138 | /** | 139 | /** |
@@ -149,15 +150,16 @@ static const struct ide_devset *ide_find_setting(const struct ide_devset **st, | |||
149 | */ | 150 | */ |
150 | 151 | ||
151 | static int ide_read_setting(ide_drive_t *drive, | 152 | static int ide_read_setting(ide_drive_t *drive, |
152 | const struct ide_devset *setting) | 153 | const struct ide_proc_devset *setting) |
153 | { | 154 | { |
155 | const struct ide_devset *ds = setting->setting; | ||
154 | int val = -EINVAL; | 156 | int val = -EINVAL; |
155 | 157 | ||
156 | if ((setting->flags & S_READ)) { | 158 | if (ds->get) { |
157 | unsigned long flags; | 159 | unsigned long flags; |
158 | 160 | ||
159 | spin_lock_irqsave(&ide_lock, flags); | 161 | spin_lock_irqsave(&ide_lock, flags); |
160 | val = setting->get(drive); | 162 | val = ds->get(drive); |
161 | spin_unlock_irqrestore(&ide_lock, flags); | 163 | spin_unlock_irqrestore(&ide_lock, flags); |
162 | } | 164 | } |
163 | 165 | ||
@@ -183,24 +185,21 @@ static int ide_read_setting(ide_drive_t *drive, | |||
183 | */ | 185 | */ |
184 | 186 | ||
185 | static int ide_write_setting(ide_drive_t *drive, | 187 | static int ide_write_setting(ide_drive_t *drive, |
186 | const struct ide_devset *setting, int val) | 188 | const struct ide_proc_devset *setting, int val) |
187 | { | 189 | { |
190 | const struct ide_devset *ds = setting->setting; | ||
191 | |||
188 | if (!capable(CAP_SYS_ADMIN)) | 192 | if (!capable(CAP_SYS_ADMIN)) |
189 | return -EACCES; | 193 | return -EACCES; |
190 | if (setting->set && (setting->flags & S_NOLOCK)) | 194 | if (!ds->set) |
191 | return setting->set(drive, val); | ||
192 | if (!(setting->flags & S_WRITE)) | ||
193 | return -EPERM; | 195 | return -EPERM; |
194 | if (val < setting->min || val > setting->max) | 196 | if ((ds->flags & DS_SYNC) |
197 | && (val < setting->min || val > setting->max)) | ||
195 | return -EINVAL; | 198 | return -EINVAL; |
196 | if (ide_spin_wait_hwgroup(drive)) | 199 | return ide_devset_execute(drive, ds, val); |
197 | return -EBUSY; | ||
198 | setting->set(drive, val); | ||
199 | spin_unlock_irq(&ide_lock); | ||
200 | return 0; | ||
201 | } | 200 | } |
202 | 201 | ||
203 | static ide_devset_get(xfer_rate, current_speed); | 202 | ide_devset_get(xfer_rate, current_speed); |
204 | 203 | ||
205 | static int set_xfer_rate (ide_drive_t *drive, int arg) | 204 | static int set_xfer_rate (ide_drive_t *drive, int arg) |
206 | { | 205 | { |
@@ -226,29 +225,22 @@ static int set_xfer_rate (ide_drive_t *drive, int arg) | |||
226 | return err; | 225 | return err; |
227 | } | 226 | } |
228 | 227 | ||
229 | ide_devset_rw_nolock(current_speed, 0, 70, xfer_rate); | 228 | ide_devset_rw(current_speed, xfer_rate); |
230 | ide_devset_rw_nolock(io_32bit, 0, 1 + (SUPPORT_VLB_SYNC << 1), io_32bit); | 229 | ide_devset_rw_field(init_speed, init_speed); |
231 | ide_devset_rw_nolock(keepsettings, 0, 1, ksettings); | 230 | ide_devset_rw_field(nice1, nice1); |
232 | ide_devset_rw_nolock(unmaskirq, 0, 1, unmaskirq); | 231 | ide_devset_rw_field(number, dn); |
233 | ide_devset_rw_nolock(using_dma, 0, 1, using_dma); | 232 | |
234 | 233 | static const struct ide_proc_devset ide_generic_settings[] = { | |
235 | ide_devset_w_nolock(pio_mode, 0, 255, pio_mode); | 234 | IDE_PROC_DEVSET(current_speed, 0, 70), |
236 | 235 | IDE_PROC_DEVSET(init_speed, 0, 70), | |
237 | ide_devset_rw(init_speed, 0, 70, init_speed); | 236 | IDE_PROC_DEVSET(io_32bit, 0, 1 + (SUPPORT_VLB_SYNC << 1)), |
238 | ide_devset_rw(nice1, 0, 1, nice1); | 237 | IDE_PROC_DEVSET(keepsettings, 0, 1), |
239 | ide_devset_rw(number, 0, 3, dn); | 238 | IDE_PROC_DEVSET(nice1, 0, 1), |
240 | 239 | IDE_PROC_DEVSET(number, 0, 3), | |
241 | static const struct ide_devset *ide_generic_settings[] = { | 240 | IDE_PROC_DEVSET(pio_mode, 0, 255), |
242 | &ide_devset_current_speed, | 241 | IDE_PROC_DEVSET(unmaskirq, 0, 1), |
243 | &ide_devset_init_speed, | 242 | IDE_PROC_DEVSET(using_dma, 0, 1), |
244 | &ide_devset_io_32bit, | 243 | { 0 }, |
245 | &ide_devset_keepsettings, | ||
246 | &ide_devset_nice1, | ||
247 | &ide_devset_number, | ||
248 | &ide_devset_pio_mode, | ||
249 | &ide_devset_unmaskirq, | ||
250 | &ide_devset_using_dma, | ||
251 | NULL | ||
252 | }; | 244 | }; |
253 | 245 | ||
254 | static void proc_ide_settings_warn(void) | 246 | static void proc_ide_settings_warn(void) |
@@ -266,7 +258,8 @@ static void proc_ide_settings_warn(void) | |||
266 | static int proc_ide_read_settings | 258 | static int proc_ide_read_settings |
267 | (char *page, char **start, off_t off, int count, int *eof, void *data) | 259 | (char *page, char **start, off_t off, int count, int *eof, void *data) |
268 | { | 260 | { |
269 | const struct ide_devset *setting, **g, **d; | 261 | const struct ide_proc_devset *setting, *g, *d; |
262 | const struct ide_devset *ds; | ||
270 | ide_drive_t *drive = (ide_drive_t *) data; | 263 | ide_drive_t *drive = (ide_drive_t *) data; |
271 | char *out = page; | 264 | char *out = page; |
272 | int len, rc, mul_factor, div_factor; | 265 | int len, rc, mul_factor, div_factor; |
@@ -278,17 +271,17 @@ static int proc_ide_read_settings | |||
278 | d = drive->settings; | 271 | d = drive->settings; |
279 | out += sprintf(out, "name\t\t\tvalue\t\tmin\t\tmax\t\tmode\n"); | 272 | out += sprintf(out, "name\t\t\tvalue\t\tmin\t\tmax\t\tmode\n"); |
280 | out += sprintf(out, "----\t\t\t-----\t\t---\t\t---\t\t----\n"); | 273 | out += sprintf(out, "----\t\t\t-----\t\t---\t\t---\t\t----\n"); |
281 | while (*g || (d && *d)) { | 274 | while (g->name || (d && d->name)) { |
282 | /* read settings in the alphabetical order */ | 275 | /* read settings in the alphabetical order */ |
283 | if (*g && d && *d) { | 276 | if (g->name && d && d->name) { |
284 | if (strcmp((*d)->name, (*g)->name) < 0) | 277 | if (strcmp(d->name, g->name) < 0) |
285 | setting = *d++; | 278 | setting = d++; |
286 | else | 279 | else |
287 | setting = *g++; | 280 | setting = g++; |
288 | } else if (d && *d) { | 281 | } else if (d && d->name) { |
289 | setting = *d++; | 282 | setting = d++; |
290 | } else | 283 | } else |
291 | setting = *g++; | 284 | setting = g++; |
292 | mul_factor = setting->mulf ? setting->mulf(drive) : 1; | 285 | mul_factor = setting->mulf ? setting->mulf(drive) : 1; |
293 | div_factor = setting->divf ? setting->divf(drive) : 1; | 286 | div_factor = setting->divf ? setting->divf(drive) : 1; |
294 | out += sprintf(out, "%-24s", setting->name); | 287 | out += sprintf(out, "%-24s", setting->name); |
@@ -298,9 +291,10 @@ static int proc_ide_read_settings | |||
298 | else | 291 | else |
299 | out += sprintf(out, "%-16s", "write-only"); | 292 | out += sprintf(out, "%-16s", "write-only"); |
300 | out += sprintf(out, "%-16d%-16d", (setting->min * mul_factor + div_factor - 1) / div_factor, setting->max * mul_factor / div_factor); | 293 | out += sprintf(out, "%-16d%-16d", (setting->min * mul_factor + div_factor - 1) / div_factor, setting->max * mul_factor / div_factor); |
301 | if (setting->flags & S_READ) | 294 | ds = setting->setting; |
295 | if (ds->get) | ||
302 | out += sprintf(out, "r"); | 296 | out += sprintf(out, "r"); |
303 | if (setting->flags & S_WRITE) | 297 | if (ds->set) |
304 | out += sprintf(out, "w"); | 298 | out += sprintf(out, "w"); |
305 | out += sprintf(out, "\n"); | 299 | out += sprintf(out, "\n"); |
306 | } | 300 | } |
@@ -319,7 +313,7 @@ static int proc_ide_write_settings(struct file *file, const char __user *buffer, | |||
319 | int for_real = 0, mul_factor, div_factor; | 313 | int for_real = 0, mul_factor, div_factor; |
320 | unsigned long n; | 314 | unsigned long n; |
321 | 315 | ||
322 | const struct ide_devset *setting; | 316 | const struct ide_proc_devset *setting; |
323 | char *buf, *s; | 317 | char *buf, *s; |
324 | 318 | ||
325 | if (!capable(CAP_SYS_ADMIN)) | 319 | if (!capable(CAP_SYS_ADMIN)) |
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 25190966ed39..f8c84df4a0bc 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c | |||
@@ -2188,40 +2188,40 @@ static int set_##name(ide_drive_t *drive, int arg) \ | |||
2188 | return 0; \ | 2188 | return 0; \ |
2189 | } | 2189 | } |
2190 | 2190 | ||
2191 | #define ide_tape_devset_rw(_name, _min, _max, _field, _mulf, _divf) \ | 2191 | #define ide_tape_devset_rw_field(_name, _field) \ |
2192 | ide_tape_devset_get(_name, _field) \ | 2192 | ide_tape_devset_get(_name, _field) \ |
2193 | ide_tape_devset_set(_name, _field) \ | 2193 | ide_tape_devset_set(_name, _field) \ |
2194 | __IDE_DEVSET(_name, S_RW, _min, _max, get_##_name, set_##_name, _mulf, _divf) | 2194 | IDE_DEVSET(_name, DS_SYNC, get_##_name, set_##_name) |
2195 | 2195 | ||
2196 | #define ide_tape_devset_r(_name, _min, _max, _field, _mulf, _divf) \ | 2196 | #define ide_tape_devset_r_field(_name, _field) \ |
2197 | ide_tape_devset_get(_name, _field) \ | 2197 | ide_tape_devset_get(_name, _field) \ |
2198 | __IDE_DEVSET(_name, S_READ, _min, _max, get_##_name, NULL, _mulf, _divf) | 2198 | IDE_DEVSET(_name, 0, get_##_name, NULL) |
2199 | 2199 | ||
2200 | static int mulf_tdsc(ide_drive_t *drive) { return 1000; } | 2200 | static int mulf_tdsc(ide_drive_t *drive) { return 1000; } |
2201 | static int divf_tdsc(ide_drive_t *drive) { return HZ; } | 2201 | static int divf_tdsc(ide_drive_t *drive) { return HZ; } |
2202 | static int divf_buffer(ide_drive_t *drive) { return 2; } | 2202 | static int divf_buffer(ide_drive_t *drive) { return 2; } |
2203 | static int divf_buffer_size(ide_drive_t *drive) { return 1024; } | 2203 | static int divf_buffer_size(ide_drive_t *drive) { return 1024; } |
2204 | 2204 | ||
2205 | ide_devset_rw(dsc_overlap, 0, 1, dsc_overlap); | 2205 | ide_devset_rw_field(dsc_overlap, dsc_overlap); |
2206 | 2206 | ||
2207 | ide_tape_devset_rw(debug_mask, 0, 0xffff, debug_mask, NULL, NULL); | 2207 | ide_tape_devset_rw_field(debug_mask, debug_mask); |
2208 | ide_tape_devset_rw(tdsc, IDETAPE_DSC_RW_MIN, IDETAPE_DSC_RW_MAX, | 2208 | ide_tape_devset_rw_field(tdsc, best_dsc_rw_freq); |
2209 | best_dsc_rw_freq, mulf_tdsc, divf_tdsc); | 2209 | |
2210 | 2210 | ide_tape_devset_r_field(avg_speed, avg_speed); | |
2211 | ide_tape_devset_r(avg_speed, 0, 0xffff, avg_speed, NULL, NULL); | 2211 | ide_tape_devset_r_field(speed, caps[14]); |
2212 | ide_tape_devset_r(speed, 0, 0xffff, caps[14], NULL, NULL); | 2212 | ide_tape_devset_r_field(buffer, caps[16]); |
2213 | ide_tape_devset_r(buffer, 0, 0xffff, caps[16], NULL, divf_buffer); | 2213 | ide_tape_devset_r_field(buffer_size, buffer_size); |
2214 | ide_tape_devset_r(buffer_size, 0, 0xffff, buffer_size, NULL, divf_buffer_size); | 2214 | |
2215 | 2215 | static const struct ide_proc_devset idetape_settings[] = { | |
2216 | static const struct ide_devset *idetape_settings[] = { | 2216 | __IDE_PROC_DEVSET(avg_speed, 0, 0xffff, NULL, NULL), |
2217 | &ide_devset_avg_speed, | 2217 | __IDE_PROC_DEVSET(buffer, 0, 0xffff, NULL, divf_buffer), |
2218 | &ide_devset_buffer, | 2218 | __IDE_PROC_DEVSET(buffer_size, 0, 0xffff, NULL, divf_buffer_size), |
2219 | &ide_devset_buffer_size, | 2219 | __IDE_PROC_DEVSET(debug_mask, 0, 0xffff, NULL, NULL), |
2220 | &ide_devset_debug_mask, | 2220 | __IDE_PROC_DEVSET(dsc_overlap, 0, 1, NULL, NULL), |
2221 | &ide_devset_dsc_overlap, | 2221 | __IDE_PROC_DEVSET(speed, 0, 0xffff, NULL, NULL), |
2222 | &ide_devset_speed, | 2222 | __IDE_PROC_DEVSET(tdsc, IDETAPE_DSC_RW_MIN, IDETAPE_DSC_RW_MAX, |
2223 | &ide_devset_tdsc, | 2223 | mulf_tdsc, divf_tdsc), |
2224 | NULL | 2224 | { 0 }, |
2225 | }; | 2225 | }; |
2226 | #endif | 2226 | #endif |
2227 | 2227 | ||
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 349d7fa75585..9dcf5aed92cb 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c | |||
@@ -250,42 +250,9 @@ void ide_init_port_hw(ide_hwif_t *hwif, hw_regs_t *hw) | |||
250 | 250 | ||
251 | DEFINE_MUTEX(ide_setting_mtx); | 251 | DEFINE_MUTEX(ide_setting_mtx); |
252 | 252 | ||
253 | /** | ||
254 | * ide_spin_wait_hwgroup - wait for group | ||
255 | * @drive: drive in the group | ||
256 | * | ||
257 | * Wait for an IDE device group to go non busy and then return | ||
258 | * holding the ide_lock which guards the hwgroup->busy status | ||
259 | * and right to use it. | ||
260 | */ | ||
261 | |||
262 | int ide_spin_wait_hwgroup (ide_drive_t *drive) | ||
263 | { | ||
264 | ide_hwgroup_t *hwgroup = HWGROUP(drive); | ||
265 | unsigned long timeout = jiffies + (3 * HZ); | ||
266 | |||
267 | spin_lock_irq(&ide_lock); | ||
268 | |||
269 | while (hwgroup->busy) { | ||
270 | unsigned long lflags; | ||
271 | spin_unlock_irq(&ide_lock); | ||
272 | local_irq_set(lflags); | ||
273 | if (time_after(jiffies, timeout)) { | ||
274 | local_irq_restore(lflags); | ||
275 | printk(KERN_ERR "%s: channel busy\n", drive->name); | ||
276 | return -EBUSY; | ||
277 | } | ||
278 | local_irq_restore(lflags); | ||
279 | spin_lock_irq(&ide_lock); | ||
280 | } | ||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | EXPORT_SYMBOL(ide_spin_wait_hwgroup); | ||
285 | |||
286 | ide_devset_get(io_32bit, io_32bit); | 253 | ide_devset_get(io_32bit, io_32bit); |
287 | 254 | ||
288 | int set_io_32bit(ide_drive_t *drive, int arg) | 255 | static int set_io_32bit(ide_drive_t *drive, int arg) |
289 | { | 256 | { |
290 | if (drive->no_io_32bit) | 257 | if (drive->no_io_32bit) |
291 | return -EPERM; | 258 | return -EPERM; |
@@ -293,37 +260,28 @@ int set_io_32bit(ide_drive_t *drive, int arg) | |||
293 | if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1)) | 260 | if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1)) |
294 | return -EINVAL; | 261 | return -EINVAL; |
295 | 262 | ||
296 | if (ide_spin_wait_hwgroup(drive)) | ||
297 | return -EBUSY; | ||
298 | |||
299 | drive->io_32bit = arg; | 263 | drive->io_32bit = arg; |
300 | 264 | ||
301 | spin_unlock_irq(&ide_lock); | ||
302 | |||
303 | return 0; | 265 | return 0; |
304 | } | 266 | } |
305 | 267 | ||
306 | ide_devset_get(ksettings, keep_settings); | 268 | ide_devset_get(ksettings, keep_settings); |
307 | 269 | ||
308 | int set_ksettings(ide_drive_t *drive, int arg) | 270 | static int set_ksettings(ide_drive_t *drive, int arg) |
309 | { | 271 | { |
310 | if (arg < 0 || arg > 1) | 272 | if (arg < 0 || arg > 1) |
311 | return -EINVAL; | 273 | return -EINVAL; |
312 | 274 | ||
313 | if (ide_spin_wait_hwgroup(drive)) | ||
314 | return -EBUSY; | ||
315 | drive->keep_settings = arg; | 275 | drive->keep_settings = arg; |
316 | spin_unlock_irq(&ide_lock); | ||
317 | 276 | ||
318 | return 0; | 277 | return 0; |
319 | } | 278 | } |
320 | 279 | ||
321 | ide_devset_get(using_dma, using_dma); | 280 | ide_devset_get(using_dma, using_dma); |
322 | 281 | ||
323 | int set_using_dma(ide_drive_t *drive, int arg) | 282 | static int set_using_dma(ide_drive_t *drive, int arg) |
324 | { | 283 | { |
325 | #ifdef CONFIG_BLK_DEV_IDEDMA | 284 | #ifdef CONFIG_BLK_DEV_IDEDMA |
326 | ide_hwif_t *hwif = drive->hwif; | ||
327 | int err = -EPERM; | 285 | int err = -EPERM; |
328 | 286 | ||
329 | if (arg < 0 || arg > 1) | 287 | if (arg < 0 || arg > 1) |
@@ -332,18 +290,9 @@ int set_using_dma(ide_drive_t *drive, int arg) | |||
332 | if (ata_id_has_dma(drive->id) == 0) | 290 | if (ata_id_has_dma(drive->id) == 0) |
333 | goto out; | 291 | goto out; |
334 | 292 | ||
335 | if (hwif->dma_ops == NULL) | 293 | if (drive->hwif->dma_ops == NULL) |
336 | goto out; | 294 | goto out; |
337 | 295 | ||
338 | err = -EBUSY; | ||
339 | if (ide_spin_wait_hwgroup(drive)) | ||
340 | goto out; | ||
341 | /* | ||
342 | * set ->busy flag, unlock and let it ride | ||
343 | */ | ||
344 | hwif->hwgroup->busy = 1; | ||
345 | spin_unlock_irq(&ide_lock); | ||
346 | |||
347 | err = 0; | 296 | err = 0; |
348 | 297 | ||
349 | if (arg) { | 298 | if (arg) { |
@@ -352,12 +301,6 @@ int set_using_dma(ide_drive_t *drive, int arg) | |||
352 | } else | 301 | } else |
353 | ide_dma_off(drive); | 302 | ide_dma_off(drive); |
354 | 303 | ||
355 | /* | ||
356 | * lock, clear ->busy flag and unlock before leaving | ||
357 | */ | ||
358 | spin_lock_irq(&ide_lock); | ||
359 | hwif->hwgroup->busy = 0; | ||
360 | spin_unlock_irq(&ide_lock); | ||
361 | out: | 304 | out: |
362 | return err; | 305 | return err; |
363 | #else | 306 | #else |
@@ -368,7 +311,7 @@ out: | |||
368 | #endif | 311 | #endif |
369 | } | 312 | } |
370 | 313 | ||
371 | int set_pio_mode(ide_drive_t *drive, int arg) | 314 | static int set_pio_mode(ide_drive_t *drive, int arg) |
372 | { | 315 | { |
373 | struct request *rq; | 316 | struct request *rq; |
374 | ide_hwif_t *hwif = drive->hwif; | 317 | ide_hwif_t *hwif = drive->hwif; |
@@ -398,7 +341,7 @@ int set_pio_mode(ide_drive_t *drive, int arg) | |||
398 | 341 | ||
399 | ide_devset_get(unmaskirq, unmask); | 342 | ide_devset_get(unmaskirq, unmask); |
400 | 343 | ||
401 | int set_unmaskirq(ide_drive_t *drive, int arg) | 344 | static int set_unmaskirq(ide_drive_t *drive, int arg) |
402 | { | 345 | { |
403 | if (drive->no_unmask) | 346 | if (drive->no_unmask) |
404 | return -EPERM; | 347 | return -EPERM; |
@@ -406,14 +349,20 @@ int set_unmaskirq(ide_drive_t *drive, int arg) | |||
406 | if (arg < 0 || arg > 1) | 349 | if (arg < 0 || arg > 1) |
407 | return -EINVAL; | 350 | return -EINVAL; |
408 | 351 | ||
409 | if (ide_spin_wait_hwgroup(drive)) | ||
410 | return -EBUSY; | ||
411 | drive->unmask = arg; | 352 | drive->unmask = arg; |
412 | spin_unlock_irq(&ide_lock); | ||
413 | 353 | ||
414 | return 0; | 354 | return 0; |
415 | } | 355 | } |
416 | 356 | ||
357 | #define ide_gen_devset_rw(_name, _func) \ | ||
358 | __IDE_DEVSET(_name, DS_SYNC, get_##_func, set_##_func) | ||
359 | |||
360 | ide_gen_devset_rw(io_32bit, io_32bit); | ||
361 | ide_gen_devset_rw(keepsettings, ksettings); | ||
362 | ide_gen_devset_rw(unmaskirq, unmaskirq); | ||
363 | ide_gen_devset_rw(using_dma, using_dma); | ||
364 | __IDE_DEVSET(pio_mode, 0, NULL, set_pio_mode); | ||
365 | |||
417 | static int generic_ide_suspend(struct device *dev, pm_message_t mesg) | 366 | static int generic_ide_suspend(struct device *dev, pm_message_t mesg) |
418 | { | 367 | { |
419 | ide_drive_t *drive = dev->driver_data; | 368 | ide_drive_t *drive = dev->driver_data; |
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 27c01e368977..90212ac33be3 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c | |||
@@ -400,25 +400,25 @@ static int set_##name(ide_drive_t *drive, int arg) \ | |||
400 | return 0; \ | 400 | return 0; \ |
401 | } | 401 | } |
402 | 402 | ||
403 | #define ide_scsi_devset_rw(_name, _min, _max, _field) \ | 403 | #define ide_scsi_devset_rw_field(_name, _field) \ |
404 | ide_scsi_devset_get(_name, _field); \ | 404 | ide_scsi_devset_get(_name, _field); \ |
405 | ide_scsi_devset_set(_name, _field); \ | 405 | ide_scsi_devset_set(_name, _field); \ |
406 | IDE_DEVSET(_name, S_RW, _min, _max, get_##_name, set_##_name) | 406 | IDE_DEVSET(_name, DS_SYNC, get_##_name, set_##_name); |
407 | 407 | ||
408 | ide_devset_rw(bios_cyl, 0, 1023, bios_cyl); | 408 | ide_devset_rw_field(bios_cyl, bios_cyl); |
409 | ide_devset_rw(bios_head, 0, 255, bios_head); | 409 | ide_devset_rw_field(bios_head, bios_head); |
410 | ide_devset_rw(bios_sect, 0, 63, bios_sect); | 410 | ide_devset_rw_field(bios_sect, bios_sect); |
411 | 411 | ||
412 | ide_scsi_devset_rw(transform, 0, 3, transform); | 412 | ide_scsi_devset_rw_field(transform, transform); |
413 | ide_scsi_devset_rw(log, 0, 1, log); | 413 | ide_scsi_devset_rw_field(log, log); |
414 | 414 | ||
415 | static const struct ide_devset *idescsi_settings[] = { | 415 | static const struct ide_proc_devset idescsi_settings[] = { |
416 | &ide_devset_bios_cyl, | 416 | IDE_PROC_DEVSET(bios_cyl, 0, 1023), |
417 | &ide_devset_bios_head, | 417 | IDE_PROC_DEVSET(bios_head, 0, 255), |
418 | &ide_devset_bios_sect, | 418 | IDE_PROC_DEVSET(bios_sect, 0, 63), |
419 | &ide_devset_log, | 419 | IDE_PROC_DEVSET(log, 0, 1), |
420 | &ide_devset_transform, | 420 | IDE_PROC_DEVSET(transform, 0, 3), |
421 | NULL | 421 | { 0 }, |
422 | }; | 422 | }; |
423 | #endif | 423 | #endif |
424 | 424 | ||
diff --git a/include/linux/ide.h b/include/linux/ide.h index a9eced25acce..a9d82d6e6bdd 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h | |||
@@ -161,6 +161,7 @@ enum { | |||
161 | * Values should be in the range of 0x20 to 0x3f. | 161 | * Values should be in the range of 0x20 to 0x3f. |
162 | */ | 162 | */ |
163 | #define REQ_DRIVE_RESET 0x20 | 163 | #define REQ_DRIVE_RESET 0x20 |
164 | #define REQ_DEVSET_EXEC 0x21 | ||
164 | 165 | ||
165 | /* | 166 | /* |
166 | * Check for an interrupt and acknowledge the interrupt status | 167 | * Check for an interrupt and acknowledge the interrupt status |
@@ -405,7 +406,7 @@ struct ide_drive_s { | |||
405 | u16 *id; /* identification info */ | 406 | u16 *id; /* identification info */ |
406 | #ifdef CONFIG_IDE_PROC_FS | 407 | #ifdef CONFIG_IDE_PROC_FS |
407 | struct proc_dir_entry *proc; /* /proc/ide/ directory entry */ | 408 | struct proc_dir_entry *proc; /* /proc/ide/ directory entry */ |
408 | const struct ide_devset **settings; /* /proc/ide/ drive settings */ | 409 | const struct ide_proc_devset *settings; /* /proc/ide/ drive settings */ |
409 | #endif | 410 | #endif |
410 | struct hwif_s *hwif; /* actually (ide_hwif_t *) */ | 411 | struct hwif_s *hwif; /* actually (ide_hwif_t *) */ |
411 | 412 | ||
@@ -707,29 +708,62 @@ typedef struct ide_driver_s ide_driver_t; | |||
707 | 708 | ||
708 | extern struct mutex ide_setting_mtx; | 709 | extern struct mutex ide_setting_mtx; |
709 | 710 | ||
710 | int get_io_32bit(ide_drive_t *); | 711 | /* |
711 | int set_io_32bit(ide_drive_t *, int); | 712 | * configurable drive settings |
712 | int get_ksettings(ide_drive_t *); | 713 | */ |
713 | int set_ksettings(ide_drive_t *, int); | 714 | |
714 | int set_pio_mode(ide_drive_t *, int); | 715 | #define DS_SYNC (1 << 0) |
715 | int get_unmaskirq(ide_drive_t *); | 716 | |
716 | int set_unmaskirq(ide_drive_t *, int); | 717 | struct ide_devset { |
717 | int get_using_dma(ide_drive_t *); | 718 | int (*get)(ide_drive_t *); |
718 | int set_using_dma(ide_drive_t *, int); | 719 | int (*set)(ide_drive_t *, int); |
720 | unsigned int flags; | ||
721 | }; | ||
722 | |||
723 | #define __DEVSET(_flags, _get, _set) { \ | ||
724 | .flags = _flags, \ | ||
725 | .get = _get, \ | ||
726 | .set = _set, \ | ||
727 | } | ||
719 | 728 | ||
720 | #define ide_devset_get(name, field) \ | 729 | #define ide_devset_get(name, field) \ |
721 | int get_##name(ide_drive_t *drive) \ | 730 | static int get_##name(ide_drive_t *drive) \ |
722 | { \ | 731 | { \ |
723 | return drive->field; \ | 732 | return drive->field; \ |
724 | } | 733 | } |
725 | 734 | ||
726 | #define ide_devset_set(name, field) \ | 735 | #define ide_devset_set(name, field) \ |
727 | int set_##name(ide_drive_t *drive, int arg) \ | 736 | static int set_##name(ide_drive_t *drive, int arg) \ |
728 | { \ | 737 | { \ |
729 | drive->field = arg; \ | 738 | drive->field = arg; \ |
730 | return 0; \ | 739 | return 0; \ |
731 | } | 740 | } |
732 | 741 | ||
742 | #define __IDE_DEVSET(_name, _flags, _get, _set) \ | ||
743 | const struct ide_devset ide_devset_##_name = \ | ||
744 | __DEVSET(_flags, _get, _set) | ||
745 | |||
746 | #define IDE_DEVSET(_name, _flags, _get, _set) \ | ||
747 | static __IDE_DEVSET(_name, _flags, _get, _set) | ||
748 | |||
749 | #define ide_devset_rw(_name, _func) \ | ||
750 | IDE_DEVSET(_name, 0, get_##_func, set_##_func) | ||
751 | |||
752 | #define ide_devset_w(_name, _func) \ | ||
753 | IDE_DEVSET(_name, 0, NULL, set_##_func) | ||
754 | |||
755 | #define ide_devset_rw_sync(_name, _func) \ | ||
756 | IDE_DEVSET(_name, DS_SYNC, get_##_func, set_##_func) | ||
757 | |||
758 | #define ide_decl_devset(_name) \ | ||
759 | extern const struct ide_devset ide_devset_##_name | ||
760 | |||
761 | ide_decl_devset(io_32bit); | ||
762 | ide_decl_devset(keepsettings); | ||
763 | ide_decl_devset(pio_mode); | ||
764 | ide_decl_devset(unmaskirq); | ||
765 | ide_decl_devset(using_dma); | ||
766 | |||
733 | /* ATAPI packet command flags */ | 767 | /* ATAPI packet command flags */ |
734 | enum { | 768 | enum { |
735 | /* set when an error is considered normal - no retry (ide-tape) */ | 769 | /* set when an error is considered normal - no retry (ide-tape) */ |
@@ -797,60 +831,34 @@ struct ide_atapi_pc { | |||
797 | 831 | ||
798 | #ifdef CONFIG_IDE_PROC_FS | 832 | #ifdef CONFIG_IDE_PROC_FS |
799 | /* | 833 | /* |
800 | * configurable drive settings | 834 | * /proc/ide interface |
801 | */ | 835 | */ |
802 | 836 | ||
803 | #define S_READ (1 << 0) | 837 | #define ide_devset_rw_field(_name, _field) \ |
804 | #define S_WRITE (1 << 1) | 838 | ide_devset_get(_name, _field); \ |
805 | #define S_RW (S_READ | S_WRITE) | 839 | ide_devset_set(_name, _field); \ |
806 | #define S_NOLOCK (1 << 2) | 840 | IDE_DEVSET(_name, DS_SYNC, get_##_name, set_##_name) |
807 | 841 | ||
808 | struct ide_devset { | 842 | struct ide_proc_devset { |
809 | const char *name; | 843 | const char *name; |
810 | unsigned int flags; | 844 | const struct ide_devset *setting; |
811 | int min, max; | 845 | int min, max; |
812 | int (*get)(ide_drive_t *); | 846 | int (*mulf)(ide_drive_t *); |
813 | int (*set)(ide_drive_t *, int); | 847 | int (*divf)(ide_drive_t *); |
814 | int (*mulf)(ide_drive_t *); | ||
815 | int (*divf)(ide_drive_t *); | ||
816 | }; | 848 | }; |
817 | 849 | ||
818 | #define __DEVSET(_name, _flags, _min, _max, _get, _set, _mulf, _divf) { \ | 850 | #define __IDE_PROC_DEVSET(_name, _min, _max, _mulf, _divf) { \ |
819 | .name = __stringify(_name), \ | 851 | .name = __stringify(_name), \ |
820 | .flags = _flags, \ | 852 | .setting = &ide_devset_##_name, \ |
821 | .min = _min, \ | 853 | .min = _min, \ |
822 | .max = _max, \ | 854 | .max = _max, \ |
823 | .get = _get, \ | 855 | .mulf = _mulf, \ |
824 | .set = _set, \ | 856 | .divf = _divf, \ |
825 | .mulf = _mulf, \ | ||
826 | .divf = _divf, \ | ||
827 | } | 857 | } |
828 | 858 | ||
829 | #define __IDE_DEVSET(_name, _flags, _min, _max, _get, _set, _mulf, _divf) \ | 859 | #define IDE_PROC_DEVSET(_name, _min, _max) \ |
830 | static const struct ide_devset ide_devset_##_name = \ | 860 | __IDE_PROC_DEVSET(_name, _min, _max, NULL, NULL) |
831 | __DEVSET(_name, _flags, _min, _max, _get, _set, _mulf, _divf) | ||
832 | |||
833 | #define IDE_DEVSET(_name, _flags, _min, _max, _get, _set) \ | ||
834 | __IDE_DEVSET(_name, _flags, _min, _max, _get, _set, NULL, NULL) | ||
835 | |||
836 | #define ide_devset_rw_nolock(_name, _min, _max, _func) \ | ||
837 | IDE_DEVSET(_name, S_RW | S_NOLOCK, _min, _max, get_##_func, set_##_func) | ||
838 | 861 | ||
839 | #define ide_devset_w_nolock(_name, _min, _max, _func) \ | ||
840 | IDE_DEVSET(_name, S_WRITE | S_NOLOCK, _min, _max, NULL, set_##_func) | ||
841 | |||
842 | #define ide_devset_rw(_name, _min, _max, _field) \ | ||
843 | static ide_devset_get(_name, _field); \ | ||
844 | static ide_devset_set(_name, _field); \ | ||
845 | IDE_DEVSET(_name, S_RW, _min, _max, get_##_name, set_##_name) | ||
846 | |||
847 | #define ide_devset_r(_name, _min, _max, _field) \ | ||
848 | ide_devset_get(_name, _field) \ | ||
849 | IDE_DEVSET(_name, S_READ, _min, _max, get_##_name, NULL) | ||
850 | |||
851 | /* | ||
852 | * /proc/ide interface | ||
853 | */ | ||
854 | typedef struct { | 862 | typedef struct { |
855 | const char *name; | 863 | const char *name; |
856 | mode_t mode; | 864 | mode_t mode; |
@@ -948,8 +956,8 @@ struct ide_driver_s { | |||
948 | void (*resume)(ide_drive_t *); | 956 | void (*resume)(ide_drive_t *); |
949 | void (*shutdown)(ide_drive_t *); | 957 | void (*shutdown)(ide_drive_t *); |
950 | #ifdef CONFIG_IDE_PROC_FS | 958 | #ifdef CONFIG_IDE_PROC_FS |
951 | ide_proc_entry_t *proc; | 959 | ide_proc_entry_t *proc; |
952 | const struct ide_devset **settings; | 960 | const struct ide_proc_devset *settings; |
953 | #endif | 961 | #endif |
954 | }; | 962 | }; |
955 | 963 | ||
@@ -961,9 +969,7 @@ void ide_device_put(ide_drive_t *); | |||
961 | struct ide_ioctl_devset { | 969 | struct ide_ioctl_devset { |
962 | unsigned int get_ioctl; | 970 | unsigned int get_ioctl; |
963 | unsigned int set_ioctl; | 971 | unsigned int set_ioctl; |
964 | 972 | const struct ide_devset *setting; | |
965 | int (*get)(ide_drive_t *); | ||
966 | int (*set)(ide_drive_t *, int); | ||
967 | }; | 973 | }; |
968 | 974 | ||
969 | int ide_setting_ioctl(ide_drive_t *, struct block_device *, unsigned int, | 975 | int ide_setting_ioctl(ide_drive_t *, struct block_device *, unsigned int, |
@@ -1002,6 +1008,9 @@ int ide_wait_stat(ide_startstop_t *, ide_drive_t *, u8, u8, unsigned long); | |||
1002 | 1008 | ||
1003 | extern ide_startstop_t ide_do_reset (ide_drive_t *); | 1009 | extern ide_startstop_t ide_do_reset (ide_drive_t *); |
1004 | 1010 | ||
1011 | extern int ide_devset_execute(ide_drive_t *drive, | ||
1012 | const struct ide_devset *setting, int arg); | ||
1013 | |||
1005 | extern void ide_do_drive_cmd(ide_drive_t *, struct request *); | 1014 | extern void ide_do_drive_cmd(ide_drive_t *, struct request *); |
1006 | 1015 | ||
1007 | extern void ide_end_drive_cmd(ide_drive_t *, u8, u8); | 1016 | extern void ide_end_drive_cmd(ide_drive_t *, u8, u8); |
@@ -1191,7 +1200,6 @@ extern int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout); | |||
1191 | 1200 | ||
1192 | extern void ide_stall_queue(ide_drive_t *drive, unsigned long timeout); | 1201 | extern void ide_stall_queue(ide_drive_t *drive, unsigned long timeout); |
1193 | 1202 | ||
1194 | extern int ide_spin_wait_hwgroup(ide_drive_t *); | ||
1195 | extern void ide_timer_expiry(unsigned long); | 1203 | extern void ide_timer_expiry(unsigned long); |
1196 | extern irqreturn_t ide_intr(int irq, void *dev_id); | 1204 | extern irqreturn_t ide_intr(int irq, void *dev_id); |
1197 | extern void do_ide_request(struct request_queue *); | 1205 | extern void do_ide_request(struct request_queue *); |