linux/drivers/ide/ide-io-std.c
<<
>>
Prefs
   1
   2#include <linux/kernel.h>
   3#include <linux/export.h>
   4#include <linux/ide.h>
   5
   6#if defined(CONFIG_ARM) || defined(CONFIG_M68K) || defined(CONFIG_MIPS) || \
   7    defined(CONFIG_PARISC) || defined(CONFIG_PPC) || defined(CONFIG_SPARC)
   8#include <asm/ide.h>
   9#else
  10#include <asm-generic/ide_iops.h>
  11#endif
  12
  13/*
  14 *      Conventional PIO operations for ATA devices
  15 */
  16
  17static u8 ide_inb(unsigned long port)
  18{
  19        return (u8) inb(port);
  20}
  21
  22static void ide_outb(u8 val, unsigned long port)
  23{
  24        outb(val, port);
  25}
  26
  27/*
  28 *      MMIO operations, typically used for SATA controllers
  29 */
  30
  31static u8 ide_mm_inb(unsigned long port)
  32{
  33        return (u8) readb((void __iomem *) port);
  34}
  35
  36static void ide_mm_outb(u8 value, unsigned long port)
  37{
  38        writeb(value, (void __iomem *) port);
  39}
  40
  41void ide_exec_command(ide_hwif_t *hwif, u8 cmd)
  42{
  43        if (hwif->host_flags & IDE_HFLAG_MMIO)
  44                writeb(cmd, (void __iomem *)hwif->io_ports.command_addr);
  45        else
  46                outb(cmd, hwif->io_ports.command_addr);
  47}
  48EXPORT_SYMBOL_GPL(ide_exec_command);
  49
  50u8 ide_read_status(ide_hwif_t *hwif)
  51{
  52        if (hwif->host_flags & IDE_HFLAG_MMIO)
  53                return readb((void __iomem *)hwif->io_ports.status_addr);
  54        else
  55                return inb(hwif->io_ports.status_addr);
  56}
  57EXPORT_SYMBOL_GPL(ide_read_status);
  58
  59u8 ide_read_altstatus(ide_hwif_t *hwif)
  60{
  61        if (hwif->host_flags & IDE_HFLAG_MMIO)
  62                return readb((void __iomem *)hwif->io_ports.ctl_addr);
  63        else
  64                return inb(hwif->io_ports.ctl_addr);
  65}
  66EXPORT_SYMBOL_GPL(ide_read_altstatus);
  67
  68void ide_write_devctl(ide_hwif_t *hwif, u8 ctl)
  69{
  70        if (hwif->host_flags & IDE_HFLAG_MMIO)
  71                writeb(ctl, (void __iomem *)hwif->io_ports.ctl_addr);
  72        else
  73                outb(ctl, hwif->io_ports.ctl_addr);
  74}
  75EXPORT_SYMBOL_GPL(ide_write_devctl);
  76
  77void ide_dev_select(ide_drive_t *drive)
  78{
  79        ide_hwif_t *hwif = drive->hwif;
  80        u8 select = drive->select | ATA_DEVICE_OBS;
  81
  82        if (hwif->host_flags & IDE_HFLAG_MMIO)
  83                writeb(select, (void __iomem *)hwif->io_ports.device_addr);
  84        else
  85                outb(select, hwif->io_ports.device_addr);
  86}
  87EXPORT_SYMBOL_GPL(ide_dev_select);
  88
  89void ide_tf_load(ide_drive_t *drive, struct ide_taskfile *tf, u8 valid)
  90{
  91        ide_hwif_t *hwif = drive->hwif;
  92        struct ide_io_ports *io_ports = &hwif->io_ports;
  93        void (*tf_outb)(u8 addr, unsigned long port);
  94        u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
  95
  96        if (mmio)
  97                tf_outb = ide_mm_outb;
  98        else
  99                tf_outb = ide_outb;
 100
 101        if (valid & IDE_VALID_FEATURE)
 102                tf_outb(tf->feature, io_ports->feature_addr);
 103        if (valid & IDE_VALID_NSECT)
 104                tf_outb(tf->nsect, io_ports->nsect_addr);
 105        if (valid & IDE_VALID_LBAL)
 106                tf_outb(tf->lbal, io_ports->lbal_addr);
 107        if (valid & IDE_VALID_LBAM)
 108                tf_outb(tf->lbam, io_ports->lbam_addr);
 109        if (valid & IDE_VALID_LBAH)
 110                tf_outb(tf->lbah, io_ports->lbah_addr);
 111        if (valid & IDE_VALID_DEVICE)
 112                tf_outb(tf->device, io_ports->device_addr);
 113}
 114EXPORT_SYMBOL_GPL(ide_tf_load);
 115
 116void ide_tf_read(ide_drive_t *drive, struct ide_taskfile *tf, u8 valid)
 117{
 118        ide_hwif_t *hwif = drive->hwif;
 119        struct ide_io_ports *io_ports = &hwif->io_ports;
 120        u8 (*tf_inb)(unsigned long port);
 121        u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
 122
 123        if (mmio)
 124                tf_inb  = ide_mm_inb;
 125        else
 126                tf_inb  = ide_inb;
 127
 128        if (valid & IDE_VALID_ERROR)
 129                tf->error  = tf_inb(io_ports->feature_addr);
 130        if (valid & IDE_VALID_NSECT)
 131                tf->nsect  = tf_inb(io_ports->nsect_addr);
 132        if (valid & IDE_VALID_LBAL)
 133                tf->lbal   = tf_inb(io_ports->lbal_addr);
 134        if (valid & IDE_VALID_LBAM)
 135                tf->lbam   = tf_inb(io_ports->lbam_addr);
 136        if (valid & IDE_VALID_LBAH)
 137                tf->lbah   = tf_inb(io_ports->lbah_addr);
 138        if (valid & IDE_VALID_DEVICE)
 139                tf->device = tf_inb(io_ports->device_addr);
 140}
 141EXPORT_SYMBOL_GPL(ide_tf_read);
 142
 143/*
 144 * Some localbus EIDE interfaces require a special access sequence
 145 * when using 32-bit I/O instructions to transfer data.  We call this
 146 * the "vlb_sync" sequence, which consists of three successive reads
 147 * of the sector count register location, with interrupts disabled
 148 * to ensure that the reads all happen together.
 149 */
 150static void ata_vlb_sync(unsigned long port)
 151{
 152        (void)inb(port);
 153        (void)inb(port);
 154        (void)inb(port);
 155}
 156
 157/*
 158 * This is used for most PIO data transfers *from* the IDE interface
 159 *
 160 * These routines will round up any request for an odd number of bytes,
 161 * so if an odd len is specified, be sure that there's at least one
 162 * extra byte allocated for the buffer.
 163 */
 164void ide_input_data(ide_drive_t *drive, struct ide_cmd *cmd, void *buf,
 165                    unsigned int len)
 166{
 167        ide_hwif_t *hwif = drive->hwif;
 168        struct ide_io_ports *io_ports = &hwif->io_ports;
 169        unsigned long data_addr = io_ports->data_addr;
 170        unsigned int words = (len + 1) >> 1;
 171        u8 io_32bit = drive->io_32bit;
 172        u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
 173
 174        if (io_32bit) {
 175                unsigned long uninitialized_var(flags);
 176
 177                if ((io_32bit & 2) && !mmio) {
 178                        local_irq_save(flags);
 179                        ata_vlb_sync(io_ports->nsect_addr);
 180                }
 181
 182                words >>= 1;
 183                if (mmio)
 184                        __ide_mm_insl((void __iomem *)data_addr, buf, words);
 185                else
 186                        insl(data_addr, buf, words);
 187
 188                if ((io_32bit & 2) && !mmio)
 189                        local_irq_restore(flags);
 190
 191                if (((len + 1) & 3) < 2)
 192                        return;
 193
 194                buf += len & ~3;
 195                words = 1;
 196        }
 197
 198        if (mmio)
 199                __ide_mm_insw((void __iomem *)data_addr, buf, words);
 200        else
 201                insw(data_addr, buf, words);
 202}
 203EXPORT_SYMBOL_GPL(ide_input_data);
 204
 205/*
 206 * This is used for most PIO data transfers *to* the IDE interface
 207 */
 208void ide_output_data(ide_drive_t *drive, struct ide_cmd *cmd, void *buf,
 209                     unsigned int len)
 210{
 211        ide_hwif_t *hwif = drive->hwif;
 212        struct ide_io_ports *io_ports = &hwif->io_ports;
 213        unsigned long data_addr = io_ports->data_addr;
 214        unsigned int words = (len + 1) >> 1;
 215        u8 io_32bit = drive->io_32bit;
 216        u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
 217
 218        if (io_32bit) {
 219                unsigned long uninitialized_var(flags);
 220
 221                if ((io_32bit & 2) && !mmio) {
 222                        local_irq_save(flags);
 223                        ata_vlb_sync(io_ports->nsect_addr);
 224                }
 225
 226                words >>= 1;
 227                if (mmio)
 228                        __ide_mm_outsl((void __iomem *)data_addr, buf, words);
 229                else
 230                        outsl(data_addr, buf, words);
 231
 232                if ((io_32bit & 2) && !mmio)
 233                        local_irq_restore(flags);
 234
 235                if (((len + 1) & 3) < 2)
 236                        return;
 237
 238                buf += len & ~3;
 239                words = 1;
 240        }
 241
 242        if (mmio)
 243                __ide_mm_outsw((void __iomem *)data_addr, buf, words);
 244        else
 245                outsw(data_addr, buf, words);
 246}
 247EXPORT_SYMBOL_GPL(ide_output_data);
 248
 249const struct ide_tp_ops default_tp_ops = {
 250        .exec_command           = ide_exec_command,
 251        .read_status            = ide_read_status,
 252        .read_altstatus         = ide_read_altstatus,
 253        .write_devctl           = ide_write_devctl,
 254
 255        .dev_select             = ide_dev_select,
 256        .tf_load                = ide_tf_load,
 257        .tf_read                = ide_tf_read,
 258
 259        .input_data             = ide_input_data,
 260        .output_data            = ide_output_data,
 261};
 262