]> err.no Git - linux-2.6/blobdiff - drivers/ide/ide-iops.c
ide-cs: fix releasing I/O resources
[linux-2.6] / drivers / ide / ide-iops.c
index 65275454a209d3cbc727de8689824fc05d6cb440..0daf923541ffbc50fe7a9e139e8f172d882b6c78 100644 (file)
@@ -37,11 +37,6 @@ static u8 ide_inb (unsigned long port)
        return (u8) inb(port);
 }
 
-static u16 ide_inw (unsigned long port)
-{
-       return (u16) inw(port);
-}
-
 static void ide_outb (u8 val, unsigned long port)
 {
        outb(val, port);
@@ -52,18 +47,11 @@ static void ide_outbsync (ide_drive_t *drive, u8 addr, unsigned long port)
        outb(addr, port);
 }
 
-static void ide_outw (u16 val, unsigned long port)
-{
-       outw(val, port);
-}
-
 void default_hwif_iops (ide_hwif_t *hwif)
 {
        hwif->OUTB      = ide_outb;
        hwif->OUTBSYNC  = ide_outbsync;
-       hwif->OUTW      = ide_outw;
        hwif->INB       = ide_inb;
-       hwif->INW       = ide_inw;
 }
 
 /*
@@ -75,11 +63,6 @@ static u8 ide_mm_inb (unsigned long port)
        return (u8) readb((void __iomem *) port);
 }
 
-static u16 ide_mm_inw (unsigned long port)
-{
-       return (u16) readw((void __iomem *) port);
-}
-
 static void ide_mm_outb (u8 value, unsigned long port)
 {
        writeb(value, (void __iomem *) port);
@@ -90,20 +73,13 @@ static void ide_mm_outbsync (ide_drive_t *drive, u8 value, unsigned long port)
        writeb(value, (void __iomem *) port);
 }
 
-static void ide_mm_outw (u16 value, unsigned long port)
-{
-       writew(value, (void __iomem *) port);
-}
-
 void default_hwif_mmiops (ide_hwif_t *hwif)
 {
        hwif->OUTB      = ide_mm_outb;
        /* Most systems will need to override OUTBSYNC, alas however
           this one is controller specific! */
        hwif->OUTBSYNC  = ide_mm_outbsync;
-       hwif->OUTW      = ide_mm_outw;
        hwif->INB       = ide_mm_inb;
-       hwif->INW       = ide_mm_inw;
 }
 
 EXPORT_SYMBOL(default_hwif_mmiops);
@@ -119,7 +95,7 @@ void SELECT_DRIVE (ide_drive_t *drive)
        hwif->OUTB(drive->select.all, hwif->io_ports.device_addr);
 }
 
-void SELECT_MASK (ide_drive_t *drive, int mask)
+static void SELECT_MASK(ide_drive_t *drive, int mask)
 {
        const struct ide_port_ops *port_ops = drive->hwif->port_ops;
 
@@ -132,8 +108,15 @@ static void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
        ide_hwif_t *hwif = drive->hwif;
        struct ide_io_ports *io_ports = &hwif->io_ports;
        struct ide_taskfile *tf = &task->tf;
+       void (*tf_outb)(u8 addr, unsigned long port);
+       u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
        u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
 
+       if (mmio)
+               tf_outb = ide_mm_outb;
+       else
+               tf_outb = ide_outb;
+
        if (task->tf_flags & IDE_TFLAG_FLAGGED)
                HIHI = 0xFF;
 
@@ -142,34 +125,40 @@ static void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
        if ((task->tf_flags & IDE_TFLAG_NO_SELECT_MASK) == 0)
                SELECT_MASK(drive, 0);
 
-       if (task->tf_flags & IDE_TFLAG_OUT_DATA)
-               hwif->OUTW((tf->hob_data << 8) | tf->data, io_ports->data_addr);
+       if (task->tf_flags & IDE_TFLAG_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 (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
-               hwif->OUTB(tf->hob_feature, io_ports->feature_addr);
+               tf_outb(tf->hob_feature, io_ports->feature_addr);
        if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
-               hwif->OUTB(tf->hob_nsect, io_ports->nsect_addr);
+               tf_outb(tf->hob_nsect, io_ports->nsect_addr);
        if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
-               hwif->OUTB(tf->hob_lbal, io_ports->lbal_addr);
+               tf_outb(tf->hob_lbal, io_ports->lbal_addr);
        if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
-               hwif->OUTB(tf->hob_lbam, io_ports->lbam_addr);
+               tf_outb(tf->hob_lbam, io_ports->lbam_addr);
        if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
-               hwif->OUTB(tf->hob_lbah, io_ports->lbah_addr);
+               tf_outb(tf->hob_lbah, io_ports->lbah_addr);
 
        if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
-               hwif->OUTB(tf->feature, io_ports->feature_addr);
+               tf_outb(tf->feature, io_ports->feature_addr);
        if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
-               hwif->OUTB(tf->nsect, io_ports->nsect_addr);
+               tf_outb(tf->nsect, io_ports->nsect_addr);
        if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
-               hwif->OUTB(tf->lbal, io_ports->lbal_addr);
+               tf_outb(tf->lbal, io_ports->lbal_addr);
        if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
-               hwif->OUTB(tf->lbam, io_ports->lbam_addr);
+               tf_outb(tf->lbam, io_ports->lbam_addr);
        if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
-               hwif->OUTB(tf->lbah, io_ports->lbah_addr);
+               tf_outb(tf->lbah, io_ports->lbah_addr);
 
        if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
-               hwif->OUTB((tf->device & HIHI) | drive->select.all,
-                          io_ports->device_addr);
+               tf_outb((tf->device & HIHI) | drive->select.all,
+                        io_ports->device_addr);
 }
 
 static void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
@@ -177,41 +166,57 @@ static void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
        ide_hwif_t *hwif = drive->hwif;
        struct ide_io_ports *io_ports = &hwif->io_ports;
        struct ide_taskfile *tf = &task->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;
+               tf_inb  = ide_mm_inb;
+       } else {
+               tf_outb = ide_outb;
+               tf_inb  = ide_inb;
+       }
 
        if (task->tf_flags & IDE_TFLAG_IN_DATA) {
-               u16 data = hwif->INW(io_ports->data_addr);
+               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 */
-       hwif->OUTB(drive->ctl & ~0x80, io_ports->ctl_addr);
+       tf_outb(drive->ctl & ~0x80, io_ports->ctl_addr);
 
        if (task->tf_flags & IDE_TFLAG_IN_NSECT)
-               tf->nsect  = hwif->INB(io_ports->nsect_addr);
+               tf->nsect  = tf_inb(io_ports->nsect_addr);
        if (task->tf_flags & IDE_TFLAG_IN_LBAL)
-               tf->lbal   = hwif->INB(io_ports->lbal_addr);
+               tf->lbal   = tf_inb(io_ports->lbal_addr);
        if (task->tf_flags & IDE_TFLAG_IN_LBAM)
-               tf->lbam   = hwif->INB(io_ports->lbam_addr);
+               tf->lbam   = tf_inb(io_ports->lbam_addr);
        if (task->tf_flags & IDE_TFLAG_IN_LBAH)
-               tf->lbah   = hwif->INB(io_ports->lbah_addr);
+               tf->lbah   = tf_inb(io_ports->lbah_addr);
        if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
-               tf->device = hwif->INB(io_ports->device_addr);
+               tf->device = tf_inb(io_ports->device_addr);
 
        if (task->tf_flags & IDE_TFLAG_LBA48) {
-               hwif->OUTB(drive->ctl | 0x80, io_ports->ctl_addr);
+               tf_outb(drive->ctl | 0x80, io_ports->ctl_addr);
 
                if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
-                       tf->hob_feature = hwif->INB(io_ports->feature_addr);
+                       tf->hob_feature = tf_inb(io_ports->feature_addr);
                if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
-                       tf->hob_nsect   = hwif->INB(io_ports->nsect_addr);
+                       tf->hob_nsect   = tf_inb(io_ports->nsect_addr);
                if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
-                       tf->hob_lbal    = hwif->INB(io_ports->lbal_addr);
+                       tf->hob_lbal    = tf_inb(io_ports->lbal_addr);
                if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
-                       tf->hob_lbam    = hwif->INB(io_ports->lbam_addr);
+                       tf->hob_lbam    = tf_inb(io_ports->lbam_addr);
                if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
-                       tf->hob_lbah    = hwif->INB(io_ports->lbah_addr);
+                       tf->hob_lbah    = tf_inb(io_ports->lbah_addr);
        }
 }
 
@@ -222,11 +227,11 @@ static void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
  * of the sector count register location, with interrupts disabled
  * to ensure that the reads all happen together.
  */
-static void ata_vlb_sync(ide_drive_t *drive, unsigned long port)
+static void ata_vlb_sync(unsigned long port)
 {
-       (void) HWIF(drive)->INB(port);
-       (void) HWIF(drive)->INB(port);
-       (void) HWIF(drive)->INB(port);
+       (void)inb(port);
+       (void)inb(port);
+       (void)inb(port);
 }
 
 /*
@@ -250,9 +255,9 @@ static void ata_input_data(ide_drive_t *drive, struct request *rq,
        if (io_32bit) {
                unsigned long uninitialized_var(flags);
 
-               if (io_32bit & 2) {
+               if ((io_32bit & 2) && !mmio) {
                        local_irq_save(flags);
-                       ata_vlb_sync(drive, io_ports->nsect_addr);
+                       ata_vlb_sync(io_ports->nsect_addr);
                }
 
                if (mmio)
@@ -260,7 +265,7 @@ static void ata_input_data(ide_drive_t *drive, struct request *rq,
                else
                        insl(data_addr, buf, len / 4);
 
-               if (io_32bit & 2)
+               if ((io_32bit & 2) && !mmio)
                        local_irq_restore(flags);
 
                if ((len & 3) >= 2) {
@@ -293,9 +298,9 @@ static void ata_output_data(ide_drive_t *drive, struct request *rq,
        if (io_32bit) {
                unsigned long uninitialized_var(flags);
 
-               if (io_32bit & 2) {
+               if ((io_32bit & 2) && !mmio) {
                        local_irq_save(flags);
-                       ata_vlb_sync(drive, io_ports->nsect_addr);
+                       ata_vlb_sync(io_ports->nsect_addr);
                }
 
                if (mmio)
@@ -303,7 +308,7 @@ static void ata_output_data(ide_drive_t *drive, struct request *rq,
                else
                        outsl(data_addr, buf, len / 4);
 
-               if (io_32bit & 2)
+               if ((io_32bit & 2) && !mmio)
                        local_irq_restore(flags);
 
                if ((len & 3) >= 2) {
@@ -620,6 +625,8 @@ static const struct drive_list_entry ivb_list[] = {
        { "TSSTcorp CDDVDW SH-S202J"    , "SB01"        },
        { "TSSTcorp CDDVDW SH-S202N"    , "SB00"        },
        { "TSSTcorp CDDVDW SH-S202N"    , "SB01"        },
+       { "TSSTcorp CDDVDW SH-S202H"    , "SB00"        },
+       { "TSSTcorp CDDVDW SH-S202H"    , "SB01"        },
        { NULL                          , NULL          }
 };