omap: i2c: add a timeout to the busy waiting
[safe/jmp/linux-2.6] / drivers / ide / ide-io-std.c
index 570c0cc..46721c4 100644 (file)
@@ -64,137 +64,78 @@ u8 ide_read_altstatus(ide_hwif_t *hwif)
 }
 EXPORT_SYMBOL_GPL(ide_read_altstatus);
 
-void ide_set_irq(ide_hwif_t *hwif, int on)
+void ide_write_devctl(ide_hwif_t *hwif, u8 ctl)
 {
-       u8 ctl = ATA_DEVCTL_OBS;
-
-       if (on == 4) { /* hack for SRST */
-               ctl |= 4;
-               on &= ~4;
-       }
-
-       ctl |= on ? 0 : 2;
-
        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_set_irq);
+EXPORT_SYMBOL_GPL(ide_write_devctl);
 
-void ide_tf_load(ide_drive_t *drive, struct ide_cmd *cmd)
+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;
-       struct ide_taskfile *tf = &cmd->tf;
        void (*tf_outb)(u8 addr, unsigned long port);
        u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
-       u8 HIHI = (cmd->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
 
        if (mmio)
                tf_outb = ide_mm_outb;
        else
                tf_outb = ide_outb;
 
-       if (cmd->ftf_flags & IDE_FTFLAG_FLAGGED)
-               HIHI = 0xFF;
-
-       if (cmd->ftf_flags & IDE_FTFLAG_OUT_DATA) {
-               u16 data = (tf->hob_data << 8) | tf->data;
-
-               if (mmio)
-                       writew(data, (void __iomem *)io_ports->data_addr);
-               else
-                       outw(data, io_ports->data_addr);
-       }
-
-       if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
-               tf_outb(tf->hob_feature, io_ports->feature_addr);
-       if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
-               tf_outb(tf->hob_nsect, io_ports->nsect_addr);
-       if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
-               tf_outb(tf->hob_lbal, io_ports->lbal_addr);
-       if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
-               tf_outb(tf->hob_lbam, io_ports->lbam_addr);
-       if (cmd->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
-               tf_outb(tf->hob_lbah, io_ports->lbah_addr);
-
-       if (cmd->tf_flags & IDE_TFLAG_OUT_FEATURE)
+       if (valid & IDE_VALID_FEATURE)
                tf_outb(tf->feature, io_ports->feature_addr);
-       if (cmd->tf_flags & IDE_TFLAG_OUT_NSECT)
+       if (valid & IDE_VALID_NSECT)
                tf_outb(tf->nsect, io_ports->nsect_addr);
-       if (cmd->tf_flags & IDE_TFLAG_OUT_LBAL)
+       if (valid & IDE_VALID_LBAL)
                tf_outb(tf->lbal, io_ports->lbal_addr);
-       if (cmd->tf_flags & IDE_TFLAG_OUT_LBAM)
+       if (valid & IDE_VALID_LBAM)
                tf_outb(tf->lbam, io_ports->lbam_addr);
-       if (cmd->tf_flags & IDE_TFLAG_OUT_LBAH)
+       if (valid & IDE_VALID_LBAH)
                tf_outb(tf->lbah, io_ports->lbah_addr);
-
-       if (cmd->tf_flags & IDE_TFLAG_OUT_DEVICE)
-               tf_outb((tf->device & HIHI) | drive->select,
-                        io_ports->device_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_cmd *cmd)
+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;
-       struct ide_taskfile *tf = &cmd->tf;
-       void (*tf_outb)(u8 addr, unsigned long port);
        u8 (*tf_inb)(unsigned long port);
        u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
 
-       if (mmio) {
-               tf_outb = ide_mm_outb;
+       if (mmio)
                tf_inb  = ide_mm_inb;
-       } else {
-               tf_outb = ide_outb;
+       else
                tf_inb  = ide_inb;
-       }
-
-       if (cmd->ftf_flags & IDE_FTFLAG_IN_DATA) {
-               u16 data;
 
-               if (mmio)
-                       data = readw((void __iomem *)io_ports->data_addr);
-               else
-                       data = inw(io_ports->data_addr);
-
-               tf->data = data & 0xff;
-               tf->hob_data = (data >> 8) & 0xff;
-       }
-
-       /* be sure we're looking at the low order bits */
-       tf_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
-
-       if (cmd->tf_flags & IDE_TFLAG_IN_FEATURE)
-               tf->feature = tf_inb(io_ports->feature_addr);
-       if (cmd->tf_flags & IDE_TFLAG_IN_NSECT)
+       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 (cmd->tf_flags & IDE_TFLAG_IN_LBAL)
+       if (valid & IDE_VALID_LBAL)
                tf->lbal   = tf_inb(io_ports->lbal_addr);
-       if (cmd->tf_flags & IDE_TFLAG_IN_LBAM)
+       if (valid & IDE_VALID_LBAM)
                tf->lbam   = tf_inb(io_ports->lbam_addr);
-       if (cmd->tf_flags & IDE_TFLAG_IN_LBAH)
+       if (valid & IDE_VALID_LBAH)
                tf->lbah   = tf_inb(io_ports->lbah_addr);
-       if (cmd->tf_flags & IDE_TFLAG_IN_DEVICE)
+       if (valid & IDE_VALID_DEVICE)
                tf->device = tf_inb(io_ports->device_addr);
-
-       if (cmd->tf_flags & IDE_TFLAG_LBA48) {
-               tf_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr);
-
-               if (cmd->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
-                       tf->hob_feature = tf_inb(io_ports->feature_addr);
-               if (cmd->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
-                       tf->hob_nsect   = tf_inb(io_ports->nsect_addr);
-               if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
-                       tf->hob_lbal    = tf_inb(io_ports->lbal_addr);
-               if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
-                       tf->hob_lbam    = tf_inb(io_ports->lbam_addr);
-               if (cmd->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
-                       tf->hob_lbah    = tf_inb(io_ports->lbah_addr);
-       }
 }
 EXPORT_SYMBOL_GPL(ide_tf_read);
 
@@ -219,17 +160,16 @@ static void ata_vlb_sync(unsigned long port)
  * 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 request *rq, void *buf,
+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;
 
-       len++;
-
        if (io_32bit) {
                unsigned long uninitialized_var(flags);
 
@@ -238,44 +178,42 @@ void ide_input_data(ide_drive_t *drive, struct request *rq, void *buf,
                        ata_vlb_sync(io_ports->nsect_addr);
                }
 
+               words >>= 1;
                if (mmio)
-                       __ide_mm_insl((void __iomem *)data_addr, buf, len / 4);
+                       __ide_mm_insl((void __iomem *)data_addr, buf, words);
                else
-                       insl(data_addr, buf, len / 4);
+                       insl(data_addr, buf, words);
 
                if ((io_32bit & 2) && !mmio)
                        local_irq_restore(flags);
 
-               if ((len & 3) >= 2) {
-                       if (mmio)
-                               __ide_mm_insw((void __iomem *)data_addr,
-                                               (u8 *)buf + (len & ~3), 1);
-                       else
-                               insw(data_addr, (u8 *)buf + (len & ~3), 1);
-               }
-       } else {
-               if (mmio)
-                       __ide_mm_insw((void __iomem *)data_addr, buf, len / 2);
-               else
-                       insw(data_addr, buf, len / 2);
+               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 request *rq, void *buf,
+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;
 
-       len++;
-
        if (io_32bit) {
                unsigned long uninitialized_var(flags);
 
@@ -284,27 +222,26 @@ void ide_output_data(ide_drive_t *drive, struct request *rq, void *buf,
                        ata_vlb_sync(io_ports->nsect_addr);
                }
 
+               words >>= 1;
                if (mmio)
-                       __ide_mm_outsl((void __iomem *)data_addr, buf, len / 4);
+                       __ide_mm_outsl((void __iomem *)data_addr, buf, words);
                else
-                       outsl(data_addr, buf, len / 4);
+                       outsl(data_addr, buf, words);
 
                if ((io_32bit & 2) && !mmio)
                        local_irq_restore(flags);
 
-               if ((len & 3) >= 2) {
-                       if (mmio)
-                               __ide_mm_outsw((void __iomem *)data_addr,
-                                                (u8 *)buf + (len & ~3), 1);
-                       else
-                               outsw(data_addr, (u8 *)buf + (len & ~3), 1);
-               }
-       } else {
-               if (mmio)
-                       __ide_mm_outsw((void __iomem *)data_addr, buf, len / 2);
-               else
-                       outsw(data_addr, buf, len / 2);
+               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);
 
@@ -312,9 +249,9 @@ 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,
 
-       .set_irq                = ide_set_irq,
-
+       .dev_select             = ide_dev_select,
        .tf_load                = ide_tf_load,
        .tf_read                = ide_tf_read,