]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/ide/pci/siimage.c
pdc202xx_new: remove ->init_setup
[linux-2.6-omap-h63xx.git] / drivers / ide / pci / siimage.c
index 1c3e354878934dd923116fe7a6723524057c8026..faf0be31ba5704ddb8f5e7c350ba832f19b3cd1b 100644 (file)
@@ -1,9 +1,10 @@
 /*
- * linux/drivers/ide/pci/siimage.c             Version 1.12    Mar 10 2007
+ * linux/drivers/ide/pci/siimage.c             Version 1.17    Oct 18 2007
  *
  * Copyright (C) 2001-2002     Andre Hedrick <andre@linux-ide.org>
  * Copyright (C) 2003          Red Hat <alan@redhat.com>
  * Copyright (C) 2007          MontaVista Software, Inc.
+ * Copyright (C) 2007          Bartlomiej Zolnierkiewicz
  *
  *  May be copied or modified under the terms of the GNU General Public License
  *
  *  unplugging/replugging the virtual CD interface when the DRAC is reset.
  *  This often causes drivers/ide/siimage to panic but is ok with the rather
  *  smarter code in libata.
+ *
+ * TODO:
+ * - IORDY fixes
+ * - VDMA support
  */
 
 #include <linux/types.h>
@@ -160,140 +165,84 @@ out:
 }
 
 /**
- *     siimage_taskfile_timing -       turn timing data to a mode
- *     @hwif: interface to query
- *
- *     Read the timing data for the interface and return the 
- *     mode that is being used.
- */
-static byte siimage_taskfile_timing (ide_hwif_t *hwif)
-{
-       u16 timing      = 0x328a;
-       unsigned long addr = siimage_selreg(hwif, 2);
-
-       if (hwif->mmio)
-               timing = hwif->INW(addr);
-       else
-               pci_read_config_word(hwif->pci_dev, addr, &timing);
-
-       switch (timing) {
-               case 0x10c1:    return 4;
-               case 0x10c3:    return 3;
-               case 0x1104:
-               case 0x1281:    return 2;
-               case 0x2283:    return 1;
-               case 0x328a:
-               default:        return 0;
-       }
-}
-
-/**
- *     simmage_tuneproc        -       tune a drive
- *     @drive: drive to tune
- *     @mode_wanted: the target operating mode
+ *     sil_set_pio_mode        -       set host controller for PIO mode
+ *     @drive: drive
+ *     @pio: PIO mode number
  *
  *     Load the timing settings for this device mode into the
  *     controller. If we are in PIO mode 3 or 4 turn on IORDY
  *     monitoring (bit 9). The TF timing is bits 31:16
  */
-static void siimage_tuneproc (ide_drive_t *drive, byte mode_wanted)
+
+static void sil_set_pio_mode(ide_drive_t *drive, u8 pio)
 {
+       const u16 tf_speed[]    = { 0x328a, 0x2283, 0x1281, 0x10c3, 0x10c1 };
+       const u16 data_speed[]  = { 0x328a, 0x2283, 0x1104, 0x10c3, 0x10c1 };
+
        ide_hwif_t *hwif        = HWIF(drive);
+       ide_drive_t *pair       = ide_get_paired_drive(drive);
        u32 speedt              = 0;
        u16 speedp              = 0;
        unsigned long addr      = siimage_seldev(drive, 0x04);
        unsigned long tfaddr    = siimage_selreg(hwif, 0x02);
-       
-       /* cheat for now and use the docs */
-       switch (mode_wanted) {
-       case 4:
-               speedp = 0x10c1;
-               speedt = 0x10c1;
-               break;
-       case 3:
-               speedp = 0x10c3;
-               speedt = 0x10c3;
-               break;
-       case 2:
-               speedp = 0x1104;
-               speedt = 0x1281;
-               break;
-       case 1:
-               speedp = 0x2283;
-               speedt = 0x2283;
-               break;
-       case 0:
-       default:
-               speedp = 0x328a;
-               speedt = 0x328a;
-               break;
+       unsigned long base      = (unsigned long)hwif->hwif_data;
+       u8 tf_pio               = pio;
+       u8 addr_mask            = hwif->channel ? (hwif->mmio ? 0xF4 : 0x84)
+                                               : (hwif->mmio ? 0xB4 : 0x80);
+       u8 mode                 = 0;
+       u8 unit                 = drive->select.b.unit;
+
+       /* trim *taskfile* PIO to the slowest of the master/slave */
+       if (pair->present) {
+               u8 pair_pio = ide_get_best_pio_mode(pair, 255, 4);
+
+               if (pair_pio < tf_pio)
+                       tf_pio = pair_pio;
        }
 
+       /* cheat for now and use the docs */
+       speedp = data_speed[pio];
+       speedt = tf_speed[tf_pio];
+
        if (hwif->mmio) {
                hwif->OUTW(speedp, addr);
                hwif->OUTW(speedt, tfaddr);
                /* Now set up IORDY */
-               if(mode_wanted == 3 || mode_wanted == 4)
+               if (pio > 2)
                        hwif->OUTW(hwif->INW(tfaddr-2)|0x200, tfaddr-2);
                else
                        hwif->OUTW(hwif->INW(tfaddr-2)&~0x200, tfaddr-2);
+
+               mode = hwif->INB(base + addr_mask);
+               mode &= ~(unit ? 0x30 : 0x03);
+               mode |= (unit ? 0x10 : 0x01);
+               hwif->OUTB(mode, base + addr_mask);
        } else {
                pci_write_config_word(hwif->pci_dev, addr, speedp);
                pci_write_config_word(hwif->pci_dev, tfaddr, speedt);
                pci_read_config_word(hwif->pci_dev, tfaddr-2, &speedp);
                speedp &= ~0x200;
                /* Set IORDY for mode 3 or 4 */
-               if(mode_wanted == 3 || mode_wanted == 4)
+               if (pio > 2)
                        speedp |= 0x200;
                pci_write_config_word(hwif->pci_dev, tfaddr-2, speedp);
+
+               pci_read_config_byte(hwif->pci_dev, addr_mask, &mode);
+               mode &= ~(unit ? 0x30 : 0x03);
+               mode |= (unit ? 0x10 : 0x01);
+               pci_write_config_byte(hwif->pci_dev, addr_mask, mode);
        }
 }
 
 /**
- *     config_siimage_chipset_for_pio  -       set drive timings
- *     @drive: drive to tune
- *     @speed we want
- *
- *     Compute the best pio mode we can for a given device. Also honour
- *     the timings for the driver when dealing with mixed devices. Some
- *     of this is ugly but its all wrapped up here
- *
- *     The SI680 can also do VDMA - we need to start using that
+ *     sil_set_dma_mode        -       set host controller for DMA mode
+ *     @drive: drive
+ *     @speed: DMA mode
  *
- *     FIXME: we use the BIOS channel timings to avoid driving the task
- *     files too fast at the disk. We need to compute the master/slave
- *     drive PIO mode properly so that we can up the speed on a hotplug
- *     system.
+ *     Tune the SiI chipset for the desired DMA mode.
  */
-static void config_siimage_chipset_for_pio (ide_drive_t *drive, byte set_speed)
-{
-       u8 channel_timings      = siimage_taskfile_timing(HWIF(drive));
-       u8 speed = 0, set_pio   = ide_get_best_pio_mode(drive, 4, 5, NULL);
 
-       /* WARNING PIO timing mess is going to happen b/w devices, argh */
-       if ((channel_timings != set_pio) && (set_pio > channel_timings))
-               set_pio = channel_timings;
-
-       siimage_tuneproc(drive, set_pio);
-       speed = XFER_PIO_0 + set_pio;
-       if (set_speed)
-               (void) ide_config_drive_speed(drive, speed);
-}
-
-/**
- *     siimage_tune_chipset    -       set controller timings
- *     @drive: Drive to set up
- *     @xferspeed: speed we want to achieve
- *
- *     Tune the SII chipset for the desired mode. If we can't achieve
- *     the desired mode then tune for a lower one, but ultimately
- *     make the thing work.
- */
-static int siimage_tune_chipset (ide_drive_t *drive, byte xferspeed)
+static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed)
 {
        u8 ultra6[]             = { 0x0F, 0x0B, 0x07, 0x05, 0x03, 0x02, 0x01 };
        u8 ultra5[]             = { 0x0C, 0x07, 0x05, 0x04, 0x02, 0x01 };
@@ -302,7 +251,6 @@ static int siimage_tune_chipset (ide_drive_t *drive, byte xferspeed)
        ide_hwif_t *hwif        = HWIF(drive);
        u16 ultra = 0, multi    = 0;
        u8 mode = 0, unit       = drive->select.b.unit;
-       u8 speed                = ide_rate_filter(drive, xferspeed);
        unsigned long base      = (unsigned long)hwif->hwif_data;
        u8 scsc = 0, addr_mask  = ((hwif->channel) ?
                                    ((hwif->mmio) ? 0xF4 : 0x84) :
@@ -330,20 +278,11 @@ static int siimage_tune_chipset (ide_drive_t *drive, byte xferspeed)
        scsc = is_sata(hwif) ? 1 : scsc;
 
        switch(speed) {
-               case XFER_PIO_4:
-               case XFER_PIO_3:
-               case XFER_PIO_2:
-               case XFER_PIO_1:
-               case XFER_PIO_0:
-                       siimage_tuneproc(drive, (speed - XFER_PIO_0));
-                       mode |= ((unit) ? 0x10 : 0x01);
-                       break;
                case XFER_MW_DMA_2:
                case XFER_MW_DMA_1:
                case XFER_MW_DMA_0:
                        multi = dma[speed - XFER_MW_DMA_0];
                        mode |= ((unit) ? 0x20 : 0x02);
-                       config_siimage_chipset_for_pio(drive, 0);
                        break;
                case XFER_UDMA_6:
                case XFER_UDMA_5:
@@ -356,10 +295,9 @@ static int siimage_tune_chipset (ide_drive_t *drive, byte xferspeed)
                        ultra |= ((scsc) ? (ultra6[speed - XFER_UDMA_0]) :
                                           (ultra5[speed - XFER_UDMA_0]));
                        mode |= ((unit) ? 0x30 : 0x03);
-                       config_siimage_chipset_for_pio(drive, 0);
                        break;
                default:
-                       return 1;
+                       return;
        }
 
        if (hwif->mmio) {
@@ -371,28 +309,6 @@ static int siimage_tune_chipset (ide_drive_t *drive, byte xferspeed)
                pci_write_config_word(hwif->pci_dev, ma, multi);
                pci_write_config_word(hwif->pci_dev, ua, ultra);
        }
-       return (ide_config_drive_speed(drive, speed));
-}
-
-/**
- *     siimage_configure_drive_for_dma -       set up for DMA transfers
- *     @drive: drive we are going to set up
- *
- *     Set up the drive for DMA, tune the controller and drive as 
- *     required. If the drive isn't suitable for DMA or we hit
- *     other problems then we will drop down to PIO and set up
- *     PIO appropriately
- */
-static int siimage_config_drive_for_dma (ide_drive_t *drive)
-{
-       if (ide_tune_dma(drive))
-               return 0;
-
-       if (ide_use_fast_pio(drive))
-               config_siimage_chipset_for_pio(drive, 1);
-
-       return -1;
 }
 
 /* returns 1 if dma irq issued, 0 otherwise */
@@ -724,13 +640,9 @@ static unsigned int setup_mmio_siimage (struct pci_dev *dev, const char *name)
 
 static unsigned int __devinit init_chipset_siimage(struct pci_dev *dev, const char *name)
 {
-       u32 class_rev   = 0;
-       u8 tmpbyte      = 0;
-       u8 BA5_EN       = 0;
+       u8 rev = dev->revision, tmpbyte = 0, BA5_EN = 0;
 
-        pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
-        class_rev &= 0xff;
-       pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (class_rev) ? 1 : 255); 
+       pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, rev ? 1 : 255);
 
        pci_read_config_byte(dev, 0x8A, &BA5_EN);
        if ((BA5_EN & 0x01) || (pci_resource_start(dev, 5))) {
@@ -909,19 +821,14 @@ static void __devinit siimage_fixup(ide_hwif_t *hwif)
 
 static void __devinit init_iops_siimage(ide_hwif_t *hwif)
 {
-       struct pci_dev *dev     = hwif->pci_dev;
-       u32 class_rev           = 0;
-
-       pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
-       class_rev &= 0xff;
-       
        hwif->hwif_data = NULL;
 
        /* Pessimal until we finish probing */
        hwif->rqsize = 15;
 
-       if (pci_get_drvdata(dev) == NULL)
+       if (pci_get_drvdata(hwif->pci_dev) == NULL)
                return;
+
        init_mmio_iops_siimage(hwif);
 }
 
@@ -957,11 +864,9 @@ static u8 __devinit ata66_siimage(ide_hwif_t *hwif)
 
 static void __devinit init_hwif_siimage(ide_hwif_t *hwif)
 {
-       hwif->autodma = 0;
-       
        hwif->resetproc = &siimage_reset;
-       hwif->speedproc = &siimage_tune_chipset;
-       hwif->tuneproc  = &siimage_tuneproc;
+       hwif->set_pio_mode = &sil_set_pio_mode;
+       hwif->set_dma_mode = &sil_set_dma_mode;
        hwif->reset_poll = &siimage_reset_poll;
        hwif->pre_reset = &siimage_pre_reset;
        hwif->udma_filter = &sil_udma_filter;
@@ -976,19 +881,14 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif)
                        first = 0;
                }
        }
-       if (!hwif->dma_base) {
-               hwif->drives[0].autotune = 1;
-               hwif->drives[1].autotune = 1;
-               return;
-       }
 
-       hwif->ultra_mask = 0x7f;
-       hwif->mwdma_mask = 0x07;
+       hwif->drives[0].autotune = hwif->drives[1].autotune = 1;
 
-       if (!is_sata(hwif))
-               hwif->atapi_dma = 1;
+       if (hwif->dma_base == 0)
+               return;
 
-       hwif->ide_dma_check = &siimage_config_drive_for_dma;
+       if (is_sata(hwif))
+               hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
 
        if (hwif->cbl != ATA_CBL_PATA40_SHORT)
                hwif->cbl = ata66_siimage(hwif);
@@ -998,15 +898,6 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif)
        } else {
                hwif->ide_dma_test_irq = & siimage_io_ide_dma_test_irq;
        }
-       
-       /*
-        *      The BIOS often doesn't set up DMA on this controller
-        *      so we always do it.
-        */
-
-       hwif->autodma = 1;
-       hwif->drives[0].autodma = hwif->autodma;
-       hwif->drives[1].autodma = hwif->autodma;
 }
 
 #define DECLARE_SII_DEV(name_str)                      \
@@ -1016,9 +907,10 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif)
                .init_iops      = init_iops_siimage,    \
                .init_hwif      = init_hwif_siimage,    \
                .fixup          = siimage_fixup,        \
-               .channels       = 2,                    \
-               .autodma        = AUTODMA,              \
-               .bootable       = ON_BOARD,             \
+               .host_flags     = IDE_HFLAG_BOOTABLE,   \
+               .pio_mask       = ATA_PIO4,             \
+               .mwdma_mask     = ATA_MWDMA2,           \
+               .udma_mask      = ATA_UDMA6,            \
        }
 
 static ide_pci_device_t siimage_chipsets[] __devinitdata = {
@@ -1041,11 +933,11 @@ static int __devinit siimage_init_one(struct pci_dev *dev, const struct pci_devi
        return ide_setup_pci_device(dev, &siimage_chipsets[id->driver_data]);
 }
 
-static struct pci_device_id siimage_pci_tbl[] = {
-       { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_680,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+static const struct pci_device_id siimage_pci_tbl[] = {
+       { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_680),    0 },
 #ifdef CONFIG_BLK_DEV_IDE_SATA
-       { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
-       { PCI_VENDOR_ID_CMD, PCI_DEVICE_ID_SII_1210SA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
+       { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_3112),   1 },
+       { PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_1210SA), 2 },
 #endif
        { 0, },
 };