Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm
[safe/jmp/linux-2.6] / drivers / ata / pata_ali.c
index 48c7531..dc61b72 100644 (file)
@@ -1,7 +1,6 @@
 /*
  * pata_ali.c  - ALI 15x3 PATA for new ATA layer
  *                       (C) 2005 Red Hat Inc
- *                       Alan Cox <alan@redhat.com>
  *
  * based in part upon
  * linux/drivers/ide/pci/alim15x3.c            Version 0.17    2003/01/02
@@ -20,7 +19,9 @@
  *
  *  TODO/CHECK
  *     Cannot have ATAPI on both master & slave for rev < c2 (???) but
- *     otherwise should do atapi DMA.
+ *     otherwise should do atapi DMA (For now for old we do PIO only for
+ *     ATAPI)
+ *     Review Sunblade workaround.
  */
 
 #include <linux/kernel.h>
 #include <linux/dmi.h>
 
 #define DRV_NAME "pata_ali"
-#define DRV_VERSION "0.7.4"
+#define DRV_VERSION "0.7.8"
+
+static int ali_atapi_dma = 0;
+module_param_named(atapi_dma, ali_atapi_dma, int, 0644);
+MODULE_PARM_DESC(atapi_dma, "Enable ATAPI DMA (0=disable, 1=enable)");
+
+static struct pci_dev *ali_isa_bridge;
 
 /*
  *     Cable special cases
  */
 
-static struct dmi_system_id cable_dmi_table[] = {
+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_NAME, "OmniBook N32N-736"),
+                       DMI_MATCH(DMI_BOARD_VERSION, "OmniBook N32N-736"),
+               },
+       },
+       {
+               .ident = "Toshiba Satelite S1800-814",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "S1800-814"),
                },
        },
        { }
@@ -56,6 +70,9 @@ 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;
@@ -107,7 +124,7 @@ static unsigned long ali_20_filter(struct ata_device *adev, unsigned long mask)
        ata_id_c_string(adev->id, model_num, ATA_ID_PROD, sizeof(model_num));
        if (strstr(model_num, "WDC"))
                return mask &= ~ATA_MASK_UDMA;
-       return ata_pci_default_filter(adev, mask);
+       return ata_bmdma_mode_filter(adev, mask);
 }
 
 /**
@@ -134,8 +151,7 @@ static void ali_fifo_control(struct ata_port *ap, struct ata_device *adev, int o
 
        pci_read_config_byte(pdev, pio_fifo, &fifo);
        fifo &= ~(0x0F << shift);
-       if (on)
-               fifo |= (on << shift);
+       fifo |= (on << shift);
        pci_write_config_byte(pdev, pio_fifo, fifo);
 }
 
@@ -143,8 +159,7 @@ static void ali_fifo_control(struct ata_port *ap, struct ata_device *adev, int o
  *     ali_program_modes       -       load mode registers
  *     @ap: ALi channel to load
  *     @adev: Device the timing is for
- *     @cmd: Command timing
- *     @data: Data timing
+ *     @t: timing data
  *     @ultra: UDMA timing or zero for off
  *
  *     Loads the timing registers for cmd/data and disable UDMA if
@@ -163,11 +178,11 @@ static void ali_program_modes(struct ata_port *ap, struct ata_device *adev, stru
        u8 udma;
 
        if (t != NULL) {
-               t->setup = FIT(t->setup, 1, 8) & 7;
-               t->act8b = FIT(t->act8b, 1, 8) & 7;
-               t->rec8b = FIT(t->rec8b, 1, 16) & 15;
-               t->active = FIT(t->active, 1, 8) & 7;
-               t->recover = FIT(t->recover, 1, 16) & 15;
+               t->setup = clamp_val(t->setup, 1, 8) & 7;
+               t->act8b = clamp_val(t->act8b, 1, 8) & 7;
+               t->rec8b = clamp_val(t->rec8b, 1, 16) & 15;
+               t->active = clamp_val(t->active, 1, 8) & 7;
+               t->recover = clamp_val(t->recover, 1, 16) & 15;
 
                pci_write_config_byte(pdev, cas, t->setup);
                pci_write_config_byte(pdev, cbt, (t->act8b << 4) | t->rec8b);
@@ -186,8 +201,7 @@ static void ali_program_modes(struct ata_port *ap, struct ata_device *adev, stru
  *     @ap: ATA interface
  *     @adev: ATA device
  *
- *     Program the ALi registers for PIO mode. FIXME: add timings for
- *     PIO5.
+ *     Program the ALi registers for PIO mode.
  */
 
 static void ali_set_piomode(struct ata_port *ap, struct ata_device *adev)
@@ -221,7 +235,7 @@ static void ali_set_piomode(struct ata_port *ap, struct ata_device *adev)
  *     @ap: ATA interface
  *     @adev: ATA device
  *
- *     FIXME: MWDMA timings
+ *     Program the ALi registers for DMA mode.
  */
 
 static void ali_set_dmamode(struct ata_port *ap, struct ata_device *adev)
@@ -260,6 +274,27 @@ static void ali_set_dmamode(struct ata_port *ap, struct ata_device *adev)
 }
 
 /**
+ *     ali_warn_atapi_dma      -       Warn about ATAPI DMA disablement
+ *     @adev: Device
+ *
+ *     Whine about ATAPI DMA disablement if @adev is an ATAPI device.
+ *     Can be used as ->dev_config.
+ */
+
+static void ali_warn_atapi_dma(struct ata_device *adev)
+{
+       struct ata_eh_context *ehc = &adev->link->eh_context;
+       int print_info = ehc->i.flags & ATA_EHI_PRINTINFO;
+
+       if (print_info && adev->class == ATA_DEV_ATAPI && !ali_atapi_dma) {
+               ata_dev_printk(adev, KERN_WARNING,
+                              "WARNING: ATAPI DMA disabled for reliability issues.  It can be enabled\n");
+               ata_dev_printk(adev, KERN_WARNING,
+                              "WARNING: via pata_ali.atapi_dma modparam or corresponding sysfs node.\n");
+       }
+}
+
+/**
  *     ali_lock_sectors        -       Keep older devices to 255 sector mode
  *     @adev: Device
  *
@@ -273,24 +308,55 @@ static void ali_set_dmamode(struct ata_port *ap, struct ata_device *adev)
 static void ali_lock_sectors(struct ata_device *adev)
 {
        adev->max_sectors = 255;
+       ali_warn_atapi_dma(adev);
+}
+
+/**
+ *     ali_check_atapi_dma     -       DMA check for most ALi controllers
+ *     @adev: Device
+ *
+ *     Called to decide whether commands should be sent by DMA or PIO
+ */
+
+static int ali_check_atapi_dma(struct ata_queued_cmd *qc)
+{
+       if (!ali_atapi_dma) {
+               /* FIXME: pata_ali can't do ATAPI DMA reliably but the
+                * IDE alim15x3 driver can.  I tried lots of things
+                * but couldn't find what the actual difference was.
+                * If you got an idea, please write it to
+                * linux-ide@vger.kernel.org and cc htejun@gmail.com.
+                *
+                * Disable ATAPI DMA for now.
+                */
+               return -EOPNOTSUPP;
+       }
+
+       /* If its not a media command, its not worth it */
+       if (atapi_cmd_type(qc->cdb[0]) == ATAPI_MISC)
+               return -EOPNOTSUPP;
+       return 0;
+}
+
+static void ali_c2_c3_postreset(struct ata_link *link, unsigned int *classes)
+{
+       u8 r;
+       int port_bit = 4 << link->ap->port_no;
+
+       /* If our bridge is an ALI 1533 then do the extra work */
+       if (ali_isa_bridge) {
+               /* Tristate and re-enable the bus signals */
+               pci_read_config_byte(ali_isa_bridge, 0x58, &r);
+               r &= ~port_bit;
+               pci_write_config_byte(ali_isa_bridge, 0x58, r);
+               r |= port_bit;
+               pci_write_config_byte(ali_isa_bridge, 0x58, r);
+       }
+       ata_sff_postreset(link, classes);
 }
 
 static struct scsi_host_template ali_sht = {
-       .module                 = THIS_MODULE,
-       .name                   = DRV_NAME,
-       .ioctl                  = ata_scsi_ioctl,
-       .queuecommand           = ata_scsi_queuecmd,
-       .can_queue              = ATA_DEF_QUEUE,
-       .this_id                = ATA_SHT_THIS_ID,
-       .sg_tablesize           = LIBATA_MAX_PRD,
-       .cmd_per_lun            = ATA_SHT_CMD_PER_LUN,
-       .emulated               = ATA_SHT_EMULATED,
-       .use_clustering         = ATA_SHT_USE_CLUSTERING,
-       .proc_name              = DRV_NAME,
-       .dma_boundary           = ATA_DMA_BOUNDARY,
-       .slave_configure        = ata_scsi_slave_config,
-       .slave_destroy          = ata_scsi_slave_destroy,
-       .bios_param             = ata_std_bios_param,
+       ATA_BMDMA_SHT(DRV_NAME),
 };
 
 /*
@@ -298,31 +364,16 @@ static struct scsi_host_template ali_sht = {
  */
 
 static struct ata_port_operations ali_early_port_ops = {
-       .port_disable   = ata_port_disable,
-       .set_piomode    = ali_set_piomode,
-       .tf_load        = ata_tf_load,
-       .tf_read        = ata_tf_read,
-       .check_status   = ata_check_status,
-       .exec_command   = ata_exec_command,
-       .dev_select     = ata_std_dev_select,
-
-       .freeze         = ata_bmdma_freeze,
-       .thaw           = ata_bmdma_thaw,
-       .error_handler  = ata_bmdma_error_handler,
-       .post_internal_cmd = ata_bmdma_post_internal_cmd,
+       .inherits       = &ata_sff_port_ops,
        .cable_detect   = ata_cable_40wire,
+       .set_piomode    = ali_set_piomode,
+       .sff_data_xfer  = ata_sff_data_xfer32,
+};
 
-       .qc_prep        = ata_qc_prep,
-       .qc_issue       = ata_qc_issue_prot,
-
-       .data_xfer      = ata_data_xfer,
-
-       .irq_handler    = ata_interrupt,
-       .irq_clear      = ata_bmdma_irq_clear,
-       .irq_on         = ata_irq_on,
-       .irq_ack        = ata_irq_ack,
-
-       .port_start     = ata_port_start,
+static const struct ata_port_operations ali_dma_base_ops = {
+       .inherits       = &ata_bmdma32_port_ops,
+       .set_piomode    = ali_set_piomode,
+       .set_dmamode    = ali_set_dmamode,
 };
 
 /*
@@ -330,118 +381,42 @@ static struct ata_port_operations ali_early_port_ops = {
  *     detect
  */
 static struct ata_port_operations ali_20_port_ops = {
-       .port_disable   = ata_port_disable,
-
-       .set_piomode    = ali_set_piomode,
-       .set_dmamode    = ali_set_dmamode,
+       .inherits       = &ali_dma_base_ops,
+       .cable_detect   = ata_cable_40wire,
        .mode_filter    = ali_20_filter,
-
-       .tf_load        = ata_tf_load,
-       .tf_read        = ata_tf_read,
-       .check_status   = ata_check_status,
-       .exec_command   = ata_exec_command,
-       .dev_select     = ata_std_dev_select,
+       .check_atapi_dma = ali_check_atapi_dma,
        .dev_config     = ali_lock_sectors,
-
-       .freeze         = ata_bmdma_freeze,
-       .thaw           = ata_bmdma_thaw,
-       .error_handler  = ata_bmdma_error_handler,
-       .post_internal_cmd = ata_bmdma_post_internal_cmd,
-       .cable_detect   = ata_cable_40wire,
-
-       .bmdma_setup    = ata_bmdma_setup,
-       .bmdma_start    = ata_bmdma_start,
-       .bmdma_stop     = ata_bmdma_stop,
-       .bmdma_status   = ata_bmdma_status,
-
-       .qc_prep        = ata_qc_prep,
-       .qc_issue       = ata_qc_issue_prot,
-
-       .data_xfer      = ata_data_xfer,
-
-       .irq_handler    = ata_interrupt,
-       .irq_clear      = ata_bmdma_irq_clear,
-       .irq_on         = ata_irq_on,
-       .irq_ack        = ata_irq_ack,
-
-       .port_start     = ata_port_start,
 };
 
 /*
  *     Port operations for DMA capable ALi with cable detect
  */
 static struct ata_port_operations ali_c2_port_ops = {
-       .port_disable   = ata_port_disable,
-       .set_piomode    = ali_set_piomode,
-       .set_dmamode    = ali_set_dmamode,
-       .mode_filter    = ata_pci_default_filter,
-       .tf_load        = ata_tf_load,
-       .tf_read        = ata_tf_read,
-       .check_status   = ata_check_status,
-       .exec_command   = ata_exec_command,
-       .dev_select     = ata_std_dev_select,
+       .inherits       = &ali_dma_base_ops,
+       .check_atapi_dma = ali_check_atapi_dma,
+       .cable_detect   = ali_c2_cable_detect,
        .dev_config     = ali_lock_sectors,
+       .postreset      = ali_c2_c3_postreset,
+};
 
-       .freeze         = ata_bmdma_freeze,
-       .thaw           = ata_bmdma_thaw,
-       .error_handler  = ata_bmdma_error_handler,
-       .post_internal_cmd = ata_bmdma_post_internal_cmd,
+/*
+ *     Port operations for DMA capable ALi with cable detect
+ */
+static struct ata_port_operations ali_c4_port_ops = {
+       .inherits       = &ali_dma_base_ops,
+       .check_atapi_dma = ali_check_atapi_dma,
        .cable_detect   = ali_c2_cable_detect,
-
-       .bmdma_setup    = ata_bmdma_setup,
-       .bmdma_start    = ata_bmdma_start,
-       .bmdma_stop     = ata_bmdma_stop,
-       .bmdma_status   = ata_bmdma_status,
-
-       .qc_prep        = ata_qc_prep,
-       .qc_issue       = ata_qc_issue_prot,
-
-       .data_xfer      = ata_data_xfer,
-
-       .irq_handler    = ata_interrupt,
-       .irq_clear      = ata_bmdma_irq_clear,
-       .irq_on         = ata_irq_on,
-       .irq_ack        = ata_irq_ack,
-
-       .port_start     = ata_port_start,
+       .dev_config     = ali_lock_sectors,
 };
 
 /*
  *     Port operations for DMA capable ALi with cable detect and LBA48
  */
 static struct ata_port_operations ali_c5_port_ops = {
-       .port_disable   = ata_port_disable,
-       .set_piomode    = ali_set_piomode,
-       .set_dmamode    = ali_set_dmamode,
-       .mode_filter    = ata_pci_default_filter,
-       .tf_load        = ata_tf_load,
-       .tf_read        = ata_tf_read,
-       .check_status   = ata_check_status,
-       .exec_command   = ata_exec_command,
-       .dev_select     = ata_std_dev_select,
-
-       .freeze         = ata_bmdma_freeze,
-       .thaw           = ata_bmdma_thaw,
-       .error_handler  = ata_bmdma_error_handler,
-       .post_internal_cmd = ata_bmdma_post_internal_cmd,
+       .inherits       = &ali_dma_base_ops,
+       .check_atapi_dma = ali_check_atapi_dma,
+       .dev_config     = ali_warn_atapi_dma,
        .cable_detect   = ali_c2_cable_detect,
-
-       .bmdma_setup    = ata_bmdma_setup,
-       .bmdma_start    = ata_bmdma_start,
-       .bmdma_stop     = ata_bmdma_stop,
-       .bmdma_status   = ata_bmdma_status,
-
-       .qc_prep        = ata_qc_prep,
-       .qc_issue       = ata_qc_issue_prot,
-
-       .data_xfer      = ata_data_xfer,
-
-       .irq_handler    = ata_interrupt,
-       .irq_clear      = ata_bmdma_irq_clear,
-       .irq_on         = ata_irq_on,
-       .irq_ack        = ata_irq_ack,
-
-       .port_start     = ata_port_start,
 };
 
 
@@ -455,57 +430,54 @@ static struct ata_port_operations ali_c5_port_ops = {
 
 static void ali_init_chipset(struct pci_dev *pdev)
 {
-       u8 rev, tmp;
-       struct pci_dev *north, *isa_bridge;
-
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
+       u8 tmp;
+       struct pci_dev *north;
 
        /*
         * The chipset revision selects the driver operations and
         * mode data.
         */
 
-       if (rev >= 0x20 && rev < 0xC2) {
-               /* 1543-E/F, 1543C-C, 1543C-D, 1543C-E */
-               pci_read_config_byte(pdev, 0x4B, &tmp);
-               /* Clear CD-ROM DMA write bit */
-               tmp &= 0x7F;
-               pci_write_config_byte(pdev, 0x4B, tmp);
-       } else if (rev >= 0xC2) {
-               /* Enable cable detection logic */
+       if (pdev->revision <= 0x20) {
+               pci_read_config_byte(pdev, 0x53, &tmp);
+               tmp |= 0x03;
+               pci_write_config_byte(pdev, 0x53, tmp);
+       } else {
+               pci_read_config_byte(pdev, 0x4a, &tmp);
+               pci_write_config_byte(pdev, 0x4a, tmp | 0x20);
                pci_read_config_byte(pdev, 0x4B, &tmp);
+               if (pdev->revision < 0xC2)
+                       /* 1543-E/F, 1543C-C, 1543C-D, 1543C-E */
+                       /* Clear CD-ROM DMA write bit */
+                       tmp &= 0x7F;
+               /* Cable and UDMA */
+               if (pdev->revision >= 0xc2)
+                       tmp |= 0x01;
                pci_write_config_byte(pdev, 0x4B, tmp | 0x08);
-       }
-       north = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
-       isa_bridge = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
-
-       if (north && north->vendor == PCI_VENDOR_ID_AL && isa_bridge) {
-               /* Configure the ALi bridge logic. For non ALi rely on BIOS.
-                  Set the south bridge enable bit */
-               pci_read_config_byte(isa_bridge, 0x79, &tmp);
-               if (rev == 0xC2)
-                       pci_write_config_byte(isa_bridge, 0x79, tmp | 0x04);
-               else if (rev > 0xC2 && rev < 0xC5)
-                       pci_write_config_byte(isa_bridge, 0x79, tmp | 0x02);
-       }
-       if (rev >= 0x20) {
                /*
                 * CD_ROM DMA on (0x53 bit 0). Enable this even if we want
                 * to use PIO. 0x53 bit 1 (rev 20 only) - enable FIFO control
                 * via 0x54/55.
                 */
                pci_read_config_byte(pdev, 0x53, &tmp);
-               if (rev <= 0x20)
-                       tmp &= ~0x02;
-               if (rev >= 0xc7)
+               if (pdev->revision >= 0xc7)
                        tmp |= 0x03;
                else
                        tmp |= 0x01;    /* CD_ROM enable for DMA */
                pci_write_config_byte(pdev, 0x53, tmp);
        }
-       pci_dev_put(isa_bridge);
+       north = pci_get_bus_and_slot(0, PCI_DEVFN(0,0));
+       if (north && north->vendor == PCI_VENDOR_ID_AL && ali_isa_bridge) {
+               /* Configure the ALi bridge logic. For non ALi rely on BIOS.
+                  Set the south bridge enable bit */
+               pci_read_config_byte(ali_isa_bridge, 0x79, &tmp);
+               if (pdev->revision == 0xC2)
+                       pci_write_config_byte(ali_isa_bridge, 0x79, tmp | 0x04);
+               else if (pdev->revision > 0xC2 && pdev->revision < 0xC5)
+                       pci_write_config_byte(ali_isa_bridge, 0x79, tmp | 0x02);
+       }
        pci_dev_put(north);
-       ata_pci_clear_simplex(pdev);
+       ata_pci_bmdma_clear_simplex(pdev);
 }
 /**
  *     ali_init_one            -       discovery callback
@@ -518,108 +490,114 @@ static void ali_init_chipset(struct pci_dev *pdev)
 
 static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
-       static struct ata_port_info info_early = {
-               .sht = &ali_sht,
-               .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
-               .pio_mask = 0x1f,
+       static const struct ata_port_info info_early = {
+               .flags = ATA_FLAG_SLAVE_POSS,
+               .pio_mask = ATA_PIO4,
                .port_ops = &ali_early_port_ops
        };
        /* Revision 0x20 added DMA */
-       static struct ata_port_info info_20 = {
-               .sht = &ali_sht,
-               .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48,
-               .pio_mask = 0x1f,
-               .mwdma_mask = 0x07,
+       static const struct ata_port_info info_20 = {
+               .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48 |
+                                                       ATA_FLAG_IGN_SIMPLEX,
+               .pio_mask = ATA_PIO4,
+               .mwdma_mask = ATA_MWDMA2,
                .port_ops = &ali_20_port_ops
        };
        /* Revision 0x20 with support logic added UDMA */
-       static struct ata_port_info info_20_udma = {
-               .sht = &ali_sht,
-               .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48,
-               .pio_mask = 0x1f,
-               .mwdma_mask = 0x07,
-               .udma_mask = 0x07,      /* UDMA33 */
+       static const struct ata_port_info info_20_udma = {
+               .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48 |
+                                                       ATA_FLAG_IGN_SIMPLEX,
+               .pio_mask = ATA_PIO4,
+               .mwdma_mask = ATA_MWDMA2,
+               .udma_mask = ATA_UDMA2,
                .port_ops = &ali_20_port_ops
        };
        /* Revision 0xC2 adds UDMA66 */
-       static struct ata_port_info info_c2 = {
-               .sht = &ali_sht,
-               .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48,
-               .pio_mask = 0x1f,
-               .mwdma_mask = 0x07,
-               .udma_mask = 0x1f,
+       static const struct ata_port_info info_c2 = {
+               .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48 |
+                                                       ATA_FLAG_IGN_SIMPLEX,
+               .pio_mask = ATA_PIO4,
+               .mwdma_mask = ATA_MWDMA2,
+               .udma_mask = ATA_UDMA4,
                .port_ops = &ali_c2_port_ops
        };
-       /* Revision 0xC3 is UDMA100 */
-       static struct ata_port_info info_c3 = {
-               .sht = &ali_sht,
-               .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48,
-               .pio_mask = 0x1f,
-               .mwdma_mask = 0x07,
-               .udma_mask = 0x3f,
+       /* Revision 0xC3 is UDMA66 for now */
+       static const struct ata_port_info info_c3 = {
+               .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48 |
+                                                       ATA_FLAG_IGN_SIMPLEX,
+               .pio_mask = ATA_PIO4,
+               .mwdma_mask = ATA_MWDMA2,
+               .udma_mask = ATA_UDMA4,
                .port_ops = &ali_c2_port_ops
        };
-       /* Revision 0xC4 is UDMA133 */
-       static struct ata_port_info info_c4 = {
-               .sht = &ali_sht,
-               .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_PIO_LBA48,
-               .pio_mask = 0x1f,
-               .mwdma_mask = 0x07,
-               .udma_mask = 0x7f,
-               .port_ops = &ali_c2_port_ops
+       /* Revision 0xC4 is UDMA100 */
+       static const struct ata_port_info info_c4 = {
+               .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48 |
+                                                       ATA_FLAG_IGN_SIMPLEX,
+               .pio_mask = ATA_PIO4,
+               .mwdma_mask = ATA_MWDMA2,
+               .udma_mask = ATA_UDMA5,
+               .port_ops = &ali_c4_port_ops
        };
        /* Revision 0xC5 is UDMA133 with LBA48 DMA */
-       static struct ata_port_info info_c5 = {
-               .sht = &ali_sht,
-               .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
-               .pio_mask = 0x1f,
-               .mwdma_mask = 0x07,
-               .udma_mask = 0x7f,
+       static const struct ata_port_info info_c5 = {
+               .flags = ATA_FLAG_SLAVE_POSS |  ATA_FLAG_IGN_SIMPLEX,
+               .pio_mask = ATA_PIO4,
+               .mwdma_mask = ATA_MWDMA2,
+               .udma_mask = ATA_UDMA6,
                .port_ops = &ali_c5_port_ops
        };
 
-       static struct ata_port_info *port_info[2];
-       u8 rev, tmp;
-       struct pci_dev *isa_bridge;
+       const struct ata_port_info *ppi[] = { NULL, NULL };
+       u8 tmp;
+       int rc;
 
-       pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
+       rc = pcim_enable_device(pdev);
+       if (rc)
+               return rc;
 
        /*
         * The chipset revision selects the driver operations and
         * mode data.
         */
 
-       if (rev < 0x20) {
-               port_info[0] = port_info[1] = &info_early;
-       } else if (rev < 0xC2) {
-               port_info[0] = port_info[1] = &info_20;
-       } else if (rev == 0xC2) {
-               port_info[0] = port_info[1] = &info_c2;
-       } else if (rev == 0xC3) {
-               port_info[0] = port_info[1] = &info_c3;
-       } else if (rev == 0xC4) {
-               port_info[0] = port_info[1] = &info_c4;
+       if (pdev->revision < 0x20) {
+               ppi[0] = &info_early;
+       } else if (pdev->revision < 0xC2) {
+               ppi[0] = &info_20;
+       } else if (pdev->revision == 0xC2) {
+               ppi[0] = &info_c2;
+       } else if (pdev->revision == 0xC3) {
+               ppi[0] = &info_c3;
+       } else if (pdev->revision == 0xC4) {
+               ppi[0] = &info_c4;
        } else
-               port_info[0] = port_info[1] = &info_c5;
+               ppi[0] = &info_c5;
 
        ali_init_chipset(pdev);
 
-       isa_bridge = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
-       if (isa_bridge && rev >= 0x20 && rev < 0xC2) {
+       if (ali_isa_bridge && pdev->revision >= 0x20 && pdev->revision < 0xC2) {
                /* Are we paired with a UDMA capable chip */
-               pci_read_config_byte(isa_bridge, 0x5E, &tmp);
+               pci_read_config_byte(ali_isa_bridge, 0x5E, &tmp);
                if ((tmp & 0x1E) == 0x12)
-                       port_info[0] = port_info[1] = &info_20_udma;
-               pci_dev_put(isa_bridge);
+                       ppi[0] = &info_20_udma;
        }
-       return ata_pci_init_one(pdev, port_info, 2);
+
+       return ata_pci_sff_init_one(pdev, ppi, &ali_sht, NULL, 0);
 }
 
 #ifdef CONFIG_PM
 static int ali_reinit_one(struct pci_dev *pdev)
 {
+       struct ata_host *host = dev_get_drvdata(&pdev->dev);
+       int rc;
+
+       rc = ata_pci_device_do_resume(pdev);
+       if (rc)
+               return rc;
        ali_init_chipset(pdev);
-       return ata_pci_device_resume(pdev);
+       ata_host_resume(host);
+       return 0;
 }
 #endif
 
@@ -643,13 +621,20 @@ static struct pci_driver ali_pci_driver = {
 
 static int __init ali_init(void)
 {
-       return pci_register_driver(&ali_pci_driver);
+       int ret;
+       ali_isa_bridge = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL);
+
+       ret = pci_register_driver(&ali_pci_driver);
+       if (ret < 0)
+               pci_dev_put(ali_isa_bridge);
+       return ret;
 }
 
 
 static void __exit ali_exit(void)
 {
        pci_unregister_driver(&ali_pci_driver);
+       pci_dev_put(ali_isa_bridge);
 }