fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / ide / ppc / pmac.c
index 3625e38..91c5344 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/ide/ide-pmac.c
+ * linux/drivers/ide/ppc/pmac.c
  *
  * Support for IDE interfaces on PowerMacs.
  * These IDE interfaces are memory-mapped and have a DBDMA channel
@@ -22,7 +22,6 @@
  * big table
  * 
  */
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -34,6 +33,7 @@
 #include <linux/pci.h>
 #include <linux/adb.h>
 #include <linux/pmu.h>
+#include <linux/scatterlist.h>
 
 #include <asm/prom.h>
 #include <asm/io.h>
@@ -51,9 +51,7 @@
 
 #include "ide-timing.h"
 
-extern void ide_do_request(ide_hwgroup_t *hwgroup, int masked_irq);
-
-#define IDE_PMAC_DEBUG
+#undef IDE_PMAC_DEBUG
 
 #define DMA_WAIT_TIMEOUT       50
 
@@ -69,6 +67,7 @@ typedef struct pmac_ide_hwif {
        struct device_node*             node;
        struct macio_dev                *mdev;
        u32                             timings[4];
+       volatile u32 __iomem *          *kauai_fcr;
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
        /* Those fields are duplicating what is in hwif. We currently
         * can't use the hwif ones because of some assumptions that are
@@ -77,15 +76,11 @@ typedef struct pmac_ide_hwif {
         */
        volatile struct dbdma_regs __iomem *    dma_regs;
        struct dbdma_cmd*               dma_table_cpu;
-       dma_addr_t                      dma_table_dma;
-       struct scatterlist*             sg_table;
-       int                             sg_nents;
-       int                             sg_dma_direction;
 #endif
        
 } pmac_ide_hwif_t;
 
-static pmac_ide_hwif_t pmac_ide[MAX_HWIFS] __pmacdata;
+static pmac_ide_hwif_t pmac_ide[MAX_HWIFS];
 static int pmac_ide_count;
 
 enum {
@@ -94,7 +89,8 @@ enum {
        controller_kl_ata3,     /* KeyLargo ATA-3 */
        controller_kl_ata4,     /* KeyLargo ATA-4 */
        controller_un_ata6,     /* UniNorth2 ATA-6 */
-       controller_k2_ata6      /* K2 ATA-6 */
+       controller_k2_ata6,     /* K2 ATA-6 */
+       controller_sh_ata6,     /* Shasta ATA-6 */
 };
 
 static const char* model_name[] = {
@@ -104,6 +100,7 @@ static const char* model_name[] = {
        "KeyLargo ATA-4",       /* KeyLargo ATA-4 (UDMA/66) */
        "UniNorth ATA-6",       /* UniNorth2 ATA-6 (UDMA/100) */
        "K2 ATA-6",             /* K2 ATA-6 (UDMA/100) */
+       "Shasta ATA-6",         /* Shasta ATA-6 (UDMA/133) */
 };
 
 /*
@@ -127,6 +124,15 @@ static const char* model_name[] = {
 #define IDE_SYSCLK_NS          30      /* 33Mhz cell */
 #define IDE_SYSCLK_66_NS       15      /* 66Mhz cell */
 
+/* 133Mhz cell, found in shasta.
+ * See comments about 100 Mhz Uninorth 2...
+ * Note that PIO_MASK and MDMA_MASK seem to overlap
+ */
+#define TR_133_PIOREG_PIO_MASK         0xff000fff
+#define TR_133_PIOREG_MDMA_MASK                0x00fff800
+#define TR_133_UDMAREG_UDMA_MASK       0x0003ffff
+#define TR_133_UDMAREG_UDMA_EN         0x00000001
+
 /* 100Mhz cell, found in Uninorth 2. I don't have much infos about
  * this one yet, it appears as a pci device (106b/0033) on uninorth
  * internal PCI bus and it's clock is controlled like gem or fw. It
@@ -214,6 +220,13 @@ static const char* model_name[] = {
 #define IDE_INTR_DMA                   0x80000000
 #define IDE_INTR_DEVICE                        0x40000000
 
+/*
+ * FCR Register on Kauai. Not sure what bit 0x4 is  ...
+ */
+#define KAUAI_FCR_UATA_MAGIC           0x00000004
+#define KAUAI_FCR_UATA_RESET_N         0x00000002
+#define KAUAI_FCR_UATA_ENABLE          0x00000001
+
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
 
 /* Rounded Multiword DMA timings
@@ -228,7 +241,7 @@ struct mdma_timings_t {
        int     cycleTime;
 };
 
-struct mdma_timings_t mdma_timings_33[] __pmacdata =
+struct mdma_timings_t mdma_timings_33[] =
 {
     { 240, 240, 480 },
     { 180, 180, 360 },
@@ -241,7 +254,7 @@ struct mdma_timings_t mdma_timings_33[] __pmacdata =
     {   0,   0,   0 }
 };
 
-struct mdma_timings_t mdma_timings_33k[] __pmacdata =
+struct mdma_timings_t mdma_timings_33k[] =
 {
     { 240, 240, 480 },
     { 180, 180, 360 },
@@ -254,7 +267,7 @@ struct mdma_timings_t mdma_timings_33k[] __pmacdata =
     {   0,   0,   0 }
 };
 
-struct mdma_timings_t mdma_timings_66[] __pmacdata =
+struct mdma_timings_t mdma_timings_66[] =
 {
     { 240, 240, 480 },
     { 180, 180, 360 },
@@ -272,7 +285,7 @@ struct {
        int     addrSetup; /* ??? */
        int     rdy2pause;
        int     wrDataSetup;
-} kl66_udma_timings[] __pmacdata =
+} kl66_udma_timings[] =
 {
     {   0, 180,  120 },        /* Mode 0 */
     {   0, 150,  90 }, /*      1 */
@@ -287,7 +300,7 @@ struct kauai_timing {
        u32     timing_reg;
 };
 
-static struct kauai_timing     kauai_pio_timings[] __pmacdata =
+static struct kauai_timing     kauai_pio_timings[] =
 {
        { 930   , 0x08000fff },
        { 600   , 0x08000a92 },
@@ -302,7 +315,7 @@ static struct kauai_timing  kauai_pio_timings[] __pmacdata =
        { 120   , 0x04000148 }
 };
 
-static struct kauai_timing     kauai_mdma_timings[] __pmacdata =
+static struct kauai_timing     kauai_mdma_timings[] =
 {
        { 1260  , 0x00fff000 },
        { 480   , 0x00618000 },
@@ -316,7 +329,7 @@ static struct kauai_timing  kauai_mdma_timings[] __pmacdata =
        { 0     , 0 },
 };
 
-static struct kauai_timing     kauai_udma_timings[] __pmacdata =
+static struct kauai_timing     kauai_udma_timings[] =
 {
        { 120   , 0x000070c0 },
        { 90    , 0x00005d80 },
@@ -327,6 +340,48 @@ static struct kauai_timing kauai_udma_timings[] __pmacdata =
        { 0     , 0 },
 };
 
+static struct kauai_timing     shasta_pio_timings[] =
+{
+       { 930   , 0x08000fff },
+       { 600   , 0x0A000c97 },
+       { 383   , 0x07000712 },
+       { 360   , 0x040003cd },
+       { 330   , 0x040003cd },
+       { 300   , 0x040003cd },
+       { 270   , 0x040003cd },
+       { 240   , 0x040003cd },
+       { 239   , 0x040003cd },
+       { 180   , 0x0400028b },
+       { 120   , 0x0400010a }
+};
+
+static struct kauai_timing     shasta_mdma_timings[] =
+{
+       { 1260  , 0x00fff000 },
+       { 480   , 0x00820800 },
+       { 360   , 0x00820800 },
+       { 270   , 0x00820800 },
+       { 240   , 0x00820800 },
+       { 210   , 0x00820800 },
+       { 180   , 0x00820800 },
+       { 150   , 0x0028b000 },
+       { 120   , 0x001ca000 },
+       { 0     , 0 },
+};
+
+static struct kauai_timing     shasta_udma133_timings[] =
+{
+       { 120   , 0x00035901, },
+       { 90    , 0x000348b1, },
+       { 60    , 0x00033881, },
+       { 45    , 0x00033861, },
+       { 30    , 0x00033841, },
+       { 20    , 0x00033031, },
+       { 15    , 0x00033021, },
+       { 0     , 0 },
+};
+
+
 static inline u32
 kauai_lookup_timing(struct kauai_timing* table, int cycle_time)
 {
@@ -361,113 +416,14 @@ static int pmac_ide_tune_chipset(ide_drive_t *drive, u8 speed);
 static void pmac_ide_tuneproc(ide_drive_t *drive, u8 pio);
 static void pmac_ide_selectproc(ide_drive_t *drive);
 static void pmac_ide_kauai_selectproc(ide_drive_t *drive);
-static int pmac_ide_dma_begin (ide_drive_t *drive);
 
 #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
 
-/*
- * Below is the code for blinking the laptop LED along with hard
- * disk activity.
- */
-
-#ifdef CONFIG_BLK_DEV_IDE_PMAC_BLINK
-
-/* Set to 50ms minimum led-on time (also used to limit frequency
- * of requests sent to the PMU
- */
-#define PMU_HD_BLINK_TIME      (HZ/50)
-
-static struct adb_request pmu_blink_on, pmu_blink_off;
-static spinlock_t pmu_blink_lock;
-static unsigned long pmu_blink_stoptime;
-static int pmu_blink_ledstate;
-static struct timer_list pmu_blink_timer;
-static int pmu_ide_blink_enabled;
-
-
-static void
-pmu_hd_blink_timeout(unsigned long data)
-{
-       unsigned long flags;
-       
-       spin_lock_irqsave(&pmu_blink_lock, flags);
-
-       /* We may have been triggered again in a racy way, check
-        * that we really want to switch it off
-        */
-       if (time_after(pmu_blink_stoptime, jiffies))
-               goto done;
-
-       /* Previous req. not complete, try 100ms more */
-       if (pmu_blink_off.complete == 0)
-               mod_timer(&pmu_blink_timer, jiffies + PMU_HD_BLINK_TIME);
-       else if (pmu_blink_ledstate) {
-               pmu_request(&pmu_blink_off, NULL, 4, 0xee, 4, 0, 0);
-               pmu_blink_ledstate = 0;
-       }
-done:
-       spin_unlock_irqrestore(&pmu_blink_lock, flags);
-}
-
-static void
-pmu_hd_kick_blink(void *data, int rw)
-{
-       unsigned long flags;
-       
-       pmu_blink_stoptime = jiffies + PMU_HD_BLINK_TIME;
-       wmb();
-       mod_timer(&pmu_blink_timer, pmu_blink_stoptime);
-       /* Fast path when LED is already ON */
-       if (pmu_blink_ledstate == 1)
-               return;
-       spin_lock_irqsave(&pmu_blink_lock, flags);
-       if (pmu_blink_on.complete && !pmu_blink_ledstate) {
-               pmu_request(&pmu_blink_on, NULL, 4, 0xee, 4, 0, 1);
-               pmu_blink_ledstate = 1;
-       }
-       spin_unlock_irqrestore(&pmu_blink_lock, flags);
-}
-
-static int
-pmu_hd_blink_init(void)
-{
-       struct device_node *dt;
-       const char *model;
-
-       /* Currently, I only enable this feature on KeyLargo based laptops,
-        * older laptops may support it (at least heathrow/paddington) but
-        * I don't feel like loading those venerable old machines with so
-        * much additional interrupt & PMU activity...
-        */
-       if (pmu_get_model() != PMU_KEYLARGO_BASED)
-               return 0;
-       
-       dt = find_devices("device-tree");
-       if (dt == NULL)
-               return 0;
-       model = (const char *)get_property(dt, "model", NULL);
-       if (model == NULL)
-               return 0;
-       if (strncmp(model, "PowerBook", strlen("PowerBook")) != 0 &&
-           strncmp(model, "iBook", strlen("iBook")) != 0)
-               return 0;
-       
-       pmu_blink_on.complete = 1;
-       pmu_blink_off.complete = 1;
-       spin_lock_init(&pmu_blink_lock);
-       init_timer(&pmu_blink_timer);
-       pmu_blink_timer.function = pmu_hd_blink_timeout;
-
-       return 1;
-}
-
-#endif /* CONFIG_BLK_DEV_IDE_PMAC_BLINK */
-
 /*
  * N.B. this can't be an initfunc, because the media-bay task can
  * call ide_[un]register at any time.
  */
-void __pmac
+void
 pmac_ide_init_hwif_ports(hw_regs_t *hw,
                              unsigned long data_port, unsigned long ctrl_port,
                              int *irq)
@@ -495,6 +451,8 @@ pmac_ide_init_hwif_ports(hw_regs_t *hw,
 
        if (irq != NULL)
                *irq = pmac_ide[ix].irq;
+
+       hw->dev = &pmac_ide[ix].mdev->ofdev.dev;
 }
 
 #define PMAC_IDE_REG(x) ((void __iomem *)(IDE_DATA_REG+(x)))
@@ -504,7 +462,7 @@ pmac_ide_init_hwif_ports(hw_regs_t *hw,
  * timing register when selecting that unit. This version is for
  * ASICs with a single timing register
  */
-static void __pmac
+static void
 pmac_ide_selectproc(ide_drive_t *drive)
 {
        pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
@@ -524,7 +482,7 @@ pmac_ide_selectproc(ide_drive_t *drive)
  * timing register when selecting that unit. This version is for
  * ASICs with a dual timing register (Kauai)
  */
-static void __pmac
+static void
 pmac_ide_kauai_selectproc(ide_drive_t *drive)
 {
        pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
@@ -545,7 +503,7 @@ pmac_ide_kauai_selectproc(ide_drive_t *drive)
 /*
  * Force an update of controller timing values for a given drive
  */
-static void __pmac
+static void
 pmac_ide_do_update_timings(ide_drive_t *drive)
 {
        pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
@@ -553,7 +511,9 @@ pmac_ide_do_update_timings(ide_drive_t *drive)
        if (pmif == NULL)
                return;
 
-       if (pmif->kind == controller_un_ata6 || pmif->kind == controller_k2_ata6)
+       if (pmif->kind == controller_sh_ata6 ||
+           pmif->kind == controller_un_ata6 ||
+           pmif->kind == controller_k2_ata6)
                pmac_ide_kauai_selectproc(drive);
        else
                pmac_ide_selectproc(drive);
@@ -576,7 +536,7 @@ pmac_outbsync(ide_drive_t *drive, u8 value, unsigned long port)
  * to sort that out sooner or later and see if I can finally get the
  * common version to work properly in all cases
  */
-static int __pmac
+static int
 pmac_ide_do_setfeature(ide_drive_t *drive, u8 command)
 {
        ide_hwif_t *hwif = HWIF(drive);
@@ -653,7 +613,7 @@ out:
 /*
  * Old tuning functions (called on hdparm -p), sets up drive PIO timings
  */
-static void __pmac
+static void
 pmac_ide_tuneproc(ide_drive_t *drive, u8 pio)
 {
        ide_pio_data_t d;
@@ -671,6 +631,14 @@ pmac_ide_tuneproc(ide_drive_t *drive, u8 pio)
        pio = ide_get_best_pio_mode(drive, pio, 4, &d);
 
        switch (pmif->kind) {
+       case controller_sh_ata6: {
+               /* 133Mhz cell */
+               u32 tr = kauai_lookup_timing(shasta_pio_timings, d.cycle_time);
+               if (tr == 0)
+                       return;
+               *timings = ((*timings) & ~TR_133_PIOREG_PIO_MASK) | tr;
+               break;
+               }
        case controller_un_ata6:
        case controller_k2_ata6: {
                /* 100Mhz cell */
@@ -736,7 +704,7 @@ pmac_ide_tuneproc(ide_drive_t *drive, u8 pio)
 /*
  * Calculate KeyLargo ATA/66 UDMA timings
  */
-static int __pmac
+static int
 set_timings_udma_ata4(u32 *timings, u8 speed)
 {
        unsigned rdyToPauseTicks, wrDataSetupTicks, addrTicks;
@@ -764,7 +732,7 @@ set_timings_udma_ata4(u32 *timings, u8 speed)
 /*
  * Calculate Kauai ATA/100 UDMA timings
  */
-static int __pmac
+static int
 set_timings_udma_ata6(u32 *pio_timings, u32 *ultra_timings, u8 speed)
 {
        struct ide_timing *t = ide_timing_find_mode(speed);
@@ -781,10 +749,30 @@ set_timings_udma_ata6(u32 *pio_timings, u32 *ultra_timings, u8 speed)
        return 0;
 }
 
+/*
+ * Calculate Shasta ATA/133 UDMA timings
+ */
+static int
+set_timings_udma_shasta(u32 *pio_timings, u32 *ultra_timings, u8 speed)
+{
+       struct ide_timing *t = ide_timing_find_mode(speed);
+       u32 tr;
+
+       if (speed > XFER_UDMA_6 || t == NULL)
+               return 1;
+       tr = kauai_lookup_timing(shasta_udma133_timings, (int)t->udma);
+       if (tr == 0)
+               return 1;
+       *ultra_timings = ((*ultra_timings) & ~TR_133_UDMAREG_UDMA_MASK) | tr;
+       *ultra_timings = (*ultra_timings) | TR_133_UDMAREG_UDMA_EN;
+
+       return 0;
+}
+
 /*
  * Calculate MDMA timings for all cells
  */
-static int __pmac
+static int
 set_timings_mdma(ide_drive_t *drive, int intf_type, u32 *timings, u32 *timings2,
                        u8 speed, int drive_cycle_time)
 {
@@ -809,6 +797,7 @@ set_timings_mdma(ide_drive_t *drive, int intf_type, u32 *timings, u32 *timings2,
                cycleTime = 150;
        /* Get the proper timing array for this controller */
        switch(intf_type) {
+               case controller_sh_ata6:
                case controller_un_ata6:
                case controller_k2_ata6:
                        break;
@@ -842,6 +831,14 @@ set_timings_mdma(ide_drive_t *drive, int intf_type, u32 *timings, u32 *timings2,
 #endif
        }
        switch(intf_type) {
+       case controller_sh_ata6: {
+               /* 133Mhz cell */
+               u32 tr = kauai_lookup_timing(shasta_mdma_timings, cycleTime);
+               if (tr == 0)
+                       return 1;
+               *timings = ((*timings) & ~TR_133_PIOREG_MDMA_MASK) | tr;
+               *timings2 = (*timings2) & ~TR_133_UDMAREG_UDMA_EN;
+               }
        case controller_un_ata6:
        case controller_k2_ata6: {
                /* 100Mhz cell */
@@ -920,7 +917,7 @@ set_timings_mdma(ide_drive_t *drive, int intf_type, u32 *timings, u32 *timings2,
  * our dedicated function is more precise as it uses the drive provided
  * cycle time value. We should probably fix this one to deal with that too...
  */
-static int __pmac
+static int
 pmac_ide_tune_chipset (ide_drive_t *drive, byte speed)
 {
        int unit = (drive->select.b.unit & 0x01);
@@ -936,9 +933,13 @@ pmac_ide_tune_chipset (ide_drive_t *drive, byte speed)
        
        switch(speed) {
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
+               case XFER_UDMA_6:
+                       if (pmif->kind != controller_sh_ata6)
+                               return 1;
                case XFER_UDMA_5:
                        if (pmif->kind != controller_un_ata6 &&
-                           pmif->kind != controller_k2_ata6)
+                           pmif->kind != controller_k2_ata6 &&
+                           pmif->kind != controller_sh_ata6)
                                return 1;
                case XFER_UDMA_4:
                case XFER_UDMA_3:
@@ -952,6 +953,8 @@ pmac_ide_tune_chipset (ide_drive_t *drive, byte speed)
                        else if (pmif->kind == controller_un_ata6
                                 || pmif->kind == controller_k2_ata6)
                                ret = set_timings_udma_ata6(timings, timings2, speed);
+                       else if (pmif->kind == controller_sh_ata6)
+                               ret = set_timings_udma_shasta(timings, timings2, speed);
                        else
                                ret = 1;                
                        break;
@@ -992,12 +995,16 @@ pmac_ide_tune_chipset (ide_drive_t *drive, byte speed)
  * Blast some well known "safe" values to the timing registers at init or
  * wakeup from sleep time, before we do real calculation
  */
-static void __pmac
+static void
 sanitize_timings(pmac_ide_hwif_t *pmif)
 {
        unsigned int value, value2 = 0;
        
        switch(pmif->kind) {
+               case controller_sh_ata6:
+                       value = 0x0a820c97;
+                       value2 = 0x00033031;
+                       break;
                case controller_un_ata6:
                case controller_k2_ata6:
                        value = 0x08618a92;
@@ -1019,13 +1026,13 @@ sanitize_timings(pmac_ide_hwif_t *pmif)
        pmif->timings[2] = pmif->timings[3] = value2;
 }
 
-unsigned long __pmac
+unsigned long
 pmac_ide_get_base(int index)
 {
        return pmac_ide[index].regbase;
 }
 
-int __pmac
+int
 pmac_ide_check_base(unsigned long base)
 {
        int ix;
@@ -1036,7 +1043,7 @@ pmac_ide_check_base(unsigned long base)
        return -1;
 }
 
-int __pmac
+int
 pmac_ide_get_irq(unsigned long base)
 {
        int ix;
@@ -1047,7 +1054,7 @@ pmac_ide_get_irq(unsigned long base)
        return 0;
 }
 
-static int ide_majors[]  __pmacdata = { 3, 22, 33, 34, 56, 57 };
+static int ide_majors[] = { 3, 22, 33, 34, 56, 57 };
 
 dev_t __init
 pmac_find_ide_boot(char *bootdevice, int n)
@@ -1083,29 +1090,22 @@ pmac_ide_do_suspend(ide_hwif_t *hwif)
        pmif->timings[0] = 0;
        pmif->timings[1] = 0;
        
-#ifdef CONFIG_BLK_DEV_IDE_PMAC_BLINK
-       /* Note: This code will be called for every hwif, thus we'll
-        * try several time to stop the LED blinker timer,  but that
-        * should be harmless
-        */
-       if (pmu_ide_blink_enabled) {
-               unsigned long flags;
-
-               /* Make sure we don't hit the PMU blink */
-               spin_lock_irqsave(&pmu_blink_lock, flags);
-               if (pmu_blink_ledstate)
-                       del_timer(&pmu_blink_timer);
-               pmu_blink_ledstate = 0;
-               spin_unlock_irqrestore(&pmu_blink_lock, flags);
-       }
-#endif /* CONFIG_BLK_DEV_IDE_PMAC_BLINK */
+       disable_irq(pmif->irq);
 
        /* The media bay will handle itself just fine */
        if (pmif->mediabay)
                return 0;
        
-       /* Disable the bus */
-       ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, pmif->node, pmif->aapl_bus_id, 0);
+       /* Kauai has bus control FCRs directly here */
+       if (pmif->kauai_fcr) {
+               u32 fcr = readl(pmif->kauai_fcr);
+               fcr &= ~(KAUAI_FCR_UATA_RESET_N | KAUAI_FCR_UATA_ENABLE);
+               writel(fcr, pmif->kauai_fcr);
+       }
+
+       /* Disable the bus on older machines and the cell on kauai */
+       ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, pmif->node, pmif->aapl_bus_id,
+                           0);
 
        return 0;
 }
@@ -1124,12 +1124,22 @@ pmac_ide_do_resume(ide_hwif_t *hwif)
                ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, pmif->node, pmif->aapl_bus_id, 1);
                msleep(10);
                ppc_md.feature_call(PMAC_FTR_IDE_RESET, pmif->node, pmif->aapl_bus_id, 0);
+
+               /* Kauai has it different */
+               if (pmif->kauai_fcr) {
+                       u32 fcr = readl(pmif->kauai_fcr);
+                       fcr |= KAUAI_FCR_UATA_RESET_N | KAUAI_FCR_UATA_ENABLE;
+                       writel(fcr, pmif->kauai_fcr);
+               }
+
                msleep(jiffies_to_msecs(IDE_WAKEUP_DELAY));
        }
 
        /* Sanitize drive timings */
        sanitize_timings(pmif);
 
+       enable_irq(pmif->irq);
+
        return 0;
 }
 
@@ -1144,11 +1154,13 @@ static int
 pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
 {
        struct device_node *np = pmif->node;
-       int *bidp, i;
+       const int *bidp;
 
        pmif->cable_80 = 0;
        pmif->broken_dma = pmif->broken_dma_warn = 0;
-       if (device_is_compatible(np, "kauai-ata"))
+       if (device_is_compatible(np, "shasta-ata"))
+               pmif->kind = controller_sh_ata6;
+       else if (device_is_compatible(np, "kauai-ata"))
                pmif->kind = controller_un_ata6;
        else if (device_is_compatible(np, "K2-UATA"))
                pmif->kind = controller_k2_ata6;
@@ -1164,16 +1176,30 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
                pmif->broken_dma = 1;
        }
 
-       bidp = (int *)get_property(np, "AAPL,bus-id", NULL);
+       bidp = get_property(np, "AAPL,bus-id", NULL);
        pmif->aapl_bus_id =  bidp ? *bidp : 0;
 
        /* Get cable type from device-tree */
        if (pmif->kind == controller_kl_ata4 || pmif->kind == controller_un_ata6
-           || pmif->kind == controller_k2_ata6) {
-               char* cable = get_property(np, "cable-type", NULL);
+           || pmif->kind == controller_k2_ata6
+           || pmif->kind == controller_sh_ata6) {
+               const char* cable = get_property(np, "cable-type", NULL);
                if (cable && !strncmp(cable, "80-", 3))
                        pmif->cable_80 = 1;
        }
+       /* G5's seem to have incorrect cable type in device-tree. Let's assume
+        * they have a 80 conductor cable, this seem to be always the case unless
+        * the user mucked around
+        */
+       if (device_is_compatible(np, "K2-UATA") ||
+           device_is_compatible(np, "shasta-ata"))
+               pmif->cable_80 = 1;
+
+       /* On Kauai-type controllers, we make sure the FCR is correct */
+       if (pmif->kauai_fcr)
+               writel(KAUAI_FCR_UATA_MAGIC |
+                      KAUAI_FCR_UATA_RESET_N |
+                      KAUAI_FCR_UATA_ENABLE, pmif->kauai_fcr);
 
        pmif->mediabay = 0;
        
@@ -1184,9 +1210,9 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
        /* XXX FIXME: Media bay stuff need re-organizing */
        if (np->parent && np->parent->name
            && strcasecmp(np->parent->name, "media-bay") == 0) {
-#ifdef CONFIG_PMAC_PBOOK
+#ifdef CONFIG_PMAC_MEDIABAY
                media_bay_set_ide_infos(np->parent, pmif->regbase, pmif->irq, hwif->index);
-#endif /* CONFIG_PMAC_PBOOK */
+#endif /* CONFIG_PMAC_MEDIABAY */
                pmif->mediabay = 1;
                if (!bidp)
                        pmif->aapl_bus_id = 1;
@@ -1223,27 +1249,24 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
        hwif->drives[0].unmask = 1;
        hwif->drives[1].unmask = 1;
        hwif->tuneproc = pmac_ide_tuneproc;
-       if (pmif->kind == controller_un_ata6 || pmif->kind == controller_k2_ata6)
+       if (pmif->kind == controller_un_ata6
+           || pmif->kind == controller_k2_ata6
+           || pmif->kind == controller_sh_ata6)
                hwif->selectproc = pmac_ide_kauai_selectproc;
        else
                hwif->selectproc = pmac_ide_selectproc;
        hwif->speedproc = pmac_ide_tune_chipset;
 
-#ifdef CONFIG_BLK_DEV_IDE_PMAC_BLINK
-       pmu_ide_blink_enabled = pmu_hd_blink_init();
-
-       if (pmu_ide_blink_enabled)
-               hwif->led_act = pmu_hd_kick_blink;
-#endif
-
        printk(KERN_INFO "ide%d: Found Apple %s controller, bus ID %d%s, irq %d\n",
               hwif->index, model_name[pmif->kind], pmif->aapl_bus_id,
               pmif->mediabay ? " (mediabay)" : "", hwif->irq);
                        
-#ifdef CONFIG_PMAC_PBOOK
+#ifdef CONFIG_PMAC_MEDIABAY
        if (pmif->mediabay && check_media_bay_by_base(pmif->regbase, MB_CD) == 0)
                hwif->noprobe = 0;
-#endif /* CONFIG_PMAC_PBOOK */
+#endif /* CONFIG_PMAC_MEDIABAY */
+
+       hwif->sg_max_nents = MAX_DCMDS;
 
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
        /* has a DBDMA controller channel */
@@ -1254,20 +1277,6 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
        /* We probe the hwif now */
        probe_hwif_init(hwif);
 
-       /* The code IDE code will have set hwif->present if we have devices attached,
-        * if we don't, the discard the interface except if we are on a media bay slot
-        */
-       if (!hwif->present && !pmif->mediabay) {
-               printk(KERN_INFO "ide%d: Bus empty, interface released.\n",
-                       hwif->index);
-               default_hwif_iops(hwif);
-               for (i = IDE_DATA_OFFSET; i <= IDE_CONTROL_OFFSET; ++i)
-                       hwif->io_ports[i] = 0;
-               hwif->chipset = ide_unknown;
-               hwif->noprobe = 1;
-               return -ENODEV;
-       }
-
        return 0;
 }
 
@@ -1275,7 +1284,7 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
  * Attach to a macio probed interface
  */
 static int __devinit
-pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_match *match)
+pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
 {
        void __iomem *base;
        unsigned long regbase;
@@ -1297,7 +1306,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_match *match)
        pmif = &pmac_ide[i];
        hwif = &ide_hwifs[i];
 
-       if (mdev->ofdev.node->n_addrs == 0) {
+       if (macio_resource_count(mdev) == 0) {
                printk(KERN_WARNING "ide%d: no address for %s\n",
                       i, mdev->ofdev.node->full_name);
                return -ENXIO;
@@ -1317,7 +1326,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_match *match)
        if (macio_irq_count(mdev) == 0) {
                printk(KERN_WARNING "ide%d: no intrs for device %s, using 13\n",
                        i, mdev->ofdev.node->full_name);
-               irq = 13;
+               irq = irq_create_mapping(NULL, 13);
        } else
                irq = macio_irq(mdev, 0);
 
@@ -1331,6 +1340,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_match *match)
        pmif->node = mdev->ofdev.node;
        pmif->regbase = regbase;
        pmif->irq = irq;
+       pmif->kauai_fcr = NULL;
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
        if (macio_resource_count(mdev) >= 2) {
                if (macio_request_resource(mdev, 1, "ide-pmac (dma)"))
@@ -1359,15 +1369,16 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_match *match)
 }
 
 static int
-pmac_ide_macio_suspend(struct macio_dev *mdev, u32 state)
+pmac_ide_macio_suspend(struct macio_dev *mdev, pm_message_t mesg)
 {
        ide_hwif_t      *hwif = (ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev);
        int             rc = 0;
 
-       if (state != mdev->ofdev.dev.power_state && state >= 2) {
+       if (mesg.event != mdev->ofdev.dev.power.power_state.event
+                       && mesg.event == PM_EVENT_SUSPEND) {
                rc = pmac_ide_do_suspend(hwif);
                if (rc == 0)
-                       mdev->ofdev.dev.power_state = state;
+                       mdev->ofdev.dev.power.power_state = mesg;
        }
 
        return rc;
@@ -1379,10 +1390,10 @@ pmac_ide_macio_resume(struct macio_dev *mdev)
        ide_hwif_t      *hwif = (ide_hwif_t *)dev_get_drvdata(&mdev->ofdev.dev);
        int             rc = 0;
        
-       if (mdev->ofdev.dev.power_state != 0) {
+       if (mdev->ofdev.dev.power.power_state.event != PM_EVENT_ON) {
                rc = pmac_ide_do_resume(hwif);
                if (rc == 0)
-                       mdev->ofdev.dev.power_state = 0;
+                       mdev->ofdev.dev.power.power_state = PMSG_ON;
        }
 
        return rc;
@@ -1444,13 +1455,9 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
        pmif->regbase = (unsigned long) base + 0x2000;
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
        pmif->dma_regs = base + 0x1000;
-#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */        
-
-       /* We use the OF node irq mapping */
-       if (np->n_intrs == 0)
-               pmif->irq = pdev->irq;
-       else
-               pmif->irq = np->intrs[0].line;
+#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
+       pmif->kauai_fcr = base;
+       pmif->irq = pdev->irq;
 
        pci_set_drvdata(pdev, hwif);
 
@@ -1467,15 +1474,16 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
 }
 
 static int
-pmac_ide_pci_suspend(struct pci_dev *pdev, u32 state)
+pmac_ide_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
 {
        ide_hwif_t      *hwif = (ide_hwif_t *)pci_get_drvdata(pdev);
        int             rc = 0;
        
-       if (state != pdev->dev.power_state && state >= 2) {
+       if (mesg.event != pdev->dev.power.power_state.event
+                       && mesg.event == PM_EVENT_SUSPEND) {
                rc = pmac_ide_do_suspend(hwif);
                if (rc == 0)
-                       pdev->dev.power_state = state;
+                       pdev->dev.power.power_state = mesg;
        }
 
        return rc;
@@ -1487,36 +1495,28 @@ pmac_ide_pci_resume(struct pci_dev *pdev)
        ide_hwif_t      *hwif = (ide_hwif_t *)pci_get_drvdata(pdev);
        int             rc = 0;
        
-       if (pdev->dev.power_state != 0) {
+       if (pdev->dev.power.power_state.event != PM_EVENT_ON) {
                rc = pmac_ide_do_resume(hwif);
                if (rc == 0)
-                       pdev->dev.power_state = 0;
+                       pdev->dev.power.power_state = PMSG_ON;
        }
 
        return rc;
 }
 
-static struct of_match pmac_ide_macio_match[] = 
+static struct of_device_id pmac_ide_macio_match[] = 
 {
        {
        .name           = "IDE",
-       .type           = OF_ANY_MATCH,
-       .compatible     = OF_ANY_MATCH
        },
        {
        .name           = "ATA",
-       .type           = OF_ANY_MATCH,
-       .compatible     = OF_ANY_MATCH
        },
        {
-       .name           = OF_ANY_MATCH,
        .type           = "ide",
-       .compatible     = OF_ANY_MATCH
        },
        {
-       .name           = OF_ANY_MATCH,
        .type           = "ata",
-       .compatible     = OF_ANY_MATCH
        },
        {},
 };
@@ -1531,9 +1531,16 @@ static struct macio_driver pmac_ide_macio_driver =
 };
 
 static struct pci_device_id pmac_ide_pci_match[] = {
-       { PCI_VENDOR_ID_APPLE, PCI_DEVIEC_ID_APPLE_UNI_N_ATA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-       { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_IPID_ATA100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-       { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_K2_ATA100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_ATA,
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_IPID_ATA100,
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_K2_ATA100,
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_SH_ATA,
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       { PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_IPID2_ATA,
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 };
 
 static struct pci_driver pmac_ide_pci_driver = {
@@ -1543,11 +1550,12 @@ static struct pci_driver pmac_ide_pci_driver = {
        .suspend        = pmac_ide_pci_suspend,
        .resume         = pmac_ide_pci_resume,
 };
+MODULE_DEVICE_TABLE(pci, pmac_ide_pci_match);
 
 void __init
 pmac_ide_probe(void)
 {
-       if (_machine != _MACH_Pmac)
+       if (!machine_is(powermac))
                return;
 
 #ifdef CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST
@@ -1556,76 +1564,16 @@ pmac_ide_probe(void)
 #else
        macio_register_driver(&pmac_ide_macio_driver);
        pci_register_driver(&pmac_ide_pci_driver);
-#endif 
+#endif
 }
 
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
 
-/*
- * This is very close to the generic ide-dma version of the function except
- * that we don't use the fields in the hwif but our own copies for sg_table
- * and friends. We build & map the sglist for a given request
- */
-static int __pmac
-pmac_ide_build_sglist(ide_drive_t *drive, struct request *rq)
-{
-       ide_hwif_t *hwif = HWIF(drive);
-       pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)hwif->hwif_data;
-       struct scatterlist *sg = pmif->sg_table;
-       int nents;
-
-       nents = blk_rq_map_sg(drive->queue, rq, sg);
-               
-       if (rq_data_dir(rq) == READ)
-               pmif->sg_dma_direction = PCI_DMA_FROMDEVICE;
-       else
-               pmif->sg_dma_direction = PCI_DMA_TODEVICE;
-
-       return pci_map_sg(hwif->pci_dev, sg, nents, pmif->sg_dma_direction);
-}
-
-/*
- * Same as above but for a "raw" taskfile request
- */
-static int __pmac
-pmac_ide_raw_build_sglist(ide_drive_t *drive, struct request *rq)
-{
-       ide_hwif_t *hwif = HWIF(drive);
-       pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)hwif->hwif_data;
-       struct scatterlist *sg = pmif->sg_table;
-       int nents = 0;
-       ide_task_t *args = rq->special;
-       unsigned char *virt_addr = rq->buffer;
-       int sector_count = rq->nr_sectors;
-
-       if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE)
-               pmif->sg_dma_direction = PCI_DMA_TODEVICE;
-       else
-               pmif->sg_dma_direction = PCI_DMA_FROMDEVICE;
-       
-       if (sector_count > 128) {
-               memset(&sg[nents], 0, sizeof(*sg));
-               sg[nents].page = virt_to_page(virt_addr);
-               sg[nents].offset = offset_in_page(virt_addr);
-               sg[nents].length = 128  * SECTOR_SIZE;
-               nents++;
-               virt_addr = virt_addr + (128 * SECTOR_SIZE);
-               sector_count -= 128;
-       }
-       memset(&sg[nents], 0, sizeof(*sg));
-       sg[nents].page = virt_to_page(virt_addr);
-       sg[nents].offset = offset_in_page(virt_addr);
-       sg[nents].length =  sector_count  * SECTOR_SIZE;
-       nents++;
-   
-       return pci_map_sg(hwif->pci_dev, sg, nents, pmif->sg_dma_direction);
-}
-
 /*
  * pmac_ide_build_dmatable builds the DBDMA command list
  * for a transfer and sets the DBDMA channel to point to it.
  */
-static int __pmac
+static int
 pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq)
 {
        struct dbdma_cmd *table;
@@ -1644,16 +1592,13 @@ pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq)
        while (readl(&dma->status) & RUN)
                udelay(1);
 
-       /* Build sglist */
-       if (HWGROUP(drive)->rq->flags & REQ_DRIVE_TASKFILE)
-               pmif->sg_nents = i = pmac_ide_raw_build_sglist(drive, rq);
-       else
-               pmif->sg_nents = i = pmac_ide_build_sglist(drive, rq);
+       hwif->sg_nents = i = ide_build_sglist(drive, rq);
+
        if (!i)
                return 0;
 
        /* Build DBDMA commands list */
-       sg = pmif->sg_table;
+       sg = hwif->sg_table;
        while (i && sg_dma_len(sg)) {
                u32 cur_addr;
                u32 cur_len;
@@ -1698,38 +1643,38 @@ pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq)
                memset(table, 0, sizeof(struct dbdma_cmd));
                st_le16(&table->command, DBDMA_STOP);
                mb();
-               writel(pmif->dma_table_dma, &dma->cmdptr);
+               writel(hwif->dmatable_dma, &dma->cmdptr);
                return 1;
        }
 
        printk(KERN_DEBUG "%s: empty DMA table?\n", drive->name);
  use_pio_instead:
        pci_unmap_sg(hwif->pci_dev,
-                    pmif->sg_table,
-                    pmif->sg_nents,
-                    pmif->sg_dma_direction);
+                    hwif->sg_table,
+                    hwif->sg_nents,
+                    hwif->sg_dma_direction);
        return 0; /* revert to PIO for this request */
 }
 
 /* Teardown mappings after DMA has completed.  */
-static void __pmac
+static void
 pmac_ide_destroy_dmatable (ide_drive_t *drive)
 {
+       ide_hwif_t *hwif = drive->hwif;
        struct pci_dev *dev = HWIF(drive)->pci_dev;
-       pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
-       struct scatterlist *sg = pmif->sg_table;
-       int nents = pmif->sg_nents;
+       struct scatterlist *sg = hwif->sg_table;
+       int nents = hwif->sg_nents;
 
        if (nents) {
-               pci_unmap_sg(dev, sg, nents, pmif->sg_dma_direction);
-               pmif->sg_nents = 0;
+               pci_unmap_sg(dev, sg, nents, hwif->sg_dma_direction);
+               hwif->sg_nents = 0;
        }
 }
 
 /*
  * Pick up best MDMA timing for the drive and apply it
  */
-static int __pmac
+static int
 pmac_ide_mdma_enable(ide_drive_t *drive, u16 mode)
 {
        ide_hwif_t *hwif = HWIF(drive);
@@ -1786,7 +1731,7 @@ pmac_ide_mdma_enable(ide_drive_t *drive, u16 mode)
 /*
  * Pick up best UDMA timing for the drive and apply it
  */
-static int __pmac
+static int
 pmac_ide_udma_enable(ide_drive_t *drive, u16 mode)
 {
        ide_hwif_t *hwif = HWIF(drive);
@@ -1804,10 +1749,15 @@ pmac_ide_udma_enable(ide_drive_t *drive, u16 mode)
        timing_local[1] = *timings2;
        
        /* Calculate timings for interface */
-       if (pmif->kind == controller_un_ata6 || pmif->kind == controller_k2_ata6)
+       if (pmif->kind == controller_un_ata6
+           || pmif->kind == controller_k2_ata6)
                ret = set_timings_udma_ata6(    &timing_local[0],
                                                &timing_local[1],
                                                mode);
+       else if (pmif->kind == controller_sh_ata6)
+               ret = set_timings_udma_shasta(  &timing_local[0],
+                                               &timing_local[1],
+                                               mode);
        else
                ret = set_timings_udma_ata4(&timing_local[0], mode);
        if (ret)
@@ -1837,7 +1787,7 @@ pmac_ide_udma_enable(ide_drive_t *drive, u16 mode)
  * Check what is the best DMA timing setting for the drive and
  * call appropriate functions to apply it.
  */
-static int __pmac
+static int
 pmac_ide_dma_check(ide_drive_t *drive)
 {
        struct hd_driveid *id = drive->id;
@@ -1858,14 +1808,19 @@ pmac_ide_dma_check(ide_drive_t *drive)
                short mode;
                
                map = XFER_MWDMA;
-               if (pmif->kind == controller_kl_ata4 || pmif->kind == controller_un_ata6
-                   || pmif->kind == controller_k2_ata6) {
+               if (pmif->kind == controller_kl_ata4
+                   || pmif->kind == controller_un_ata6
+                   || pmif->kind == controller_k2_ata6
+                   || pmif->kind == controller_sh_ata6) {
                        map |= XFER_UDMA;
                        if (pmif->cable_80) {
                                map |= XFER_UDMA_66;
                                if (pmif->kind == controller_un_ata6 ||
-                                   pmif->kind == controller_k2_ata6)
+                                   pmif->kind == controller_k2_ata6 ||
+                                   pmif->kind == controller_sh_ata6)
                                        map |= XFER_UDMA_100;
+                               if (pmif->kind == controller_sh_ata6)
+                                       map |= XFER_UDMA_133;
                        }
                }
                mode = ide_find_best_mode(drive, map);
@@ -1884,8 +1839,8 @@ pmac_ide_dma_check(ide_drive_t *drive)
  * Prepare a DMA transfer. We build the DMA table, adjust the timings for
  * a read on KeyLargo ATA/66 and mark us as waiting for DMA completion
  */
-static int __pmac
-pmac_ide_dma_start(ide_drive_t *drive, int reading)
+static int
+pmac_ide_dma_setup(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = HWIF(drive);
        pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)hwif->hwif_data;
@@ -1897,12 +1852,14 @@ pmac_ide_dma_start(ide_drive_t *drive, int reading)
                return 1;
        ata4 = (pmif->kind == controller_kl_ata4);      
 
-       if (!pmac_ide_build_dmatable(drive, rq))
+       if (!pmac_ide_build_dmatable(drive, rq)) {
+               ide_map_sg(drive, rq);
                return 1;
+       }
 
        /* Apple adds 60ns to wrDataSetup on reads */
        if (ata4 && (pmif->timings[unit] & TR_66_UDMA_EN)) {
-               writel(pmif->timings[unit] + (reading ? 0x00800000UL : 0),
+               writel(pmif->timings[unit] + (!rq_data_dir(rq) ? 0x00800000UL : 0),
                        PMAC_IDE_REG(IDE_TIMING_CONFIG));
                (void)readl(PMAC_IDE_REG(IDE_TIMING_CONFIG));
        }
@@ -1912,93 +1869,34 @@ pmac_ide_dma_start(ide_drive_t *drive, int reading)
        return 0;
 }
 
-/*
- * Start a DMA READ command
- */
-static int __pmac
-pmac_ide_dma_read(ide_drive_t *drive)
-{
-       struct request *rq = HWGROUP(drive)->rq;
-       u8 lba48 = (drive->addressing == 1) ? 1 : 0;
-       task_ioreg_t command = WIN_NOP;
-
-       if (pmac_ide_dma_start(drive, 1))
-               return 1;
-
-       if (drive->media != ide_disk)
-               return 0;
-
-       command = (lba48) ? WIN_READDMA_EXT : WIN_READDMA;
-       
-       if (drive->vdma)
-               command = (lba48) ? WIN_READ_EXT: WIN_READ;
-               
-       if (rq->flags & REQ_DRIVE_TASKFILE) {
-               ide_task_t *args = rq->special;
-               command = args->tfRegister[IDE_COMMAND_OFFSET];
-       }
-
-       /* issue cmd to drive */
-       ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, NULL);
-
-       return pmac_ide_dma_begin(drive);
-}
-
-/*
- * Start a DMA WRITE command
- */
-static int __pmac
-pmac_ide_dma_write (ide_drive_t *drive)
+static void
+pmac_ide_dma_exec_cmd(ide_drive_t *drive, u8 command)
 {
-       struct request *rq = HWGROUP(drive)->rq;
-       u8 lba48 = (drive->addressing == 1) ? 1 : 0;
-       task_ioreg_t command = WIN_NOP;
-
-       if (pmac_ide_dma_start(drive, 0))
-               return 1;
-
-       if (drive->media != ide_disk)
-               return 0;
-
-       command = (lba48) ? WIN_WRITEDMA_EXT : WIN_WRITEDMA;
-       if (drive->vdma)
-               command = (lba48) ? WIN_WRITE_EXT: WIN_WRITE;
-               
-       if (rq->flags & REQ_DRIVE_TASKFILE) {
-               ide_task_t *args = rq->special;
-               command = args->tfRegister[IDE_COMMAND_OFFSET];
-       }
-
        /* issue cmd to drive */
        ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, NULL);
-
-       return pmac_ide_dma_begin(drive);
 }
 
 /*
  * Kick the DMA controller into life after the DMA command has been issued
  * to the drive.
  */
-static int __pmac
-pmac_ide_dma_begin (ide_drive_t *drive)
+static void
+pmac_ide_dma_start(ide_drive_t *drive)
 {
        pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
        volatile struct dbdma_regs __iomem *dma;
 
-       if (pmif == NULL)
-               return 1;
        dma = pmif->dma_regs;
 
        writel((RUN << 16) | RUN, &dma->control);
        /* Make sure it gets to the controller right now */
        (void)readl(&dma->control);
-       return 0;
 }
 
 /*
  * After a DMA transfer, make sure the controller is stopped
  */
-static int __pmac
+static int
 pmac_ide_dma_end (ide_drive_t *drive)
 {
        pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
@@ -2026,7 +1924,7 @@ pmac_ide_dma_end (ide_drive_t *drive)
  * that's not implemented yet), on the other hand, we don't have shared interrupts
  * so it's not really a problem
  */
-static int __pmac
+static int
 pmac_ide_dma_test_irq (ide_drive_t *drive)
 {
        pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
@@ -2082,19 +1980,19 @@ pmac_ide_dma_test_irq (ide_drive_t *drive)
        return 1;
 }
 
-static int __pmac
+static int
 pmac_ide_dma_host_off (ide_drive_t *drive)
 {
        return 0;
 }
 
-static int __pmac
+static int
 pmac_ide_dma_host_on (ide_drive_t *drive)
 {
        return 0;
 }
 
-static int __pmac
+static int
 pmac_ide_dma_lostirq (ide_drive_t *drive)
 {
        pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data;
@@ -2130,44 +2028,33 @@ pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
        pmif->dma_table_cpu = (struct dbdma_cmd*)pci_alloc_consistent(
                hwif->pci_dev,
                (MAX_DCMDS + 2) * sizeof(struct dbdma_cmd),
-               &pmif->dma_table_dma);
+               &hwif->dmatable_dma);
        if (pmif->dma_table_cpu == NULL) {
                printk(KERN_ERR "%s: unable to allocate DMA command list\n",
                       hwif->name);
                return;
        }
 
-       pmif->sg_table = kmalloc(sizeof(struct scatterlist) * MAX_DCMDS,
-                                GFP_KERNEL);
-       if (pmif->sg_table == NULL) {
-               pci_free_consistent(    hwif->pci_dev,
-                                       (MAX_DCMDS + 2) * sizeof(struct dbdma_cmd),
-                                       pmif->dma_table_cpu, pmif->dma_table_dma);
-               return;
-       }
        hwif->ide_dma_off_quietly = &__ide_dma_off_quietly;
        hwif->ide_dma_on = &__ide_dma_on;
        hwif->ide_dma_check = &pmac_ide_dma_check;
-       hwif->ide_dma_read = &pmac_ide_dma_read;
-       hwif->ide_dma_write = &pmac_ide_dma_write;
-       hwif->ide_dma_begin = &pmac_ide_dma_begin;
+       hwif->dma_setup = &pmac_ide_dma_setup;
+       hwif->dma_exec_cmd = &pmac_ide_dma_exec_cmd;
+       hwif->dma_start = &pmac_ide_dma_start;
        hwif->ide_dma_end = &pmac_ide_dma_end;
        hwif->ide_dma_test_irq = &pmac_ide_dma_test_irq;
        hwif->ide_dma_host_off = &pmac_ide_dma_host_off;
        hwif->ide_dma_host_on = &pmac_ide_dma_host_on;
-       hwif->ide_dma_verbose = &__ide_dma_verbose;
        hwif->ide_dma_timeout = &__ide_dma_timeout;
        hwif->ide_dma_lostirq = &pmac_ide_dma_lostirq;
 
-#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO
-       if (!noautodma)
-               hwif->autodma = 1;
-#endif
-       hwif->drives[0].autodma = hwif->autodma;
-       hwif->drives[1].autodma = hwif->autodma;
-
        hwif->atapi_dma = 1;
        switch(pmif->kind) {
+               case controller_sh_ata6:
+                       hwif->ultra_mask = pmif->cable_80 ? 0x7f : 0x07;
+                       hwif->mwdma_mask = 0x07;
+                       hwif->swdma_mask = 0x00;
+                       break;
                case controller_un_ata6:
                case controller_k2_ata6:
                        hwif->ultra_mask = pmif->cable_80 ? 0x3f : 0x07;