Root/
1 | |
2 | #include <linux/kernel.h> |
3 | #include <linux/ide.h> |
4 | |
5 | DEFINE_MUTEX(ide_setting_mtx); |
6 | |
7 | ide_devset_get(io_32bit, io_32bit); |
8 | |
9 | static int set_io_32bit(ide_drive_t *drive, int arg) |
10 | { |
11 | if (drive->dev_flags & IDE_DFLAG_NO_IO_32BIT) |
12 | return -EPERM; |
13 | |
14 | if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1)) |
15 | return -EINVAL; |
16 | |
17 | drive->io_32bit = arg; |
18 | |
19 | return 0; |
20 | } |
21 | |
22 | ide_devset_get_flag(ksettings, IDE_DFLAG_KEEP_SETTINGS); |
23 | |
24 | static int set_ksettings(ide_drive_t *drive, int arg) |
25 | { |
26 | if (arg < 0 || arg > 1) |
27 | return -EINVAL; |
28 | |
29 | if (arg) |
30 | drive->dev_flags |= IDE_DFLAG_KEEP_SETTINGS; |
31 | else |
32 | drive->dev_flags &= ~IDE_DFLAG_KEEP_SETTINGS; |
33 | |
34 | return 0; |
35 | } |
36 | |
37 | ide_devset_get_flag(using_dma, IDE_DFLAG_USING_DMA); |
38 | |
39 | static int set_using_dma(ide_drive_t *drive, int arg) |
40 | { |
41 | #ifdef CONFIG_BLK_DEV_IDEDMA |
42 | int err = -EPERM; |
43 | |
44 | if (arg < 0 || arg > 1) |
45 | return -EINVAL; |
46 | |
47 | if (ata_id_has_dma(drive->id) == 0) |
48 | goto out; |
49 | |
50 | if (drive->hwif->dma_ops == NULL) |
51 | goto out; |
52 | |
53 | err = 0; |
54 | |
55 | if (arg) { |
56 | if (ide_set_dma(drive)) |
57 | err = -EIO; |
58 | } else |
59 | ide_dma_off(drive); |
60 | |
61 | out: |
62 | return err; |
63 | #else |
64 | if (arg < 0 || arg > 1) |
65 | return -EINVAL; |
66 | |
67 | return -EPERM; |
68 | #endif |
69 | } |
70 | |
71 | /* |
72 | * handle HDIO_SET_PIO_MODE ioctl abusers here, eventually it will go away |
73 | */ |
74 | static int set_pio_mode_abuse(ide_hwif_t *hwif, u8 req_pio) |
75 | { |
76 | switch (req_pio) { |
77 | case 202: |
78 | case 201: |
79 | case 200: |
80 | case 102: |
81 | case 101: |
82 | case 100: |
83 | return (hwif->host_flags & IDE_HFLAG_ABUSE_DMA_MODES) ? 1 : 0; |
84 | case 9: |
85 | case 8: |
86 | return (hwif->host_flags & IDE_HFLAG_ABUSE_PREFETCH) ? 1 : 0; |
87 | case 7: |
88 | case 6: |
89 | return (hwif->host_flags & IDE_HFLAG_ABUSE_FAST_DEVSEL) ? 1 : 0; |
90 | default: |
91 | return 0; |
92 | } |
93 | } |
94 | |
95 | static int set_pio_mode(ide_drive_t *drive, int arg) |
96 | { |
97 | ide_hwif_t *hwif = drive->hwif; |
98 | const struct ide_port_ops *port_ops = hwif->port_ops; |
99 | |
100 | if (arg < 0 || arg > 255) |
101 | return -EINVAL; |
102 | |
103 | if (port_ops == NULL || port_ops->set_pio_mode == NULL || |
104 | (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)) |
105 | return -ENOSYS; |
106 | |
107 | if (set_pio_mode_abuse(drive->hwif, arg)) { |
108 | if (arg == 8 || arg == 9) { |
109 | unsigned long flags; |
110 | |
111 | /* take lock for IDE_DFLAG_[NO_]UNMASK/[NO_]IO_32BIT */ |
112 | spin_lock_irqsave(&hwif->lock, flags); |
113 | port_ops->set_pio_mode(drive, arg); |
114 | spin_unlock_irqrestore(&hwif->lock, flags); |
115 | } else |
116 | port_ops->set_pio_mode(drive, arg); |
117 | } else { |
118 | int keep_dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA); |
119 | |
120 | ide_set_pio(drive, arg); |
121 | |
122 | if (hwif->host_flags & IDE_HFLAG_SET_PIO_MODE_KEEP_DMA) { |
123 | if (keep_dma) |
124 | ide_dma_on(drive); |
125 | } |
126 | } |
127 | |
128 | return 0; |
129 | } |
130 | |
131 | ide_devset_get_flag(unmaskirq, IDE_DFLAG_UNMASK); |
132 | |
133 | static int set_unmaskirq(ide_drive_t *drive, int arg) |
134 | { |
135 | if (drive->dev_flags & IDE_DFLAG_NO_UNMASK) |
136 | return -EPERM; |
137 | |
138 | if (arg < 0 || arg > 1) |
139 | return -EINVAL; |
140 | |
141 | if (arg) |
142 | drive->dev_flags |= IDE_DFLAG_UNMASK; |
143 | else |
144 | drive->dev_flags &= ~IDE_DFLAG_UNMASK; |
145 | |
146 | return 0; |
147 | } |
148 | |
149 | ide_ext_devset_rw_sync(io_32bit, io_32bit); |
150 | ide_ext_devset_rw_sync(keepsettings, ksettings); |
151 | ide_ext_devset_rw_sync(unmaskirq, unmaskirq); |
152 | ide_ext_devset_rw_sync(using_dma, using_dma); |
153 | __IDE_DEVSET(pio_mode, DS_SYNC, NULL, set_pio_mode); |
154 | |
155 | int ide_devset_execute(ide_drive_t *drive, const struct ide_devset *setting, |
156 | int arg) |
157 | { |
158 | struct request_queue *q = drive->queue; |
159 | struct request *rq; |
160 | int ret = 0; |
161 | |
162 | if (!(setting->flags & DS_SYNC)) |
163 | return setting->set(drive, arg); |
164 | |
165 | rq = blk_get_request(q, READ, __GFP_WAIT); |
166 | rq->cmd_type = REQ_TYPE_SPECIAL; |
167 | rq->cmd_len = 5; |
168 | rq->cmd[0] = REQ_DEVSET_EXEC; |
169 | *(int *)&rq->cmd[1] = arg; |
170 | rq->special = setting->set; |
171 | |
172 | if (blk_execute_rq(q, NULL, rq, 0)) |
173 | ret = rq->errors; |
174 | blk_put_request(rq); |
175 | |
176 | return ret; |
177 | } |
178 | |
179 | ide_startstop_t ide_do_devset(ide_drive_t *drive, struct request *rq) |
180 | { |
181 | int err, (*setfunc)(ide_drive_t *, int) = rq->special; |
182 | |
183 | err = setfunc(drive, *(int *)&rq->cmd[1]); |
184 | if (err) |
185 | rq->errors = err; |
186 | ide_complete_rq(drive, err, blk_rq_bytes(rq)); |
187 | return ide_stopped; |
188 | } |
189 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9