diff options
Diffstat (limited to 'drivers/ata/sata_promise.c')
-rw-r--r-- | drivers/ata/sata_promise.c | 412 |
1 files changed, 227 insertions, 185 deletions
diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c index 2339813ce9f..2b924a69b36 100644 --- a/drivers/ata/sata_promise.c +++ b/drivers/ata/sata_promise.c @@ -45,10 +45,11 @@ #include "sata_promise.h" #define DRV_NAME "sata_promise" -#define DRV_VERSION "2.00" +#define DRV_VERSION "2.07" enum { + PDC_MAX_PORTS = 4, PDC_MMIO_BAR = 3, /* register offsets */ @@ -70,14 +71,31 @@ enum { PDC_TBG_MODE = 0x41C, /* TBG mode (not SATAII) */ PDC_SLEW_CTL = 0x470, /* slew rate control reg (not SATAII) */ - PDC_ERR_MASK = (1<<19) | (1<<20) | (1<<21) | (1<<22) | - (1<<8) | (1<<9) | (1<<10), + /* PDC_GLOBAL_CTL bit definitions */ + PDC_PH_ERR = (1 << 8), /* PCI error while loading packet */ + PDC_SH_ERR = (1 << 9), /* PCI error while loading S/G table */ + PDC_DH_ERR = (1 << 10), /* PCI error while loading data */ + PDC2_HTO_ERR = (1 << 12), /* host bus timeout */ + PDC2_ATA_HBA_ERR = (1 << 13), /* error during SATA DATA FIS transmission */ + PDC2_ATA_DMA_CNT_ERR = (1 << 14), /* DMA DATA FIS size differs from S/G count */ + PDC_OVERRUN_ERR = (1 << 19), /* S/G byte count larger than HD requires */ + PDC_UNDERRUN_ERR = (1 << 20), /* S/G byte count less than HD requires */ + PDC_DRIVE_ERR = (1 << 21), /* drive error */ + PDC_PCI_SYS_ERR = (1 << 22), /* PCI system error */ + PDC1_PCI_PARITY_ERR = (1 << 23), /* PCI parity error (from SATA150 driver) */ + PDC1_ERR_MASK = PDC1_PCI_PARITY_ERR, + PDC2_ERR_MASK = PDC2_HTO_ERR | PDC2_ATA_HBA_ERR | PDC2_ATA_DMA_CNT_ERR, + PDC_ERR_MASK = (PDC_PH_ERR | PDC_SH_ERR | PDC_DH_ERR | PDC_OVERRUN_ERR + | PDC_UNDERRUN_ERR | PDC_DRIVE_ERR | PDC_PCI_SYS_ERR + | PDC1_ERR_MASK | PDC2_ERR_MASK), board_2037x = 0, /* FastTrak S150 TX2plus */ - board_20319 = 1, /* FastTrak S150 TX4 */ - board_20619 = 2, /* FastTrak TX4000 */ - board_2057x = 3, /* SATAII150 Tx2plus */ - board_40518 = 4, /* SATAII150 Tx4 */ + board_2037x_pata = 1, /* FastTrak S150 TX2plus PATA port */ + board_20319 = 2, /* FastTrak S150 TX4 */ + board_20619 = 3, /* FastTrak TX4000 */ + board_2057x = 4, /* SATAII150 Tx2plus */ + board_2057x_pata = 5, /* SATAII150 Tx2plus */ + board_40518 = 6, /* SATAII150 Tx4 */ PDC_HAS_PATA = (1 << 1), /* PDC20375/20575 has PATA */ @@ -100,8 +118,10 @@ enum { ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING, - /* hp->flags bits */ - PDC_FLAG_GEN_II = (1 << 0), + /* ap->flags bits */ + PDC_FLAG_GEN_II = (1 << 24), + PDC_FLAG_SATA_PATA = (1 << 25), /* supports SATA + PATA */ + PDC_FLAG_4_PORTS = (1 << 26), /* 4 ports */ }; @@ -110,28 +130,25 @@ struct pdc_port_priv { dma_addr_t pkt_dma; }; -struct pdc_host_priv { - unsigned long flags; - unsigned long port_flags[ATA_MAX_PORTS]; -}; - 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, u32 val); static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); -static irqreturn_t pdc_interrupt (int irq, void *dev_instance); -static int pdc_port_start(struct ata_port *ap); +static int pdc_common_port_start(struct ata_port *ap); +static int pdc_sata_port_start(struct ata_port *ap); 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_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_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 unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc); static void pdc_freeze(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 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 = { .module = THIS_MODULE, @@ -164,17 +181,17 @@ static const struct ata_port_operations pdc_sata_ops = { .qc_issue = pdc_qc_issue_prot, .freeze = pdc_freeze, .thaw = pdc_thaw, - .error_handler = pdc_error_handler, + .error_handler = pdc_sata_error_handler, .post_internal_cmd = pdc_post_internal_cmd, + .cable_detect = pdc_sata_cable_detect, .data_xfer = ata_data_xfer, - .irq_handler = pdc_interrupt, .irq_clear = pdc_irq_clear, .irq_on = ata_irq_on, .irq_ack = ata_irq_ack, .scr_read = pdc_sata_scr_read, .scr_write = pdc_sata_scr_write, - .port_start = pdc_port_start, + .port_start = pdc_sata_port_start, }; /* First-generation chips need a more restrictive ->check_atapi_dma op */ @@ -185,23 +202,23 @@ static const struct ata_port_operations pdc_old_sata_ops = { .check_status = ata_check_status, .exec_command = pdc_exec_command_mmio, .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_issue = pdc_qc_issue_prot, .freeze = pdc_freeze, .thaw = pdc_thaw, - .error_handler = pdc_error_handler, + .error_handler = pdc_sata_error_handler, .post_internal_cmd = pdc_post_internal_cmd, + .cable_detect = pdc_sata_cable_detect, .data_xfer = ata_data_xfer, - .irq_handler = pdc_interrupt, .irq_clear = pdc_irq_clear, .irq_on = ata_irq_on, .irq_ack = ata_irq_ack, .scr_read = pdc_sata_scr_read, .scr_write = pdc_sata_scr_write, - .port_start = pdc_port_start, + .port_start = pdc_sata_port_start, }; static const struct ata_port_operations pdc_pata_ops = { @@ -217,32 +234,41 @@ static const struct ata_port_operations pdc_pata_ops = { .qc_issue = pdc_qc_issue_prot, .freeze = pdc_freeze, .thaw = pdc_thaw, - .error_handler = pdc_error_handler, + .error_handler = pdc_pata_error_handler, .post_internal_cmd = pdc_post_internal_cmd, + .cable_detect = pdc_pata_cable_detect, .data_xfer = ata_data_xfer, - .irq_handler = pdc_interrupt, .irq_clear = pdc_irq_clear, .irq_on = ata_irq_on, .irq_ack = ata_irq_ack, - .port_start = pdc_port_start, + .port_start = pdc_common_port_start, }; static const struct ata_port_info pdc_port_info[] = { /* board_2037x */ { - .sht = &pdc_ata_sht, - .flags = PDC_COMMON_FLAGS, + .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA | + PDC_FLAG_SATA_PATA, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &pdc_old_sata_ops, }, + /* board_2037x_pata */ + { + .flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS, + .pio_mask = 0x1f, /* pio0-4 */ + .mwdma_mask = 0x07, /* mwdma0-2 */ + .udma_mask = 0x7f, /* udma0-6 ; FIXME */ + .port_ops = &pdc_pata_ops, + }, + /* board_20319 */ { - .sht = &pdc_ata_sht, - .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA, + .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA | + PDC_FLAG_4_PORTS, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ @@ -251,8 +277,8 @@ static const struct ata_port_info pdc_port_info[] = { /* board_20619 */ { - .sht = &pdc_ata_sht, - .flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS, + .flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS | + PDC_FLAG_4_PORTS, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ @@ -261,18 +287,28 @@ static const struct ata_port_info pdc_port_info[] = { /* board_2057x */ { - .sht = &pdc_ata_sht, - .flags = PDC_COMMON_FLAGS, + .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA | + PDC_FLAG_GEN_II | PDC_FLAG_SATA_PATA, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &pdc_sata_ops, }, + /* board_2057x_pata */ + { + .flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS | + PDC_FLAG_GEN_II, + .pio_mask = 0x1f, /* pio0-4 */ + .mwdma_mask = 0x07, /* mwdma0-2 */ + .udma_mask = 0x7f, /* udma0-6 ; FIXME */ + .port_ops = &pdc_pata_ops, + }, + /* board_40518 */ { - .sht = &pdc_ata_sht, - .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA, + .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA | + PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ @@ -313,18 +349,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 pdc_host_priv *hp = ap->host->private_data; struct pdc_port_priv *pp; 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); if (rc) return rc; @@ -339,8 +369,19 @@ static int pdc_port_start(struct ata_port *ap) ap->private_data = pp; + return 0; +} + +static int pdc_sata_port_start(struct ata_port *ap) +{ + int rc; + + rc = pdc_common_port_start(ap); + if (rc) + return rc; + /* fix up PHYMODE4 align timing */ - if ((hp->flags & PDC_FLAG_GEN_II) && sata_scr_valid(ap)) { + if (ap->flags & PDC_FLAG_GEN_II) { void __iomem *mmio = (void __iomem *) ap->ioaddr.scr_addr; unsigned int tmp; @@ -374,23 +415,25 @@ static void pdc_reset_port(struct ata_port *ap) readl(mmio); /* flush */ } -static void pdc_pata_cbl_detect(struct ata_port *ap) +static int pdc_pata_cable_detect(struct ata_port *ap) { u8 tmp; void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr + PDC_CTLSTAT + 0x03; tmp = readb(mmio); + if (tmp & 0x01) + return ATA_CBL_PATA40; + return ATA_CBL_PATA80; +} - if (tmp & 0x01) { - ap->cbl = ATA_CBL_PATA40; - ap->udma_mask &= ATA_UDMA_MASK_40C; - } else - ap->cbl = ATA_CBL_PATA80; +static int pdc_sata_cable_detect(struct ata_port *ap) +{ + return ATA_CBL_SATA; } 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 readl(ap->ioaddr.scr_addr + (sc_reg * 4)); } @@ -399,7 +442,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, u32 val) { - if (sc_reg > SCR_CONTROL || ap->cbl != ATA_CBL_SATA) + if (sc_reg > SCR_CONTROL) return; writel(val, ap->ioaddr.scr_addr + (sc_reg * 4)); } @@ -555,52 +598,81 @@ static void pdc_thaw(struct ata_port *ap) readl(mmio + PDC_CTLSTAT); /* flush */ } -static int pdc_pre_reset(struct ata_port *ap) -{ - if (!sata_scr_valid(ap)) - pdc_pata_cbl_detect(ap); - return ata_std_prereset(ap); -} - -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)) pdc_reset_port(ap); - hardreset = NULL; - if (sata_scr_valid(ap)) - hardreset = sata_std_hardreset; - /* perform recovery */ - ata_do_eh(ap, pdc_pre_reset, ata_std_softreset, hardreset, + 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); +} + static void pdc_post_internal_cmd(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; - if (qc->flags & ATA_QCFLAG_FAILED) - qc->err_mask |= AC_ERR_OTHER; - /* make DMA engine forget about the failed command */ - if (qc->err_mask) + if (qc->flags & ATA_QCFLAG_FAILED) pdc_reset_port(ap); } +static void pdc_error_intr(struct ata_port *ap, struct ata_queued_cmd *qc, + u32 port_status, u32 err_mask) +{ + struct ata_eh_info *ehi = &ap->eh_info; + unsigned int ac_err_mask = 0; + + ata_ehi_clear_desc(ehi); + ata_ehi_push_desc(ehi, "port_status 0x%08x", port_status); + port_status &= err_mask; + + if (port_status & PDC_DRIVE_ERR) + ac_err_mask |= AC_ERR_DEV; + if (port_status & (PDC_OVERRUN_ERR | PDC_UNDERRUN_ERR)) + ac_err_mask |= AC_ERR_HSM; + if (port_status & (PDC2_ATA_HBA_ERR | PDC2_ATA_DMA_CNT_ERR)) + ac_err_mask |= AC_ERR_ATA_BUS; + if (port_status & (PDC_PH_ERR | PDC_SH_ERR | PDC_DH_ERR | PDC2_HTO_ERR + | PDC_PCI_SYS_ERR | PDC1_PCI_PARITY_ERR)) + ac_err_mask |= AC_ERR_HOST_BUS; + + if (sata_scr_valid(ap)) + ehi->serror |= pdc_sata_scr_read(ap, SCR_ERROR); + + qc->err_mask |= ac_err_mask; + + pdc_reset_port(ap); + + ata_port_abort(ap); +} + static inline unsigned int pdc_host_intr( struct ata_port *ap, struct ata_queued_cmd *qc) { unsigned int handled = 0; - u32 tmp; - void __iomem *mmio = ap->ioaddr.cmd_addr + PDC_GLOBAL_CTL; + void __iomem *port_mmio = ap->ioaddr.cmd_addr; + u32 port_status, err_mask; - tmp = readl(mmio); - if (tmp & PDC_ERR_MASK) { - qc->err_mask |= AC_ERR_DEV; - pdc_reset_port(ap); + err_mask = PDC_ERR_MASK; + if (ap->flags & PDC_FLAG_GEN_II) + err_mask &= ~PDC1_ERR_MASK; + else + err_mask &= ~PDC2_ERR_MASK; + port_status = readl(port_mmio + PDC_GLOBAL_CTL); + if (unlikely(port_status & err_mask)) { + pdc_error_intr(ap, qc, port_status, err_mask); + return 1; } switch (qc->tf.protocol) { @@ -767,44 +839,40 @@ static int pdc_check_atapi_dma(struct ata_queued_cmd *qc) 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 */ - if (sata_scr_valid(ap)) - return 1; - return pdc_check_atapi_dma(qc); + return 1; } -static void pdc_ata_setup_port(struct ata_ioports *port, void __iomem *base, - void __iomem *scr_addr) +static void pdc_ata_setup_port(struct ata_port *ap, + void __iomem *base, void __iomem *scr_addr) { - port->cmd_addr = base; - port->data_addr = base; - port->feature_addr = - port->error_addr = base + 0x4; - port->nsect_addr = base + 0x8; - port->lbal_addr = base + 0xc; - port->lbam_addr = base + 0x10; - port->lbah_addr = base + 0x14; - port->device_addr = base + 0x18; - port->command_addr = - port->status_addr = base + 0x1c; - port->altstatus_addr = - port->ctl_addr = base + 0x38; - port->scr_addr = scr_addr; + ap->ioaddr.cmd_addr = base; + ap->ioaddr.data_addr = base; + ap->ioaddr.feature_addr = + ap->ioaddr.error_addr = base + 0x4; + ap->ioaddr.nsect_addr = base + 0x8; + ap->ioaddr.lbal_addr = base + 0xc; + ap->ioaddr.lbam_addr = base + 0x10; + ap->ioaddr.lbah_addr = base + 0x14; + ap->ioaddr.device_addr = base + 0x18; + ap->ioaddr.command_addr = + ap->ioaddr.status_addr = base + 0x1c; + ap->ioaddr.altstatus_addr = + ap->ioaddr.ctl_addr = base + 0x38; + ap->ioaddr.scr_addr = scr_addr; } -static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe) +static void pdc_host_init(struct ata_host *host) { - void __iomem *mmio = pe->iomap[PDC_MMIO_BAR]; - struct pdc_host_priv *hp = pe->private_data; + void __iomem *mmio = host->iomap[PDC_MMIO_BAR]; + int is_gen2 = host->ports[0]->flags & PDC_FLAG_GEN_II; int hotplug_offset; u32 tmp; - if (hp->flags & PDC_FLAG_GEN_II) + if (is_gen2) hotplug_offset = PDC2_SATA_PLUG_CSR; else hotplug_offset = PDC_SATA_PLUG_CSR; @@ -818,7 +886,7 @@ static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe) /* enable BMR_BURST, maybe change FIFO_SHD to 8 dwords */ tmp = readl(mmio + PDC_FLASH_CTL); tmp |= 0x02000; /* bit 13 (enable bmr burst) */ - if (!(hp->flags & PDC_FLAG_GEN_II)) + if (!is_gen2) tmp |= 0x10000; /* bit 16 (fifo threshold at 8 dw) */ writel(tmp, mmio + PDC_FLASH_CTL); @@ -831,7 +899,7 @@ static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe) writel(tmp | 0xff0000, mmio + hotplug_offset); /* don't initialise TBG or SLEW on 2nd generation chips */ - if (hp->flags & PDC_FLAG_GEN_II) + if (is_gen2) return; /* reduce TBG clock to 133 Mhz. */ @@ -853,16 +921,17 @@ static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe) static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version; - struct ata_probe_ent *probe_ent; - struct pdc_host_priv *hp; + const struct ata_port_info *pi = &pdc_port_info[ent->driver_data]; + const struct ata_port_info *ppi[PDC_MAX_PORTS]; + struct ata_host *host; void __iomem *base; - unsigned int board_idx = (unsigned int) ent->driver_data; - int rc; - u8 tmp; + int n_ports, i, rc; + int is_sataii_tx4; if (!printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); + /* enable and acquire resources */ rc = pcim_enable_device(pdev); if (rc) return rc; @@ -872,89 +941,62 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e pcim_pin_device(pdev); if (rc) return rc; + base = pcim_iomap_table(pdev)[PDC_MMIO_BAR]; - rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); - if (rc) - return rc; - rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); - if (rc) - return rc; - - probe_ent = devm_kzalloc(&pdev->dev, sizeof(*probe_ent), GFP_KERNEL); - if (probe_ent == NULL) - return -ENOMEM; + /* determine port configuration and setup host */ + n_ports = 2; + if (pi->flags & PDC_FLAG_4_PORTS) + n_ports = 4; + for (i = 0; i < n_ports; i++) + ppi[i] = pi; - probe_ent->dev = pci_dev_to_dev(pdev); - INIT_LIST_HEAD(&probe_ent->node); + if (pi->flags & PDC_FLAG_SATA_PATA) { + u8 tmp = readb(base + PDC_FLASH_CTL+1); + if (!(tmp & 0x80)) { + ppi[n_ports++] = pi + 1; + dev_printk(KERN_INFO, &pdev->dev, "PATA port found\n"); + } + } - hp = devm_kzalloc(&pdev->dev, sizeof(*hp), GFP_KERNEL); - if (hp == NULL) + host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); + if (!host) { + dev_printk(KERN_ERR, &pdev->dev, "failed to allocate host\n"); return -ENOMEM; + } + host->iomap = pcim_iomap_table(pdev); - probe_ent->private_data = hp; - - probe_ent->sht = pdc_port_info[board_idx].sht; - probe_ent->port_flags = pdc_port_info[board_idx].flags; - probe_ent->pio_mask = pdc_port_info[board_idx].pio_mask; - probe_ent->mwdma_mask = pdc_port_info[board_idx].mwdma_mask; - probe_ent->udma_mask = pdc_port_info[board_idx].udma_mask; - probe_ent->port_ops = pdc_port_info[board_idx].port_ops; - - probe_ent->irq = pdev->irq; - probe_ent->irq_flags = IRQF_SHARED; - probe_ent->iomap = pcim_iomap_table(pdev); - - base = probe_ent->iomap[PDC_MMIO_BAR]; - - pdc_ata_setup_port(&probe_ent->port[0], base + 0x200, base + 0x400); - pdc_ata_setup_port(&probe_ent->port[1], base + 0x280, base + 0x500); - - /* notice 4-port boards */ - switch (board_idx) { - case board_40518: - hp->flags |= PDC_FLAG_GEN_II; - /* Fall through */ - case board_20319: - probe_ent->n_ports = 4; - pdc_ata_setup_port(&probe_ent->port[2], base + 0x300, base + 0x600); - pdc_ata_setup_port(&probe_ent->port[3], base + 0x380, base + 0x700); - break; - case board_2057x: - hp->flags |= PDC_FLAG_GEN_II; - /* Fall through */ - case board_2037x: - /* TX2plus boards also have a PATA port */ - tmp = readb(base + PDC_FLASH_CTL+1); - if (!(tmp & 0x80)) { - probe_ent->n_ports = 3; - pdc_ata_setup_port(&probe_ent->port[2], base + 0x300, NULL); - hp->port_flags[2] = ATA_FLAG_SLAVE_POSS; - printk(KERN_INFO DRV_NAME " PATA port found\n"); - } else - probe_ent->n_ports = 2; - hp->port_flags[0] = ATA_FLAG_SATA; - hp->port_flags[1] = ATA_FLAG_SATA; - break; - case board_20619: - probe_ent->n_ports = 4; - pdc_ata_setup_port(&probe_ent->port[2], base + 0x300, NULL); - pdc_ata_setup_port(&probe_ent->port[3], base + 0x380, NULL); - break; - default: - BUG(); - break; + is_sataii_tx4 = 0; + if ((pi->flags & (PDC_FLAG_GEN_II|PDC_FLAG_4_PORTS)) == (PDC_FLAG_GEN_II|PDC_FLAG_4_PORTS)) { + is_sataii_tx4 = 1; + dev_printk(KERN_INFO, &pdev->dev, "applying SATAII TX4 port numbering workaround\n"); } + for (i = 0; i < host->n_ports; i++) { + static const unsigned char sataii_tx4_port_remap[4] = { 3, 1, 0, 2}; + int ata_nr; - pci_set_master(pdev); + ata_nr = i; + if (is_sataii_tx4) + ata_nr = sataii_tx4_port_remap[i]; + + pdc_ata_setup_port(host->ports[i], + base + 0x200 + ata_nr * 0x80, + base + 0x400 + ata_nr * 0x100); + } /* initialize adapter */ - pdc_host_init(board_idx, probe_ent); + pdc_host_init(host); - if (!ata_device_add(probe_ent)) - return -ENODEV; + rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); + if (rc) + return rc; + rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); + if (rc) + return rc; - devm_kfree(&pdev->dev, probe_ent); - return 0; + /* start host, request IRQ and attach */ + pci_set_master(pdev); + return ata_host_activate(host, pdev->irq, pdc_interrupt, IRQF_SHARED, + &pdc_ata_sht); } |