sata_promise: separate SATA and PATA ops
This patch changes sata_promise so that the PATA ports on TX2plus chips are bound to the pdc_pata_ops structure. This means that operations called from the SATA ops structures don't need any SATA-vs-PATA tests any more. Instead, operations that depend on a port being SATA or PATA are separated into different procedures. * pdc_cable_type() is split into a PATA version and a SATA version * pdc_error_handler() is split into a PATA version and a SATA version, that both call a common version after setting up the `hardreset' function pointer * pdc_old_check_atapi_dma() is now only used for SATAI ports, so is renamed to pdc_old_sata_check_atapi_dma() and simplified * pdc_sata_scr_{read,write}() are now only used for SATA ports, so their is-not-SATA tests are removed * pdc_port_start() is split into three procedures: a wrapper which performs the ->ops adjustment on TX2plus PATA ports, a procedure with the common code, and a procedure with the SATA-specific code (this bit might be cleaned up by Tejun's new init model) Tested on 20619, 20575, and 20775 chips. Signed-off-by: Mikael Pettersson <mikpe@it.uu.se> Signed-off-by: Jeff Garzik <jeff@garzik.org>
This commit is contained in:
committed by
Jeff Garzik
parent
799331fda0
commit
724114a573
@@ -45,7 +45,7 @@
|
|||||||
#include "sata_promise.h"
|
#include "sata_promise.h"
|
||||||
|
|
||||||
#define DRV_NAME "sata_promise"
|
#define DRV_NAME "sata_promise"
|
||||||
#define DRV_VERSION "2.02"
|
#define DRV_VERSION "2.03"
|
||||||
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -124,14 +124,16 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc);
|
|||||||
static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
|
static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
|
||||||
static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
|
static void pdc_exec_command_mmio(struct ata_port *ap, const struct ata_taskfile *tf);
|
||||||
static int pdc_check_atapi_dma(struct ata_queued_cmd *qc);
|
static int pdc_check_atapi_dma(struct ata_queued_cmd *qc);
|
||||||
static int pdc_old_check_atapi_dma(struct ata_queued_cmd *qc);
|
static int pdc_old_sata_check_atapi_dma(struct ata_queued_cmd *qc);
|
||||||
static void pdc_irq_clear(struct ata_port *ap);
|
static void pdc_irq_clear(struct ata_port *ap);
|
||||||
static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc);
|
static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc);
|
||||||
static void pdc_freeze(struct ata_port *ap);
|
static void pdc_freeze(struct ata_port *ap);
|
||||||
static void pdc_thaw(struct ata_port *ap);
|
static void pdc_thaw(struct ata_port *ap);
|
||||||
static void pdc_error_handler(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_post_internal_cmd(struct ata_queued_cmd *qc);
|
static void pdc_post_internal_cmd(struct ata_queued_cmd *qc);
|
||||||
static int pdc_cable_detect(struct ata_port *ap);
|
static int pdc_pata_cable_detect(struct ata_port *ap);
|
||||||
|
static int pdc_sata_cable_detect(struct ata_port *ap);
|
||||||
|
|
||||||
static struct scsi_host_template pdc_ata_sht = {
|
static struct scsi_host_template pdc_ata_sht = {
|
||||||
.module = THIS_MODULE,
|
.module = THIS_MODULE,
|
||||||
@@ -164,9 +166,9 @@ static const struct ata_port_operations pdc_sata_ops = {
|
|||||||
.qc_issue = pdc_qc_issue_prot,
|
.qc_issue = pdc_qc_issue_prot,
|
||||||
.freeze = pdc_freeze,
|
.freeze = pdc_freeze,
|
||||||
.thaw = pdc_thaw,
|
.thaw = pdc_thaw,
|
||||||
.error_handler = pdc_error_handler,
|
.error_handler = pdc_sata_error_handler,
|
||||||
.post_internal_cmd = pdc_post_internal_cmd,
|
.post_internal_cmd = pdc_post_internal_cmd,
|
||||||
.cable_detect = pdc_cable_detect,
|
.cable_detect = pdc_sata_cable_detect,
|
||||||
.data_xfer = ata_data_xfer,
|
.data_xfer = ata_data_xfer,
|
||||||
.irq_handler = pdc_interrupt,
|
.irq_handler = pdc_interrupt,
|
||||||
.irq_clear = pdc_irq_clear,
|
.irq_clear = pdc_irq_clear,
|
||||||
@@ -186,15 +188,15 @@ static const struct ata_port_operations pdc_old_sata_ops = {
|
|||||||
.check_status = ata_check_status,
|
.check_status = ata_check_status,
|
||||||
.exec_command = pdc_exec_command_mmio,
|
.exec_command = pdc_exec_command_mmio,
|
||||||
.dev_select = ata_std_dev_select,
|
.dev_select = ata_std_dev_select,
|
||||||
.check_atapi_dma = pdc_old_check_atapi_dma,
|
.check_atapi_dma = pdc_old_sata_check_atapi_dma,
|
||||||
|
|
||||||
.qc_prep = pdc_qc_prep,
|
.qc_prep = pdc_qc_prep,
|
||||||
.qc_issue = pdc_qc_issue_prot,
|
.qc_issue = pdc_qc_issue_prot,
|
||||||
.freeze = pdc_freeze,
|
.freeze = pdc_freeze,
|
||||||
.thaw = pdc_thaw,
|
.thaw = pdc_thaw,
|
||||||
.error_handler = pdc_error_handler,
|
.error_handler = pdc_sata_error_handler,
|
||||||
.post_internal_cmd = pdc_post_internal_cmd,
|
.post_internal_cmd = pdc_post_internal_cmd,
|
||||||
.cable_detect = pdc_cable_detect,
|
.cable_detect = pdc_sata_cable_detect,
|
||||||
.data_xfer = ata_data_xfer,
|
.data_xfer = ata_data_xfer,
|
||||||
.irq_handler = pdc_interrupt,
|
.irq_handler = pdc_interrupt,
|
||||||
.irq_clear = pdc_irq_clear,
|
.irq_clear = pdc_irq_clear,
|
||||||
@@ -219,9 +221,9 @@ static const struct ata_port_operations pdc_pata_ops = {
|
|||||||
.qc_issue = pdc_qc_issue_prot,
|
.qc_issue = pdc_qc_issue_prot,
|
||||||
.freeze = pdc_freeze,
|
.freeze = pdc_freeze,
|
||||||
.thaw = pdc_thaw,
|
.thaw = pdc_thaw,
|
||||||
.error_handler = pdc_error_handler,
|
.error_handler = pdc_pata_error_handler,
|
||||||
.post_internal_cmd = pdc_post_internal_cmd,
|
.post_internal_cmd = pdc_post_internal_cmd,
|
||||||
.cable_detect = pdc_cable_detect,
|
.cable_detect = pdc_pata_cable_detect,
|
||||||
.data_xfer = ata_data_xfer,
|
.data_xfer = ata_data_xfer,
|
||||||
.irq_handler = pdc_interrupt,
|
.irq_handler = pdc_interrupt,
|
||||||
.irq_clear = pdc_irq_clear,
|
.irq_clear = pdc_irq_clear,
|
||||||
@@ -316,18 +318,12 @@ static struct pci_driver pdc_ata_pci_driver = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static int pdc_port_start(struct ata_port *ap)
|
static int pdc_common_port_start(struct ata_port *ap)
|
||||||
{
|
{
|
||||||
struct device *dev = ap->host->dev;
|
struct device *dev = ap->host->dev;
|
||||||
struct pdc_host_priv *hp = ap->host->private_data;
|
|
||||||
struct pdc_port_priv *pp;
|
struct pdc_port_priv *pp;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* fix up port flags and cable type for SATA+PATA chips */
|
|
||||||
ap->flags |= hp->port_flags[ap->port_no];
|
|
||||||
if (ap->flags & ATA_FLAG_SATA)
|
|
||||||
ap->cbl = ATA_CBL_SATA;
|
|
||||||
|
|
||||||
rc = ata_port_start(ap);
|
rc = ata_port_start(ap);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
@@ -342,8 +338,20 @@ static int pdc_port_start(struct ata_port *ap)
|
|||||||
|
|
||||||
ap->private_data = pp;
|
ap->private_data = pp;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pdc_sata_port_start(struct ata_port *ap)
|
||||||
|
{
|
||||||
|
struct pdc_host_priv *hp = ap->host->private_data;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = pdc_common_port_start(ap);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
/* fix up PHYMODE4 align timing */
|
/* fix up PHYMODE4 align timing */
|
||||||
if ((hp->flags & PDC_FLAG_GEN_II) && sata_scr_valid(ap)) {
|
if (hp->flags & PDC_FLAG_GEN_II) {
|
||||||
void __iomem *mmio = (void __iomem *) ap->ioaddr.scr_addr;
|
void __iomem *mmio = (void __iomem *) ap->ioaddr.scr_addr;
|
||||||
unsigned int tmp;
|
unsigned int tmp;
|
||||||
|
|
||||||
@@ -355,6 +363,21 @@ static int pdc_port_start(struct ata_port *ap)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int pdc_port_start(struct ata_port *ap)
|
||||||
|
{
|
||||||
|
struct pdc_host_priv *hp = ap->host->private_data;
|
||||||
|
|
||||||
|
/* fix up port flags and cable type for SATA+PATA chips */
|
||||||
|
ap->flags |= hp->port_flags[ap->port_no];
|
||||||
|
if (ap->flags & ATA_FLAG_SATA) {
|
||||||
|
ap->cbl = ATA_CBL_SATA;
|
||||||
|
return pdc_sata_port_start(ap);
|
||||||
|
} else {
|
||||||
|
ap->ops = &pdc_pata_ops;
|
||||||
|
return pdc_common_port_start(ap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void pdc_reset_port(struct ata_port *ap)
|
static void pdc_reset_port(struct ata_port *ap)
|
||||||
{
|
{
|
||||||
void __iomem *mmio = ap->ioaddr.cmd_addr + PDC_CTLSTAT;
|
void __iomem *mmio = ap->ioaddr.cmd_addr + PDC_CTLSTAT;
|
||||||
@@ -377,23 +400,25 @@ static void pdc_reset_port(struct ata_port *ap)
|
|||||||
readl(mmio); /* flush */
|
readl(mmio); /* flush */
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pdc_cable_detect(struct ata_port *ap)
|
static int pdc_pata_cable_detect(struct ata_port *ap)
|
||||||
{
|
{
|
||||||
u8 tmp;
|
u8 tmp;
|
||||||
void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr + PDC_CTLSTAT + 0x03;
|
void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr + PDC_CTLSTAT + 0x03;
|
||||||
|
|
||||||
if (!sata_scr_valid(ap)) {
|
tmp = readb(mmio);
|
||||||
tmp = readb(mmio);
|
if (tmp & 0x01)
|
||||||
if (tmp & 0x01)
|
return ATA_CBL_PATA40;
|
||||||
return ATA_CBL_PATA40;
|
return ATA_CBL_PATA80;
|
||||||
return ATA_CBL_PATA80;
|
}
|
||||||
}
|
|
||||||
|
static int pdc_sata_cable_detect(struct ata_port *ap)
|
||||||
|
{
|
||||||
return ATA_CBL_SATA;
|
return ATA_CBL_SATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
|
static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
|
||||||
{
|
{
|
||||||
if (sc_reg > SCR_CONTROL || ap->cbl != ATA_CBL_SATA)
|
if (sc_reg > SCR_CONTROL)
|
||||||
return 0xffffffffU;
|
return 0xffffffffU;
|
||||||
return readl(ap->ioaddr.scr_addr + (sc_reg * 4));
|
return readl(ap->ioaddr.scr_addr + (sc_reg * 4));
|
||||||
}
|
}
|
||||||
@@ -402,7 +427,7 @@ static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg)
|
|||||||
static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg,
|
static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg,
|
||||||
u32 val)
|
u32 val)
|
||||||
{
|
{
|
||||||
if (sc_reg > SCR_CONTROL || ap->cbl != ATA_CBL_SATA)
|
if (sc_reg > SCR_CONTROL)
|
||||||
return;
|
return;
|
||||||
writel(val, ap->ioaddr.scr_addr + (sc_reg * 4));
|
writel(val, ap->ioaddr.scr_addr + (sc_reg * 4));
|
||||||
}
|
}
|
||||||
@@ -558,22 +583,26 @@ static void pdc_thaw(struct ata_port *ap)
|
|||||||
readl(mmio + PDC_CTLSTAT); /* flush */
|
readl(mmio + PDC_CTLSTAT); /* flush */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pdc_error_handler(struct ata_port *ap)
|
static void pdc_common_error_handler(struct ata_port *ap, ata_reset_fn_t hardreset)
|
||||||
{
|
{
|
||||||
ata_reset_fn_t hardreset;
|
|
||||||
|
|
||||||
if (!(ap->pflags & ATA_PFLAG_FROZEN))
|
if (!(ap->pflags & ATA_PFLAG_FROZEN))
|
||||||
pdc_reset_port(ap);
|
pdc_reset_port(ap);
|
||||||
|
|
||||||
hardreset = NULL;
|
|
||||||
if (sata_scr_valid(ap))
|
|
||||||
hardreset = sata_std_hardreset;
|
|
||||||
|
|
||||||
/* perform recovery */
|
/* perform recovery */
|
||||||
ata_do_eh(ap, ata_std_prereset, ata_std_softreset, hardreset,
|
ata_do_eh(ap, ata_std_prereset, ata_std_softreset, hardreset,
|
||||||
ata_std_postreset);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
static void pdc_post_internal_cmd(struct ata_queued_cmd *qc)
|
static void pdc_post_internal_cmd(struct ata_queued_cmd *qc)
|
||||||
{
|
{
|
||||||
struct ata_port *ap = qc->ap;
|
struct ata_port *ap = qc->ap;
|
||||||
@@ -763,14 +792,10 @@ static int pdc_check_atapi_dma(struct ata_queued_cmd *qc)
|
|||||||
return pio;
|
return pio;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pdc_old_check_atapi_dma(struct ata_queued_cmd *qc)
|
static int pdc_old_sata_check_atapi_dma(struct ata_queued_cmd *qc)
|
||||||
{
|
{
|
||||||
struct ata_port *ap = qc->ap;
|
|
||||||
|
|
||||||
/* First generation chips cannot use ATAPI DMA on SATA ports */
|
/* First generation chips cannot use ATAPI DMA on SATA ports */
|
||||||
if (sata_scr_valid(ap))
|
return 1;
|
||||||
return 1;
|
|
||||||
return pdc_check_atapi_dma(qc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pdc_ata_setup_port(struct ata_ioports *port, void __iomem *base,
|
static void pdc_ata_setup_port(struct ata_ioports *port, void __iomem *base,
|
||||||
|
Reference in New Issue
Block a user