static void ahci_thaw(struct ata_port *ap);
 static void ahci_pmp_attach(struct ata_port *ap);
 static void ahci_pmp_detach(struct ata_port *ap);
+static int ahci_softreset(struct ata_link *link, unsigned int *class,
+                         unsigned long deadline);
+static int ahci_hardreset(struct ata_link *link, unsigned int *class,
+                         unsigned long deadline);
+static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
+                                unsigned long deadline);
+static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
+                               unsigned long deadline);
+static void ahci_postreset(struct ata_link *link, unsigned int *class);
+static int ahci_pmp_softreset(struct ata_link *link, unsigned int *class,
+                             unsigned long deadline);
 static void ahci_error_handler(struct ata_port *ap);
-static void ahci_vt8251_error_handler(struct ata_port *ap);
-static void ahci_p5wdh_error_handler(struct ata_port *ap);
 static void ahci_post_internal_cmd(struct ata_queued_cmd *qc);
 static int ahci_port_resume(struct ata_port *ap);
 static void ahci_dev_config(struct ata_device *dev);
 
        .freeze                 = ahci_freeze,
        .thaw                   = ahci_thaw,
+       .softreset              = ahci_softreset,
+       .hardreset              = ahci_hardreset,
+       .postreset              = ahci_postreset,
+       .pmp_softreset          = ahci_pmp_softreset,
        .error_handler          = ahci_error_handler,
        .post_internal_cmd      = ahci_post_internal_cmd,
        .dev_config             = ahci_dev_config,
 
 static struct ata_port_operations ahci_vt8251_ops = {
        .inherits               = &ahci_ops,
-       .error_handler          = ahci_vt8251_error_handler,
+       .hardreset              = ahci_vt8251_hardreset,
 };
 
 static struct ata_port_operations ahci_p5wdh_ops = {
        .inherits               = &ahci_ops,
-       .error_handler          = ahci_p5wdh_error_handler,
+       .hardreset              = ahci_p5wdh_hardreset,
 };
 
 #define AHCI_HFLAGS(flags)     .private_data   = (void *)(flags)
                ahci_start_engine(ap);
        }
 
-       /* perform recovery */
-       sata_pmp_do_eh(ap, ata_std_prereset, ahci_softreset,
-                      ahci_hardreset, ahci_postreset,
-                      sata_pmp_std_prereset, ahci_pmp_softreset,
-                      sata_pmp_std_hardreset, sata_pmp_std_postreset);
-}
-
-static void ahci_vt8251_error_handler(struct ata_port *ap)
-{
-       if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
-               /* restart engine */
-               ahci_stop_engine(ap);
-               ahci_start_engine(ap);
-       }
-
-       /* perform recovery */
-       ata_do_eh(ap, ata_std_prereset, ahci_softreset, ahci_vt8251_hardreset,
-                 ahci_postreset);
-}
-
-static void ahci_p5wdh_error_handler(struct ata_port *ap)
-{
-       if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
-               /* restart engine */
-               ahci_stop_engine(ap);
-               ahci_start_engine(ap);
-       }
-
-       /* perform recovery */
-       ata_do_eh(ap, ata_std_prereset, ahci_softreset, ahci_p5wdh_hardreset,
-                 ahci_postreset);
+       sata_pmp_error_handler(ap);
 }
 
 static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
 
 
 static int piix_init_one(struct pci_dev *pdev,
                         const struct pci_device_id *ent);
-static void piix_pata_error_handler(struct ata_port *ap);
+static int piix_pata_prereset(struct ata_link *link, unsigned long deadline);
 static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev);
 static void piix_set_dmamode(struct ata_port *ap, struct ata_device *adev);
 static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev);
 static int ich_pata_cable_detect(struct ata_port *ap);
 static u8 piix_vmw_bmdma_status(struct ata_port *ap);
+static int piix_sidpr_hardreset(struct ata_link *link, unsigned int *class,
+                               unsigned long deadline);
 static int piix_sidpr_scr_read(struct ata_port *ap, unsigned int reg, u32 *val);
 static int piix_sidpr_scr_write(struct ata_port *ap, unsigned int reg, u32 val);
-static void piix_sidpr_error_handler(struct ata_port *ap);
 #ifdef CONFIG_PM
 static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
 static int piix_pci_device_resume(struct pci_dev *pdev);
        .cable_detect           = ata_cable_40wire,
        .set_piomode            = piix_set_piomode,
        .set_dmamode            = piix_set_dmamode,
-       .error_handler          = piix_pata_error_handler,
+       .prereset               = piix_pata_prereset,
 };
 
 static struct ata_port_operations piix_vmw_ops = {
 
 static struct ata_port_operations piix_sidpr_sata_ops = {
        .inherits               = &piix_sata_ops,
+       .hardreset              = piix_sidpr_hardreset,
        .scr_read               = piix_sidpr_scr_read,
        .scr_write              = piix_sidpr_scr_write,
-       .error_handler          = piix_sidpr_error_handler,
 };
 
 static const struct piix_map_db ich5_map_db = {
        return ata_std_prereset(link, deadline);
 }
 
-static void piix_pata_error_handler(struct ata_port *ap)
-{
-       ata_bmdma_drive_eh(ap, piix_pata_prereset, ata_std_softreset, NULL,
-                          ata_std_postreset);
-}
-
 /**
  *     piix_set_piomode - Initialize host controller PATA PIO timings
  *     @ap: Port whose timings we are configuring
        return -EAGAIN;
 }
 
-static void piix_sidpr_error_handler(struct ata_port *ap)
-{
-       ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset,
-                          piix_sidpr_hardreset, ata_std_postreset);
-}
-
 #ifdef CONFIG_PM
 static int piix_broken_suspend(void)
 {
 
 
 const struct ata_port_operations ata_base_port_ops = {
        .irq_clear              = ata_noop_irq_clear,
+       .prereset               = ata_std_prereset,
+       .hardreset              = sata_std_hardreset,
+       .postreset              = ata_std_postreset,
+       .error_handler          = ata_std_error_handler,
 };
 
 const struct ata_port_operations sata_port_ops = {
 
 const struct ata_port_operations sata_pmp_port_ops = {
        .inherits               = &sata_port_ops,
+
+       .pmp_prereset           = sata_pmp_std_prereset,
+       .pmp_hardreset          = sata_pmp_std_hardreset,
+       .pmp_postreset          = sata_pmp_std_postreset,
+       .error_handler          = sata_pmp_error_handler,
 };
 
 const struct ata_port_operations ata_sff_port_ops = {
 
        .freeze                 = ata_bmdma_freeze,
        .thaw                   = ata_bmdma_thaw,
+       .softreset              = ata_std_softreset,
        .error_handler          = ata_bmdma_error_handler,
        .post_internal_cmd      = ata_bmdma_post_internal_cmd,
 
 EXPORT_SYMBOL_GPL(ata_bmdma_stop);
 EXPORT_SYMBOL_GPL(ata_bmdma_freeze);
 EXPORT_SYMBOL_GPL(ata_bmdma_thaw);
-EXPORT_SYMBOL_GPL(ata_bmdma_drive_eh);
 EXPORT_SYMBOL_GPL(ata_bmdma_error_handler);
 EXPORT_SYMBOL_GPL(ata_bmdma_post_internal_cmd);
 EXPORT_SYMBOL_GPL(ata_port_probe);
 EXPORT_SYMBOL_GPL(sata_pmp_std_prereset);
 EXPORT_SYMBOL_GPL(sata_pmp_std_hardreset);
 EXPORT_SYMBOL_GPL(sata_pmp_std_postreset);
-EXPORT_SYMBOL_GPL(sata_pmp_do_eh);
+EXPORT_SYMBOL_GPL(sata_pmp_error_handler);
 
 EXPORT_SYMBOL_GPL(__ata_ehi_push_desc);
 EXPORT_SYMBOL_GPL(ata_ehi_push_desc);
 EXPORT_SYMBOL_GPL(ata_eh_qc_complete);
 EXPORT_SYMBOL_GPL(ata_eh_qc_retry);
 EXPORT_SYMBOL_GPL(ata_do_eh);
+EXPORT_SYMBOL_GPL(ata_std_error_handler);
 EXPORT_SYMBOL_GPL(ata_irq_on);
 EXPORT_SYMBOL_GPL(ata_dev_try_classify);
 
 
 /**
  *     ata_do_eh - do standard error handling
  *     @ap: host port to handle error for
+ *
  *     @prereset: prereset method (can be NULL)
  *     @softreset: softreset method (can be NULL)
  *     @hardreset: hardreset method (can be NULL)
        ata_eh_finish(ap);
 }
 
+/**
+ *     ata_std_error_handler - standard error handler
+ *     @ap: host port to handle error for
+ *
+ *     Standard error handler
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep).
+ */
+void ata_std_error_handler(struct ata_port *ap)
+{
+       struct ata_port_operations *ops = ap->ops;
+       ata_reset_fn_t hardreset = ops->hardreset;
+
+       /* sata_std_hardreset is inherited to all drivers from
+        * ata_base_port_ops.  Ignore it if SCR access is not
+        * available.
+        */
+       if (hardreset == sata_std_hardreset && !sata_scr_valid(&ap->link))
+               hardreset = NULL;
+
+       ata_do_eh(ap, ops->prereset, ops->softreset, hardreset, ops->postreset);
+}
+
 #ifdef CONFIG_PM
 /**
  *     ata_eh_handle_port_suspend - perform port suspend operation
 
 /**
  *     sata_pmp_eh_recover - recover PMP-enabled port
  *     @ap: ATA port to recover
- *     @prereset: prereset method (can be NULL)
- *     @softreset: softreset method
- *     @hardreset: hardreset method
- *     @postreset: postreset method (can be NULL)
- *     @pmp_prereset: PMP prereset method (can be NULL)
- *     @pmp_softreset: PMP softreset method (can be NULL)
- *     @pmp_hardreset: PMP hardreset method (can be NULL)
- *     @pmp_postreset: PMP postreset method (can be NULL)
  *
  *     Drive EH recovery operation for PMP enabled port @ap.  This
  *     function recovers host and PMP ports with proper retrials and
  *     RETURNS:
  *     0 on success, -errno on failure.
  */
-static int sata_pmp_eh_recover(struct ata_port *ap,
-               ata_prereset_fn_t prereset, ata_reset_fn_t softreset,
-               ata_reset_fn_t hardreset, ata_postreset_fn_t postreset,
-               ata_prereset_fn_t pmp_prereset, ata_reset_fn_t pmp_softreset,
-               ata_reset_fn_t pmp_hardreset, ata_postreset_fn_t pmp_postreset)
+static int sata_pmp_eh_recover(struct ata_port *ap)
 {
+       struct ata_port_operations *ops = ap->ops;
        int pmp_tries, link_tries[SATA_PMP_MAX_PORTS];
        struct ata_link *pmp_link = &ap->link;
        struct ata_device *pmp_dev = pmp_link->device;
  retry:
        /* PMP attached? */
        if (!ap->nr_pmp_links) {
-               rc = ata_eh_recover(ap, prereset, softreset, hardreset,
-                                   postreset, NULL);
+               rc = ata_eh_recover(ap, ops->prereset, ops->softreset,
+                                   ops->hardreset, ops->postreset, NULL);
                if (rc) {
                        ata_link_for_each_dev(dev, &ap->link)
                                ata_dev_disable(dev);
        }
 
        /* recover pmp */
-       rc = sata_pmp_eh_recover_pmp(ap, prereset, softreset, hardreset,
-                                    postreset);
+       rc = sata_pmp_eh_recover_pmp(ap, ops->prereset, ops->softreset,
+                                    ops->hardreset, ops->postreset);
        if (rc)
                goto pmp_fail;
 
                goto pmp_fail;
 
        /* recover links */
-       rc = ata_eh_recover(ap, pmp_prereset, pmp_softreset, pmp_hardreset,
-                           pmp_postreset, &link);
+       rc = ata_eh_recover(ap, ops->pmp_prereset, ops->pmp_softreset,
+                           ops->pmp_hardreset, ops->pmp_postreset, &link);
        if (rc)
                goto link_fail;
 
 }
 
 /**
- *     sata_pmp_do_eh - do standard error handling for PMP-enabled host
+ *     sata_pmp_error_handler - do standard error handling for PMP-enabled host
  *     @ap: host port to handle error for
- *     @prereset: prereset method (can be NULL)
- *     @softreset: softreset method
- *     @hardreset: hardreset method
- *     @postreset: postreset method (can be NULL)
- *     @pmp_prereset: PMP prereset method (can be NULL)
- *     @pmp_softreset: PMP softreset method (can be NULL)
- *     @pmp_hardreset: PMP hardreset method (can be NULL)
- *     @pmp_postreset: PMP postreset method (can be NULL)
  *
  *     Perform standard error handling sequence for PMP-enabled host
  *     @ap.
  *     LOCKING:
  *     Kernel thread context (may sleep).
  */
-void sata_pmp_do_eh(struct ata_port *ap,
-               ata_prereset_fn_t prereset, ata_reset_fn_t softreset,
-               ata_reset_fn_t hardreset, ata_postreset_fn_t postreset,
-               ata_prereset_fn_t pmp_prereset, ata_reset_fn_t pmp_softreset,
-               ata_reset_fn_t pmp_hardreset, ata_postreset_fn_t pmp_postreset)
+void sata_pmp_error_handler(struct ata_port *ap)
 {
        ata_eh_autopsy(ap);
        ata_eh_report(ap);
-       sata_pmp_eh_recover(ap, prereset, softreset, hardreset, postreset,
-                           pmp_prereset, pmp_softreset, pmp_hardreset,
-                           pmp_postreset);
+       sata_pmp_eh_recover(ap);
        ata_eh_finish(ap);
 }
 
 }
 
 /**
- *     ata_bmdma_drive_eh - Perform EH with given methods for BMDMA controller
+ *     ata_bmdma_error_handler - Stock error handler for BMDMA controller
  *     @ap: port to handle error for
- *     @prereset: prereset method (can be NULL)
- *     @softreset: softreset method (can be NULL)
- *     @hardreset: hardreset method (can be NULL)
- *     @postreset: postreset method (can be NULL)
  *
- *     Handle error for ATA BMDMA controller.  It can handle both
+ *     Stock error handler for BMDMA controller.  It can handle both
  *     PATA and SATA controllers.  Many controllers should be able to
  *     use this EH as-is or with some added handling before and
  *     after.
  *
- *     This function is intended to be used for constructing
- *     ->error_handler callback by low level drivers.
- *
  *     LOCKING:
  *     Kernel thread context (may sleep)
  */
-void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
-                       ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
-                       ata_postreset_fn_t postreset)
+void ata_bmdma_error_handler(struct ata_port *ap)
 {
+       ata_reset_fn_t softreset = ap->ops->softreset;
+       ata_reset_fn_t hardreset = ap->ops->hardreset;
        struct ata_queued_cmd *qc;
        unsigned long flags;
        int thaw = 0;
                ata_eh_thaw_port(ap);
 
        /* PIO and DMA engines have been stopped, perform recovery */
-       ata_do_eh(ap, prereset, softreset, hardreset, postreset);
-}
-
-/**
- *     ata_bmdma_error_handler - Stock error handler for BMDMA controller
- *     @ap: port to handle error for
- *
- *     Stock error handler for BMDMA controller.
- *
- *     LOCKING:
- *     Kernel thread context (may sleep)
- */
-void ata_bmdma_error_handler(struct ata_port *ap)
-{
-       ata_reset_fn_t softreset = NULL, hardreset = NULL;
 
-       if (ap->ioaddr.ctl_addr)
-               softreset = ata_std_softreset;
-       if (sata_scr_valid(&ap->link))
-               hardreset = sata_std_hardreset;
+       /* ata_std_softreset and sata_std_hardreset are inherited to
+        * all SFF drivers from ata_sff_port_ops.  Ignore softreset if
+        * ctl isn't accessible.  Ignore hardreset if SCR access isn't
+        * available.
+        */
+       if (softreset == ata_std_softreset && !ap->ioaddr.ctl_addr)
+               softreset = NULL;
+       if (hardreset == sata_std_hardreset && !sata_scr_valid(&ap->link))
+               hardreset = NULL;
 
-       ata_bmdma_drive_eh(ap, ata_std_prereset, softreset, hardreset,
-                          ata_std_postreset);
+       ata_do_eh(ap, ap->ops->prereset, softreset, hardreset,
+                 ap->ops->postreset);
 }
 
 /**
 
        return ata_std_prereset(link, deadline);
 }
 
-/**
- *     artop6210_error_handler - Probe specified port on PATA host controller
- *     @ap: Port to probe
- *
- *     LOCKING:
- *     None (inherited from caller).
- */
-
-static void artop6210_error_handler(struct ata_port *ap)
-{
-       ata_bmdma_drive_eh(ap, artop6210_pre_reset,
-                                   ata_std_softreset, NULL,
-                                   ata_std_postreset);
-}
-
 /**
  *     artop6260_pre_reset     -       check for 40/80 pin
  *     @link: link
        return ATA_CBL_PATA80;
 }
 
-/**
- *     artop6260_error_handler - Probe specified port on PATA host controller
- *     @ap: Port to probe
- *
- *     LOCKING:
- *     None (inherited from caller).
- */
-
-static void artop6260_error_handler(struct ata_port *ap)
-{
-       ata_bmdma_drive_eh(ap, artop6260_pre_reset,
-                                   ata_std_softreset, NULL,
-                                   ata_std_postreset);
-}
-
 /**
  *     artop6210_load_piomode - Load a set of PATA PIO timings
  *     @ap: Port whose timings we are configuring
        .cable_detect           = ata_cable_40wire,
        .set_piomode            = artop6210_set_piomode,
        .set_dmamode            = artop6210_set_dmamode,
-       .error_handler          = artop6210_error_handler,
+       .prereset               = artop6210_pre_reset,
 };
 
 static struct ata_port_operations artop6260_ops = {
        .cable_detect           = artop6260_cable_detect,
        .set_piomode            = artop6260_set_piomode,
        .set_dmamode            = artop6260_set_dmamode,
-       .error_handler          = artop6260_error_handler,
+       .prereset               = artop6260_pre_reset,
 };
 
 
 
        return ata_std_prereset(link, deadline);
 }
 
-static void atiixp_error_handler(struct ata_port *ap)
-{
-       ata_bmdma_drive_eh(ap, atiixp_pre_reset, ata_std_softreset, NULL,   ata_std_postreset);
-}
-
 static int atiixp_cable_detect(struct ata_port *ap)
 {
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
        .cable_detect   = atiixp_cable_detect,
        .set_piomode    = atiixp_set_piomode,
        .set_dmamode    = atiixp_set_dmamode,
-       .error_handler  = atiixp_error_handler,
+       .prereset       = atiixp_pre_reset,
 };
 
 static int atiixp_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 
        write_atapi_register(base, ATA_REG_CTRL, ap->ctl);
 }
 
-/**
- *     bfin_error_handler - Stock error handler for DMA controller
- *     @ap: port to handle error for
- */
-
-static void bfin_error_handler(struct ata_port *ap)
-{
-       ata_bmdma_drive_eh(ap, ata_std_prereset, bfin_std_softreset, NULL,
-                          bfin_std_postreset);
-}
-
 static void bfin_port_stop(struct ata_port *ap)
 {
        dev_dbg(ap->dev, "in atapi port stop\n");
 
        .freeze                 = bfin_bmdma_freeze,
        .thaw                   = bfin_bmdma_thaw,
-       .error_handler          = bfin_error_handler,
+       .softreset              = bfin_std_softreset,
+       .postreset              = bfin_std_postreset,
        .post_internal_cmd      = bfin_bmdma_stop,
 
        .irq_clear              = bfin_irq_clear,
 
        return ata_std_prereset(link, deadline);
 }
 
-/**
- *     efar_probe_reset - Probe specified port on PATA host controller
- *     @ap: Port to probe
- *
- *     LOCKING:
- *     None (inherited from caller).
- */
-
-static void efar_error_handler(struct ata_port *ap)
-{
-       ata_bmdma_drive_eh(ap, efar_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
-}
-
 /**
  *     efar_cable_detect       -       check for 40/80 pin
  *     @ap: Port
        .cable_detect           = efar_cable_detect,
        .set_piomode            = efar_set_piomode,
        .set_dmamode            = efar_set_dmamode,
-       .error_handler          = efar_error_handler,
+       .prereset               = efar_pre_reset,
 };
 
 
 
        return ata_std_prereset(link, deadline);
 }
 
-/**
- *     hpt37x_error_handler    -       reset the hpt374
- *     @ap: ATA port to reset
- *
- *     Perform probe for HPT37x, except for HPT374 channel 2
- */
-
-static void hpt37x_error_handler(struct ata_port *ap)
-{
-       ata_bmdma_drive_eh(ap, hpt37x_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
-}
-
-static int hpt374_pre_reset(struct ata_link *link, unsigned long deadline)
+static int hpt374_fn1_pre_reset(struct ata_link *link, unsigned long deadline)
 {
        static const struct pci_bits hpt37x_enable_bits[] = {
                { 0x50, 1, 0x04, 0x04 },
        return ata_std_prereset(link, deadline);
 }
 
-/**
- *     hpt374_error_handler    -       reset the hpt374
- *     @classes:
- *
- *     The 374 cable detect is a little different due to the extra
- *     channels. The function 0 channels work like usual but function 1
- *     is special
- */
-
-static void hpt374_error_handler(struct ata_port *ap)
-{
-       struct pci_dev *pdev = to_pci_dev(ap->host->dev);
-
-       if (!(PCI_FUNC(pdev->devfn) & 1))
-               hpt37x_error_handler(ap);
-       else
-               ata_bmdma_drive_eh(ap, hpt374_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
-}
-
 /**
  *     hpt370_set_piomode              -       PIO setup
  *     @ap: ATA interface
        .mode_filter    = hpt370_filter,
        .set_piomode    = hpt370_set_piomode,
        .set_dmamode    = hpt370_set_dmamode,
-       .error_handler  = hpt37x_error_handler,
+       .prereset       = hpt37x_pre_reset,
 };
 
 /*
 
        .set_piomode    = hpt372_set_piomode,
        .set_dmamode    = hpt372_set_dmamode,
-       .error_handler  = hpt37x_error_handler,
+       .prereset       = hpt37x_pre_reset,
 };
 
 /*
  *     Configuration for HPT374. Mode setting works like 372 and friends
- *     but we have a different cable detection procedure.
+ *     but we have a different cable detection procedure for function 1.
  */
 
-static struct ata_port_operations hpt374_port_ops = {
+static struct ata_port_operations hpt374_fn1_port_ops = {
        .inherits       = &hpt372_port_ops,
-       .error_handler  = hpt374_error_handler,
+       .prereset       = hpt374_fn1_pre_reset,
 };
 
 /**
                .udma_mask = ATA_UDMA6,
                .port_ops = &hpt372_port_ops
        };
-       /* HPT374 - UDMA100 */
-       static const struct ata_port_info info_hpt374 = {
+       /* HPT374 - UDMA100, function 1 uses different prereset method */
+       static const struct ata_port_info info_hpt374_fn0 = {
+               .flags = ATA_FLAG_SLAVE_POSS,
+               .pio_mask = 0x1f,
+               .mwdma_mask = 0x07,
+               .udma_mask = ATA_UDMA5,
+               .port_ops = &hpt372_port_ops
+       };
+       static const struct ata_port_info info_hpt374_fn1 = {
                .flags = ATA_FLAG_SLAVE_POSS,
                .pio_mask = 0x1f,
                .mwdma_mask = 0x07,
                .udma_mask = ATA_UDMA5,
-               .port_ops = &hpt374_port_ops
+               .port_ops = &hpt374_fn1_port_ops
        };
 
        static const int MHz[4] = { 33, 40, 50, 66 };
                                break;
                        case PCI_DEVICE_ID_TTI_HPT374:
                                chip_table = &hpt374;
-                               ppi[0] = &info_hpt374;
+                               if (!(PCI_FUNC(dev->devfn) & 1))
+                                       *ppi = &info_hpt374_fn0;
+                               else
+                                       *ppi = &info_hpt374_fn1;
                                break;
                        default:
                                printk(KERN_ERR "pata_hpt37x: PCI table is bogus please report (%d).\n", dev->device);
 
  *     Reset the hardware and state machine,
  */
 
-static int hpt3xn_pre_reset(struct ata_link *link, unsigned long deadline)
+static int hpt3x2n_pre_reset(struct ata_link *link, unsigned long deadline)
 {
        struct ata_port *ap = link->ap;
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
        return ata_std_prereset(link, deadline);
 }
 
-/**
- *     hpt3x2n_error_handler   -       probe the hpt3x2n bus
- *     @ap: ATA port to reset
- *
- *     Perform the probe reset handling for the 3x2N
- */
-
-static void hpt3x2n_error_handler(struct ata_port *ap)
-{
-       ata_bmdma_drive_eh(ap, hpt3xn_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
-}
-
 /**
  *     hpt3x2n_set_piomode             -       PIO setup
  *     @ap: ATA interface
        .cable_detect   = hpt3x2n_cable_detect,
        .set_piomode    = hpt3x2n_set_piomode,
        .set_dmamode    = hpt3x2n_set_dmamode,
-       .error_handler  = hpt3x2n_error_handler,
+       .prereset       = hpt3x2n_pre_reset,
 };
 
 /**
 
        }
 }
 
-static void pata_icside_error_handler(struct ata_port *ap)
-{
-       ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, NULL,
-                          pata_icside_postreset);
-}
-
 static struct ata_port_operations pata_icside_port_ops = {
        .inherits               = &ata_sff_port_ops,
        /* no need to build any PRD tables for DMA */
 
        .cable_detect           = ata_cable_40wire,
        .set_dmamode            = pata_icside_set_dmamode,
-       .error_handler          = pata_icside_error_handler,
+       .postreset              = pata_icside_postreset,
        .post_internal_cmd      = pata_icside_bmdma_stop,
 };
 
 
        return ata_std_prereset(link, deadline);
 }
 
-/**
- *     it8213_error_handler - Probe specified port on PATA host controller
- *     @ap: Port to probe
- *
- *     LOCKING:
- *     None (inherited from caller).
- */
-
-static void it8213_error_handler(struct ata_port *ap)
-{
-       ata_bmdma_drive_eh(ap, it8213_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
-}
-
 /**
  *     it8213_cable_detect     -       check for 40/80 pin
  *     @ap: Port
        .cable_detect           = it8213_cable_detect,
        .set_piomode            = it8213_set_piomode,
        .set_dmamode            = it8213_set_dmamode,
-       .error_handler          = it8213_error_handler,
+       .prereset               = it8213_pre_reset,
 };
 
 
 
        ata_std_dev_select(ap,device);
 }
 
-static void
-mpc52xx_ata_error_handler(struct ata_port *ap)
-{
-       ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, NULL,
-                       ata_std_postreset);
-}
-
-
-
 static struct scsi_host_template mpc52xx_ata_sht = {
        ATA_PIO_SHT(DRV_NAME),
 };
        .dev_select             = mpc52xx_ata_dev_select,
        .cable_detect           = ata_cable_40wire,
        .set_piomode            = mpc52xx_ata_set_piomode,
-       .error_handler          = mpc52xx_ata_error_handler,
        .post_internal_cmd      = ATA_OP_NULL,
 };
 
 
        return ata_std_prereset(link, deadline);
 }
 
-/**
- *     mpiix_error_handler             -       probe reset
- *     @ap: ATA port
- *
- *     Perform the ATA probe and bus reset sequence plus specific handling
- *     for this hardware. The MPIIX has the enable bits in a different place
- *     to PIIX4 and friends. As a pure PIO device it has no cable detect
- */
-
-static void mpiix_error_handler(struct ata_port *ap)
-{
-       ata_bmdma_drive_eh(ap, mpiix_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
-}
-
 /**
  *     mpiix_set_piomode       -       set initial PIO mode data
  *     @ap: ATA interface
        .qc_issue       = mpiix_qc_issue_prot,
        .cable_detect   = ata_cable_40wire,
        .set_piomode    = mpiix_set_piomode,
-       .error_handler  = mpiix_error_handler,
+       .prereset       = mpiix_pre_reset,
 };
 
 static int mpiix_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 
        return ata_std_prereset(link, deadline);
 }
 
-/**
- *     ns87410_error_handler           -       probe reset
- *     @ap: ATA port
- *
- *     Perform the ATA probe and bus reset sequence plus specific handling
- *     for this hardware. The MPIIX has the enable bits in a different place
- *     to PIIX4 and friends. As a pure PIO device it has no cable detect
- */
-
-static void ns87410_error_handler(struct ata_port *ap)
-{
-       ata_bmdma_drive_eh(ap, ns87410_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
-}
-
 /**
  *     ns87410_set_piomode     -       set initial PIO mode data
  *     @ap: ATA interface
        .qc_issue       = ns87410_qc_issue_prot,
        .cable_detect   = ata_cable_40wire,
        .set_piomode    = ns87410_set_piomode,
-       .error_handler  = ns87410_error_handler,
+       .prereset       = ns87410_pre_reset,
 };
 
 static int ns87410_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 
        return ata_std_prereset(link, deadline);
 }
 
-/**
- *     oldpiix_pata_error_handler - Probe specified port on PATA host controller
- *     @ap: Port to probe
- *     @classes:
- *
- *     LOCKING:
- *     None (inherited from caller).
- */
-
-static void oldpiix_pata_error_handler(struct ata_port *ap)
-{
-       ata_bmdma_drive_eh(ap, oldpiix_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
-}
-
 /**
  *     oldpiix_set_piomode - Initialize host controller PATA PIO timings
  *     @ap: Port whose timings we are configuring
        .cable_detect           = ata_cable_40wire,
        .set_piomode            = oldpiix_set_piomode,
        .set_dmamode            = oldpiix_set_dmamode,
-       .error_handler          = oldpiix_pata_error_handler,
+       .prereset               = oldpiix_pre_reset,
 };
 
 
 
        return ata_std_prereset(link, deadline);
 }
 
-/**
- *     opti_probe_reset                -       probe reset
- *     @ap: ATA port
- *
- *     Perform the ATA probe and bus reset sequence plus specific handling
- *     for this hardware. The Opti needs little handling - we have no UDMA66
- *     capability that needs cable detection. All we must do is check the port
- *     is enabled.
- */
-
-static void opti_error_handler(struct ata_port *ap)
-{
-       ata_bmdma_drive_eh(ap, opti_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
-}
-
 /**
  *     opti_write_reg          -       control register setup
  *     @ap: ATA port
        .inherits       = &ata_sff_port_ops,
        .cable_detect   = ata_cable_40wire,
        .set_piomode    = opti_set_piomode,
-       .error_handler  = opti_error_handler,
+       .prereset       = opti_pre_reset,
 };
 
 static int opti_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 
        return ata_std_prereset(link, deadline);
 }
 
-/**
- *     optidma_probe_reset             -       probe reset
- *     @ap: ATA port
- *
- *     Perform the ATA probe and bus reset sequence plus specific handling
- *     for this hardware. The Opti needs little handling - we have no UDMA66
- *     capability that needs cable detection. All we must do is check the port
- *     is enabled.
- */
-
-static void optidma_error_handler(struct ata_port *ap)
-{
-       ata_bmdma_drive_eh(ap, optidma_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
-}
-
 /**
  *     optidma_unlock          -       unlock control registers
  *     @ap: ATA port
        .set_piomode    = optidma_set_pio_mode,
        .set_dmamode    = optidma_set_dma_mode,
        .set_mode       = optidma_set_mode,
-       .error_handler  = optidma_error_handler,
+       .prereset       = optidma_pre_reset,
 };
 
 static struct ata_port_operations optiplus_port_ops = {
 
 };
 
 static int pdc2027x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
-static void pdc2027x_error_handler(struct ata_port *ap);
+static int pdc2027x_prereset(struct ata_link *link, unsigned long deadline);
 static void pdc2027x_set_piomode(struct ata_port *ap, struct ata_device *adev);
 static void pdc2027x_set_dmamode(struct ata_port *ap, struct ata_device *adev);
 static int pdc2027x_check_atapi_dma(struct ata_queued_cmd *qc);
        .inherits               = &ata_bmdma_port_ops,
        .check_atapi_dma        = pdc2027x_check_atapi_dma,
        .cable_detect           = pdc2027x_cable_detect,
-       .error_handler          = pdc2027x_error_handler,
+       .prereset               = pdc2027x_prereset,
 };
 
 static struct ata_port_operations pdc2027x_pata133_ops = {
        return ata_std_prereset(link, deadline);
 }
 
-/**
- *     pdc2027x_error_handler - Perform reset on PATA port and classify
- *     @ap: Port to reset
- *
- *     Reset PATA phy and classify attached devices.
- *
- *     LOCKING:
- *     None (inherited from caller).
- */
-
-static void pdc2027x_error_handler(struct ata_port *ap)
-{
-       ata_bmdma_drive_eh(ap, pdc2027x_prereset, ata_std_softreset, NULL, ata_std_postreset);
-}
-
 /**
  *     pdc2720x_mode_filter    -       mode selection filter
  *     @adev: ATA device
 
        DPRINTK("EXIT\n");
 }
 
-/**
- *     scc_error_handler - Stock error handler for BMDMA controller
- *     @ap: port to handle error for
- */
-
-static void scc_error_handler (struct ata_port *ap)
-{
-       ata_bmdma_drive_eh(ap, scc_pata_prereset, scc_std_softreset, NULL,
-                          scc_std_postreset);
-}
-
 /**
  *     scc_bmdma_irq_clear - Clear PCI IDE BMDMA interrupt.
  *     @ap: Port associated with this ATA transaction.
        .data_xfer              = scc_data_xfer,
 
        .freeze                 = scc_bmdma_freeze,
-       .error_handler          = scc_error_handler,
+       .prereset               = scc_pata_prereset,
+       .softreset              = scc_std_softreset,
+       .postreset              = scc_std_postreset,
        .post_internal_cmd      = scc_bmdma_stop,
 
        .irq_clear              = scc_bmdma_irq_clear,
 
 }
 
 
-/**
- *     sis_error_handler - Probe specified port on PATA host controller
- *     @ap: Port to probe
- *
- *     LOCKING:
- *     None (inherited from caller).
- */
-
-static void sis_error_handler(struct ata_port *ap)
-{
-       ata_bmdma_drive_eh(ap, sis_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
-}
-
 /**
  *     sis_set_fifo    -       Set RWP fifo bits for this device
  *     @ap: Port
 
 static struct ata_port_operations sis_base_ops = {
        .inherits               = &ata_bmdma_port_ops,
-       .error_handler          = sis_error_handler,
+       .prereset               = sis_pre_reset,
 };
 
 static struct ata_port_operations sis_133_ops = {
 
 }
 
 
-static void sl82c105_error_handler(struct ata_port *ap)
-{
-       ata_bmdma_drive_eh(ap, sl82c105_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
-}
-
-
 /**
  *     sl82c105_configure_piomode      -       set chip PIO timing
  *     @ap: ATA interface
        .bmdma_stop     = sl82c105_bmdma_stop,
        .cable_detect   = ata_cable_40wire,
        .set_piomode    = sl82c105_set_piomode,
-       .error_handler  = sl82c105_error_handler,
+       .prereset       = sl82c105_pre_reset,
 };
 
 /**
 
 
 
 
-static void triflex_error_handler(struct ata_port *ap)
-{
-       ata_bmdma_drive_eh(ap, triflex_prereset, ata_std_softreset, NULL, ata_std_postreset);
-}
-
 /**
  *     triflex_load_timing             -       timing configuration
  *     @ap: ATA interface
        .bmdma_stop     = triflex_bmdma_stop,
        .cable_detect   = ata_cable_40wire,
        .set_piomode    = triflex_set_piomode,
-       .error_handler  = triflex_error_handler,
+       .prereset       = triflex_prereset,
 };
 
 static int triflex_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 
 }
 
 
-/**
- *     via_error_handler               -       reset for VIA chips
- *     @ap: ATA port
- *
- *     Handle the reset callback for the later chips with cable detect
- */
-
-static void via_error_handler(struct ata_port *ap)
-{
-       ata_bmdma_drive_eh(ap, via_pre_reset, ata_std_softreset, NULL, ata_std_postreset);
-}
-
 /**
  *     via_do_set_mode -       set initial PIO mode data
  *     @ap: ATA interface
        .cable_detect   = via_cable_detect,
        .set_piomode    = via_set_piomode,
        .set_dmamode    = via_set_dmamode,
-       .error_handler  = via_error_handler,
+       .prereset       = via_pre_reset,
 };
 
 static struct ata_port_operations via_port_ops_noirq = {
 
 static u8 adma_bmdma_status(struct ata_port *ap);
 static void adma_freeze(struct ata_port *ap);
 static void adma_thaw(struct ata_port *ap);
-static void adma_error_handler(struct ata_port *ap);
+static int adma_prereset(struct ata_link *link, unsigned long deadline);
 
 static struct scsi_host_template adma_ata_sht = {
        ATA_BASE_SHT(DRV_NAME),
 
        .freeze                 = adma_freeze,
        .thaw                   = adma_thaw,
-       .error_handler          = adma_error_handler,
+       .prereset               = adma_prereset,
+       .softreset              = ata_std_softreset,
 
        .port_start             = adma_port_start,
        .port_stop              = adma_port_stop,
        return ata_std_prereset(link, deadline);
 }
 
-static void adma_error_handler(struct ata_port *ap)
-{
-       ata_do_eh(ap, adma_prereset, ata_std_softreset, NULL,
-                 ata_std_postreset);
-}
-
 static int adma_fill_sg(struct ata_queued_cmd *qc)
 {
        struct scatterlist *sg;
 
        return -EIO;
 }
 
-static void sata_fsl_error_handler(struct ata_port *ap)
-{
-
-       DPRINTK("in xx_error_handler\n");
-
-       /* perform recovery */
-       ata_do_eh(ap, ata_std_prereset, sata_fsl_softreset, sata_std_hardreset,
-                 ata_std_postreset);
-}
-
 static void sata_fsl_post_internal_cmd(struct ata_queued_cmd *qc)
 {
        if (qc->flags & ATA_QCFLAG_FAILED)
 
        .freeze = sata_fsl_freeze,
        .thaw = sata_fsl_thaw,
-       .error_handler = sata_fsl_error_handler,
+       .softreset = sata_fsl_softreset,
        .post_internal_cmd = sata_fsl_post_internal_cmd,
 
        .port_start = sata_fsl_port_start,
 
        spin_unlock_irqrestore(ap->lock, flags);
 
        /* PIO and DMA engines have been stopped, perform recovery */
-       ata_do_eh(ap, ata_std_prereset, NULL, inic_hardreset,
-                 ata_std_postreset);
+       ata_std_error_handler(ap);
 }
 
 static void inic_post_internal_cmd(struct ata_queued_cmd *qc)
 
        .freeze                 = inic_freeze,
        .thaw                   = inic_thaw,
+       .softreset              = ATA_OP_NULL,  /* softreset is broken */
+       .hardreset              = inic_hardreset,
        .error_handler          = inic_error_handler,
        .post_internal_cmd      = inic_post_internal_cmd,
        .dev_config             = inic_dev_config,
 
 static void mv_qc_prep(struct ata_queued_cmd *qc);
 static void mv_qc_prep_iie(struct ata_queued_cmd *qc);
 static unsigned int mv_qc_issue(struct ata_queued_cmd *qc);
-static void mv_error_handler(struct ata_port *ap);
+static int mv_prereset(struct ata_link *link, unsigned long deadline);
+static int mv_hardreset(struct ata_link *link, unsigned int *class,
+                       unsigned long deadline);
+static void mv_postreset(struct ata_link *link, unsigned int *classes);
 static void mv_eh_freeze(struct ata_port *ap);
 static void mv_eh_thaw(struct ata_port *ap);
 static void mv6_dev_config(struct ata_device *dev);
 
        .freeze                 = mv_eh_freeze,
        .thaw                   = mv_eh_thaw,
-       .error_handler          = mv_error_handler,
+       .prereset               = mv_prereset,
+       .hardreset              = mv_hardreset,
+       .postreset              = mv_postreset,
+       .error_handler          = ata_std_error_handler, /* avoid SFF EH */
        .post_internal_cmd      = ATA_OP_NULL,
 
        .scr_read               = mv5_scr_read,
        iowrite8(ap->ctl, ap->ioaddr.ctl_addr);
 }
 
-static void mv_error_handler(struct ata_port *ap)
-{
-       ata_do_eh(ap, mv_prereset, ata_std_softreset,
-                 mv_hardreset, mv_postreset);
-}
-
 static void mv_eh_freeze(struct ata_port *ap)
 {
        struct mv_host_priv *hpriv = ap->host->private_data;
 
 static void nv_nf2_thaw(struct ata_port *ap);
 static void nv_ck804_freeze(struct ata_port *ap);
 static void nv_ck804_thaw(struct ata_port *ap);
-static void nv_error_handler(struct ata_port *ap);
+static int nv_hardreset(struct ata_link *link, unsigned int *class,
+                       unsigned long deadline);
 static int nv_adma_slave_config(struct scsi_device *sdev);
 static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc);
 static void nv_adma_qc_prep(struct ata_queued_cmd *qc);
 
 static struct ata_port_operations nv_generic_ops = {
        .inherits               = &ata_bmdma_port_ops,
-       .error_handler          = nv_error_handler,
+       .hardreset              = nv_hardreset,
        .scr_read               = nv_scr_read,
        .scr_write              = nv_scr_write,
 };
        return sata_std_hardreset(link, &dummy, deadline);
 }
 
-static void nv_error_handler(struct ata_port *ap)
-{
-       ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset,
-                          nv_hardreset, ata_std_postreset);
-}
-
 static void nv_adma_error_handler(struct ata_port *ap)
 {
        struct nv_adma_port_priv *pp = ap->private_data;
                readw(mmio + NV_ADMA_CTL);      /* flush posted write */
        }
 
-       ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset,
-                          nv_hardreset, ata_std_postreset);
+       ata_bmdma_error_handler(ap);
 }
 
 static void nv_swncq_qc_to_dq(struct ata_port *ap, struct ata_queued_cmd *qc)
                ehc->i.action |= ATA_EH_RESET;
        }
 
-       ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset,
-                          nv_hardreset, ata_std_postreset);
+       ata_bmdma_error_handler(ap);
 }
 
 #ifdef CONFIG_PM
 
 static void pdc_sata_freeze(struct ata_port *ap);
 static void pdc_thaw(struct ata_port *ap);
 static void pdc_sata_thaw(struct ata_port *ap);
-static void pdc_pata_error_handler(struct ata_port *ap);
-static void pdc_sata_error_handler(struct ata_port *ap);
+static void pdc_error_handler(struct ata_port *ap);
 static void pdc_post_internal_cmd(struct ata_queued_cmd *qc);
 static int pdc_pata_cable_detect(struct ata_port *ap);
 static int pdc_sata_cable_detect(struct ata_port *ap);
        .irq_clear              = pdc_irq_clear,
 
        .post_internal_cmd      = pdc_post_internal_cmd,
+       .error_handler          = pdc_error_handler,
 };
 
 static struct ata_port_operations pdc_sata_ops = {
        .cable_detect           = pdc_sata_cable_detect,
        .freeze                 = pdc_sata_freeze,
        .thaw                   = pdc_sata_thaw,
-       .error_handler          = pdc_sata_error_handler,
        .scr_read               = pdc_sata_scr_read,
        .scr_write              = pdc_sata_scr_write,
        .port_start             = pdc_sata_port_start,
        .cable_detect           = pdc_pata_cable_detect,
        .freeze                 = pdc_freeze,
        .thaw                   = pdc_thaw,
-       .error_handler          = pdc_pata_error_handler,
        .port_start             = pdc_common_port_start,
 };
 
        readl(host_mmio + hotplug_offset); /* flush */
 }
 
-static void pdc_common_error_handler(struct ata_port *ap, ata_reset_fn_t hardreset)
+static void pdc_error_handler(struct ata_port *ap)
 {
        if (!(ap->pflags & ATA_PFLAG_FROZEN))
                pdc_reset_port(ap);
 
-       /* perform recovery */
-       ata_do_eh(ap, ata_std_prereset, ata_std_softreset, hardreset,
-                 ata_std_postreset);
-}
-
-static void pdc_pata_error_handler(struct ata_port *ap)
-{
-       pdc_common_error_handler(ap, NULL);
-}
-
-static void pdc_sata_error_handler(struct ata_port *ap)
-{
-       pdc_common_error_handler(ap, sata_std_hardreset);
+       ata_std_error_handler(ap);
 }
 
 static void pdc_post_internal_cmd(struct ata_queued_cmd *qc)
 
 static u8 qs_bmdma_status(struct ata_port *ap);
 static void qs_freeze(struct ata_port *ap);
 static void qs_thaw(struct ata_port *ap);
+static int qs_prereset(struct ata_link *link, unsigned long deadline);
 static void qs_error_handler(struct ata_port *ap);
 
 static struct scsi_host_template qs_ata_sht = {
 
        .freeze                 = qs_freeze,
        .thaw                   = qs_thaw,
+       .prereset               = qs_prereset,
+       .softreset              = ATA_OP_NULL,
        .error_handler          = qs_error_handler,
        .post_internal_cmd      = ATA_OP_NULL,
 
 static void qs_error_handler(struct ata_port *ap)
 {
        qs_enter_reg_mode(ap);
-       ata_do_eh(ap, qs_prereset, NULL, sata_std_hardreset,
-                 ata_std_postreset);
+       ata_std_error_handler(ap);
 }
 
 static int qs_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val)
 
 static void sil24_pmp_detach(struct ata_port *ap);
 static void sil24_freeze(struct ata_port *ap);
 static void sil24_thaw(struct ata_port *ap);
+static int sil24_softreset(struct ata_link *link, unsigned int *class,
+                          unsigned long deadline);
+static int sil24_hardreset(struct ata_link *link, unsigned int *class,
+                          unsigned long deadline);
+static int sil24_pmp_softreset(struct ata_link *link, unsigned int *class,
+                              unsigned long deadline);
+static int sil24_pmp_hardreset(struct ata_link *link, unsigned int *class,
+                              unsigned long deadline);
 static void sil24_error_handler(struct ata_port *ap);
 static void sil24_post_internal_cmd(struct ata_queued_cmd *qc);
 static int sil24_port_start(struct ata_port *ap);
 
        .freeze                 = sil24_freeze,
        .thaw                   = sil24_thaw,
+       .softreset              = sil24_softreset,
+       .hardreset              = sil24_hardreset,
+       .pmp_softreset          = sil24_pmp_softreset,
+       .pmp_hardreset          = sil24_pmp_hardreset,
        .error_handler          = sil24_error_handler,
        .post_internal_cmd      = sil24_post_internal_cmd,
        .dev_config             = sil24_dev_config,
        if (sil24_init_port(ap))
                ata_eh_freeze_port(ap);
 
-       /* perform recovery */
-       sata_pmp_do_eh(ap, ata_std_prereset, sil24_softreset, sil24_hardreset,
-                      ata_std_postreset, sata_pmp_std_prereset,
-                      sil24_pmp_softreset, sil24_pmp_hardreset,
-                      sata_pmp_std_postreset);
+       sata_pmp_error_handler(ap);
 
        pp->do_port_rst = 0;
 }
 
 static int svia_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val);
 static int svia_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val);
 static void svia_noop_freeze(struct ata_port *ap);
-static void vt6420_error_handler(struct ata_port *ap);
+static int vt6420_prereset(struct ata_link *link, unsigned long deadline);
 static int vt6421_pata_cable_detect(struct ata_port *ap);
 static void vt6421_set_pio_mode(struct ata_port *ap, struct ata_device *adev);
 static void vt6421_set_dma_mode(struct ata_port *ap, struct ata_device *adev);
 static struct ata_port_operations vt6420_sata_ops = {
        .inherits               = &ata_bmdma_port_ops,
        .freeze                 = svia_noop_freeze,
-       .error_handler          = vt6420_error_handler,
+       .prereset               = vt6420_prereset,
 };
 
 static struct ata_port_operations vt6421_pata_ops = {
        return 0;
 }
 
-static void vt6420_error_handler(struct ata_port *ap)
-{
-       ata_bmdma_drive_eh(ap, vt6420_prereset, ata_std_softreset, NULL,
-                          ata_std_postreset);
-}
-
 static int vt6421_pata_cable_detect(struct ata_port *ap)
 {
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 
        if (ipr_is_gata(res) && res->sata_port) {
                ap = res->sata_port->ap;
                spin_unlock_irq(scsi_cmd->device->host->host_lock);
-               ata_do_eh(ap, NULL, NULL, ipr_sata_reset, NULL);
+               ata_std_error_handler(ap);
                spin_lock_irq(scsi_cmd->device->host->host_lock);
 
                list_for_each_entry(ipr_cmd, &ioa_cfg->pending_q, queue) {
        .check_altstatus = ipr_ata_check_altstatus,
        .dev_select = ata_noop_dev_select,
        .phy_reset = ipr_ata_phy_reset,
+       .hardreset = ipr_sata_reset,
        .post_internal_cmd = ipr_ata_post_internal,
        .tf_read = ipr_tf_read,
        .qc_prep = ata_noop_qc_prep,
 
 
        void (*freeze)(struct ata_port *ap);
        void (*thaw)(struct ata_port *ap);
+       ata_prereset_fn_t       prereset;
+       ata_reset_fn_t          softreset;
+       ata_reset_fn_t          hardreset;
+       ata_postreset_fn_t      postreset;
+       ata_prereset_fn_t       pmp_prereset;
+       ata_reset_fn_t          pmp_softreset;
+       ata_reset_fn_t          pmp_hardreset;
+       ata_postreset_fn_t      pmp_postreset;
        void (*error_handler)(struct ata_port *ap);
        void (*post_internal_cmd)(struct ata_queued_cmd *qc);
 
 extern void ata_noop_irq_clear(struct ata_port *ap);
 extern void ata_bmdma_freeze(struct ata_port *ap);
 extern void ata_bmdma_thaw(struct ata_port *ap);
-extern void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
-                              ata_reset_fn_t softreset,
-                              ata_reset_fn_t hardreset,
-                              ata_postreset_fn_t postreset);
 extern void ata_bmdma_error_handler(struct ata_port *ap);
 extern void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc);
 extern int ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
 extern int sata_pmp_std_hardreset(struct ata_link *link, unsigned int *class,
                                  unsigned long deadline);
 extern void sata_pmp_std_postreset(struct ata_link *link, unsigned int *class);
-extern void sata_pmp_do_eh(struct ata_port *ap,
-               ata_prereset_fn_t prereset, ata_reset_fn_t softreset,
-               ata_reset_fn_t hardreset, ata_postreset_fn_t postreset,
-               ata_prereset_fn_t pmp_prereset, ata_reset_fn_t pmp_softreset,
-               ata_reset_fn_t pmp_hardreset, ata_postreset_fn_t pmp_postreset);
+extern void sata_pmp_error_handler(struct ata_port *ap);
 
 /*
  * EH
 extern void ata_do_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
                      ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
                      ata_postreset_fn_t postreset);
+extern void ata_std_error_handler(struct ata_port *ap);
 
 /*
  * Base operations to inherit from and initializers for sht