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_write_devctl(ide_hwif_t *hwif, u8 ctl) 68{ 69 if (hwif->host_flags & IDE_HFLAG_MMIO) 70 writeb(ctl, (void __iomem *)hwif->io_ports.ctl_addr); 71 else 72 outb(ctl, hwif->io_ports.ctl_addr); 73} 74EXPORT_SYMBOL_GPL(ide_write_devctl); 75 76void 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} 86EXPORT_SYMBOL_GPL(ide_dev_select); 87 88void ide_tf_load(ide_drive_t *drive, struct ide_taskfile *tf, u8 valid) 89{ 90 ide_hwif_t *hwif = drive->hwif; 91 struct ide_io_ports *io_ports = &hwif->io_ports; 92 void (*tf_outb)(u8 addr, unsigned long port); 93 u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; 94 95 if (mmio) 96 tf_outb = ide_mm_outb; 97 else 98 tf_outb = ide_outb; 99 100 if (valid & IDE_VALID_FEATURE) 101 tf_outb(tf->feature, io_ports->feature_addr); 102 if (valid & IDE_VALID_NSECT) 103 tf_outb(tf->nsect, io_ports->nsect_addr); 104 if (valid & IDE_VALID_LBAL) 105 tf_outb(tf->lbal, io_ports->lbal_addr); 106 if (valid & IDE_VALID_LBAM) 107 tf_outb(tf->lbam, io_ports->lbam_addr); 108 if (valid & IDE_VALID_LBAH) 109 tf_outb(tf->lbah, io_ports->lbah_addr); 110 if (valid & IDE_VALID_DEVICE) 111 tf_outb(tf->device, io_ports->device_addr); 112} 113EXPORT_SYMBOL_GPL(ide_tf_load); 114 115void ide_tf_read(ide_drive_t *drive, struct ide_taskfile *tf, u8 valid) 116{ 117 ide_hwif_t *hwif = drive->hwif; 118 struct ide_io_ports *io_ports = &hwif->io_ports; 119 u8 (*tf_inb)(unsigned long port); 120 u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; 121 122 if (mmio) 123 tf_inb = ide_mm_inb; 124 else 125 tf_inb = ide_inb; 126 127 if (valid & IDE_VALID_ERROR) 128 tf->error = tf_inb(io_ports->feature_addr); 129 if (valid & IDE_VALID_NSECT) 130 tf->nsect = tf_inb(io_ports->nsect_addr); 131 if (valid & IDE_VALID_LBAL) 132 tf->lbal = tf_inb(io_ports->lbal_addr); 133 if (valid & IDE_VALID_LBAM) 134 tf->lbam = tf_inb(io_ports->lbam_addr); 135 if (valid & IDE_VALID_LBAH) 136 tf->lbah = tf_inb(io_ports->lbah_addr); 137 if (valid & IDE_VALID_DEVICE) 138 tf->device = tf_inb(io_ports->device_addr); 139} 140EXPORT_SYMBOL_GPL(ide_tf_read); 141 142/* 143 * Some localbus EIDE interfaces require a special access sequence 144 * when using 32-bit I/O instructions to transfer data. We call this 145 * the "vlb_sync" sequence, which consists of three successive reads 146 * of the sector count register location, with interrupts disabled 147 * to ensure that the reads all happen together. 148 */ 149static void ata_vlb_sync(unsigned long port) 150{ 151 (void)inb(port); 152 (void)inb(port); 153 (void)inb(port); 154} 155 156/* 157 * This is used for most PIO data transfers *from* the IDE interface 158 * 159 * These routines will round up any request for an odd number of bytes, 160 * so if an odd len is specified, be sure that there's at least one 161 * extra byte allocated for the buffer. 162 */ 163void ide_input_data(ide_drive_t *drive, struct ide_cmd *cmd, void *buf, 164 unsigned int len) 165{ 166 ide_hwif_t *hwif = drive->hwif; 167 struct ide_io_ports *io_ports = &hwif->io_ports; 168 unsigned long data_addr = io_ports->data_addr; 169 unsigned int words = (len + 1) >> 1; 170 u8 io_32bit = drive->io_32bit; 171 u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; 172 173 if (io_32bit) { 174 unsigned long uninitialized_var(flags); 175 176 if ((io_32bit & 2) && !mmio) { 177 local_irq_save(flags); 178 ata_vlb_sync(io_ports->nsect_addr); 179 } 180 181 words >>= 1; 182 if (mmio) 183 __ide_mm_insl((void __iomem *)data_addr, buf, words); 184 else 185 insl(data_addr, buf, words); 186 187 if ((io_32bit & 2) && !mmio) 188 local_irq_restore(flags); 189 190 if (((len + 1) & 3) < 2) 191 return; 192 193 buf += len & ~3; 194 words = 1; 195 } 196 197 if (mmio) 198 __ide_mm_insw((void __iomem *)data_addr, buf, words); 199 else 200 insw(data_addr, buf, words); 201} 202EXPORT_SYMBOL_GPL(ide_input_data); 203 204/* 205 * This is used for most PIO data transfers *to* the IDE interface 206 */ 207void ide_output_data(ide_drive_t *drive, struct ide_cmd *cmd, void *buf, 208 unsigned int len) 209{ 210 ide_hwif_t *hwif = drive->hwif; 211 struct ide_io_ports *io_ports = &hwif->io_ports; 212 unsigned long data_addr = io_ports->data_addr; 213 unsigned int words = (len + 1) >> 1; 214 u8 io_32bit = drive->io_32bit; 215 u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; 216 217 if (io_32bit) { 218 unsigned long uninitialized_var(flags); 219 220 if ((io_32bit & 2) && !mmio) { 221 local_irq_save(flags); 222 ata_vlb_sync(io_ports->nsect_addr); 223 } 224 225 words >>= 1; 226 if (mmio) 227 __ide_mm_outsl((void __iomem *)data_addr, buf, words); 228 else 229 outsl(data_addr, buf, words); 230 231 if ((io_32bit & 2) && !mmio) 232 local_irq_restore(flags); 233 234 if (((len + 1) & 3) < 2) 235 return; 236 237 buf += len & ~3; 238 words = 1; 239 } 240 241 if (mmio) 242 __ide_mm_outsw((void __iomem *)data_addr, buf, words); 243 else 244 outsw(data_addr, buf, words); 245} 246EXPORT_SYMBOL_GPL(ide_output_data); 247 248const struct ide_tp_ops default_tp_ops = { 249 .exec_command = ide_exec_command, 250 .read_status = ide_read_status, 251 .read_altstatus = ide_read_altstatus, 252 .write_devctl = ide_write_devctl, 253 254 .dev_select = ide_dev_select, 255 .tf_load = ide_tf_load, 256 .tf_read = ide_tf_read, 257 258 .input_data = ide_input_data, 259 .output_data = ide_output_data, 260}; 261