Revert "tty: fix a little bug in scrup, vt.c"
[safe/jmp/linux-2.6] / drivers / ide / cmd64x.c
index d1fc198..5f80312 100644 (file)
@@ -7,7 +7,8 @@
  * Copyright (C) 1998          David S. Miller (davem@redhat.com)
  *
  * Copyright (C) 1999-2002     Andre Hedrick <andre@linux-ide.org>
- * Copyright (C) 2007          MontaVista Software, Inc. <source@mvista.com>
+ * Copyright (C) 2007-2010     Bartlomiej Zolnierkiewicz
+ * Copyright (C) 2007,2009     MontaVista Software, Inc. <source@mvista.com>
  */
 
 #include <linux/module.h>
 
 #define DRV_NAME "cmd64x"
 
-#define CMD_DEBUG 0
-
-#if CMD_DEBUG
-#define cmdprintk(x...)        printk(x)
-#else
-#define cmdprintk(x...)
-#endif
-
 /*
  * CMD64x specific registers definition.
  */
 #define UDIDETCR1      0x7B
 #define DTPR1          0x7C
 
-static u8 quantize_timing(int timing, int quant)
-{
-       return (timing + quant - 1) / quant;
-}
-
-/*
- * This routine calculates active/recovery counts and then writes them into
- * the chipset registers.
- */
-static void program_cycle_times (ide_drive_t *drive, int cycle_time, int active_time)
+static void cmd64x_program_timings(ide_drive_t *drive, u8 mode)
 {
+       ide_hwif_t *hwif = drive->hwif;
        struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
-       int clock_time = 1000 / (ide_pci_clk ? ide_pci_clk : 33);
-       u8  cycle_count, active_count, recovery_count, drwtim;
+       int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
+       const unsigned long T = 1000000 / bus_speed;
        static const u8 recovery_values[] =
                {15, 15, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0};
+       static const u8 setup_values[] = {0x40, 0x40, 0x40, 0x80, 0, 0xc0};
+       static const u8 arttim_regs[4] = {ARTTIM0, ARTTIM1, ARTTIM23, ARTTIM23};
        static const u8 drwtim_regs[4] = {DRWTIM0, DRWTIM1, DRWTIM2, DRWTIM3};
+       struct ide_timing t;
+       u8 arttim = 0;
 
-       cmdprintk("program_cycle_times parameters: total=%d, active=%d\n",
-                 cycle_time, active_time);
-
-       cycle_count     = quantize_timing( cycle_time, clock_time);
-       active_count    = quantize_timing(active_time, clock_time);
-       recovery_count  = cycle_count - active_count;
+       ide_timing_compute(drive, mode, &t, T, 0);
 
        /*
         * In case we've got too long recovery phase, try to lengthen
         * the active phase
         */
-       if (recovery_count > 16) {
-               active_count += recovery_count - 16;
-               recovery_count = 16;
+       if (t.recover > 16) {
+               t.active += t.recover - 16;
+               t.recover = 16;
        }
-       if (active_count > 16)          /* shouldn't actually happen... */
-               active_count = 16;
-
-       cmdprintk("Final counts: total=%d, active=%d, recovery=%d\n",
-                 cycle_count, active_count, recovery_count);
+       if (t.active > 16)              /* shouldn't actually happen... */
+               t.active = 16;
 
        /*
         * Convert values to internal chipset representation
         */
-       recovery_count = recovery_values[recovery_count];
-       active_count  &= 0x0f;
+       t.recover = recovery_values[t.recover];
+       t.active &= 0x0f;
 
        /* Program the active/recovery counts into the DRWTIM register */
-       drwtim = (active_count << 4) | recovery_count;
-       (void) pci_write_config_byte(dev, drwtim_regs[drive->dn], drwtim);
-       cmdprintk("Write 0x%02x to reg 0x%x\n", drwtim, drwtim_regs[drive->dn]);
-}
-
-/*
- * This routine writes into the chipset registers
- * PIO setup/active/recovery timings.
- */
-static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio)
-{
-       ide_hwif_t *hwif        = drive->hwif;
-       struct pci_dev *dev     = to_pci_dev(hwif->dev);
-       struct ide_timing *t    = ide_timing_find_mode(XFER_PIO_0 + pio);
-       unsigned int cycle_time;
-       u8 setup_count, arttim = 0;
-
-       static const u8 setup_values[] = {0x40, 0x40, 0x40, 0x80, 0, 0xc0};
-       static const u8 arttim_regs[4] = {ARTTIM0, ARTTIM1, ARTTIM23, ARTTIM23};
-
-       cycle_time = ide_pio_cycle_time(drive, pio);
-
-       program_cycle_times(drive, cycle_time, t->active);
-
-       setup_count = quantize_timing(t->setup,
-                       1000 / (ide_pci_clk ? ide_pci_clk : 33));
+       pci_write_config_byte(dev, drwtim_regs[drive->dn],
+                             (t.active << 4) | t.recover);
 
        /*
         * The primary channel has individual address setup timing registers
@@ -138,15 +95,23 @@ static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio)
         * the slowest address setup timing ourselves.
         */
        if (hwif->channel) {
-               ide_drive_t *drives = hwif->drives;
+               ide_drive_t *pair = ide_get_pair_dev(drive);
 
-               drive->drive_data = setup_count;
-               setup_count = max(drives[0].drive_data, drives[1].drive_data);
+               if (pair) {
+                       struct ide_timing tp;
+
+                       ide_timing_compute(pair, pair->pio_mode, &tp, T, 0);
+                       ide_timing_merge(&t, &tp, &t, IDE_TIMING_SETUP);
+                       if (pair->dma_mode) {
+                               ide_timing_compute(pair, pair->dma_mode,
+                                               &tp, T, 0);
+                               ide_timing_merge(&tp, &t, &t, IDE_TIMING_SETUP);
+                       }
+               }
        }
 
-       if (setup_count > 5)            /* shouldn't actually happen... */
-               setup_count = 5;
-       cmdprintk("Final address setup count: %d\n", setup_count);
+       if (t.setup > 5)                /* shouldn't actually happen... */
+               t.setup = 5;
 
        /*
         * Program the address setup clocks into the ARTTIM registers.
@@ -156,9 +121,8 @@ static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio)
        if (hwif->channel)
                arttim &= ~ARTTIM23_INTR_CH1;
        arttim &= ~0xc0;
-       arttim |= setup_values[setup_count];
+       arttim |= setup_values[t.setup];
        (void) pci_write_config_byte(dev, arttim_regs[drive->dn], arttim);
-       cmdprintk("Write 0x%02x to reg 0x%x\n", arttim, arttim_regs[drive->dn]);
 }
 
 /*
@@ -166,8 +130,10 @@ static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio)
  * Special cases are 8: prefetch off, 9: prefetch on (both never worked)
  */
 
-static void cmd64x_set_pio_mode(ide_drive_t *drive, const u8 pio)
+static void cmd64x_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
+       const u8 pio = drive->pio_mode - XFER_PIO_0;
+
        /*
         * Filter out the prefetch control values
         * to prevent PIO5 from being programmed
@@ -175,20 +141,18 @@ static void cmd64x_set_pio_mode(ide_drive_t *drive, const u8 pio)
        if (pio == 8 || pio == 9)
                return;
 
-       cmd64x_tune_pio(drive, pio);
+       cmd64x_program_timings(drive, XFER_PIO_0 + pio);
 }
 
-static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed)
+static void cmd64x_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
 {
-       ide_hwif_t *hwif        = drive->hwif;
        struct pci_dev *dev     = to_pci_dev(hwif->dev);
        u8 unit                 = drive->dn & 0x01;
        u8 regU = 0, pciU       = hwif->channel ? UDIDETCR1 : UDIDETCR0;
+       const u8 speed          = drive->dma_mode;
 
-       if (speed >= XFER_SW_DMA_0) {
-               (void) pci_read_config_byte(dev, pciU, &regU);
-               regU &= ~(unit ? 0xCA : 0x35);
-       }
+       pci_read_config_byte(dev, pciU, &regU);
+       regU &= ~(unit ? 0xCA : 0x35);
 
        switch(speed) {
        case XFER_UDMA_5:
@@ -210,25 +174,20 @@ static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed)
                regU |= unit ? 0xC2 : 0x31;
                break;
        case XFER_MW_DMA_2:
-               program_cycle_times(drive, 120, 70);
-               break;
        case XFER_MW_DMA_1:
-               program_cycle_times(drive, 150, 80);
-               break;
        case XFER_MW_DMA_0:
-               program_cycle_times(drive, 480, 215);
+               cmd64x_program_timings(drive, speed);
                break;
        }
 
-       if (speed >= XFER_SW_DMA_0)
-               (void) pci_write_config_byte(dev, pciU, regU);
+       pci_write_config_byte(dev, pciU, regU);
 }
 
-static int cmd648_dma_end(ide_drive_t *drive)
+static void cmd648_clear_irq(ide_drive_t *drive)
 {
        ide_hwif_t *hwif        = drive->hwif;
-       unsigned long base      = hwif->dma_base - (hwif->channel * 8);
-       int err                 = ide_dma_end(drive);
+       struct pci_dev *dev     = to_pci_dev(hwif->dev);
+       unsigned long base      = pci_resource_start(dev, 4);
        u8  irq_mask            = hwif->channel ? MRDMODE_INTR_CH1 :
                                                  MRDMODE_INTR_CH0;
        u8  mrdmode             = inb(base + 1);
@@ -236,11 +195,9 @@ static int cmd648_dma_end(ide_drive_t *drive)
        /* clear the interrupt bit */
        outb((mrdmode & ~(MRDMODE_INTR_CH0 | MRDMODE_INTR_CH1)) | irq_mask,
             base + 1);
-
-       return err;
 }
 
-static int cmd64x_dma_end(ide_drive_t *drive)
+static void cmd64x_clear_irq(ide_drive_t *drive)
 {
        ide_hwif_t *hwif        = drive->hwif;
        struct pci_dev *dev     = to_pci_dev(hwif->dev);
@@ -248,62 +205,40 @@ static int cmd64x_dma_end(ide_drive_t *drive)
        u8  irq_mask            = hwif->channel ? ARTTIM23_INTR_CH1 :
                                                  CFR_INTR_CH0;
        u8  irq_stat            = 0;
-       int err                 = ide_dma_end(drive);
 
        (void) pci_read_config_byte(dev, irq_reg, &irq_stat);
        /* clear the interrupt bit */
        (void) pci_write_config_byte(dev, irq_reg, irq_stat | irq_mask);
-
-       return err;
 }
 
-static int cmd648_dma_test_irq(ide_drive_t *drive)
+static int cmd648_test_irq(ide_hwif_t *hwif)
 {
-       ide_hwif_t *hwif        = drive->hwif;
-       unsigned long base      = hwif->dma_base - (hwif->channel * 8);
+       struct pci_dev *dev     = to_pci_dev(hwif->dev);
+       unsigned long base      = pci_resource_start(dev, 4);
        u8 irq_mask             = hwif->channel ? MRDMODE_INTR_CH1 :
                                                  MRDMODE_INTR_CH0;
-       u8 dma_stat             = inb(hwif->dma_base + ATA_DMA_STATUS);
        u8 mrdmode              = inb(base + 1);
 
-#ifdef DEBUG
-       printk("%s: dma_stat: 0x%02x mrdmode: 0x%02x irq_mask: 0x%02x\n",
-              drive->name, dma_stat, mrdmode, irq_mask);
-#endif
-       if (!(mrdmode & irq_mask))
-               return 0;
+       pr_debug("%s: mrdmode: 0x%02x irq_mask: 0x%02x\n",
+                hwif->name, mrdmode, irq_mask);
 
-       /* return 1 if INTR asserted */
-       if (dma_stat & 4)
-               return 1;
-
-       return 0;
+       return (mrdmode & irq_mask) ? 1 : 0;
 }
 
-static int cmd64x_dma_test_irq(ide_drive_t *drive)
+static int cmd64x_test_irq(ide_hwif_t *hwif)
 {
-       ide_hwif_t *hwif        = drive->hwif;
        struct pci_dev *dev     = to_pci_dev(hwif->dev);
        int irq_reg             = hwif->channel ? ARTTIM23 : CFR;
        u8  irq_mask            = hwif->channel ? ARTTIM23_INTR_CH1 :
                                                  CFR_INTR_CH0;
-       u8  dma_stat            = inb(hwif->dma_base + ATA_DMA_STATUS);
        u8  irq_stat            = 0;
 
        (void) pci_read_config_byte(dev, irq_reg, &irq_stat);
 
-#ifdef DEBUG
-       printk("%s: dma_stat: 0x%02x irq_stat: 0x%02x irq_mask: 0x%02x\n",
-              drive->name, dma_stat, irq_stat, irq_mask);
-#endif
-       if (!(irq_stat & irq_mask))
-               return 0;
-
-       /* return 1 if INTR asserted */
-       if (dma_stat & 4)
-               return 1;
+       pr_debug("%s: irq_stat: 0x%02x irq_mask: 0x%02x\n",
+                hwif->name, irq_stat, irq_mask);
 
-       return 0;
+       return (irq_stat & irq_mask) ? 1 : 0;
 }
 
 /*
@@ -316,7 +251,6 @@ static int cmd646_1_dma_end(ide_drive_t *drive)
        ide_hwif_t *hwif = drive->hwif;
        u8 dma_stat = 0, dma_cmd = 0;
 
-       drive->waiting_for_dma = 0;
        /* get DMA status */
        dma_stat = inb(hwif->dma_base + ATA_DMA_STATUS);
        /* read DMA command state */
@@ -325,13 +259,11 @@ static int cmd646_1_dma_end(ide_drive_t *drive)
        outb(dma_cmd & ~1, hwif->dma_base + ATA_DMA_CMD);
        /* clear the INTR & ERROR bits */
        outb(dma_stat | 6, hwif->dma_base + ATA_DMA_STATUS);
-       /* and free any DMA resources */
-       ide_destroy_dmatable(drive);
        /* verify good DMA status */
        return (dma_stat & 7) != 4;
 }
 
-static unsigned int init_chipset_cmd64x(struct pci_dev *dev)
+static int init_chipset_cmd64x(struct pci_dev *dev)
 {
        u8 mrdmode = 0;
 
@@ -371,40 +303,28 @@ static u8 cmd64x_cable_detect(ide_hwif_t *hwif)
 static const struct ide_port_ops cmd64x_port_ops = {
        .set_pio_mode           = cmd64x_set_pio_mode,
        .set_dma_mode           = cmd64x_set_dma_mode,
+       .clear_irq              = cmd64x_clear_irq,
+       .test_irq               = cmd64x_test_irq,
        .cable_detect           = cmd64x_cable_detect,
 };
 
-static const struct ide_dma_ops cmd64x_dma_ops = {
-       .dma_host_set           = ide_dma_host_set,
-       .dma_setup              = ide_dma_setup,
-       .dma_exec_cmd           = ide_dma_exec_cmd,
-       .dma_start              = ide_dma_start,
-       .dma_end                = cmd64x_dma_end,
-       .dma_test_irq           = cmd64x_dma_test_irq,
-       .dma_lost_irq           = ide_dma_lost_irq,
-       .dma_timeout            = ide_dma_timeout,
+static const struct ide_port_ops cmd648_port_ops = {
+       .set_pio_mode           = cmd64x_set_pio_mode,
+       .set_dma_mode           = cmd64x_set_dma_mode,
+       .clear_irq              = cmd648_clear_irq,
+       .test_irq               = cmd648_test_irq,
+       .cable_detect           = cmd64x_cable_detect,
 };
 
 static const struct ide_dma_ops cmd646_rev1_dma_ops = {
        .dma_host_set           = ide_dma_host_set,
        .dma_setup              = ide_dma_setup,
-       .dma_exec_cmd           = ide_dma_exec_cmd,
        .dma_start              = ide_dma_start,
        .dma_end                = cmd646_1_dma_end,
        .dma_test_irq           = ide_dma_test_irq,
        .dma_lost_irq           = ide_dma_lost_irq,
-       .dma_timeout            = ide_dma_timeout,
-};
-
-static const struct ide_dma_ops cmd648_dma_ops = {
-       .dma_host_set           = ide_dma_host_set,
-       .dma_setup              = ide_dma_setup,
-       .dma_exec_cmd           = ide_dma_exec_cmd,
-       .dma_start              = ide_dma_start,
-       .dma_end                = cmd648_dma_end,
-       .dma_test_irq           = cmd648_dma_test_irq,
-       .dma_lost_irq           = ide_dma_lost_irq,
-       .dma_timeout            = ide_dma_timeout,
+       .dma_timer_expiry       = ide_dma_sff_timer_expiry,
+       .dma_sff_read_status    = ide_dma_sff_read_status,
 };
 
 static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
@@ -413,9 +333,9 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
                .init_chipset   = init_chipset_cmd64x,
                .enablebits     = {{0x00,0x00,0x00}, {0x51,0x08,0x08}},
                .port_ops       = &cmd64x_port_ops,
-               .dma_ops        = &cmd64x_dma_ops,
                .host_flags     = IDE_HFLAG_CLEAR_SIMPLEX |
-                                 IDE_HFLAG_ABUSE_PREFETCH,
+                                 IDE_HFLAG_ABUSE_PREFETCH |
+                                 IDE_HFLAG_SERIALIZE,
                .pio_mask       = ATA_PIO5,
                .mwdma_mask     = ATA_MWDMA2,
                .udma_mask      = 0x00, /* no udma */
@@ -424,10 +344,9 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
                .name           = DRV_NAME,
                .init_chipset   = init_chipset_cmd64x,
                .enablebits     = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
-               .port_ops       = &cmd64x_port_ops,
-               .dma_ops        = &cmd648_dma_ops,
-               .host_flags     = IDE_HFLAG_SERIALIZE |
-                                 IDE_HFLAG_ABUSE_PREFETCH,
+               .port_ops       = &cmd648_port_ops,
+               .host_flags     = IDE_HFLAG_ABUSE_PREFETCH |
+                                 IDE_HFLAG_SERIALIZE,
                .pio_mask       = ATA_PIO5,
                .mwdma_mask     = ATA_MWDMA2,
                .udma_mask      = ATA_UDMA2,
@@ -436,8 +355,7 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
                .name           = DRV_NAME,
                .init_chipset   = init_chipset_cmd64x,
                .enablebits     = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
-               .port_ops       = &cmd64x_port_ops,
-               .dma_ops        = &cmd648_dma_ops,
+               .port_ops       = &cmd648_port_ops,
                .host_flags     = IDE_HFLAG_ABUSE_PREFETCH,
                .pio_mask       = ATA_PIO5,
                .mwdma_mask     = ATA_MWDMA2,
@@ -447,8 +365,7 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
                .name           = DRV_NAME,
                .init_chipset   = init_chipset_cmd64x,
                .enablebits     = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
-               .port_ops       = &cmd64x_port_ops,
-               .dma_ops        = &cmd648_dma_ops,
+               .port_ops       = &cmd648_port_ops,
                .host_flags     = IDE_HFLAG_ABUSE_PREFETCH,
                .pio_mask       = ATA_PIO5,
                .mwdma_mask     = ATA_MWDMA2,
@@ -485,10 +402,9 @@ static int __devinit cmd64x_init_one(struct pci_dev *dev, const struct pci_devic
                         */
                        if (dev->revision < 3) {
                                d.enablebits[0].reg = 0;
+                               d.port_ops = &cmd64x_port_ops;
                                if (dev->revision == 1)
                                        d.dma_ops = &cmd646_rev1_dma_ops;
-                               else
-                                       d.dma_ops = &cmd64x_dma_ops;
                        }
                }
        }
@@ -527,6 +443,6 @@ static void __exit cmd64x_ide_exit(void)
 module_init(cmd64x_ide_init);
 module_exit(cmd64x_ide_exit);
 
-MODULE_AUTHOR("Eddie Dost, David Miller, Andre Hedrick");
+MODULE_AUTHOR("Eddie Dost, David Miller, Andre Hedrick, Bartlomiej Zolnierkiewicz");
 MODULE_DESCRIPTION("PCI driver module for CMD64x IDE");
 MODULE_LICENSE("GPL");