]> err.no Git - linux-2.6/blobdiff - drivers/ide/pci/cs5530.c
Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
[linux-2.6] / drivers / ide / pci / cs5530.c
index 845500115f3c93d55792126124743379f2da473c..741507b4cd93b0c789599fec220240c8424e7c92 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/ide/pci/cs5530.c              Version 0.71    Mar 10 2007
+ * linux/drivers/ide/pci/cs5530.c              Version 0.74    Jul 28 2007
  *
  * Copyright (C) 2000                  Andre Hedrick <andre@linux-ide.org>
  * Copyright (C) 2000                  Mark Lord <mlord@pobox.com>
@@ -62,29 +62,29 @@ static unsigned int cs5530_pio_timings[2][5] = {
 #define CS5530_BAD_PIO(timings) (((timings)&~0x80000000)==0x0000e132)
 #define CS5530_BASEREG(hwif)   (((hwif)->dma_base & ~0xf) + ((hwif)->channel ? 0x30 : 0x20))
 
+static void cs5530_tunepio(ide_drive_t *drive, u8 pio)
+{
+       unsigned long basereg = CS5530_BASEREG(drive->hwif);
+       unsigned int format = (inl(basereg + 4) >> 31) & 1;
+
+       outl(cs5530_pio_timings[format][pio], basereg + ((drive->dn & 1)<<3));
+}
+
 /**
- *     cs5530_tuneproc         -       select/set PIO modes
+ *     cs5530_set_pio_mode     -       set PIO mode
+ *     @drive: drive
+ *     @pio: PIO mode number
  *
- *     cs5530_tuneproc() handles selection/setting of PIO modes
- *     for both the chipset and drive.
+ *     Handles setting of PIO mode for both the chipset and drive.
  *
- *     The ide_init_cs5530() routine guarantees that all drives
+ *     The init_hwif_cs5530() routine guarantees that all drives
  *     will have valid default PIO timings set up before we get here.
  */
 
-static void cs5530_tuneproc (ide_drive_t *drive, u8 pio)       /* pio=255 means "autotune" */
+static void cs5530_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
-       ide_hwif_t      *hwif = HWIF(drive);
-       unsigned int    format;
-       unsigned long basereg = CS5530_BASEREG(hwif);
-       static u8       modes[5] = { XFER_PIO_0, XFER_PIO_1, XFER_PIO_2, XFER_PIO_3, XFER_PIO_4};
-
-       pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
-       if (!cs5530_set_xfer_mode(drive, modes[pio])) {
-               format = (inl(basereg + 4) >> 31) & 1;
-               outl(cs5530_pio_timings[format][pio],
-                       basereg+(drive->select.b.unit<<3));
-       }
+       if (cs5530_set_xfer_mode(drive, XFER_PIO_0 + pio) == 0)
+               cs5530_tunepio(drive, pio);
 }
 
 /**
@@ -136,23 +136,21 @@ out:
 
 static int cs5530_config_dma(ide_drive_t *drive)
 {
-       ide_hwif_t *hwif = drive->hwif;
-       unsigned int reg, timings = 0;
-       unsigned long basereg;
-       u8 unit = drive->dn & 1, mode = 0;
+       if (ide_tune_dma(drive))
+               return 0;
 
-       /*
-        * Default to DMA-off in case we run into trouble here.
-        */
-       hwif->dma_off_quietly(drive);
+       return 1;
+}
 
-       if (ide_use_dma(drive))
-               mode = ide_max_dma_mode(drive);
+static int cs5530_tune_chipset(ide_drive_t *drive, const u8 mode)
+{
+       unsigned long basereg;
+       unsigned int reg, timings = 0;
 
        /*
         * Tell the drive to switch to the new mode; abort on failure.
         */
-       if (!mode || cs5530_set_xfer_mode(drive, mode))
+       if (cs5530_set_xfer_mode(drive, mode))
                return 1;       /* failure */
 
        /*
@@ -169,10 +167,10 @@ static int cs5530_config_dma(ide_drive_t *drive)
                        BUG();
                        break;
        }
-       basereg = CS5530_BASEREG(hwif);
+       basereg = CS5530_BASEREG(drive->hwif);
        reg = inl(basereg + 4);                 /* get drive0 config register */
        timings |= reg & 0x80000000;            /* preserve PIO format bit */
-       if (unit == 0) {                        /* are we configuring drive0? */
+       if ((drive-> dn & 1) == 0) {            /* are we configuring drive0? */
                outl(timings, basereg + 4);     /* write drive0 config register */
        } else {
                if (timings & 0x00100000)
@@ -199,6 +197,9 @@ static unsigned int __devinit init_chipset_cs5530 (struct pci_dev *dev, const ch
        struct pci_dev *master_0 = NULL, *cs5530_0 = NULL;
        unsigned long flags;
 
+       if (pci_resource_start(dev, 4) == 0)
+               return -EFAULT;
+
        dev = NULL;
        while ((dev = pci_get_device(PCI_VENDOR_ID_CYRIX, PCI_ANY_ID, dev)) != NULL) {
                switch (dev->device) {
@@ -228,7 +229,7 @@ static unsigned int __devinit init_chipset_cs5530 (struct pci_dev *dev, const ch
         */
 
        pci_set_master(cs5530_0);
-       pci_set_mwi(cs5530_0);
+       pci_try_set_mwi(cs5530_0);
 
        /*
         * Set PCI CacheLineSize to 16-bytes:
@@ -297,7 +298,9 @@ static void __devinit init_hwif_cs5530 (ide_hwif_t *hwif)
        if (hwif->mate)
                hwif->serialized = hwif->mate->serialized = 1;
 
-       hwif->tuneproc = &cs5530_tuneproc;
+       hwif->set_pio_mode = &cs5530_set_pio_mode;
+       hwif->speedproc = &cs5530_tune_chipset;
+
        basereg = CS5530_BASEREG(hwif);
        d0_timings = inl(basereg + 0);
        if (CS5530_BAD_PIO(d0_timings)) {
@@ -315,6 +318,9 @@ static void __devinit init_hwif_cs5530 (ide_hwif_t *hwif)
                        /* needs autotuning later */
        }
 
+       if (hwif->dma_base == 0)
+               return;
+
        hwif->atapi_dma = 1;
        hwif->ultra_mask = 0x07;
        hwif->mwdma_mask = 0x07;
@@ -331,9 +337,9 @@ static ide_pci_device_t cs5530_chipset __devinitdata = {
        .name           = "CS5530",
        .init_chipset   = init_chipset_cs5530,
        .init_hwif      = init_hwif_cs5530,
-       .channels       = 2,
        .autodma        = AUTODMA,
        .bootable       = ON_BOARD,
+       .pio_mask       = ATA_PIO4,
 };
 
 static int __devinit cs5530_init_one(struct pci_dev *dev, const struct pci_device_id *id)