diff options
| author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2009-03-24 18:22:46 -0400 |
|---|---|---|
| committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2009-03-24 18:22:46 -0400 |
| commit | 1574cf6cb4800525be769ee6023c567113fa2d18 (patch) | |
| tree | 402ba6391dbc71d7a143ddba6cf998845530c77c | |
| parent | 0d6a9754c06e173552b0ad5fad45f69786b6de99 (diff) | |
ide: move standard I/O code to ide-io-std.c
Acked-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
| -rw-r--r-- | drivers/ide/Makefile | 3 | ||||
| -rw-r--r-- | drivers/ide/ide-io-std.c | 316 | ||||
| -rw-r--r-- | drivers/ide/ide-iops.c | 313 |
3 files changed, 318 insertions, 314 deletions
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index d0976e6ee090..cbb1aea2aea3 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile | |||
| @@ -5,7 +5,8 @@ | |||
| 5 | EXTRA_CFLAGS += -Idrivers/ide | 5 | EXTRA_CFLAGS += -Idrivers/ide |
| 6 | 6 | ||
| 7 | ide-core-y += ide.o ide-ioctls.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \ | 7 | ide-core-y += ide.o ide-ioctls.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \ |
| 8 | ide-taskfile.o ide-pm.o ide-park.o ide-sysfs.o ide-devsets.o | 8 | ide-taskfile.o ide-pm.o ide-park.o ide-sysfs.o ide-devsets.o \ |
| 9 | ide-io-std.o | ||
| 9 | 10 | ||
| 10 | # core IDE code | 11 | # core IDE code |
| 11 | ide-core-$(CONFIG_IDE_XFER_MODE) += ide-pio-blacklist.o ide-xfer-mode.o | 12 | ide-core-$(CONFIG_IDE_XFER_MODE) += ide-pio-blacklist.o ide-xfer-mode.o |
diff --git a/drivers/ide/ide-io-std.c b/drivers/ide/ide-io-std.c new file mode 100644 index 000000000000..45b43dd49cda --- /dev/null +++ b/drivers/ide/ide-io-std.c | |||
| @@ -0,0 +1,316 @@ | |||
| 1 | |||
| 2 | #include <linux/kernel.h> | ||
| 3 | #include <linux/ide.h> | ||
| 4 | |||
| 5 | /* | ||
| 6 | * Conventional PIO operations for ATA devices | ||
| 7 | */ | ||
| 8 | |||
| 9 | static u8 ide_inb(unsigned long port) | ||
| 10 | { | ||
| 11 | return (u8) inb(port); | ||
| 12 | } | ||
| 13 | |||
| 14 | static void ide_outb(u8 val, unsigned long port) | ||
| 15 | { | ||
| 16 | outb(val, port); | ||
| 17 | } | ||
| 18 | |||
| 19 | /* | ||
| 20 | * MMIO operations, typically used for SATA controllers | ||
| 21 | */ | ||
| 22 | |||
| 23 | static u8 ide_mm_inb(unsigned long port) | ||
| 24 | { | ||
| 25 | return (u8) readb((void __iomem *) port); | ||
| 26 | } | ||
| 27 | |||
| 28 | static void ide_mm_outb(u8 value, unsigned long port) | ||
| 29 | { | ||
| 30 | writeb(value, (void __iomem *) port); | ||
| 31 | } | ||
| 32 | |||
| 33 | void ide_exec_command(ide_hwif_t *hwif, u8 cmd) | ||
| 34 | { | ||
| 35 | if (hwif->host_flags & IDE_HFLAG_MMIO) | ||
| 36 | writeb(cmd, (void __iomem *)hwif->io_ports.command_addr); | ||
| 37 | else | ||
| 38 | outb(cmd, hwif->io_ports.command_addr); | ||
| 39 | } | ||
| 40 | EXPORT_SYMBOL_GPL(ide_exec_command); | ||
| 41 | |||
| 42 | u8 ide_read_status(ide_hwif_t *hwif) | ||
| 43 | { | ||
| 44 | if (hwif->host_flags & IDE_HFLAG_MMIO) | ||
| 45 | return readb((void __iomem *)hwif->io_ports.status_addr); | ||
| 46 | else | ||
| 47 | return inb(hwif->io_ports.status_addr); | ||
| 48 | } | ||
| 49 | EXPORT_SYMBOL_GPL(ide_read_status); | ||
| 50 | |||
| 51 | u8 ide_read_altstatus(ide_hwif_t *hwif) | ||
| 52 | { | ||
| 53 | if (hwif->host_flags & IDE_HFLAG_MMIO) | ||
| 54 | return readb((void __iomem *)hwif->io_ports.ctl_addr); | ||
| 55 | else | ||
| 56 | return inb(hwif->io_ports.ctl_addr); | ||
| 57 | } | ||
| 58 | EXPORT_SYMBOL_GPL(ide_read_altstatus); | ||
| 59 | |||
| 60 | void ide_set_irq(ide_hwif_t *hwif, int on) | ||
| 61 | { | ||
| 62 | u8 ctl = ATA_DEVCTL_OBS; | ||
| 63 | |||
| 64 | if (on == 4) { /* hack for SRST */ | ||
| 65 | ctl |= 4; | ||
| 66 | on &= ~4; | ||
| 67 | } | ||
| 68 | |||
| 69 | ctl |= on ? 0 : 2; | ||
| 70 | |||
| 71 | if (hwif->host_flags & IDE_HFLAG_MMIO) | ||
| 72 | writeb(ctl, (void __iomem *)hwif->io_ports.ctl_addr); | ||
| 73 | else | ||
| 74 | outb(ctl, hwif->io_ports.ctl_addr); | ||
| 75 | } | ||
| 76 | EXPORT_SYMBOL_GPL(ide_set_irq); | ||
| 77 | |||
| 78 | void ide_tf_load(ide_drive_t *drive, ide_task_t *task) | ||
| 79 | { | ||
| 80 | ide_hwif_t *hwif = drive->hwif; | ||
| 81 | struct ide_io_ports *io_ports = &hwif->io_ports; | ||
| 82 | struct ide_taskfile *tf = &task->tf; | ||
| 83 | void (*tf_outb)(u8 addr, unsigned long port); | ||
| 84 | u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; | ||
| 85 | u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF; | ||
| 86 | |||
| 87 | if (mmio) | ||
| 88 | tf_outb = ide_mm_outb; | ||
| 89 | else | ||
| 90 | tf_outb = ide_outb; | ||
| 91 | |||
| 92 | if (task->tf_flags & IDE_TFLAG_FLAGGED) | ||
| 93 | HIHI = 0xFF; | ||
| 94 | |||
| 95 | if (task->tf_flags & IDE_TFLAG_OUT_DATA) { | ||
| 96 | u16 data = (tf->hob_data << 8) | tf->data; | ||
| 97 | |||
| 98 | if (mmio) | ||
| 99 | writew(data, (void __iomem *)io_ports->data_addr); | ||
| 100 | else | ||
| 101 | outw(data, io_ports->data_addr); | ||
| 102 | } | ||
| 103 | |||
| 104 | if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) | ||
| 105 | tf_outb(tf->hob_feature, io_ports->feature_addr); | ||
| 106 | if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) | ||
| 107 | tf_outb(tf->hob_nsect, io_ports->nsect_addr); | ||
| 108 | if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL) | ||
| 109 | tf_outb(tf->hob_lbal, io_ports->lbal_addr); | ||
| 110 | if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM) | ||
| 111 | tf_outb(tf->hob_lbam, io_ports->lbam_addr); | ||
| 112 | if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH) | ||
| 113 | tf_outb(tf->hob_lbah, io_ports->lbah_addr); | ||
| 114 | |||
| 115 | if (task->tf_flags & IDE_TFLAG_OUT_FEATURE) | ||
| 116 | tf_outb(tf->feature, io_ports->feature_addr); | ||
| 117 | if (task->tf_flags & IDE_TFLAG_OUT_NSECT) | ||
| 118 | tf_outb(tf->nsect, io_ports->nsect_addr); | ||
| 119 | if (task->tf_flags & IDE_TFLAG_OUT_LBAL) | ||
| 120 | tf_outb(tf->lbal, io_ports->lbal_addr); | ||
| 121 | if (task->tf_flags & IDE_TFLAG_OUT_LBAM) | ||
| 122 | tf_outb(tf->lbam, io_ports->lbam_addr); | ||
| 123 | if (task->tf_flags & IDE_TFLAG_OUT_LBAH) | ||
| 124 | tf_outb(tf->lbah, io_ports->lbah_addr); | ||
| 125 | |||
| 126 | if (task->tf_flags & IDE_TFLAG_OUT_DEVICE) | ||
| 127 | tf_outb((tf->device & HIHI) | drive->select, | ||
| 128 | io_ports->device_addr); | ||
| 129 | } | ||
| 130 | EXPORT_SYMBOL_GPL(ide_tf_load); | ||
| 131 | |||
| 132 | void ide_tf_read(ide_drive_t *drive, ide_task_t *task) | ||
| 133 | { | ||
| 134 | ide_hwif_t *hwif = drive->hwif; | ||
| 135 | struct ide_io_ports *io_ports = &hwif->io_ports; | ||
| 136 | struct ide_taskfile *tf = &task->tf; | ||
| 137 | void (*tf_outb)(u8 addr, unsigned long port); | ||
| 138 | u8 (*tf_inb)(unsigned long port); | ||
| 139 | u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; | ||
| 140 | |||
| 141 | if (mmio) { | ||
| 142 | tf_outb = ide_mm_outb; | ||
| 143 | tf_inb = ide_mm_inb; | ||
| 144 | } else { | ||
| 145 | tf_outb = ide_outb; | ||
| 146 | tf_inb = ide_inb; | ||
| 147 | } | ||
| 148 | |||
| 149 | if (task->tf_flags & IDE_TFLAG_IN_DATA) { | ||
| 150 | u16 data; | ||
| 151 | |||
| 152 | if (mmio) | ||
| 153 | data = readw((void __iomem *)io_ports->data_addr); | ||
| 154 | else | ||
| 155 | data = inw(io_ports->data_addr); | ||
| 156 | |||
| 157 | tf->data = data & 0xff; | ||
| 158 | tf->hob_data = (data >> 8) & 0xff; | ||
| 159 | } | ||
| 160 | |||
| 161 | /* be sure we're looking at the low order bits */ | ||
| 162 | tf_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr); | ||
| 163 | |||
| 164 | if (task->tf_flags & IDE_TFLAG_IN_FEATURE) | ||
| 165 | tf->feature = tf_inb(io_ports->feature_addr); | ||
| 166 | if (task->tf_flags & IDE_TFLAG_IN_NSECT) | ||
| 167 | tf->nsect = tf_inb(io_ports->nsect_addr); | ||
| 168 | if (task->tf_flags & IDE_TFLAG_IN_LBAL) | ||
| 169 | tf->lbal = tf_inb(io_ports->lbal_addr); | ||
| 170 | if (task->tf_flags & IDE_TFLAG_IN_LBAM) | ||
| 171 | tf->lbam = tf_inb(io_ports->lbam_addr); | ||
| 172 | if (task->tf_flags & IDE_TFLAG_IN_LBAH) | ||
| 173 | tf->lbah = tf_inb(io_ports->lbah_addr); | ||
| 174 | if (task->tf_flags & IDE_TFLAG_IN_DEVICE) | ||
| 175 | tf->device = tf_inb(io_ports->device_addr); | ||
| 176 | |||
| 177 | if (task->tf_flags & IDE_TFLAG_LBA48) { | ||
| 178 | tf_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr); | ||
| 179 | |||
| 180 | if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) | ||
| 181 | tf->hob_feature = tf_inb(io_ports->feature_addr); | ||
| 182 | if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT) | ||
| 183 | tf->hob_nsect = tf_inb(io_ports->nsect_addr); | ||
| 184 | if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL) | ||
| 185 | tf->hob_lbal = tf_inb(io_ports->lbal_addr); | ||
| 186 | if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM) | ||
| 187 | tf->hob_lbam = tf_inb(io_ports->lbam_addr); | ||
| 188 | if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH) | ||
| 189 | tf->hob_lbah = tf_inb(io_ports->lbah_addr); | ||
| 190 | } | ||
| 191 | } | ||
| 192 | EXPORT_SYMBOL_GPL(ide_tf_read); | ||
| 193 | |||
| 194 | /* | ||
| 195 | * Some localbus EIDE interfaces require a special access sequence | ||
| 196 | * when using 32-bit I/O instructions to transfer data. We call this | ||
| 197 | * the "vlb_sync" sequence, which consists of three successive reads | ||
| 198 | * of the sector count register location, with interrupts disabled | ||
| 199 | * to ensure that the reads all happen together. | ||
| 200 | */ | ||
| 201 | static void ata_vlb_sync(unsigned long port) | ||
| 202 | { | ||
| 203 | (void)inb(port); | ||
| 204 | (void)inb(port); | ||
| 205 | (void)inb(port); | ||
| 206 | } | ||
| 207 | |||
| 208 | /* | ||
| 209 | * This is used for most PIO data transfers *from* the IDE interface | ||
| 210 | * | ||
| 211 | * These routines will round up any request for an odd number of bytes, | ||
| 212 | * so if an odd len is specified, be sure that there's at least one | ||
| 213 | * extra byte allocated for the buffer. | ||
| 214 | */ | ||
| 215 | void ide_input_data(ide_drive_t *drive, struct request *rq, void *buf, | ||
| 216 | unsigned int len) | ||
| 217 | { | ||
| 218 | ide_hwif_t *hwif = drive->hwif; | ||
| 219 | struct ide_io_ports *io_ports = &hwif->io_ports; | ||
| 220 | unsigned long data_addr = io_ports->data_addr; | ||
| 221 | u8 io_32bit = drive->io_32bit; | ||
| 222 | u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; | ||
| 223 | |||
| 224 | len++; | ||
| 225 | |||
| 226 | if (io_32bit) { | ||
| 227 | unsigned long uninitialized_var(flags); | ||
| 228 | |||
| 229 | if ((io_32bit & 2) && !mmio) { | ||
| 230 | local_irq_save(flags); | ||
| 231 | ata_vlb_sync(io_ports->nsect_addr); | ||
| 232 | } | ||
| 233 | |||
| 234 | if (mmio) | ||
| 235 | __ide_mm_insl((void __iomem *)data_addr, buf, len / 4); | ||
| 236 | else | ||
| 237 | insl(data_addr, buf, len / 4); | ||
| 238 | |||
| 239 | if ((io_32bit & 2) && !mmio) | ||
| 240 | local_irq_restore(flags); | ||
| 241 | |||
| 242 | if ((len & 3) >= 2) { | ||
| 243 | if (mmio) | ||
| 244 | __ide_mm_insw((void __iomem *)data_addr, | ||
| 245 | (u8 *)buf + (len & ~3), 1); | ||
| 246 | else | ||
| 247 | insw(data_addr, (u8 *)buf + (len & ~3), 1); | ||
| 248 | } | ||
| 249 | } else { | ||
| 250 | if (mmio) | ||
| 251 | __ide_mm_insw((void __iomem *)data_addr, buf, len / 2); | ||
| 252 | else | ||
| 253 | insw(data_addr, buf, len / 2); | ||
| 254 | } | ||
| 255 | } | ||
| 256 | EXPORT_SYMBOL_GPL(ide_input_data); | ||
| 257 | |||
| 258 | /* | ||
| 259 | * This is used for most PIO data transfers *to* the IDE interface | ||
| 260 | */ | ||
| 261 | void ide_output_data(ide_drive_t *drive, struct request *rq, void *buf, | ||
| 262 | unsigned int len) | ||
| 263 | { | ||
| 264 | ide_hwif_t *hwif = drive->hwif; | ||
| 265 | struct ide_io_ports *io_ports = &hwif->io_ports; | ||
| 266 | unsigned long data_addr = io_ports->data_addr; | ||
| 267 | u8 io_32bit = drive->io_32bit; | ||
| 268 | u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; | ||
| 269 | |||
| 270 | len++; | ||
| 271 | |||
| 272 | if (io_32bit) { | ||
| 273 | unsigned long uninitialized_var(flags); | ||
| 274 | |||
| 275 | if ((io_32bit & 2) && !mmio) { | ||
| 276 | local_irq_save(flags); | ||
| 277 | ata_vlb_sync(io_ports->nsect_addr); | ||
| 278 | } | ||
| 279 | |||
| 280 | if (mmio) | ||
| 281 | __ide_mm_outsl((void __iomem *)data_addr, buf, len / 4); | ||
| 282 | else | ||
| 283 | outsl(data_addr, buf, len / 4); | ||
| 284 | |||
| 285 | if ((io_32bit & 2) && !mmio) | ||
| 286 | local_irq_restore(flags); | ||
| 287 | |||
| 288 | if ((len & 3) >= 2) { | ||
| 289 | if (mmio) | ||
| 290 | __ide_mm_outsw((void __iomem *)data_addr, | ||
| 291 | (u8 *)buf + (len & ~3), 1); | ||
| 292 | else | ||
| 293 | outsw(data_addr, (u8 *)buf + (len & ~3), 1); | ||
| 294 | } | ||
| 295 | } else { | ||
| 296 | if (mmio) | ||
| 297 | __ide_mm_outsw((void __iomem *)data_addr, buf, len / 2); | ||
| 298 | else | ||
| 299 | outsw(data_addr, buf, len / 2); | ||
| 300 | } | ||
| 301 | } | ||
| 302 | EXPORT_SYMBOL_GPL(ide_output_data); | ||
| 303 | |||
| 304 | const struct ide_tp_ops default_tp_ops = { | ||
| 305 | .exec_command = ide_exec_command, | ||
| 306 | .read_status = ide_read_status, | ||
| 307 | .read_altstatus = ide_read_altstatus, | ||
| 308 | |||
| 309 | .set_irq = ide_set_irq, | ||
| 310 | |||
| 311 | .tf_load = ide_tf_load, | ||
| 312 | .tf_read = ide_tf_read, | ||
| 313 | |||
| 314 | .input_data = ide_input_data, | ||
| 315 | .output_data = ide_output_data, | ||
| 316 | }; | ||
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index d24add692129..91a49b543bd5 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c | |||
| @@ -27,34 +27,6 @@ | |||
| 27 | #include <asm/uaccess.h> | 27 | #include <asm/uaccess.h> |
| 28 | #include <asm/io.h> | 28 | #include <asm/io.h> |
| 29 | 29 | ||
| 30 | /* | ||
| 31 | * Conventional PIO operations for ATA devices | ||
| 32 | */ | ||
| 33 | |||
| 34 | static u8 ide_inb (unsigned long port) | ||
| 35 | { | ||
| 36 | return (u8) inb(port); | ||
| 37 | } | ||
| 38 | |||
| 39 | static void ide_outb (u8 val, unsigned long port) | ||
| 40 | { | ||
| 41 | outb(val, port); | ||
| 42 | } | ||
| 43 | |||
| 44 | /* | ||
| 45 | * MMIO operations, typically used for SATA controllers | ||
| 46 | */ | ||
| 47 | |||
| 48 | static u8 ide_mm_inb (unsigned long port) | ||
| 49 | { | ||
| 50 | return (u8) readb((void __iomem *) port); | ||
| 51 | } | ||
| 52 | |||
| 53 | static void ide_mm_outb (u8 value, unsigned long port) | ||
| 54 | { | ||
| 55 | writeb(value, (void __iomem *) port); | ||
| 56 | } | ||
| 57 | |||
| 58 | void SELECT_DRIVE (ide_drive_t *drive) | 30 | void SELECT_DRIVE (ide_drive_t *drive) |
| 59 | { | 31 | { |
| 60 | ide_hwif_t *hwif = drive->hwif; | 32 | ide_hwif_t *hwif = drive->hwif; |
| @@ -78,277 +50,6 @@ void SELECT_MASK(ide_drive_t *drive, int mask) | |||
| 78 | port_ops->maskproc(drive, mask); | 50 | port_ops->maskproc(drive, mask); |
| 79 | } | 51 | } |
| 80 | 52 | ||
| 81 | void ide_exec_command(ide_hwif_t *hwif, u8 cmd) | ||
| 82 | { | ||
| 83 | if (hwif->host_flags & IDE_HFLAG_MMIO) | ||
| 84 | writeb(cmd, (void __iomem *)hwif->io_ports.command_addr); | ||
| 85 | else | ||
| 86 | outb(cmd, hwif->io_ports.command_addr); | ||
| 87 | } | ||
| 88 | EXPORT_SYMBOL_GPL(ide_exec_command); | ||
| 89 | |||
| 90 | u8 ide_read_status(ide_hwif_t *hwif) | ||
| 91 | { | ||
| 92 | if (hwif->host_flags & IDE_HFLAG_MMIO) | ||
| 93 | return readb((void __iomem *)hwif->io_ports.status_addr); | ||
| 94 | else | ||
| 95 | return inb(hwif->io_ports.status_addr); | ||
| 96 | } | ||
| 97 | EXPORT_SYMBOL_GPL(ide_read_status); | ||
| 98 | |||
| 99 | u8 ide_read_altstatus(ide_hwif_t *hwif) | ||
| 100 | { | ||
| 101 | if (hwif->host_flags & IDE_HFLAG_MMIO) | ||
| 102 | return readb((void __iomem *)hwif->io_ports.ctl_addr); | ||
| 103 | else | ||
| 104 | return inb(hwif->io_ports.ctl_addr); | ||
| 105 | } | ||
| 106 | EXPORT_SYMBOL_GPL(ide_read_altstatus); | ||
| 107 | |||
| 108 | void ide_set_irq(ide_hwif_t *hwif, int on) | ||
| 109 | { | ||
| 110 | u8 ctl = ATA_DEVCTL_OBS; | ||
| 111 | |||
| 112 | if (on == 4) { /* hack for SRST */ | ||
| 113 | ctl |= 4; | ||
| 114 | on &= ~4; | ||
| 115 | } | ||
| 116 | |||
| 117 | ctl |= on ? 0 : 2; | ||
| 118 | |||
| 119 | if (hwif->host_flags & IDE_HFLAG_MMIO) | ||
| 120 | writeb(ctl, (void __iomem *)hwif->io_ports.ctl_addr); | ||
| 121 | else | ||
| 122 | outb(ctl, hwif->io_ports.ctl_addr); | ||
| 123 | } | ||
| 124 | EXPORT_SYMBOL_GPL(ide_set_irq); | ||
| 125 | |||
| 126 | void ide_tf_load(ide_drive_t *drive, ide_task_t *task) | ||
| 127 | { | ||
| 128 | ide_hwif_t *hwif = drive->hwif; | ||
| 129 | struct ide_io_ports *io_ports = &hwif->io_ports; | ||
| 130 | struct ide_taskfile *tf = &task->tf; | ||
| 131 | void (*tf_outb)(u8 addr, unsigned long port); | ||
| 132 | u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; | ||
| 133 | u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF; | ||
| 134 | |||
| 135 | if (mmio) | ||
| 136 | tf_outb = ide_mm_outb; | ||
| 137 | else | ||
| 138 | tf_outb = ide_outb; | ||
| 139 | |||
| 140 | if (task->tf_flags & IDE_TFLAG_FLAGGED) | ||
| 141 | HIHI = 0xFF; | ||
| 142 | |||
| 143 | if (task->tf_flags & IDE_TFLAG_OUT_DATA) { | ||
| 144 | u16 data = (tf->hob_data << 8) | tf->data; | ||
| 145 | |||
| 146 | if (mmio) | ||
| 147 | writew(data, (void __iomem *)io_ports->data_addr); | ||
| 148 | else | ||
| 149 | outw(data, io_ports->data_addr); | ||
| 150 | } | ||
| 151 | |||
| 152 | if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) | ||
| 153 | tf_outb(tf->hob_feature, io_ports->feature_addr); | ||
| 154 | if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) | ||
| 155 | tf_outb(tf->hob_nsect, io_ports->nsect_addr); | ||
| 156 | if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL) | ||
| 157 | tf_outb(tf->hob_lbal, io_ports->lbal_addr); | ||
| 158 | if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM) | ||
| 159 | tf_outb(tf->hob_lbam, io_ports->lbam_addr); | ||
| 160 | if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH) | ||
| 161 | tf_outb(tf->hob_lbah, io_ports->lbah_addr); | ||
| 162 | |||
| 163 | if (task->tf_flags & IDE_TFLAG_OUT_FEATURE) | ||
| 164 | tf_outb(tf->feature, io_ports->feature_addr); | ||
| 165 | if (task->tf_flags & IDE_TFLAG_OUT_NSECT) | ||
| 166 | tf_outb(tf->nsect, io_ports->nsect_addr); | ||
| 167 | if (task->tf_flags & IDE_TFLAG_OUT_LBAL) | ||
| 168 | tf_outb(tf->lbal, io_ports->lbal_addr); | ||
| 169 | if (task->tf_flags & IDE_TFLAG_OUT_LBAM) | ||
| 170 | tf_outb(tf->lbam, io_ports->lbam_addr); | ||
| 171 | if (task->tf_flags & IDE_TFLAG_OUT_LBAH) | ||
| 172 | tf_outb(tf->lbah, io_ports->lbah_addr); | ||
| 173 | |||
| 174 | if (task->tf_flags & IDE_TFLAG_OUT_DEVICE) | ||
| 175 | tf_outb((tf->device & HIHI) | drive->select, | ||
| 176 | io_ports->device_addr); | ||
| 177 | } | ||
| 178 | EXPORT_SYMBOL_GPL(ide_tf_load); | ||
| 179 | |||
| 180 | void ide_tf_read(ide_drive_t *drive, ide_task_t *task) | ||
| 181 | { | ||
| 182 | ide_hwif_t *hwif = drive->hwif; | ||
| 183 | struct ide_io_ports *io_ports = &hwif->io_ports; | ||
| 184 | struct ide_taskfile *tf = &task->tf; | ||
| 185 | void (*tf_outb)(u8 addr, unsigned long port); | ||
| 186 | u8 (*tf_inb)(unsigned long port); | ||
| 187 | u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; | ||
| 188 | |||
| 189 | if (mmio) { | ||
| 190 | tf_outb = ide_mm_outb; | ||
| 191 | tf_inb = ide_mm_inb; | ||
| 192 | } else { | ||
| 193 | tf_outb = ide_outb; | ||
| 194 | tf_inb = ide_inb; | ||
| 195 | } | ||
| 196 | |||
| 197 | if (task->tf_flags & IDE_TFLAG_IN_DATA) { | ||
| 198 | u16 data; | ||
| 199 | |||
| 200 | if (mmio) | ||
| 201 | data = readw((void __iomem *)io_ports->data_addr); | ||
| 202 | else | ||
| 203 | data = inw(io_ports->data_addr); | ||
| 204 | |||
| 205 | tf->data = data & 0xff; | ||
| 206 | tf->hob_data = (data >> 8) & 0xff; | ||
| 207 | } | ||
| 208 | |||
| 209 | /* be sure we're looking at the low order bits */ | ||
| 210 | tf_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr); | ||
| 211 | |||
| 212 | if (task->tf_flags & IDE_TFLAG_IN_FEATURE) | ||
| 213 | tf->feature = tf_inb(io_ports->feature_addr); | ||
| 214 | if (task->tf_flags & IDE_TFLAG_IN_NSECT) | ||
| 215 | tf->nsect = tf_inb(io_ports->nsect_addr); | ||
| 216 | if (task->tf_flags & IDE_TFLAG_IN_LBAL) | ||
| 217 | tf->lbal = tf_inb(io_ports->lbal_addr); | ||
| 218 | if (task->tf_flags & IDE_TFLAG_IN_LBAM) | ||
| 219 | tf->lbam = tf_inb(io_ports->lbam_addr); | ||
| 220 | if (task->tf_flags & IDE_TFLAG_IN_LBAH) | ||
| 221 | tf->lbah = tf_inb(io_ports->lbah_addr); | ||
| 222 | if (task->tf_flags & IDE_TFLAG_IN_DEVICE) | ||
| 223 | tf->device = tf_inb(io_ports->device_addr); | ||
| 224 | |||
| 225 | if (task->tf_flags & IDE_TFLAG_LBA48) { | ||
| 226 | tf_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr); | ||
| 227 | |||
| 228 | if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) | ||
| 229 | tf->hob_feature = tf_inb(io_ports->feature_addr); | ||
| 230 | if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT) | ||
| 231 | tf->hob_nsect = tf_inb(io_ports->nsect_addr); | ||
| 232 | if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL) | ||
| 233 | tf->hob_lbal = tf_inb(io_ports->lbal_addr); | ||
| 234 | if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM) | ||
| 235 | tf->hob_lbam = tf_inb(io_ports->lbam_addr); | ||
| 236 | if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH) | ||
| 237 | tf->hob_lbah = tf_inb(io_ports->lbah_addr); | ||
| 238 | } | ||
| 239 | } | ||
| 240 | EXPORT_SYMBOL_GPL(ide_tf_read); | ||
| 241 | |||
| 242 | /* | ||
| 243 | * Some localbus EIDE interfaces require a special access sequence | ||
| 244 | * when using 32-bit I/O instructions to transfer data. We call this | ||
| 245 | * the "vlb_sync" sequence, which consists of three successive reads | ||
| 246 | * of the sector count register location, with interrupts disabled | ||
| 247 | * to ensure that the reads all happen together. | ||
| 248 | */ | ||
| 249 | static void ata_vlb_sync(unsigned long port) | ||
| 250 | { | ||
| 251 | (void)inb(port); | ||
| 252 | (void)inb(port); | ||
| 253 | (void)inb(port); | ||
| 254 | } | ||
| 255 | |||
| 256 | /* | ||
| 257 | * This is used for most PIO data transfers *from* the IDE interface | ||
| 258 | * | ||
| 259 | * These routines will round up any request for an odd number of bytes, | ||
| 260 | * so if an odd len is specified, be sure that there's at least one | ||
| 261 | * extra byte allocated for the buffer. | ||
| 262 | */ | ||
| 263 | void ide_input_data(ide_drive_t *drive, struct request *rq, void *buf, | ||
| 264 | unsigned int len) | ||
| 265 | { | ||
| 266 | ide_hwif_t *hwif = drive->hwif; | ||
| 267 | struct ide_io_ports *io_ports = &hwif->io_ports; | ||
| 268 | unsigned long data_addr = io_ports->data_addr; | ||
| 269 | u8 io_32bit = drive->io_32bit; | ||
| 270 | u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; | ||
| 271 | |||
| 272 | len++; | ||
| 273 | |||
| 274 | if (io_32bit) { | ||
| 275 | unsigned long uninitialized_var(flags); | ||
| 276 | |||
| 277 | if ((io_32bit & 2) && !mmio) { | ||
| 278 | local_irq_save(flags); | ||
| 279 | ata_vlb_sync(io_ports->nsect_addr); | ||
| 280 | } | ||
| 281 | |||
| 282 | if (mmio) | ||
| 283 | __ide_mm_insl((void __iomem *)data_addr, buf, len / 4); | ||
| 284 | else | ||
| 285 | insl(data_addr, buf, len / 4); | ||
| 286 | |||
| 287 | if ((io_32bit & 2) && !mmio) | ||
| 288 | local_irq_restore(flags); | ||
| 289 | |||
| 290 | if ((len & 3) >= 2) { | ||
| 291 | if (mmio) | ||
| 292 | __ide_mm_insw((void __iomem *)data_addr, | ||
| 293 | (u8 *)buf + (len & ~3), 1); | ||
| 294 | else | ||
| 295 | insw(data_addr, (u8 *)buf + (len & ~3), 1); | ||
| 296 | } | ||
| 297 | } else { | ||
| 298 | if (mmio) | ||
| 299 | __ide_mm_insw((void __iomem *)data_addr, buf, len / 2); | ||
| 300 | else | ||
| 301 | insw(data_addr, buf, len / 2); | ||
| 302 | } | ||
| 303 | } | ||
| 304 | EXPORT_SYMBOL_GPL(ide_input_data); | ||
| 305 | |||
| 306 | /* | ||
| 307 | * This is used for most PIO data transfers *to* the IDE interface | ||
| 308 | */ | ||
| 309 | void ide_output_data(ide_drive_t *drive, struct request *rq, void *buf, | ||
| 310 | unsigned int len) | ||
| 311 | { | ||
| 312 | ide_hwif_t *hwif = drive->hwif; | ||
| 313 | struct ide_io_ports *io_ports = &hwif->io_ports; | ||
| 314 | unsigned long data_addr = io_ports->data_addr; | ||
| 315 | u8 io_32bit = drive->io_32bit; | ||
| 316 | u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; | ||
| 317 | |||
| 318 | len++; | ||
| 319 | |||
| 320 | if (io_32bit) { | ||
| 321 | unsigned long uninitialized_var(flags); | ||
| 322 | |||
| 323 | if ((io_32bit & 2) && !mmio) { | ||
| 324 | local_irq_save(flags); | ||
| 325 | ata_vlb_sync(io_ports->nsect_addr); | ||
| 326 | } | ||
| 327 | |||
| 328 | if (mmio) | ||
| 329 | __ide_mm_outsl((void __iomem *)data_addr, buf, len / 4); | ||
| 330 | else | ||
| 331 | outsl(data_addr, buf, len / 4); | ||
| 332 | |||
| 333 | if ((io_32bit & 2) && !mmio) | ||
| 334 | local_irq_restore(flags); | ||
| 335 | |||
| 336 | if ((len & 3) >= 2) { | ||
| 337 | if (mmio) | ||
| 338 | __ide_mm_outsw((void __iomem *)data_addr, | ||
| 339 | (u8 *)buf + (len & ~3), 1); | ||
| 340 | else | ||
| 341 | outsw(data_addr, (u8 *)buf + (len & ~3), 1); | ||
| 342 | } | ||
| 343 | } else { | ||
| 344 | if (mmio) | ||
| 345 | __ide_mm_outsw((void __iomem *)data_addr, buf, len / 2); | ||
| 346 | else | ||
| 347 | outsw(data_addr, buf, len / 2); | ||
| 348 | } | ||
| 349 | } | ||
| 350 | EXPORT_SYMBOL_GPL(ide_output_data); | ||
| 351 | |||
| 352 | u8 ide_read_error(ide_drive_t *drive) | 53 | u8 ide_read_error(ide_drive_t *drive) |
| 353 | { | 54 | { |
| 354 | ide_task_t task; | 55 | ide_task_t task; |
| @@ -362,20 +63,6 @@ u8 ide_read_error(ide_drive_t *drive) | |||
| 362 | } | 63 | } |
| 363 | EXPORT_SYMBOL_GPL(ide_read_error); | 64 | EXPORT_SYMBOL_GPL(ide_read_error); |
| 364 | 65 | ||
| 365 | const struct ide_tp_ops default_tp_ops = { | ||
| 366 | .exec_command = ide_exec_command, | ||
| 367 | .read_status = ide_read_status, | ||
| 368 | .read_altstatus = ide_read_altstatus, | ||
| 369 | |||
| 370 | .set_irq = ide_set_irq, | ||
| 371 | |||
| 372 | .tf_load = ide_tf_load, | ||
| 373 | .tf_read = ide_tf_read, | ||
| 374 | |||
| 375 | .input_data = ide_input_data, | ||
| 376 | .output_data = ide_output_data, | ||
| 377 | }; | ||
| 378 | |||
| 379 | void ide_fix_driveid(u16 *id) | 66 | void ide_fix_driveid(u16 *id) |
| 380 | { | 67 | { |
| 381 | #ifndef __LITTLE_ENDIAN | 68 | #ifndef __LITTLE_ENDIAN |
