diff options
Diffstat (limited to 'drivers/ide/ide-io-std.c')
-rw-r--r-- | drivers/ide/ide-io-std.c | 130 |
1 files changed, 54 insertions, 76 deletions
diff --git a/drivers/ide/ide-io-std.c b/drivers/ide/ide-io-std.c index 2d9c6dc3f956..9cac281d82c4 100644 --- a/drivers/ide/ide-io-std.c +++ b/drivers/ide/ide-io-std.c | |||
@@ -64,23 +64,26 @@ u8 ide_read_altstatus(ide_hwif_t *hwif) | |||
64 | } | 64 | } |
65 | EXPORT_SYMBOL_GPL(ide_read_altstatus); | 65 | EXPORT_SYMBOL_GPL(ide_read_altstatus); |
66 | 66 | ||
67 | void ide_set_irq(ide_hwif_t *hwif, int on) | 67 | void ide_write_devctl(ide_hwif_t *hwif, u8 ctl) |
68 | { | 68 | { |
69 | u8 ctl = ATA_DEVCTL_OBS; | ||
70 | |||
71 | if (on == 4) { /* hack for SRST */ | ||
72 | ctl |= 4; | ||
73 | on &= ~4; | ||
74 | } | ||
75 | |||
76 | ctl |= on ? 0 : 2; | ||
77 | |||
78 | if (hwif->host_flags & IDE_HFLAG_MMIO) | 69 | if (hwif->host_flags & IDE_HFLAG_MMIO) |
79 | writeb(ctl, (void __iomem *)hwif->io_ports.ctl_addr); | 70 | writeb(ctl, (void __iomem *)hwif->io_ports.ctl_addr); |
80 | else | 71 | else |
81 | outb(ctl, hwif->io_ports.ctl_addr); | 72 | outb(ctl, hwif->io_ports.ctl_addr); |
82 | } | 73 | } |
83 | EXPORT_SYMBOL_GPL(ide_set_irq); | 74 | EXPORT_SYMBOL_GPL(ide_write_devctl); |
75 | |||
76 | void ide_dev_select(ide_drive_t *drive) | ||
77 | { | ||
78 | ide_hwif_t *hwif = drive->hwif; | ||
79 | u8 select = drive->select | ATA_DEVICE_OBS; | ||
80 | |||
81 | if (hwif->host_flags & IDE_HFLAG_MMIO) | ||
82 | writeb(select, (void __iomem *)hwif->io_ports.device_addr); | ||
83 | else | ||
84 | outb(select, hwif->io_ports.device_addr); | ||
85 | } | ||
86 | EXPORT_SYMBOL_GPL(ide_dev_select); | ||
84 | 87 | ||
85 | void ide_tf_load(ide_drive_t *drive, struct ide_cmd *cmd) | 88 | void ide_tf_load(ide_drive_t *drive, struct ide_cmd *cmd) |
86 | { | 89 | { |
@@ -99,15 +102,6 @@ void ide_tf_load(ide_drive_t *drive, struct ide_cmd *cmd) | |||
99 | if (cmd->ftf_flags & IDE_FTFLAG_FLAGGED) | 102 | if (cmd->ftf_flags & IDE_FTFLAG_FLAGGED) |
100 | HIHI = 0xFF; | 103 | HIHI = 0xFF; |
101 | 104 | ||
102 | if (cmd->ftf_flags & IDE_FTFLAG_OUT_DATA) { | ||
103 | u16 data = (tf->hob_data << 8) | tf->data; | ||
104 | |||
105 | if (mmio) | ||
106 | writew(data, (void __iomem *)io_ports->data_addr); | ||
107 | else | ||
108 | outw(data, io_ports->data_addr); | ||
109 | } | ||
110 | |||
111 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) | 105 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) |
112 | tf_outb(tf->hob_feature, io_ports->feature_addr); | 106 | tf_outb(tf->hob_feature, io_ports->feature_addr); |
113 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) | 107 | if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) |
@@ -153,23 +147,11 @@ void ide_tf_read(ide_drive_t *drive, struct ide_cmd *cmd) | |||
153 | tf_inb = ide_inb; | 147 | tf_inb = ide_inb; |
154 | } | 148 | } |
155 | 149 | ||
156 | if (cmd->ftf_flags & IDE_FTFLAG_IN_DATA) { | ||
157 | u16 data; | ||
158 | |||
159 | if (mmio) | ||
160 | data = readw((void __iomem *)io_ports->data_addr); | ||
161 | else | ||
162 | data = inw(io_ports->data_addr); | ||
163 | |||
164 | tf->data = data & 0xff; | ||
165 | tf->hob_data = (data >> 8) & 0xff; | ||
166 | } | ||
167 | |||
168 | /* be sure we're looking at the low order bits */ | 150 | /* be sure we're looking at the low order bits */ |
169 | tf_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr); | 151 | tf_outb(ATA_DEVCTL_OBS, io_ports->ctl_addr); |
170 | 152 | ||
171 | if (cmd->tf_flags & IDE_TFLAG_IN_FEATURE) | 153 | if (cmd->tf_flags & IDE_TFLAG_IN_ERROR) |
172 | tf->feature = tf_inb(io_ports->feature_addr); | 154 | tf->error = tf_inb(io_ports->feature_addr); |
173 | if (cmd->tf_flags & IDE_TFLAG_IN_NSECT) | 155 | if (cmd->tf_flags & IDE_TFLAG_IN_NSECT) |
174 | tf->nsect = tf_inb(io_ports->nsect_addr); | 156 | tf->nsect = tf_inb(io_ports->nsect_addr); |
175 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAL) | 157 | if (cmd->tf_flags & IDE_TFLAG_IN_LBAL) |
@@ -182,18 +164,18 @@ void ide_tf_read(ide_drive_t *drive, struct ide_cmd *cmd) | |||
182 | tf->device = tf_inb(io_ports->device_addr); | 164 | tf->device = tf_inb(io_ports->device_addr); |
183 | 165 | ||
184 | if (cmd->tf_flags & IDE_TFLAG_LBA48) { | 166 | if (cmd->tf_flags & IDE_TFLAG_LBA48) { |
185 | tf_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr); | 167 | tf_outb(ATA_HOB | ATA_DEVCTL_OBS, io_ports->ctl_addr); |
186 | 168 | ||
187 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) | 169 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_ERROR) |
188 | tf->hob_feature = tf_inb(io_ports->feature_addr); | 170 | tf->hob_error = tf_inb(io_ports->feature_addr); |
189 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_NSECT) | 171 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_NSECT) |
190 | tf->hob_nsect = tf_inb(io_ports->nsect_addr); | 172 | tf->hob_nsect = tf_inb(io_ports->nsect_addr); |
191 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAL) | 173 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAL) |
192 | tf->hob_lbal = tf_inb(io_ports->lbal_addr); | 174 | tf->hob_lbal = tf_inb(io_ports->lbal_addr); |
193 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAM) | 175 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAM) |
194 | tf->hob_lbam = tf_inb(io_ports->lbam_addr); | 176 | tf->hob_lbam = tf_inb(io_ports->lbam_addr); |
195 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAH) | 177 | if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAH) |
196 | tf->hob_lbah = tf_inb(io_ports->lbah_addr); | 178 | tf->hob_lbah = tf_inb(io_ports->lbah_addr); |
197 | } | 179 | } |
198 | } | 180 | } |
199 | EXPORT_SYMBOL_GPL(ide_tf_read); | 181 | EXPORT_SYMBOL_GPL(ide_tf_read); |
@@ -225,11 +207,10 @@ void ide_input_data(ide_drive_t *drive, struct ide_cmd *cmd, void *buf, | |||
225 | ide_hwif_t *hwif = drive->hwif; | 207 | ide_hwif_t *hwif = drive->hwif; |
226 | struct ide_io_ports *io_ports = &hwif->io_ports; | 208 | struct ide_io_ports *io_ports = &hwif->io_ports; |
227 | unsigned long data_addr = io_ports->data_addr; | 209 | unsigned long data_addr = io_ports->data_addr; |
210 | unsigned int words = (len + 1) >> 1; | ||
228 | u8 io_32bit = drive->io_32bit; | 211 | u8 io_32bit = drive->io_32bit; |
229 | u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; | 212 | u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; |
230 | 213 | ||
231 | len++; | ||
232 | |||
233 | if (io_32bit) { | 214 | if (io_32bit) { |
234 | unsigned long uninitialized_var(flags); | 215 | unsigned long uninitialized_var(flags); |
235 | 216 | ||
@@ -238,27 +219,26 @@ void ide_input_data(ide_drive_t *drive, struct ide_cmd *cmd, void *buf, | |||
238 | ata_vlb_sync(io_ports->nsect_addr); | 219 | ata_vlb_sync(io_ports->nsect_addr); |
239 | } | 220 | } |
240 | 221 | ||
222 | words >>= 1; | ||
241 | if (mmio) | 223 | if (mmio) |
242 | __ide_mm_insl((void __iomem *)data_addr, buf, len / 4); | 224 | __ide_mm_insl((void __iomem *)data_addr, buf, words); |
243 | else | 225 | else |
244 | insl(data_addr, buf, len / 4); | 226 | insl(data_addr, buf, words); |
245 | 227 | ||
246 | if ((io_32bit & 2) && !mmio) | 228 | if ((io_32bit & 2) && !mmio) |
247 | local_irq_restore(flags); | 229 | local_irq_restore(flags); |
248 | 230 | ||
249 | if ((len & 3) >= 2) { | 231 | if (((len + 1) & 3) < 2) |
250 | if (mmio) | 232 | return; |
251 | __ide_mm_insw((void __iomem *)data_addr, | 233 | |
252 | (u8 *)buf + (len & ~3), 1); | 234 | buf += len & ~3; |
253 | else | 235 | words = 1; |
254 | insw(data_addr, (u8 *)buf + (len & ~3), 1); | ||
255 | } | ||
256 | } else { | ||
257 | if (mmio) | ||
258 | __ide_mm_insw((void __iomem *)data_addr, buf, len / 2); | ||
259 | else | ||
260 | insw(data_addr, buf, len / 2); | ||
261 | } | 236 | } |
237 | |||
238 | if (mmio) | ||
239 | __ide_mm_insw((void __iomem *)data_addr, buf, words); | ||
240 | else | ||
241 | insw(data_addr, buf, words); | ||
262 | } | 242 | } |
263 | EXPORT_SYMBOL_GPL(ide_input_data); | 243 | EXPORT_SYMBOL_GPL(ide_input_data); |
264 | 244 | ||
@@ -271,11 +251,10 @@ void ide_output_data(ide_drive_t *drive, struct ide_cmd *cmd, void *buf, | |||
271 | ide_hwif_t *hwif = drive->hwif; | 251 | ide_hwif_t *hwif = drive->hwif; |
272 | struct ide_io_ports *io_ports = &hwif->io_ports; | 252 | struct ide_io_ports *io_ports = &hwif->io_ports; |
273 | unsigned long data_addr = io_ports->data_addr; | 253 | unsigned long data_addr = io_ports->data_addr; |
254 | unsigned int words = (len + 1) >> 1; | ||
274 | u8 io_32bit = drive->io_32bit; | 255 | u8 io_32bit = drive->io_32bit; |
275 | u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; | 256 | u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; |
276 | 257 | ||
277 | len++; | ||
278 | |||
279 | if (io_32bit) { | 258 | if (io_32bit) { |
280 | unsigned long uninitialized_var(flags); | 259 | unsigned long uninitialized_var(flags); |
281 | 260 | ||
@@ -284,27 +263,26 @@ void ide_output_data(ide_drive_t *drive, struct ide_cmd *cmd, void *buf, | |||
284 | ata_vlb_sync(io_ports->nsect_addr); | 263 | ata_vlb_sync(io_ports->nsect_addr); |
285 | } | 264 | } |
286 | 265 | ||
266 | words >>= 1; | ||
287 | if (mmio) | 267 | if (mmio) |
288 | __ide_mm_outsl((void __iomem *)data_addr, buf, len / 4); | 268 | __ide_mm_outsl((void __iomem *)data_addr, buf, words); |
289 | else | 269 | else |
290 | outsl(data_addr, buf, len / 4); | 270 | outsl(data_addr, buf, words); |
291 | 271 | ||
292 | if ((io_32bit & 2) && !mmio) | 272 | if ((io_32bit & 2) && !mmio) |
293 | local_irq_restore(flags); | 273 | local_irq_restore(flags); |
294 | 274 | ||
295 | if ((len & 3) >= 2) { | 275 | if (((len + 1) & 3) < 2) |
296 | if (mmio) | 276 | return; |
297 | __ide_mm_outsw((void __iomem *)data_addr, | 277 | |
298 | (u8 *)buf + (len & ~3), 1); | 278 | buf += len & ~3; |
299 | else | 279 | words = 1; |
300 | outsw(data_addr, (u8 *)buf + (len & ~3), 1); | ||
301 | } | ||
302 | } else { | ||
303 | if (mmio) | ||
304 | __ide_mm_outsw((void __iomem *)data_addr, buf, len / 2); | ||
305 | else | ||
306 | outsw(data_addr, buf, len / 2); | ||
307 | } | 280 | } |
281 | |||
282 | if (mmio) | ||
283 | __ide_mm_outsw((void __iomem *)data_addr, buf, words); | ||
284 | else | ||
285 | outsw(data_addr, buf, words); | ||
308 | } | 286 | } |
309 | EXPORT_SYMBOL_GPL(ide_output_data); | 287 | EXPORT_SYMBOL_GPL(ide_output_data); |
310 | 288 | ||
@@ -312,9 +290,9 @@ const struct ide_tp_ops default_tp_ops = { | |||
312 | .exec_command = ide_exec_command, | 290 | .exec_command = ide_exec_command, |
313 | .read_status = ide_read_status, | 291 | .read_status = ide_read_status, |
314 | .read_altstatus = ide_read_altstatus, | 292 | .read_altstatus = ide_read_altstatus, |
293 | .write_devctl = ide_write_devctl, | ||
315 | 294 | ||
316 | .set_irq = ide_set_irq, | 295 | .dev_select = ide_dev_select, |
317 | |||
318 | .tf_load = ide_tf_load, | 296 | .tf_load = ide_tf_load, |
319 | .tf_read = ide_tf_read, | 297 | .tf_read = ide_tf_read, |
320 | 298 | ||