via82cxxx: add support for VT6415 PCIE PATA IDE Host Controller
[safe/jmp/linux-2.6] / drivers / ide / pmac.c
index 052b9bf..7a4e788 100644 (file)
 #include <asm/pmac_feature.h>
 #include <asm/sections.h>
 #include <asm/irq.h>
-
-#ifndef CONFIG_PPC64
 #include <asm/mediabay.h>
-#endif
 
 #define DRV_NAME "ide-pmac"
 
@@ -59,13 +56,14 @@ typedef struct pmac_ide_hwif {
        int                             irq;
        int                             kind;
        int                             aapl_bus_id;
-       unsigned                        mediabay : 1;
        unsigned                        broken_dma : 1;
        unsigned                        broken_dma_warn : 1;
        struct device_node*             node;
        struct macio_dev                *mdev;
        u32                             timings[4];
        volatile u32 __iomem *          *kauai_fcr;
+       ide_hwif_t                      *hwif;
+
        /* Those fields are duplicating what is in hwif. We currently
         * can't use the hwif ones because of some assumptions that are
         * beeing done by the generic code about the kind of dma controller
@@ -854,6 +852,11 @@ sanitize_timings(pmac_ide_hwif_t *pmif)
        pmif->timings[2] = pmif->timings[3] = value2;
 }
 
+static int on_media_bay(pmac_ide_hwif_t *pmif)
+{
+       return pmif->mdev && pmif->mdev->media_bay != NULL;
+}
+
 /* Suspend call back, should be called after the child devices
  * have actually been suspended
  */
@@ -866,7 +869,7 @@ static int pmac_ide_do_suspend(pmac_ide_hwif_t *pmif)
        disable_irq(pmif->irq);
 
        /* The media bay will handle itself just fine */
-       if (pmif->mediabay)
+       if (on_media_bay(pmif))
                return 0;
        
        /* Kauai has bus control FCRs directly here */
@@ -889,7 +892,7 @@ static int pmac_ide_do_suspend(pmac_ide_hwif_t *pmif)
 static int pmac_ide_do_resume(pmac_ide_hwif_t *pmif)
 {
        /* Hard reset & re-enable controller (do we really need to reset ? -BenH) */
-       if (!pmif->mediabay) {
+       if (!on_media_bay(pmif)) {
                ppc_md.feature_call(PMAC_FTR_IDE_RESET, pmif->node, pmif->aapl_bus_id, 1);
                ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, pmif->node, pmif->aapl_bus_id, 1);
                msleep(10);
@@ -950,13 +953,11 @@ static void pmac_ide_init_dev(ide_drive_t *drive)
        pmac_ide_hwif_t *pmif =
                (pmac_ide_hwif_t *)dev_get_drvdata(hwif->gendev.parent);
 
-       if (pmif->mediabay) {
-#ifdef CONFIG_PMAC_MEDIABAY
-               if (check_media_bay_by_base(pmif->regbase, MB_CD) == 0) {
+       if (on_media_bay(pmif)) {
+               if (check_media_bay(pmif->mdev->media_bay) == MB_CD) {
                        drive->dev_flags &= ~IDE_DFLAG_NOPROBE;
                        return;
                }
-#endif
                drive->dev_flags |= IDE_DFLAG_NOPROBE;
        }
 }
@@ -1023,13 +1024,14 @@ static const struct ide_port_info pmac_port_info = {
  * Setup, register & probe an IDE channel driven by this driver, this is
  * called by one of the 2 probe functions (macio or PCI).
  */
-static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif, hw_regs_t *hw)
+static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif,
+                                          struct ide_hw *hw)
 {
        struct device_node *np = pmif->node;
        const int *bidp;
        struct ide_host *host;
        ide_hwif_t *hwif;
-       hw_regs_t *hws[] = { hw, NULL, NULL, NULL };
+       struct ide_hw *hws[] = { hw };
        struct ide_port_info d = pmac_port_info;
        int rc;
 
@@ -1071,26 +1073,23 @@ static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif, hw_regs_t *hw)
                writel(KAUAI_FCR_UATA_MAGIC |
                       KAUAI_FCR_UATA_RESET_N |
                       KAUAI_FCR_UATA_ENABLE, pmif->kauai_fcr);
-
-       pmif->mediabay = 0;
        
        /* Make sure we have sane timings */
        sanitize_timings(pmif);
 
-       host = ide_host_alloc(&d, hws);
-       if (host == NULL)
-               return -ENOMEM;
-       hwif = host->ports[0];
+       /* If we are on a media bay, wait for it to settle and lock it */
+       if (pmif->mdev)
+               lock_media_bay(pmif->mdev->media_bay);
 
-#ifndef CONFIG_PPC64
-       /* XXX FIXME: Media bay stuff need re-organizing */
-       if (np->parent && np->parent->name
-           && strcasecmp(np->parent->name, "media-bay") == 0) {
-#ifdef CONFIG_PMAC_MEDIABAY
-               media_bay_set_ide_infos(np->parent, pmif->regbase, pmif->irq,
-                                       hwif);
-#endif /* CONFIG_PMAC_MEDIABAY */
-               pmif->mediabay = 1;
+       host = ide_host_alloc(&d, hws, 1);
+       if (host == NULL) {
+               rc = -ENOMEM;
+               goto bail;
+       }
+       hwif = pmif->hwif = host->ports[0];
+
+       if (on_media_bay(pmif)) {
+               /* Fixup bus ID for media bay */
                if (!bidp)
                        pmif->aapl_bus_id = 1;
        } else if (pmif->kind == controller_ohare) {
@@ -1099,9 +1098,7 @@ static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif, hw_regs_t *hw)
                 * units, I keep the old way
                 */
                ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, 0, 1);
-       } else
-#endif
-       {
+       } else {
                /* This is necessary to enable IDE when net-booting */
                ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmif->aapl_bus_id, 1);
                ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, pmif->aapl_bus_id, 1);
@@ -1111,20 +1108,24 @@ static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif, hw_regs_t *hw)
        }
 
        printk(KERN_INFO DRV_NAME ": Found Apple %s controller (%s), "
-                        "bus ID %d%s, irq %d\n", model_name[pmif->kind],
-                        pmif->mdev ? "macio" : "PCI", pmif->aapl_bus_id,
-                        pmif->mediabay ? " (mediabay)" : "", hw->irq);
+              "bus ID %d%s, irq %d\n", model_name[pmif->kind],
+              pmif->mdev ? "macio" : "PCI", pmif->aapl_bus_id,
+              on_media_bay(pmif) ? " (mediabay)" : "", hw->irq);
 
        rc = ide_host_register(host, &d, hws);
-       if (rc) {
-               ide_host_free(host);
-               return rc;
-       }
+       if (rc)
+               pmif->hwif = NULL;
 
-       return 0;
+       if (pmif->mdev)
+               unlock_media_bay(pmif->mdev->media_bay);
+
+ bail:
+       if (rc && host)
+               ide_host_free(host);
+       return rc;
 }
 
-static void __devinit pmac_ide_init_ports(hw_regs_t *hw, unsigned long base)
+static void __devinit pmac_ide_init_ports(struct ide_hw *hw, unsigned long base)
 {
        int i;
 
@@ -1144,7 +1145,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
        unsigned long regbase;
        pmac_ide_hwif_t *pmif;
        int irq, rc;
-       hw_regs_t hw;
+       struct ide_hw hw;
 
        pmif = kzalloc(sizeof(*pmif), GFP_KERNEL);
        if (pmif == NULL)
@@ -1268,7 +1269,7 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
        void __iomem *base;
        unsigned long rbase, rlen;
        int rc;
-       hw_regs_t hw;
+       struct ide_hw hw;
 
        np = pci_device_to_OF_node(pdev);
        if (np == NULL) {
@@ -1361,6 +1362,25 @@ pmac_ide_pci_resume(struct pci_dev *pdev)
        return rc;
 }
 
+#ifdef CONFIG_PMAC_MEDIABAY
+static void pmac_ide_macio_mb_event(struct macio_dev* mdev, int mb_state)
+{
+       pmac_ide_hwif_t *pmif =
+               (pmac_ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev);
+
+       switch(mb_state) {
+       case MB_CD:
+               if (!pmif->hwif->present)
+                       ide_port_scan(pmif->hwif);
+               break;
+       default:
+               if (pmif->hwif->present)
+                       ide_port_unregister_devices(pmif->hwif);
+       }
+}
+#endif /* CONFIG_PMAC_MEDIABAY */
+
+
 static struct of_device_id pmac_ide_macio_match[] = 
 {
        {
@@ -1385,6 +1405,9 @@ static struct macio_driver pmac_ide_macio_driver =
        .probe          = pmac_ide_macio_attach,
        .suspend        = pmac_ide_macio_suspend,
        .resume         = pmac_ide_macio_resume,
+#ifdef CONFIG_PMAC_MEDIABAY
+       .mediabay_event = pmac_ide_macio_mb_event,
+#endif
 };
 
 static const struct pci_device_id pmac_ide_pci_match[] = {
@@ -1682,7 +1705,7 @@ static int __devinit pmac_ide_init_dma(ide_hwif_t *hwif,
         * The +2 is +1 for the stop command and +1 to allow for
         * aligning the start address to a multiple of 16 bytes.
         */
-       pmif->dma_table_cpu = (struct dbdma_cmd*)pci_alloc_consistent(
+       pmif->dma_table_cpu = pci_alloc_consistent(
                dev,
                (MAX_DCMDS + 2) * sizeof(struct dbdma_cmd),
                &hwif->dmatable_dma);