Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / ide / ide-io-std.c
diff --git a/kernel/drivers/ide/ide-io-std.c b/kernel/drivers/ide/ide-io-std.c
new file mode 100644 (file)
index 0000000..4169433
--- /dev/null
@@ -0,0 +1,261 @@
+
+#include <linux/kernel.h>
+#include <linux/export.h>
+#include <linux/ide.h>
+
+#if defined(CONFIG_ARM) || defined(CONFIG_M68K) || defined(CONFIG_MIPS) || \
+    defined(CONFIG_PARISC) || defined(CONFIG_PPC) || defined(CONFIG_SPARC)
+#include <asm/ide.h>
+#else
+#include <asm-generic/ide_iops.h>
+#endif
+
+/*
+ *     Conventional PIO operations for ATA devices
+ */
+
+static u8 ide_inb(unsigned long port)
+{
+       return (u8) inb(port);
+}
+
+static void ide_outb(u8 val, unsigned long port)
+{
+       outb(val, port);
+}
+
+/*
+ *     MMIO operations, typically used for SATA controllers
+ */
+
+static u8 ide_mm_inb(unsigned long port)
+{
+       return (u8) readb((void __iomem *) port);
+}
+
+static void ide_mm_outb(u8 value, unsigned long port)
+{
+       writeb(value, (void __iomem *) port);
+}
+
+void ide_exec_command(ide_hwif_t *hwif, u8 cmd)
+{
+       if (hwif->host_flags & IDE_HFLAG_MMIO)
+               writeb(cmd, (void __iomem *)hwif->io_ports.command_addr);
+       else
+               outb(cmd, hwif->io_ports.command_addr);
+}
+EXPORT_SYMBOL_GPL(ide_exec_command);
+
+u8 ide_read_status(ide_hwif_t *hwif)
+{
+       if (hwif->host_flags & IDE_HFLAG_MMIO)
+               return readb((void __iomem *)hwif->io_ports.status_addr);
+       else
+               return inb(hwif->io_ports.status_addr);
+}
+EXPORT_SYMBOL_GPL(ide_read_status);
+
+u8 ide_read_altstatus(ide_hwif_t *hwif)
+{
+       if (hwif->host_flags & IDE_HFLAG_MMIO)
+               return readb((void __iomem *)hwif->io_ports.ctl_addr);
+       else
+               return inb(hwif->io_ports.ctl_addr);
+}
+EXPORT_SYMBOL_GPL(ide_read_altstatus);
+
+void ide_write_devctl(ide_hwif_t *hwif, u8 ctl)
+{
+       if (hwif->host_flags & IDE_HFLAG_MMIO)
+               writeb(ctl, (void __iomem *)hwif->io_ports.ctl_addr);
+       else
+               outb(ctl, hwif->io_ports.ctl_addr);
+}
+EXPORT_SYMBOL_GPL(ide_write_devctl);
+
+void ide_dev_select(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       u8 select = drive->select | ATA_DEVICE_OBS;
+
+       if (hwif->host_flags & IDE_HFLAG_MMIO)
+               writeb(select, (void __iomem *)hwif->io_ports.device_addr);
+       else
+               outb(select, hwif->io_ports.device_addr);
+}
+EXPORT_SYMBOL_GPL(ide_dev_select);
+
+void ide_tf_load(ide_drive_t *drive, struct ide_taskfile *tf, u8 valid)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       struct ide_io_ports *io_ports = &hwif->io_ports;
+       void (*tf_outb)(u8 addr, unsigned long port);
+       u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
+
+       if (mmio)
+               tf_outb = ide_mm_outb;
+       else
+               tf_outb = ide_outb;
+
+       if (valid & IDE_VALID_FEATURE)
+               tf_outb(tf->feature, io_ports->feature_addr);
+       if (valid & IDE_VALID_NSECT)
+               tf_outb(tf->nsect, io_ports->nsect_addr);
+       if (valid & IDE_VALID_LBAL)
+               tf_outb(tf->lbal, io_ports->lbal_addr);
+       if (valid & IDE_VALID_LBAM)
+               tf_outb(tf->lbam, io_ports->lbam_addr);
+       if (valid & IDE_VALID_LBAH)
+               tf_outb(tf->lbah, io_ports->lbah_addr);
+       if (valid & IDE_VALID_DEVICE)
+               tf_outb(tf->device, io_ports->device_addr);
+}
+EXPORT_SYMBOL_GPL(ide_tf_load);
+
+void ide_tf_read(ide_drive_t *drive, struct ide_taskfile *tf, u8 valid)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       struct ide_io_ports *io_ports = &hwif->io_ports;
+       u8 (*tf_inb)(unsigned long port);
+       u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
+
+       if (mmio)
+               tf_inb  = ide_mm_inb;
+       else
+               tf_inb  = ide_inb;
+
+       if (valid & IDE_VALID_ERROR)
+               tf->error  = tf_inb(io_ports->feature_addr);
+       if (valid & IDE_VALID_NSECT)
+               tf->nsect  = tf_inb(io_ports->nsect_addr);
+       if (valid & IDE_VALID_LBAL)
+               tf->lbal   = tf_inb(io_ports->lbal_addr);
+       if (valid & IDE_VALID_LBAM)
+               tf->lbam   = tf_inb(io_ports->lbam_addr);
+       if (valid & IDE_VALID_LBAH)
+               tf->lbah   = tf_inb(io_ports->lbah_addr);
+       if (valid & IDE_VALID_DEVICE)
+               tf->device = tf_inb(io_ports->device_addr);
+}
+EXPORT_SYMBOL_GPL(ide_tf_read);
+
+/*
+ * Some localbus EIDE interfaces require a special access sequence
+ * when using 32-bit I/O instructions to transfer data.  We call this
+ * the "vlb_sync" sequence, which consists of three successive reads
+ * of the sector count register location, with interrupts disabled
+ * to ensure that the reads all happen together.
+ */
+static void ata_vlb_sync(unsigned long port)
+{
+       (void)inb(port);
+       (void)inb(port);
+       (void)inb(port);
+}
+
+/*
+ * This is used for most PIO data transfers *from* the IDE interface
+ *
+ * These routines will round up any request for an odd number of bytes,
+ * so if an odd len is specified, be sure that there's at least one
+ * extra byte allocated for the buffer.
+ */
+void ide_input_data(ide_drive_t *drive, struct ide_cmd *cmd, void *buf,
+                   unsigned int len)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       struct ide_io_ports *io_ports = &hwif->io_ports;
+       unsigned long data_addr = io_ports->data_addr;
+       unsigned int words = (len + 1) >> 1;
+       u8 io_32bit = drive->io_32bit;
+       u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
+
+       if (io_32bit) {
+               unsigned long uninitialized_var(flags);
+
+               if ((io_32bit & 2) && !mmio) {
+                       local_irq_save_nort(flags);
+                       ata_vlb_sync(io_ports->nsect_addr);
+               }
+
+               words >>= 1;
+               if (mmio)
+                       __ide_mm_insl((void __iomem *)data_addr, buf, words);
+               else
+                       insl(data_addr, buf, words);
+
+               if ((io_32bit & 2) && !mmio)
+                       local_irq_restore_nort(flags);
+
+               if (((len + 1) & 3) < 2)
+                       return;
+
+               buf += len & ~3;
+               words = 1;
+       }
+
+       if (mmio)
+               __ide_mm_insw((void __iomem *)data_addr, buf, words);
+       else
+               insw(data_addr, buf, words);
+}
+EXPORT_SYMBOL_GPL(ide_input_data);
+
+/*
+ * This is used for most PIO data transfers *to* the IDE interface
+ */
+void ide_output_data(ide_drive_t *drive, struct ide_cmd *cmd, void *buf,
+                    unsigned int len)
+{
+       ide_hwif_t *hwif = drive->hwif;
+       struct ide_io_ports *io_ports = &hwif->io_ports;
+       unsigned long data_addr = io_ports->data_addr;
+       unsigned int words = (len + 1) >> 1;
+       u8 io_32bit = drive->io_32bit;
+       u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
+
+       if (io_32bit) {
+               unsigned long uninitialized_var(flags);
+
+               if ((io_32bit & 2) && !mmio) {
+                       local_irq_save_nort(flags);
+                       ata_vlb_sync(io_ports->nsect_addr);
+               }
+
+               words >>= 1;
+               if (mmio)
+                       __ide_mm_outsl((void __iomem *)data_addr, buf, words);
+               else
+                       outsl(data_addr, buf, words);
+
+               if ((io_32bit & 2) && !mmio)
+                       local_irq_restore_nort(flags);
+
+               if (((len + 1) & 3) < 2)
+                       return;
+
+               buf += len & ~3;
+               words = 1;
+       }
+
+       if (mmio)
+               __ide_mm_outsw((void __iomem *)data_addr, buf, words);
+       else
+               outsw(data_addr, buf, words);
+}
+EXPORT_SYMBOL_GPL(ide_output_data);
+
+const struct ide_tp_ops default_tp_ops = {
+       .exec_command           = ide_exec_command,
+       .read_status            = ide_read_status,
+       .read_altstatus         = ide_read_altstatus,
+       .write_devctl           = ide_write_devctl,
+
+       .dev_select             = ide_dev_select,
+       .tf_load                = ide_tf_load,
+       .tf_read                = ide_tf_read,
+
+       .input_data             = ide_input_data,
+       .output_data            = ide_output_data,
+};