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