ide-io-std.c revision 4d74c3fcf2b90487eacec511bc8c07177711c81c
1 2#include <linux/kernel.h> 3#include <linux/ide.h> 4 5#if defined(CONFIG_ARM) || defined(CONFIG_M68K) || defined(CONFIG_MIPS) || \ 6 defined(CONFIG_PARISC) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) 7#include <asm/ide.h> 8#else 9#include <asm-generic/ide_iops.h> 10#endif 11 12/* 13 * Conventional PIO operations for ATA devices 14 */ 15 16static u8 ide_inb(unsigned long port) 17{ 18 return (u8) inb(port); 19} 20 21static void ide_outb(u8 val, unsigned long port) 22{ 23 outb(val, port); 24} 25 26/* 27 * MMIO operations, typically used for SATA controllers 28 */ 29 30static u8 ide_mm_inb(unsigned long port) 31{ 32 return (u8) readb((void __iomem *) port); 33} 34 35static void ide_mm_outb(u8 value, unsigned long port) 36{ 37 writeb(value, (void __iomem *) port); 38} 39 40void ide_exec_command(ide_hwif_t *hwif, u8 cmd) 41{ 42 if (hwif->host_flags & IDE_HFLAG_MMIO) 43 writeb(cmd, (void __iomem *)hwif->io_ports.command_addr); 44 else 45 outb(cmd, hwif->io_ports.command_addr); 46} 47EXPORT_SYMBOL_GPL(ide_exec_command); 48 49u8 ide_read_status(ide_hwif_t *hwif) 50{ 51 if (hwif->host_flags & IDE_HFLAG_MMIO) 52 return readb((void __iomem *)hwif->io_ports.status_addr); 53 else 54 return inb(hwif->io_ports.status_addr); 55} 56EXPORT_SYMBOL_GPL(ide_read_status); 57 58u8 ide_read_altstatus(ide_hwif_t *hwif) 59{ 60 if (hwif->host_flags & IDE_HFLAG_MMIO) 61 return readb((void __iomem *)hwif->io_ports.ctl_addr); 62 else 63 return inb(hwif->io_ports.ctl_addr); 64} 65EXPORT_SYMBOL_GPL(ide_read_altstatus); 66 67void ide_set_irq(ide_hwif_t *hwif, int on) 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) 79 writeb(ctl, (void __iomem *)hwif->io_ports.ctl_addr); 80 else 81 outb(ctl, hwif->io_ports.ctl_addr); 82} 83EXPORT_SYMBOL_GPL(ide_set_irq); 84 85void ide_tf_load(ide_drive_t *drive, struct ide_cmd *cmd) 86{ 87 ide_hwif_t *hwif = drive->hwif; 88 struct ide_io_ports *io_ports = &hwif->io_ports; 89 struct ide_taskfile *tf = &cmd->tf; 90 void (*tf_outb)(u8 addr, unsigned long port); 91 u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; 92 u8 HIHI = (cmd->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF; 93 94 if (mmio) 95 tf_outb = ide_mm_outb; 96 else 97 tf_outb = ide_outb; 98 99 if (cmd->ftf_flags & IDE_FTFLAG_FLAGGED) 100 HIHI = 0xFF; 101 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) 112 tf_outb(tf->hob_feature, io_ports->feature_addr); 113 if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) 114 tf_outb(tf->hob_nsect, io_ports->nsect_addr); 115 if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAL) 116 tf_outb(tf->hob_lbal, io_ports->lbal_addr); 117 if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAM) 118 tf_outb(tf->hob_lbam, io_ports->lbam_addr); 119 if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAH) 120 tf_outb(tf->hob_lbah, io_ports->lbah_addr); 121 122 if (cmd->tf_flags & IDE_TFLAG_OUT_FEATURE) 123 tf_outb(tf->feature, io_ports->feature_addr); 124 if (cmd->tf_flags & IDE_TFLAG_OUT_NSECT) 125 tf_outb(tf->nsect, io_ports->nsect_addr); 126 if (cmd->tf_flags & IDE_TFLAG_OUT_LBAL) 127 tf_outb(tf->lbal, io_ports->lbal_addr); 128 if (cmd->tf_flags & IDE_TFLAG_OUT_LBAM) 129 tf_outb(tf->lbam, io_ports->lbam_addr); 130 if (cmd->tf_flags & IDE_TFLAG_OUT_LBAH) 131 tf_outb(tf->lbah, io_ports->lbah_addr); 132 133 if (cmd->tf_flags & IDE_TFLAG_OUT_DEVICE) 134 tf_outb((tf->device & HIHI) | drive->select, 135 io_ports->device_addr); 136} 137EXPORT_SYMBOL_GPL(ide_tf_load); 138 139void ide_tf_read(ide_drive_t *drive, struct ide_cmd *cmd) 140{ 141 ide_hwif_t *hwif = drive->hwif; 142 struct ide_io_ports *io_ports = &hwif->io_ports; 143 struct ide_taskfile *tf = &cmd->tf; 144 void (*tf_outb)(u8 addr, unsigned long port); 145 u8 (*tf_inb)(unsigned long port); 146 u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; 147 148 if (mmio) { 149 tf_outb = ide_mm_outb; 150 tf_inb = ide_mm_inb; 151 } else { 152 tf_outb = ide_outb; 153 tf_inb = ide_inb; 154 } 155 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 */ 169 tf_outb(ATA_DEVCTL_OBS, io_ports->ctl_addr); 170 171 if (cmd->tf_flags & IDE_TFLAG_IN_FEATURE) 172 tf->feature = tf_inb(io_ports->feature_addr); 173 if (cmd->tf_flags & IDE_TFLAG_IN_NSECT) 174 tf->nsect = tf_inb(io_ports->nsect_addr); 175 if (cmd->tf_flags & IDE_TFLAG_IN_LBAL) 176 tf->lbal = tf_inb(io_ports->lbal_addr); 177 if (cmd->tf_flags & IDE_TFLAG_IN_LBAM) 178 tf->lbam = tf_inb(io_ports->lbam_addr); 179 if (cmd->tf_flags & IDE_TFLAG_IN_LBAH) 180 tf->lbah = tf_inb(io_ports->lbah_addr); 181 if (cmd->tf_flags & IDE_TFLAG_IN_DEVICE) 182 tf->device = tf_inb(io_ports->device_addr); 183 184 if (cmd->tf_flags & IDE_TFLAG_LBA48) { 185 tf_outb(ATA_HOB | ATA_DEVCTL_OBS, io_ports->ctl_addr); 186 187 if (cmd->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) 188 tf->hob_feature = tf_inb(io_ports->feature_addr); 189 if (cmd->tf_flags & IDE_TFLAG_IN_HOB_NSECT) 190 tf->hob_nsect = tf_inb(io_ports->nsect_addr); 191 if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAL) 192 tf->hob_lbal = tf_inb(io_ports->lbal_addr); 193 if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAM) 194 tf->hob_lbam = tf_inb(io_ports->lbam_addr); 195 if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAH) 196 tf->hob_lbah = tf_inb(io_ports->lbah_addr); 197 } 198} 199EXPORT_SYMBOL_GPL(ide_tf_read); 200 201/* 202 * Some localbus EIDE interfaces require a special access sequence 203 * when using 32-bit I/O instructions to transfer data. We call this 204 * the "vlb_sync" sequence, which consists of three successive reads 205 * of the sector count register location, with interrupts disabled 206 * to ensure that the reads all happen together. 207 */ 208static void ata_vlb_sync(unsigned long port) 209{ 210 (void)inb(port); 211 (void)inb(port); 212 (void)inb(port); 213} 214 215/* 216 * This is used for most PIO data transfers *from* the IDE interface 217 * 218 * These routines will round up any request for an odd number of bytes, 219 * so if an odd len is specified, be sure that there's at least one 220 * extra byte allocated for the buffer. 221 */ 222void ide_input_data(ide_drive_t *drive, struct ide_cmd *cmd, void *buf, 223 unsigned int len) 224{ 225 ide_hwif_t *hwif = drive->hwif; 226 struct ide_io_ports *io_ports = &hwif->io_ports; 227 unsigned long data_addr = io_ports->data_addr; 228 u8 io_32bit = drive->io_32bit; 229 u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; 230 231 len++; 232 233 if (io_32bit) { 234 unsigned long uninitialized_var(flags); 235 236 if ((io_32bit & 2) && !mmio) { 237 local_irq_save(flags); 238 ata_vlb_sync(io_ports->nsect_addr); 239 } 240 241 if (mmio) 242 __ide_mm_insl((void __iomem *)data_addr, buf, len / 4); 243 else 244 insl(data_addr, buf, len / 4); 245 246 if ((io_32bit & 2) && !mmio) 247 local_irq_restore(flags); 248 249 if ((len & 3) >= 2) { 250 if (mmio) 251 __ide_mm_insw((void __iomem *)data_addr, 252 (u8 *)buf + (len & ~3), 1); 253 else 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 } 262} 263EXPORT_SYMBOL_GPL(ide_input_data); 264 265/* 266 * This is used for most PIO data transfers *to* the IDE interface 267 */ 268void ide_output_data(ide_drive_t *drive, struct ide_cmd *cmd, void *buf, 269 unsigned int len) 270{ 271 ide_hwif_t *hwif = drive->hwif; 272 struct ide_io_ports *io_ports = &hwif->io_ports; 273 unsigned long data_addr = io_ports->data_addr; 274 u8 io_32bit = drive->io_32bit; 275 u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; 276 277 len++; 278 279 if (io_32bit) { 280 unsigned long uninitialized_var(flags); 281 282 if ((io_32bit & 2) && !mmio) { 283 local_irq_save(flags); 284 ata_vlb_sync(io_ports->nsect_addr); 285 } 286 287 if (mmio) 288 __ide_mm_outsl((void __iomem *)data_addr, buf, len / 4); 289 else 290 outsl(data_addr, buf, len / 4); 291 292 if ((io_32bit & 2) && !mmio) 293 local_irq_restore(flags); 294 295 if ((len & 3) >= 2) { 296 if (mmio) 297 __ide_mm_outsw((void __iomem *)data_addr, 298 (u8 *)buf + (len & ~3), 1); 299 else 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 } 308} 309EXPORT_SYMBOL_GPL(ide_output_data); 310 311const struct ide_tp_ops default_tp_ops = { 312 .exec_command = ide_exec_command, 313 .read_status = ide_read_status, 314 .read_altstatus = ide_read_altstatus, 315 316 .set_irq = ide_set_irq, 317 318 .tf_load = ide_tf_load, 319 .tf_read = ide_tf_read, 320 321 .input_data = ide_input_data, 322 .output_data = ide_output_data, 323}; 324