Commit 7f5e5107 authored by Jeff Garzik's avatar Jeff Garzik

[libata] consolidate legacy/native mode init code into helpers

Eliminates duplicate code in sata_nv, sata_sis, and sata_via.
parent 09e1a022
......@@ -3252,6 +3252,95 @@ void ata_std_ports(struct ata_ioports *ioaddr)
ioaddr->command_addr = ioaddr->cmd_addr + ATA_REG_CMD;
}
static struct ata_probe_ent *
ata_probe_ent_alloc(int n, struct pci_dev *pdev, struct ata_port_info **port)
{
struct ata_probe_ent *probe_ent;
int i;
probe_ent = kmalloc(sizeof(*probe_ent) * n, GFP_KERNEL);
if (!probe_ent) {
printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
pci_name(pdev));
return NULL;
}
memset(probe_ent, 0, sizeof(*probe_ent) * n);
for (i = 0; i < n; i++) {
INIT_LIST_HEAD(&probe_ent[i].node);
probe_ent[i].pdev = pdev;
probe_ent[i].sht = port[i]->sht;
probe_ent[i].host_flags = port[i]->host_flags;
probe_ent[i].pio_mask = port[i]->pio_mask;
probe_ent[i].mwdma_mask = port[i]->mwdma_mask;
probe_ent[i].udma_mask = port[i]->udma_mask;
probe_ent[i].port_ops = port[i]->port_ops;
}
return probe_ent;
}
struct ata_probe_ent *
ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port)
{
struct ata_probe_ent *probe_ent = ata_probe_ent_alloc(1, pdev, port);
if (!probe_ent)
return NULL;
probe_ent->n_ports = 2;
probe_ent->irq = pdev->irq;
probe_ent->irq_flags = SA_SHIRQ;
probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
probe_ent->port[0].altstatus_addr =
probe_ent->port[0].ctl_addr =
pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4);
probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
probe_ent->port[1].altstatus_addr =
probe_ent->port[1].ctl_addr =
pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8;
ata_std_ports(&probe_ent->port[0]);
ata_std_ports(&probe_ent->port[1]);
return probe_ent;
}
struct ata_probe_ent *
ata_pci_init_legacy_mode(struct pci_dev *pdev, struct ata_port_info **port)
{
struct ata_probe_ent *probe_ent = ata_probe_ent_alloc(2, pdev, port);
if (!probe_ent)
return NULL;
probe_ent[0].n_ports = 1;
probe_ent[0].irq = 14;
probe_ent[1].n_ports = 1;
probe_ent[1].irq = 15;
probe_ent[0].port[0].cmd_addr = 0x1f0;
probe_ent[0].port[0].altstatus_addr =
probe_ent[0].port[0].ctl_addr = 0x3f6;
probe_ent[0].port[0].bmdma_addr = pci_resource_start(pdev, 4);
probe_ent[1].port[0].cmd_addr = 0x170;
probe_ent[1].port[0].altstatus_addr =
probe_ent[1].port[0].ctl_addr = 0x376;
probe_ent[1].port[0].bmdma_addr = pci_resource_start(pdev, 4)+8;
ata_std_ports(&probe_ent[0].port[0]);
ata_std_ports(&probe_ent[1].port[0]);
return probe_ent;
}
/**
* ata_pci_init_one - Initialize/register PCI IDE host controller
* @pdev: Controller to be initialized
......@@ -3269,20 +3358,20 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
unsigned int n_ports)
{
struct ata_probe_ent *probe_ent, *probe_ent2 = NULL;
struct ata_port_info *port0, *port1;
struct ata_port_info *port[2];
u8 tmp8, mask;
unsigned int legacy_mode = 0;
int rc;
DPRINTK("ENTER\n");
port0 = port_info[0];
port[0] = port_info[0];
if (n_ports > 1)
port1 = port_info[1];
port[1] = port_info[1];
else
port1 = port0;
port[1] = port[0];
if ((port0->host_flags & ATA_FLAG_NO_LEGACY) == 0) {
if ((port[0]->host_flags & ATA_FLAG_NO_LEGACY) == 0) {
/* TODO: support transitioning to native mode? */
pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8);
mask = (1 << 2) | (1 << 0);
......@@ -3343,77 +3432,17 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
if (rc)
goto err_out_regions;
probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
if (legacy_mode) {
probe_ent = ata_pci_init_legacy_mode(pdev, port);
if (probe_ent)
probe_ent2 = &probe_ent[1];
} else
probe_ent = ata_pci_init_native_mode(pdev, port);
if (!probe_ent) {
rc = -ENOMEM;
goto err_out_regions;
}
memset(probe_ent, 0, sizeof(*probe_ent));
probe_ent->pdev = pdev;
INIT_LIST_HEAD(&probe_ent->node);
if (legacy_mode) {
probe_ent2 = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
if (!probe_ent2) {
rc = -ENOMEM;
goto err_out_free_ent;
}
memset(probe_ent2, 0, sizeof(*probe_ent));
probe_ent2->pdev = pdev;
INIT_LIST_HEAD(&probe_ent2->node);
}
probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4);
probe_ent->sht = port0->sht;
probe_ent->host_flags = port0->host_flags;
probe_ent->pio_mask = port0->pio_mask;
probe_ent->mwdma_mask = port0->mwdma_mask;
probe_ent->udma_mask = port0->udma_mask;
probe_ent->port_ops = port0->port_ops;
if (legacy_mode) {
probe_ent->port[0].cmd_addr = 0x1f0;
probe_ent->port[0].altstatus_addr =
probe_ent->port[0].ctl_addr = 0x3f6;
probe_ent->n_ports = 1;
probe_ent->irq = 14;
ata_std_ports(&probe_ent->port[0]);
probe_ent2->port[0].cmd_addr = 0x170;
probe_ent2->port[0].altstatus_addr =
probe_ent2->port[0].ctl_addr = 0x376;
probe_ent2->port[0].bmdma_addr = pci_resource_start(pdev, 4)+8;
probe_ent2->n_ports = 1;
probe_ent2->irq = 15;
ata_std_ports(&probe_ent2->port[0]);
probe_ent2->sht = port1->sht;
probe_ent2->host_flags = port1->host_flags;
probe_ent2->pio_mask = port1->pio_mask;
probe_ent2->mwdma_mask = port1->mwdma_mask;
probe_ent2->udma_mask = port1->udma_mask;
probe_ent2->port_ops = port1->port_ops;
} else {
probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
ata_std_ports(&probe_ent->port[0]);
probe_ent->port[0].altstatus_addr =
probe_ent->port[0].ctl_addr =
pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
ata_std_ports(&probe_ent->port[1]);
probe_ent->port[1].altstatus_addr =
probe_ent->port[1].ctl_addr =
pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8;
probe_ent->n_ports = 2;
probe_ent->irq = pdev->irq;
probe_ent->irq_flags = SA_SHIRQ;
}
pci_set_master(pdev);
/* FIXME: check ata_device_add return */
......@@ -3422,17 +3451,13 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
ata_device_add(probe_ent);
if (legacy_mode & (1 << 1))
ata_device_add(probe_ent2);
kfree(probe_ent2);
} else {
ata_device_add(probe_ent);
assert(probe_ent2 == NULL);
}
kfree(probe_ent);
return 0;
err_out_free_ent:
kfree(probe_ent);
err_out_regions:
if (legacy_mode & (1 << 0))
release_region(0x1f0, 8);
......@@ -3586,6 +3611,8 @@ EXPORT_SYMBOL_GPL(ata_tf_load);
EXPORT_SYMBOL_GPL(ata_tf_read);
EXPORT_SYMBOL_GPL(ata_tf_to_fis);
EXPORT_SYMBOL_GPL(ata_tf_from_fis);
EXPORT_SYMBOL_GPL(ata_pci_init_legacy_mode);
EXPORT_SYMBOL_GPL(ata_pci_init_native_mode);
EXPORT_SYMBOL_GPL(ata_check_status);
EXPORT_SYMBOL_GPL(ata_exec_command);
EXPORT_SYMBOL_GPL(ata_port_start);
......
......@@ -219,6 +219,18 @@ static struct ata_port_operations nv_ops = {
.host_stop = nv_host_stop,
};
static struct ata_port_info nv_port_info = {
.sht = &nv_sht,
.host_flags = ATA_FLAG_SATA |
ATA_FLAG_SATA_RESET |
ATA_FLAG_SRST |
ATA_FLAG_NO_LEGACY,
.pio_mask = NV_PIO_MASK,
.mwdma_mask = NV_MWDMA_MASK,
.udma_mask = NV_UDMA_MASK,
.port_ops = &nv_ops,
};
MODULE_AUTHOR("NVIDIA");
MODULE_DESCRIPTION("low-level driver for NVIDIA nForce SATA controller");
MODULE_LICENSE("GPL");
......@@ -299,6 +311,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
{
static int printed_version = 0;
struct nv_host *host;
struct ata_port_info *ppi;
struct ata_probe_ent *probe_ent = NULL;
int rc;
......@@ -320,7 +333,8 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc)
goto err_out_regions;
probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
ppi = &nv_port_info;
probe_ent = ata_pci_init_native_mode(pdev, &ppi);
if (!probe_ent) {
rc = -ENOMEM;
goto err_out_regions;
......@@ -334,40 +348,6 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
host->host_desc = &nv_device_tbl[ent->driver_data];
memset(probe_ent, 0, sizeof(*probe_ent));
INIT_LIST_HEAD(&probe_ent->node);
probe_ent->pdev = pdev;
probe_ent->sht = &nv_sht;
probe_ent->host_flags = ATA_FLAG_SATA |
ATA_FLAG_SATA_RESET |
ATA_FLAG_SRST |
ATA_FLAG_NO_LEGACY;
probe_ent->port_ops = &nv_ops;
probe_ent->n_ports = NV_PORTS;
probe_ent->irq = pdev->irq;
probe_ent->irq_flags = SA_SHIRQ;
probe_ent->pio_mask = NV_PIO_MASK;
probe_ent->mwdma_mask = NV_MWDMA_MASK;
probe_ent->udma_mask = NV_UDMA_MASK;
probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
ata_std_ports(&probe_ent->port[0]);
probe_ent->port[0].altstatus_addr =
probe_ent->port[0].ctl_addr =
pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
probe_ent->port[0].bmdma_addr =
pci_resource_start(pdev, 4) | NV_PORT0_BMDMA_REG_OFFSET;
probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
ata_std_ports(&probe_ent->port[1]);
probe_ent->port[1].altstatus_addr =
probe_ent->port[1].ctl_addr =
pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
probe_ent->port[1].bmdma_addr =
pci_resource_start(pdev, 4) | NV_PORT1_BMDMA_REG_OFFSET;
probe_ent->private_data = host;
if (host->host_desc->host_flags & NV_HOST_FLAGS_SCR_MMIO) {
......
......@@ -112,6 +112,16 @@ static struct ata_port_operations sis_ops = {
.port_stop = ata_port_stop,
};
static struct ata_port_info sis_port_info = {
.sht = &sis_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET |
ATA_FLAG_NO_LEGACY,
.pio_mask = 0x1f,
.mwdma_mask = 0x7,
.udma_mask = 0x7f,
.port_ops = &sis_ops,
};
MODULE_AUTHOR("Uwe Koziolek");
MODULE_DESCRIPTION("low-level driver for Silicon Integratad Systems SATA controller");
......@@ -185,6 +195,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
struct ata_probe_ent *probe_ent = NULL;
int rc;
u32 genctl;
struct ata_port_info *ppi;
rc = pci_enable_device(pdev);
if (rc)
......@@ -201,20 +212,13 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc)
goto err_out_regions;
probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
ppi = &sis_port_info;
probe_ent = ata_pci_init_native_mode(pdev, &ppi);
if (!probe_ent) {
rc = -ENOMEM;
goto err_out_regions;
}
memset(probe_ent, 0, sizeof(*probe_ent));
probe_ent->pdev = pdev;
INIT_LIST_HEAD(&probe_ent->node);
probe_ent->sht = &sis_sht;
probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET |
ATA_FLAG_NO_LEGACY;
/* check and see if the SCRs are in IO space or PCI cfg space */
pci_read_config_dword(pdev, SIS_GENCTL, &genctl);
if ((genctl & GENCTL_IOMAPPED_SCR) == 0)
......@@ -231,32 +235,12 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
probe_ent->host_flags |= SIS_FLAG_CFGSCR;
}
probe_ent->pio_mask = 0x1f;
probe_ent->mwdma_mask = 0x7;
probe_ent->udma_mask = 0x7f;
probe_ent->port_ops = &sis_ops;
probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
ata_std_ports(&probe_ent->port[0]);
probe_ent->port[0].ctl_addr =
pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4);
if (!(probe_ent->host_flags & SIS_FLAG_CFGSCR))
if (!(probe_ent->host_flags & SIS_FLAG_CFGSCR)) {
probe_ent->port[0].scr_addr =
pci_resource_start(pdev, SIS_SCR_PCI_BAR);
probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
ata_std_ports(&probe_ent->port[1]);
probe_ent->port[1].ctl_addr =
pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8;
if (!(probe_ent->host_flags & SIS_FLAG_CFGSCR))
probe_ent->port[1].scr_addr =
pci_resource_start(pdev, SIS_SCR_PCI_BAR) + 64;
probe_ent->n_ports = 2;
probe_ent->irq = pdev->irq;
probe_ent->irq_flags = SA_SHIRQ;
}
pci_set_master(pdev);
pci_enable_intx(pdev);
......
......@@ -124,6 +124,15 @@ static struct ata_port_operations svia_sata_ops = {
.port_stop = ata_port_stop,
};
static struct ata_port_info svia_port_info = {
.sht = &svia_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST | ATA_FLAG_NO_LEGACY,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = 0x7f,
.port_ops = &svia_sata_ops,
};
MODULE_AUTHOR("Jeff Garzik");
MODULE_DESCRIPTION("SCSI low-level driver for VIA SATA controllers");
MODULE_LICENSE("GPL");
......@@ -157,6 +166,7 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
static int printed_version;
unsigned int i;
int rc;
struct ata_port_info *ppi;
struct ata_probe_ent *probe_ent;
u8 tmp8;
......@@ -197,42 +207,17 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc)
goto err_out_regions;
probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
ppi = &svia_port_info;
probe_ent = ata_pci_init_native_mode(pdev, &ppi);
if (!probe_ent) {
printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
pci_name(pdev));
rc = -ENOMEM;
goto err_out_regions;
}
memset(probe_ent, 0, sizeof(*probe_ent));
INIT_LIST_HEAD(&probe_ent->node);
probe_ent->pdev = pdev;
probe_ent->sht = &svia_sht;
probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST |
ATA_FLAG_NO_LEGACY;
probe_ent->port_ops = &svia_sata_ops;
probe_ent->n_ports = 2;
probe_ent->irq = pdev->irq;
probe_ent->irq_flags = SA_SHIRQ;
probe_ent->pio_mask = 0x1f;
probe_ent->mwdma_mask = 0x07;
probe_ent->udma_mask = 0x7f;
probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
ata_std_ports(&probe_ent->port[0]);
probe_ent->port[0].altstatus_addr =
probe_ent->port[0].ctl_addr =
pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4);
probe_ent->port[0].scr_addr =
svia_scr_addr(pci_resource_start(pdev, 5), 0);
probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
ata_std_ports(&probe_ent->port[1]);
probe_ent->port[1].altstatus_addr =
probe_ent->port[1].ctl_addr =
pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8;
probe_ent->port[1].scr_addr =
svia_scr_addr(pci_resource_start(pdev, 5), 1);
......
......@@ -388,6 +388,10 @@ extern void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf);
extern int ata_port_start (struct ata_port *ap);
extern void ata_port_stop (struct ata_port *ap);
extern irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
extern struct ata_probe_ent *
ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port);
extern struct ata_probe_ent *
ata_pci_init_legacy_mode(struct pci_dev *pdev, struct ata_port_info **port);
extern void ata_qc_prep(struct ata_queued_cmd *qc);
extern int ata_qc_issue_prot(struct ata_queued_cmd *qc);
extern void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment