it8213: remove DECLARE_ITE_DEV() macro
[safe/jmp/linux-2.6] / drivers / ide / pci / alim15x3.c
index 89109be..ac17150 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * linux/drivers/ide/pci/alim15x3.c            Version 0.17    2003/01/02
- *
  *  Copyright (C) 1998-2000 Michel Aubry, Maintainer
  *  Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer
  *  Copyright (C) 1999-2000 CJ, cjtsai@ali.com.tw, Maintainer
@@ -9,6 +7,8 @@
  *  May be copied or modified under the terms of the GNU General Public License
  *  Copyright (C) 2002 Alan Cox <alan@redhat.com>
  *  ALi (now ULi M5228) support by Clear Zhang <Clear.Zhang@ali.com.tw>
+ *  Copyright (C) 2007 MontaVista Software, Inc. <source@mvista.com>
+ *  Copyright (C) 2007 Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
  *
  *  (U)DMA capable version of ali 1533/1543(C), 1535(D)
  *
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
-#include <linux/delay.h>
 #include <linux/hdreg.h>
 #include <linux/ide.h>
 #include <linux/init.h>
+#include <linux/dmi.h>
 
 #include <asm/io.h>
 
-#define DISPLAY_ALI_TIMINGS
+/*
+ * Allow UDMA on M1543C-E chipset for WDC disks that ignore CRC checking
+ * (this is DANGEROUS and could result in data corruption).
+ */
+static int wdc_udma;
+
+module_param(wdc_udma, bool, 0);
+MODULE_PARM_DESC(wdc_udma,
+                "allow UDMA on M1543C-E chipset for WDC disks (DANGEROUS)");
 
 /*
  *     ALi devices are not plug in. Otherwise these static values would
@@ -49,272 +57,32 @@ static u8 m5229_revision;
 static u8 chip_is_1543c_e;
 static struct pci_dev *isa_dev;
 
-#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static u8 ali_proc = 0;
-
-static struct pci_dev *bmide_dev;
-
-static char *fifo[4] = {
-       "FIFO Off",
-       "FIFO On ",
-       "DMA mode",
-       "PIO mode" };
-
-static char *udmaT[8] = {
-       "1.5T",
-       "  2T",
-       "2.5T",
-       "  3T",
-       "3.5T",
-       "  4T",
-       "  6T",
-       "  8T"
-};
-
-static char *channel_status[8] = {
-       "OK            ",
-       "busy          ",
-       "DRQ           ",
-       "DRQ busy      ",
-       "error         ",
-       "error busy    ",
-       "error DRQ     ",
-       "error DRQ busy"
-};
-
 /**
- *     ali_get_info            -       generate proc file for ALi IDE
- *     @buffer: buffer to fill
- *     @addr: address of user start in buffer
- *     @offset: offset into 'file'
- *     @count: buffer count
+ *     ali_set_pio_mode        -       set host controller for PIO mode
+ *     @drive: drive
+ *     @pio: PIO mode number
  *
- *     Walks the Ali devices and outputs summary data on the tuning and
- *     anything else that will help with debugging
+ *     Program the controller for the given PIO mode.
  */
-static int ali_get_info (char *buffer, char **addr, off_t offset, int count)
-{
-       unsigned long bibma;
-       u8 reg53h, reg5xh, reg5yh, reg5xh1, reg5yh1, c0, c1, rev, tmp;
-       char *q, *p = buffer;
-
-       /* fetch rev. */
-       pci_read_config_byte(bmide_dev, 0x08, &rev);
-       if (rev >= 0xc1)        /* M1543C or newer */
-               udmaT[7] = " ???";
-       else
-               fifo[3]  = "   ???  ";
-
-       /* first fetch bibma: */
-       
-       bibma = pci_resource_start(bmide_dev, 4);
 
-       /*
-        * at that point bibma+0x2 et bibma+0xa are byte
-        * registers to investigate:
-        */
-       c0 = inb(bibma + 0x02);
-       c1 = inb(bibma + 0x0a);
-
-       p += sprintf(p,
-               "\n                                Ali M15x3 Chipset.\n");
-       p += sprintf(p,
-               "                                ------------------\n");
-       pci_read_config_byte(bmide_dev, 0x78, &reg53h);
-       p += sprintf(p, "PCI Clock: %d.\n", reg53h);
-
-       pci_read_config_byte(bmide_dev, 0x53, &reg53h);
-       p += sprintf(p,
-               "CD_ROM FIFO:%s, CD_ROM DMA:%s\n",
-               (reg53h & 0x02) ? "Yes" : "No ",
-               (reg53h & 0x01) ? "Yes" : "No " );
-       pci_read_config_byte(bmide_dev, 0x74, &reg53h);
-       p += sprintf(p,
-               "FIFO Status: contains %d Words, runs%s%s\n\n",
-               (reg53h & 0x3f),
-               (reg53h & 0x40) ? " OVERWR" : "",
-               (reg53h & 0x80) ? " OVERRD." : "." );
-
-       p += sprintf(p,
-               "-------------------primary channel"
-               "-------------------secondary channel"
-               "---------\n\n");
-
-       pci_read_config_byte(bmide_dev, 0x09, &reg53h);
-       p += sprintf(p,
-               "channel status:       %s"
-               "                               %s\n",
-               (reg53h & 0x20) ? "On " : "Off",
-               (reg53h & 0x10) ? "On " : "Off" );
-
-       p += sprintf(p,
-               "both channels togth:  %s"
-               "                               %s\n",
-               (c0&0x80) ? "No " : "Yes",
-               (c1&0x80) ? "No " : "Yes" );
-
-       pci_read_config_byte(bmide_dev, 0x76, &reg53h);
-       p += sprintf(p,
-               "Channel state:        %s                    %s\n",
-               channel_status[reg53h & 0x07],
-               channel_status[(reg53h & 0x70) >> 4] );
-
-       pci_read_config_byte(bmide_dev, 0x58, &reg5xh);
-       pci_read_config_byte(bmide_dev, 0x5c, &reg5yh);
-       p += sprintf(p,
-               "Add. Setup Timing:    %dT"
-               "                                %dT\n",
-               (reg5xh & 0x07) ? (reg5xh & 0x07) : 8,
-               (reg5yh & 0x07) ? (reg5yh & 0x07) : 8 );
-
-       pci_read_config_byte(bmide_dev, 0x59, &reg5xh);
-       pci_read_config_byte(bmide_dev, 0x5d, &reg5yh);
-       p += sprintf(p,
-               "Command Act. Count:   %dT"
-               "                                %dT\n"
-               "Command Rec. Count:   %dT"
-               "                               %dT\n\n",
-               (reg5xh & 0x70) ? ((reg5xh & 0x70) >> 4) : 8,
-               (reg5yh & 0x70) ? ((reg5yh & 0x70) >> 4) : 8, 
-               (reg5xh & 0x0f) ? (reg5xh & 0x0f) : 16,
-               (reg5yh & 0x0f) ? (reg5yh & 0x0f) : 16 );
-
-       p += sprintf(p,
-               "----------------drive0-----------drive1"
-               "------------drive0-----------drive1------\n\n");
-       p += sprintf(p,
-               "DMA enabled:      %s              %s"
-               "               %s              %s\n",
-               (c0&0x20) ? "Yes" : "No ",
-               (c0&0x40) ? "Yes" : "No ",
-               (c1&0x20) ? "Yes" : "No ",
-               (c1&0x40) ? "Yes" : "No " );
-
-       pci_read_config_byte(bmide_dev, 0x54, &reg5xh);
-       pci_read_config_byte(bmide_dev, 0x55, &reg5yh);
-       q = "FIFO threshold:   %2d Words         %2d Words"
-               "          %2d Words         %2d Words\n";
-       if (rev < 0xc1) {
-               if ((rev == 0x20) &&
-                   (pci_read_config_byte(bmide_dev, 0x4f, &tmp), (tmp &= 0x20))) {
-                       p += sprintf(p, q, 8, 8, 8, 8);
-               } else {
-                       p += sprintf(p, q,
-                               (reg5xh & 0x03) + 12,
-                               ((reg5xh & 0x30)>>4) + 12,
-                               (reg5yh & 0x03) + 12,
-                               ((reg5yh & 0x30)>>4) + 12 );
-               }
-       } else {
-               int t1 = (tmp = (reg5xh & 0x03)) ? (tmp << 3) : 4;
-               int t2 = (tmp = ((reg5xh & 0x30)>>4)) ? (tmp << 3) : 4;
-               int t3 = (tmp = (reg5yh & 0x03)) ? (tmp << 3) : 4;
-               int t4 = (tmp = ((reg5yh & 0x30)>>4)) ? (tmp << 3) : 4;
-               p += sprintf(p, q, t1, t2, t3, t4);
-       }
-
-#if 0
-       p += sprintf(p, 
-               "FIFO threshold:   %2d Words         %2d Words"
-               "          %2d Words         %2d Words\n",
-               (reg5xh & 0x03) + 12,
-               ((reg5xh & 0x30)>>4) + 12,
-               (reg5yh & 0x03) + 12,
-               ((reg5yh & 0x30)>>4) + 12 );
-#endif
-
-       p += sprintf(p,
-               "FIFO mode:        %s         %s          %s         %s\n",
-               fifo[((reg5xh & 0x0c) >> 2)],
-               fifo[((reg5xh & 0xc0) >> 6)],
-               fifo[((reg5yh & 0x0c) >> 2)],
-               fifo[((reg5yh & 0xc0) >> 6)] );
-
-       pci_read_config_byte(bmide_dev, 0x5a, &reg5xh);
-       pci_read_config_byte(bmide_dev, 0x5b, &reg5xh1);
-       pci_read_config_byte(bmide_dev, 0x5e, &reg5yh);
-       pci_read_config_byte(bmide_dev, 0x5f, &reg5yh1);
-
-       p += sprintf(p,/*
-               "------------------drive0-----------drive1"
-               "------------drive0-----------drive1------\n")*/
-               "Dt RW act. Cnt    %2dT              %2dT"
-               "               %2dT              %2dT\n"
-               "Dt RW rec. Cnt    %2dT              %2dT"
-               "               %2dT              %2dT\n\n",
-               (reg5xh & 0x70) ? ((reg5xh & 0x70) >> 4) : 8,
-               (reg5xh1 & 0x70) ? ((reg5xh1 & 0x70) >> 4) : 8,
-               (reg5yh & 0x70) ? ((reg5yh & 0x70) >> 4) : 8,
-               (reg5yh1 & 0x70) ? ((reg5yh1 & 0x70) >> 4) : 8,
-               (reg5xh & 0x0f) ? (reg5xh & 0x0f) : 16,
-               (reg5xh1 & 0x0f) ? (reg5xh1 & 0x0f) : 16,
-               (reg5yh & 0x0f) ? (reg5yh & 0x0f) : 16,
-               (reg5yh1 & 0x0f) ? (reg5yh1 & 0x0f) : 16 );
-
-       p += sprintf(p,
-               "-----------------------------------UDMA Timings"
-               "--------------------------------\n\n");
-
-       pci_read_config_byte(bmide_dev, 0x56, &reg5xh);
-       pci_read_config_byte(bmide_dev, 0x57, &reg5yh);
-       p += sprintf(p,
-               "UDMA:             %s               %s"
-               "                %s               %s\n"
-               "UDMA timings:     %s             %s"
-               "              %s             %s\n\n",
-               (reg5xh & 0x08) ? "OK" : "No",
-               (reg5xh & 0x80) ? "OK" : "No",
-               (reg5yh & 0x08) ? "OK" : "No",
-               (reg5yh & 0x80) ? "OK" : "No",
-               udmaT[(reg5xh & 0x07)],
-               udmaT[(reg5xh & 0x70) >> 4],
-               udmaT[reg5yh & 0x07],
-               udmaT[(reg5yh & 0x70) >> 4] );
-
-       return p-buffer; /* => must be less than 4k! */
-}
-#endif  /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */
-
-/**
- *     ali15x3_tune_drive      -       set up a drive
- *     @drive: drive to tune
- *     @pio: unused
- *
- *     Select the best PIO timing for the drive in question. Then
- *     program the controller for this drive set up
- */
-static void ali15x3_tune_drive (ide_drive_t *drive, u8 pio)
+static void ali_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
-       ide_pio_data_t d;
        ide_hwif_t *hwif = HWIF(drive);
-       struct pci_dev *dev = hwif->pci_dev;
-       int s_time, a_time, c_time;
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+       struct ide_timing *t = ide_timing_find_mode(XFER_PIO_0 + pio);
+       int s_time = t->setup, a_time = t->active, c_time = t->cycle;
        u8 s_clc, a_clc, r_clc;
        unsigned long flags;
-       int bus_speed = system_bus_clock();
+       int bus_speed = ide_pci_clk ? ide_pci_clk : 33;
        int port = hwif->channel ? 0x5c : 0x58;
        int portFIFO = hwif->channel ? 0x55 : 0x54;
        u8 cd_dma_fifo = 0;
        int unit = drive->select.b.unit & 1;
 
-       pio = ide_get_best_pio_mode(drive, pio, 5, &d);
-       s_time = ide_pio_timings[pio].setup_time;
-       a_time = ide_pio_timings[pio].active_time;
        if ((s_clc = (s_time * bus_speed + 999) / 1000) >= 8)
                s_clc = 0;
        if ((a_clc = (a_time * bus_speed + 999) / 1000) >= 8)
                a_clc = 0;
-       c_time = ide_pio_timings[pio].cycle_time;
-
-#if 0
-       if ((r_clc = ((c_time - s_time - a_time) * bus_speed + 999) / 1000) >= 16)
-               r_clc = 0;
-#endif
 
        if (!(r_clc = (c_time * bus_speed + 999) / 1000 - a_clc - s_clc)) {
                r_clc = 1;
@@ -345,104 +113,45 @@ static void ali15x3_tune_drive (ide_drive_t *drive, u8 pio)
        pci_write_config_byte(dev, port, s_clc);
        pci_write_config_byte(dev, port+drive->select.b.unit+2, (a_clc << 4) | r_clc);
        local_irq_restore(flags);
-
-       /*
-        * setup   active  rec
-        * { 70,   165,    365 },   PIO Mode 0
-        * { 50,   125,    208 },   PIO Mode 1
-        * { 30,   100,    110 },   PIO Mode 2
-        * { 30,   80,     70  },   PIO Mode 3 with IORDY
-        * { 25,   70,     25  },   PIO Mode 4 with IORDY  ns
-        * { 20,   50,     30  }    PIO Mode 5 with IORDY (nonstandard)
-        */
-
 }
 
 /**
- *     ali15x3_can_ultra       -       check for ultra DMA support
- *     @drive: drive to do the check
+ *     ali_udma_filter         -       compute UDMA mask
+ *     @drive: IDE device
+ *
+ *     Return available UDMA modes.
  *
- *     Check the drive and controller revisions. Return 0 if UDMA is
- *     not available, or 1 if UDMA can be used. The actual rules for
- *     the ALi are
+ *     The actual rules for the ALi are:
  *             No UDMA on revisions <= 0x20
  *             Disk only for revisions < 0xC2
- *             Not WDC drives for revisions < 0xC2
- *
- *     FIXME: WDC ifdef needs to die
+ *             Not WDC drives on M1543C-E (?)
  */
-static u8 ali15x3_can_ultra (ide_drive_t *drive)
-{
-#ifndef CONFIG_WDC_ALI15X3
-       struct hd_driveid *id   = drive->id;
-#endif /* CONFIG_WDC_ALI15X3 */
-
-       if (m5229_revision <= 0x20) {
-               return 0;
-       } else if ((m5229_revision < 0xC2) &&
-#ifndef CONFIG_WDC_ALI15X3
-                  ((chip_is_1543c_e && strstr(id->model, "WDC ")) ||
-                   (drive->media!=ide_disk))) {
-#else /* CONFIG_WDC_ALI15X3 */
-                  (drive->media!=ide_disk)) {
-#endif /* CONFIG_WDC_ALI15X3 */
-               return 0;
-       } else {
-               return 1;
-       }
-}
 
-/**
- *     ali15x3_ratemask        -       generate DMA mode list
- *     @drive: drive to compute against
- *
- *     Generate a list of the available DMA modes for the drive. 
- *     FIXME: this function contains lots of bogus masking we can dump
- *
- *     Return the highest available mode (UDMA33, UDMA66, UDMA100,..)
- */
-static u8 ali15x3_ratemask (ide_drive_t *drive)
+static u8 ali_udma_filter(ide_drive_t *drive)
 {
-       u8 mode = 0, can_ultra  = ali15x3_can_ultra(drive);
-
-       if (m5229_revision > 0xC4 && can_ultra) {
-               mode = 4;
-       } else if (m5229_revision == 0xC4 && can_ultra) {
-               mode = 3;
-       } else if (m5229_revision >= 0xC2 && can_ultra) {
-               mode = 2;
-       } else if (can_ultra) {
-               return 1;
-       } else {
-               return 0;
+       if (m5229_revision > 0x20 && m5229_revision < 0xC2) {
+               if (drive->media != ide_disk)
+                       return 0;
+               if (chip_is_1543c_e && strstr(drive->id->model, "WDC ") &&
+                   wdc_udma == 0)
+                       return 0;
        }
 
-       /*
-        *      If the drive sees no suitable cable then UDMA 33
-        *      is the highest permitted mode
-        */
-        
-       if (!eighty_ninty_three(drive))
-               mode = min(mode, (u8)1);
-       return mode;
+       return drive->hwif->ultra_mask;
 }
 
 /**
- *     ali15x3_tune_chipset    -       set up chiset for new speed
- *     @drive: drive to configure for
- *     @xferspeed: desired speed
+ *     ali_set_dma_mode        -       set host controller for DMA mode
+ *     @drive: drive
+ *     @speed: DMA mode
  *
  *     Configure the hardware for the desired IDE transfer mode.
- *     We also do the needed drive configuration through helpers
  */
-static int ali15x3_tune_chipset (ide_drive_t *drive, u8 xferspeed)
+
+static void ali_set_dma_mode(ide_drive_t *drive, const u8 speed)
 {
        ide_hwif_t *hwif        = HWIF(drive);
-       struct pci_dev *dev     = hwif->pci_dev;
-       u8 speed                = ide_rate_filter(ali15x3_ratemask(drive), xferspeed);
+       struct pci_dev *dev     = to_pci_dev(hwif->dev);
        u8 speed1               = speed;
        u8 unit                 = (drive->select.b.unit & 0x01);
        u8 tmpbyte              = 0x00;
@@ -460,8 +169,9 @@ static int ali15x3_tune_chipset (ide_drive_t *drive, u8 xferspeed)
                tmpbyte &= ultra_enable;
                pci_write_config_byte(dev, m5229_udma, tmpbyte);
 
-               if (speed < XFER_SW_DMA_0)
-                       ali15x3_tune_drive(drive, speed);
+               /*
+                * FIXME: Oh, my... DMA timings are never set.
+                */
        } else {
                pci_read_config_byte(dev, m5229_udma, &tmpbyte);
                tmpbyte &= (0x0f << ((1-unit) << 2));
@@ -476,85 +186,6 @@ static int ali15x3_tune_chipset (ide_drive_t *drive, u8 xferspeed)
                        pci_write_config_byte(dev, 0x4b, tmpbyte);
                }
        }
-       return (ide_config_drive_speed(drive, speed));
-}
-
-
-/**
- *     config_chipset_for_dma  -       set up DMA mode
- *     @drive: drive to configure for
- *
- *     Place a drive into DMA mode and tune the chipset for
- *     the selected speed.
- *
- *     Returns true if DMA mode can be used
- */
-static int config_chipset_for_dma (ide_drive_t *drive)
-{
-       u8 speed = ide_dma_speed(drive, ali15x3_ratemask(drive));
-
-       if (!(speed))
-               return 0;
-
-       (void) ali15x3_tune_chipset(drive, speed);
-       return ide_dma_enable(drive);
-}
-
-/**
- *     ali15x3_config_drive_for_dma    -       configure for DMA
- *     @drive: drive to configure
- *
- *     Configure a drive for DMA operation. If DMA is not possible we
- *     drop the drive into PIO mode instead.
- *
- *     FIXME: exactly what are we trying to return here
- */
-static int ali15x3_config_drive_for_dma(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif        = HWIF(drive);
-       struct hd_driveid *id   = drive->id;
-
-       if ((m5229_revision<=0x20) && (drive->media!=ide_disk))
-               return hwif->ide_dma_off_quietly(drive);
-
-       drive->init_speed = 0;
-
-       if ((id != NULL) && ((id->capability & 1) != 0) && drive->autodma) {
-               /* Consult the list of known "bad" drives */
-               if (__ide_dma_bad_drive(drive))
-                       goto ata_pio;
-               if ((id->field_valid & 4) && (m5229_revision >= 0xC2)) {
-                       if (id->dma_ultra & hwif->ultra_mask) {
-                               /* Force if Capable UltraDMA */
-                               int dma = config_chipset_for_dma(drive);
-                               if ((id->field_valid & 2) && !dma)
-                                       goto try_dma_modes;
-                       }
-               } else if (id->field_valid & 2) {
-try_dma_modes:
-                       if ((id->dma_mword & hwif->mwdma_mask) ||
-                           (id->dma_1word & hwif->swdma_mask)) {
-                               /* Force if Capable regular DMA modes */
-                               if (!config_chipset_for_dma(drive))
-                                       goto no_dma_set;
-                       }
-               } else if (__ide_dma_good_drive(drive) &&
-                          (id->eide_dma_time < 150)) {
-                       /* Consult the list of known "good" drives */
-                       if (!config_chipset_for_dma(drive))
-                               goto no_dma_set;
-               } else {
-                       goto ata_pio;
-               }
-       } else {
-ata_pio:
-               hwif->tuneproc(drive, 255);
-no_dma_set:
-               return hwif->ide_dma_off_quietly(drive);
-       }
-       return hwif->ide_dma_on(drive);
 }
 
 /**
@@ -588,18 +219,10 @@ static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const c
        u8 tmpbyte;
        struct pci_dev *north = pci_get_slot(dev->bus, PCI_DEVFN(0,0));
 
-       pci_read_config_byte(dev, PCI_REVISION_ID, &m5229_revision);
+       m5229_revision = dev->revision;
 
        isa_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
 
-#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS)
-       if (!ali_proc) {
-               ali_proc = 1;
-               bmide_dev = dev;
-               ide_pci_create_host_proc("ali", ali_get_info);
-       }
-#endif  /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */
-
        local_irq_save(flags);
 
        if (m5229_revision < 0xC2) {
@@ -613,6 +236,13 @@ static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const c
                 * clear bit 7
                 */
                pci_write_config_byte(dev, 0x4b, tmpbyte & 0x7F);
+               /*
+                * check m1533, 0x5e, bit 1~4 == 1001 => & 00011110 = 00010010
+                */
+               if (m5229_revision >= 0x20 && isa_dev) {
+                       pci_read_config_byte(isa_dev, 0x5e, &tmpbyte);
+                       chip_is_1543c_e = ((tmpbyte & 0x1e) == 0x12) ? 1: 0;
+               }
                goto out;
        }
 
@@ -658,15 +288,79 @@ static unsigned int __devinit init_chipset_ali15x3 (struct pci_dev *dev, const c
                        pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x02);
                }
        }
+
 out:
+       /*
+        * CD_ROM DMA on (m5229, 0x53, bit0)
+        *      Enable this bit even if we want to use PIO.
+        * PIO FIFO off (m5229, 0x53, bit1)
+        *      The hardware will use 0x54h and 0x55h to control PIO FIFO.
+        *      (Not on later devices it seems)
+        *
+        *      0x53 changes meaning on later revs - we must no touch
+        *      bit 1 on them.  Need to check if 0x20 is the right break.
+        */
+       if (m5229_revision >= 0x20) {
+               pci_read_config_byte(dev, 0x53, &tmpbyte);
+
+               if (m5229_revision <= 0x20)
+                       tmpbyte = (tmpbyte & (~0x02)) | 0x01;
+               else if (m5229_revision == 0xc7 || m5229_revision == 0xc8)
+                       tmpbyte |= 0x03;
+               else
+                       tmpbyte |= 0x01;
+
+               pci_write_config_byte(dev, 0x53, tmpbyte);
+       }
        pci_dev_put(north);
        pci_dev_put(isa_dev);
        local_irq_restore(flags);
        return 0;
 }
 
+/*
+ *     Cable special cases
+ */
+
+static const struct dmi_system_id cable_dmi_table[] = {
+       {
+               .ident = "HP Pavilion N5430",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
+                       DMI_MATCH(DMI_BOARD_VERSION, "OmniBook N32N-736"),
+               },
+       },
+       {
+               .ident = "Toshiba Satellite S1800-814",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "S1800-814"),
+               },
+       },
+       { }
+};
+
+static int ali_cable_override(struct pci_dev *pdev)
+{
+       /* Fujitsu P2000 */
+       if (pdev->subsystem_vendor == 0x10CF &&
+           pdev->subsystem_device == 0x10AF)
+               return 1;
+
+       /* Mitac 8317 (Winbook-A) and relatives */
+       if (pdev->subsystem_vendor == 0x1071 &&
+           pdev->subsystem_device == 0x8317)
+               return 1;
+
+       /* Systems by DMI */
+       if (dmi_check_system(cable_dmi_table))
+               return 1;
+
+       return 0;
+}
+
 /**
- *     ata66_ali15x3   -       check for UDMA 66 support
+ *     ali_cable_detect        -       cable detection
  *     @hwif: IDE interface
  *
  *     This checks if the controller and the cable are capable
@@ -676,133 +370,57 @@ out:
  *     FIXME: frobs bits that are not defined on newer ALi devicea
  */
 
-static unsigned int __devinit ata66_ali15x3 (ide_hwif_t *hwif)
+static u8 __devinit ali_cable_detect(ide_hwif_t *hwif)
 {
-       struct pci_dev *dev     = hwif->pci_dev;
-       unsigned int ata66      = 0;
-       u8 cable_80_pin[2]      = { 0, 0 };
-
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
        unsigned long flags;
-       u8 tmpbyte;
+       u8 cbl = ATA_CBL_PATA40, tmpbyte;
 
        local_irq_save(flags);
 
        if (m5229_revision >= 0xC2) {
                /*
-                * Ultra66 cable detection (from Host View)
-                * m5229, 0x4a, bit0: primary, bit1: secondary 80 pin
-                */
-               pci_read_config_byte(dev, 0x4a, &tmpbyte);
-               /*
-                * 0x4a, bit0 is 0 => primary channel
-                * has 80-pin (from host view)
-                */
-               if (!(tmpbyte & 0x01)) cable_80_pin[0] = 1;
-               /*
-                * 0x4a, bit1 is 0 => secondary channel
-                * has 80-pin (from host view)
-                */
-               if (!(tmpbyte & 0x02)) cable_80_pin[1] = 1;
-               /*
-                * Allow ata66 if cable of current channel has 80 pins
+                * m5229 80-pin cable detection (from Host View)
+                *
+                * 0x4a bit0 is 0 => primary channel has 80-pin
+                * 0x4a bit1 is 0 => secondary channel has 80-pin
+                *
+                * Certain laptops use short but suitable cables
+                * and don't implement the detect logic.
                 */
-               ata66 = (hwif->channel)?cable_80_pin[1]:cable_80_pin[0];
-       } else {
-               /*
-                * check m1533, 0x5e, bit 1~4 == 1001 => & 00011110 = 00010010
-                */
-               pci_read_config_byte(isa_dev, 0x5e, &tmpbyte);
-               chip_is_1543c_e = ((tmpbyte & 0x1e) == 0x12) ? 1: 0;
+               if (ali_cable_override(dev))
+                       cbl = ATA_CBL_PATA40_SHORT;
+               else {
+                       pci_read_config_byte(dev, 0x4a, &tmpbyte);
+                       if ((tmpbyte & (1 << hwif->channel)) == 0)
+                               cbl = ATA_CBL_PATA80;
+               }
        }
 
-       /*
-        * CD_ROM DMA on (m5229, 0x53, bit0)
-        *      Enable this bit even if we want to use PIO
-        * PIO FIFO off (m5229, 0x53, bit1)
-        *      The hardware will use 0x54h and 0x55h to control PIO FIFO
-        *      (Not on later devices it seems)
-        *
-        *      0x53 changes meaning on later revs - we must no touch
-        *      bit 1 on them. Need to check if 0x20 is the right break
-        */
-        
-       pci_read_config_byte(dev, 0x53, &tmpbyte);
-       
-       if(m5229_revision <= 0x20)
-               tmpbyte = (tmpbyte & (~0x02)) | 0x01;
-       else if (m5229_revision == 0xc7 || m5229_revision == 0xc8)
-               tmpbyte |= 0x03;
-       else
-               tmpbyte |= 0x01;
-
-       pci_write_config_byte(dev, 0x53, tmpbyte);
-
        local_irq_restore(flags);
 
-       return(ata66);
-}
-
-/**
- *     init_hwif_common_ali15x3        -       Set up ALI IDE hardware
- *     @hwif: IDE interface
- *
- *     Initialize the IDE structure side of the ALi 15x3 driver.
- */
-static void __devinit init_hwif_common_ali15x3 (ide_hwif_t *hwif)
-{
-       hwif->autodma = 0;
-       hwif->tuneproc = &ali15x3_tune_drive;
-       hwif->speedproc = &ali15x3_tune_chipset;
-
-       /* don't use LBA48 DMA on ALi devices before rev 0xC5 */
-       hwif->no_lba48_dma = (m5229_revision <= 0xC4) ? 1 : 0;
-
-       if (!hwif->dma_base) {
-               hwif->drives[0].autotune = 1;
-               hwif->drives[1].autotune = 1;
-               return;
-       }
-
-       hwif->atapi_dma = 1;
-
-       if (m5229_revision > 0x20)
-               hwif->ultra_mask = 0x7f;
-       hwif->mwdma_mask = 0x07;
-       hwif->swdma_mask = 0x07;
-
-        if (m5229_revision >= 0x20) {
-                /*
-                 * M1543C or newer for DMAing
-                 */
-                hwif->ide_dma_check = &ali15x3_config_drive_for_dma;
-               hwif->dma_setup = &ali15x3_dma_setup;
-               if (!noautodma)
-                       hwif->autodma = 1;
-               if (!(hwif->udma_four))
-                       hwif->udma_four = ata66_ali15x3(hwif);
-       }
-       hwif->drives[0].autodma = hwif->autodma;
-       hwif->drives[1].autodma = hwif->autodma;
+       return cbl;
 }
 
+#if !defined(CONFIG_SPARC64) && !defined(CONFIG_PPC)
 /**
  *     init_hwif_ali15x3       -       Initialize the ALI IDE x86 stuff
  *     @hwif: interface to configure
  *
  *     Obtain the IRQ tables for an ALi based IDE solution on the PC
  *     class platforms. This part of the code isn't applicable to the
- *     Sparc systems
+ *     Sparc and PowerPC systems.
  */
 
 static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif)
 {
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
        u8 ideic, inmir;
        s8 irq_routing_table[] = { -1,  9, 3, 10, 4,  5, 7,  6,
                                      1, 11, 0, 12, 0, 14, 0, 15 };
        int irq = -1;
 
-       if (hwif->pci_dev->device == PCI_DEVICE_ID_AL_M5229)
+       if (dev->device == PCI_DEVICE_ID_AL_M5229)
                hwif->irq = hwif->channel ? 15 : 14;
 
        if (isa_dev) {
@@ -834,37 +452,77 @@ static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif)
                if(irq >= 0)
                        hwif->irq = irq;
        }
-
-       init_hwif_common_ali15x3(hwif);
 }
+#else
+#define init_hwif_ali15x3 NULL
+#endif /* !defined(CONFIG_SPARC64) && !defined(CONFIG_PPC) */
 
 /**
  *     init_dma_ali15x3        -       set up DMA on ALi15x3
  *     @hwif: IDE interface
- *     @dmabase: DMA interface base PCI address
+ *     @d: IDE port info
  *
- *     Set up the DMA functionality on the ALi 15x3. For the ALi
- *     controllers this is generic so we can let the generic code do
- *     the actual work.
+ *     Set up the DMA functionality on the ALi 15x3.
  */
 
-static void __devinit init_dma_ali15x3 (ide_hwif_t *hwif, unsigned long dmabase)
+static int __devinit init_dma_ali15x3(ide_hwif_t *hwif,
+                                     const struct ide_port_info *d)
 {
-       if (m5229_revision < 0x20)
-               return;
-       if (!(hwif->channel))
-               hwif->OUTB(hwif->INB(dmabase+2) & 0x60, dmabase+2);
-       ide_setup_dma(hwif, dmabase, 8);
+       struct pci_dev *dev = to_pci_dev(hwif->dev);
+       unsigned long base = ide_pci_dma_base(hwif, d);
+
+       if (base == 0)
+               return -1;
+
+       hwif->dma_base = base;
+
+       if (ide_pci_check_simplex(hwif, d) < 0)
+               return -1;
+
+       if (ide_pci_set_master(dev, d->name) < 0)
+               return -1;
+
+       if (!hwif->channel)
+               outb(inb(base + 2) & 0x60, base + 2);
+
+       printk(KERN_INFO "    %s: BM-DMA at 0x%04lx-0x%04lx\n",
+                        hwif->name, base, base + 7);
+
+       if (ide_allocate_dma_engine(hwif))
+               return -1;
+
+       hwif->dma_ops = &sff_dma_ops;
+
+       return 0;
 }
 
-static ide_pci_device_t ali15x3_chipset __devinitdata = {
+static const struct ide_port_ops ali_port_ops = {
+       .set_pio_mode           = ali_set_pio_mode,
+       .set_dma_mode           = ali_set_dma_mode,
+       .udma_filter            = ali_udma_filter,
+       .cable_detect           = ali_cable_detect,
+};
+
+static const struct ide_dma_ops ali_dma_ops = {
+       .dma_host_set           = ide_dma_host_set,
+       .dma_setup              = ali15x3_dma_setup,
+       .dma_exec_cmd           = ide_dma_exec_cmd,
+       .dma_start              = ide_dma_start,
+       .dma_end                = __ide_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_port_info ali15x3_chipset __devinitdata = {
        .name           = "ALI15X3",
        .init_chipset   = init_chipset_ali15x3,
        .init_hwif      = init_hwif_ali15x3,
        .init_dma       = init_dma_ali15x3,
-       .channels       = 2,
-       .autodma        = AUTODMA,
-       .bootable       = ON_BOARD,
+       .port_ops       = &ali_port_ops,
+       .pio_mask       = ATA_PIO5,
+       .swdma_mask     = ATA_SWDMA2,
+       .mwdma_mask     = ATA_MWDMA2,
 };
 
 /**
@@ -877,26 +535,43 @@ static ide_pci_device_t ali15x3_chipset __devinitdata = {
  
 static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
-       static struct pci_device_id ati_rs100[] = {
-               { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS100) },
-               { },
-       };
+       struct ide_port_info d = ali15x3_chipset;
+       u8 rev = dev->revision, idx = id->driver_data;
+
+       /* don't use LBA48 DMA on ALi devices before rev 0xC5 */
+       if (rev <= 0xC4)
+               d.host_flags |= IDE_HFLAG_NO_LBA48_DMA;
+
+       if (rev >= 0x20) {
+               if (rev == 0x20)
+                       d.host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
+
+               if (rev < 0xC2)
+                       d.udma_mask = ATA_UDMA2;
+               else if (rev == 0xC2 || rev == 0xC3)
+                       d.udma_mask = ATA_UDMA4;
+               else if (rev == 0xC4)
+                       d.udma_mask = ATA_UDMA5;
+               else
+                       d.udma_mask = ATA_UDMA6;
+
+               d.dma_ops = &ali_dma_ops;
+       } else {
+               d.host_flags |= IDE_HFLAG_NO_DMA;
 
-       ide_pci_device_t *d = &ali15x3_chipset;
+               d.mwdma_mask = d.swdma_mask = 0;
+       }
 
-       if (pci_dev_present(ati_rs100))
-               printk(KERN_WARNING "alim15x3: ATI Radeon IGP Northbridge is not yet fully tested.\n");
+       if (idx == 0)
+               d.host_flags |= IDE_HFLAG_CLEAR_SIMPLEX;
 
-#if defined(CONFIG_SPARC64)
-       d->init_hwif = init_hwif_common_ali15x3;
-#endif /* CONFIG_SPARC64 */
-       return ide_setup_pci_device(dev, d);
+       return ide_pci_init_one(dev, &d, NULL);
 }
 
 
-static struct pci_device_id alim15x3_pci_tbl[] = {
-       { PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-       { PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5228, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+static const struct pci_device_id alim15x3_pci_tbl[] = {
+       { PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5229), 0 },
+       { PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5228), 1 },
        { 0, },
 };
 MODULE_DEVICE_TABLE(pci, alim15x3_pci_tbl);
@@ -905,14 +580,21 @@ static struct pci_driver driver = {
        .name           = "ALI15x3_IDE",
        .id_table       = alim15x3_pci_tbl,
        .probe          = alim15x3_init_one,
+       .remove         = ide_pci_remove,
 };
 
-static int ali15x3_ide_init(void)
+static int __init ali15x3_ide_init(void)
 {
        return ide_pci_register_driver(&driver);
 }
 
+static void __exit ali15x3_ide_exit(void)
+{
+       return pci_unregister_driver(&driver);
+}
+
 module_init(ali15x3_ide_init);
+module_exit(ali15x3_ide_exit);
 
 MODULE_AUTHOR("Michael Aubry, Andrzej Krzysztofowicz, CJ, Andre Hedrick, Alan Cox");
 MODULE_DESCRIPTION("PCI driver module for ALi 15x3 IDE");