#include "sata_promise.h"
#define DRV_NAME "sata_promise"
-#define DRV_VERSION "2.11"
+#define DRV_VERSION "2.12"
enum {
PDC_MAX_PORTS = 4,
static int pdc_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 unsigned int pdc_qc_issue(struct ata_queued_cmd *qc);
static void pdc_freeze(struct ata_port *ap);
+static void pdc_sata_freeze(struct ata_port *ap);
static void pdc_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_sata_thaw(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);
static struct scsi_host_template pdc_ata_sht = {
- .module = THIS_MODULE,
- .name = DRV_NAME,
- .ioctl = ata_scsi_ioctl,
- .queuecommand = ata_scsi_queuecmd,
- .can_queue = ATA_DEF_QUEUE,
- .this_id = ATA_SHT_THIS_ID,
+ ATA_BASE_SHT(DRV_NAME),
.sg_tablesize = PDC_MAX_PRD,
- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
- .emulated = ATA_SHT_EMULATED,
- .use_clustering = ATA_SHT_USE_CLUSTERING,
- .proc_name = DRV_NAME,
.dma_boundary = ATA_DMA_BOUNDARY,
- .slave_configure = ata_scsi_slave_config,
- .slave_destroy = ata_scsi_slave_destroy,
- .bios_param = ata_std_bios_param,
};
-static const struct ata_port_operations pdc_sata_ops = {
- .tf_load = pdc_tf_load_mmio,
- .tf_read = ata_tf_read,
- .check_status = ata_check_status,
- .exec_command = pdc_exec_command_mmio,
- .dev_select = ata_std_dev_select,
- .check_atapi_dma = pdc_check_atapi_dma,
+static const struct ata_port_operations pdc_common_ops = {
+ .inherits = &ata_sff_port_ops,
+ .sff_tf_load = pdc_tf_load_mmio,
+ .sff_exec_command = pdc_exec_command_mmio,
+ .check_atapi_dma = pdc_check_atapi_dma,
.qc_prep = pdc_qc_prep,
- .qc_issue = pdc_qc_issue_prot,
- .freeze = pdc_freeze,
- .thaw = pdc_thaw,
- .error_handler = pdc_sata_error_handler,
+ .qc_issue = pdc_qc_issue,
+ .sff_irq_clear = pdc_irq_clear,
+
.post_internal_cmd = pdc_post_internal_cmd,
- .cable_detect = pdc_sata_cable_detect,
- .data_xfer = ata_data_xfer,
- .irq_clear = pdc_irq_clear,
- .irq_on = ata_irq_on,
+ .error_handler = pdc_error_handler,
+};
+static struct ata_port_operations pdc_sata_ops = {
+ .inherits = &pdc_common_ops,
+ .cable_detect = pdc_sata_cable_detect,
+ .freeze = pdc_sata_freeze,
+ .thaw = pdc_sata_thaw,
.scr_read = pdc_sata_scr_read,
.scr_write = pdc_sata_scr_write,
.port_start = pdc_sata_port_start,
};
/* First-generation chips need a more restrictive ->check_atapi_dma op */
-static const struct ata_port_operations pdc_old_sata_ops = {
- .tf_load = pdc_tf_load_mmio,
- .tf_read = ata_tf_read,
- .check_status = ata_check_status,
- .exec_command = pdc_exec_command_mmio,
- .dev_select = ata_std_dev_select,
+static struct ata_port_operations pdc_old_sata_ops = {
+ .inherits = &pdc_sata_ops,
.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_sata_error_handler,
- .post_internal_cmd = pdc_post_internal_cmd,
- .cable_detect = pdc_sata_cable_detect,
- .data_xfer = ata_data_xfer,
- .irq_clear = pdc_irq_clear,
- .irq_on = ata_irq_on,
-
- .scr_read = pdc_sata_scr_read,
- .scr_write = pdc_sata_scr_write,
- .port_start = pdc_sata_port_start,
};
-static const struct ata_port_operations pdc_pata_ops = {
- .tf_load = pdc_tf_load_mmio,
- .tf_read = ata_tf_read,
- .check_status = ata_check_status,
- .exec_command = pdc_exec_command_mmio,
- .dev_select = ata_std_dev_select,
- .check_atapi_dma = pdc_check_atapi_dma,
-
- .qc_prep = pdc_qc_prep,
- .qc_issue = pdc_qc_issue_prot,
+static struct ata_port_operations pdc_pata_ops = {
+ .inherits = &pdc_common_ops,
+ .cable_detect = pdc_pata_cable_detect,
.freeze = pdc_freeze,
.thaw = pdc_thaw,
- .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_clear = pdc_irq_clear,
- .irq_on = ata_irq_on,
-
.port_start = pdc_common_port_start,
};
u8 *cdb = qc->cdb;
struct pdc_port_priv *pp = ap->private_data;
u8 *buf = pp->pkt;
- u32 *buf32 = (u32 *) buf;
- unsigned int dev_sel, feature, nbytes;
+ __le32 *buf32 = (__le32 *) buf;
+ unsigned int dev_sel, feature;
/* set control bits (byte 0), zero delay seq id (byte 3),
* and seq id (byte 2)
*/
switch (qc->tf.protocol) {
- case ATA_PROT_ATAPI_DMA:
+ case ATAPI_PROT_DMA:
if (!(qc->tf.flags & ATA_TFLAG_WRITE))
buf32[0] = cpu_to_le32(PDC_PKT_READ);
else
buf32[0] = 0;
break;
- case ATA_PROT_ATAPI_NODATA:
+ case ATAPI_PROT_NODATA:
buf32[0] = cpu_to_le32(PDC_PKT_NODATA);
break;
default:
buf32[2] = 0; /* no next-packet */
/* select drive */
- if (sata_scr_valid(&ap->link)) {
+ if (sata_scr_valid(&ap->link))
dev_sel = PDC_DEVICE_SATA;
- } else {
- dev_sel = ATA_DEVICE_OBS;
- if (qc->dev->devno != 0)
- dev_sel |= ATA_DEV1;
- }
+ else
+ dev_sel = qc->tf.device;
+
buf[12] = (1 << 5) | ATA_REG_DEVICE;
buf[13] = dev_sel;
buf[14] = (1 << 5) | ATA_REG_DEVICE | PDC_PKT_CLEAR_BSY;
buf[15] = dev_sel; /* once more, waiting for BSY to clear */
buf[16] = (1 << 5) | ATA_REG_NSECT;
- buf[17] = 0x00;
+ buf[17] = qc->tf.nsect;
buf[18] = (1 << 5) | ATA_REG_LBAL;
- buf[19] = 0x00;
+ buf[19] = qc->tf.lbal;
/* set feature and byte counter registers */
- if (qc->tf.protocol != ATA_PROT_ATAPI_DMA) {
+ if (qc->tf.protocol != ATAPI_PROT_DMA)
feature = PDC_FEATURE_ATAPI_PIO;
- /* set byte counter register to real transfer byte count */
- nbytes = qc->nbytes;
- if (nbytes > 0xffff)
- nbytes = 0xffff;
- } else {
+ else
feature = PDC_FEATURE_ATAPI_DMA;
- /* set byte counter register to 0 */
- nbytes = 0;
- }
+
buf[20] = (1 << 5) | ATA_REG_FEATURE;
buf[21] = feature;
buf[22] = (1 << 5) | ATA_REG_BYTEL;
- buf[23] = nbytes & 0xFF;
+ buf[23] = qc->tf.lbam;
buf[24] = (1 << 5) | ATA_REG_BYTEH;
- buf[25] = (nbytes >> 8) & 0xFF;
+ buf[25] = qc->tf.lbah;
/* send ATAPI packet command 0xA0 */
buf[26] = (1 << 5) | ATA_REG_CMD;
- buf[27] = ATA_CMD_PACKET;
+ buf[27] = qc->tf.command;
/* select drive and check DRQ */
buf[28] = (1 << 5) | ATA_REG_DEVICE | PDC_PKT_WAIT_DRDY;
{
struct ata_port *ap = qc->ap;
struct scatterlist *sg;
- unsigned int idx;
const u32 SG_COUNT_ASIC_BUG = 41*4;
+ unsigned int si, idx;
+ u32 len;
if (!(qc->flags & ATA_QCFLAG_DMAMAP))
return;
- WARN_ON(qc->__sg == NULL);
- WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
-
idx = 0;
- ata_for_each_sg(sg, qc) {
+ for_each_sg(qc->sg, sg, qc->n_elem, si) {
u32 addr, offset;
- u32 sg_len, len;
+ u32 sg_len;
/* determine if physical DMA addr spans 64K boundary.
* Note h/w doesn't support 64-bit, so we unconditionally
}
}
- if (idx) {
- u32 len = le32_to_cpu(ap->prd[idx - 1].flags_len);
-
- if (len > SG_COUNT_ASIC_BUG) {
- u32 addr;
+ len = le32_to_cpu(ap->prd[idx - 1].flags_len);
- VPRINTK("Splitting last PRD.\n");
+ if (len > SG_COUNT_ASIC_BUG) {
+ u32 addr;
- addr = le32_to_cpu(ap->prd[idx - 1].addr);
- ap->prd[idx - 1].flags_len = cpu_to_le32(len - SG_COUNT_ASIC_BUG);
- VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx - 1, addr, SG_COUNT_ASIC_BUG);
+ VPRINTK("Splitting last PRD.\n");
- addr = addr + len - SG_COUNT_ASIC_BUG;
- len = SG_COUNT_ASIC_BUG;
- ap->prd[idx].addr = cpu_to_le32(addr);
- ap->prd[idx].flags_len = cpu_to_le32(len);
- VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len);
+ addr = le32_to_cpu(ap->prd[idx - 1].addr);
+ ap->prd[idx - 1].flags_len = cpu_to_le32(len - SG_COUNT_ASIC_BUG);
+ VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx - 1, addr, SG_COUNT_ASIC_BUG);
- idx++;
- }
+ addr = addr + len - SG_COUNT_ASIC_BUG;
+ len = SG_COUNT_ASIC_BUG;
+ ap->prd[idx].addr = cpu_to_le32(addr);
+ ap->prd[idx].flags_len = cpu_to_le32(len);
+ VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len);
- ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
+ idx++;
}
+
+ ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
}
static void pdc_qc_prep(struct ata_queued_cmd *qc)
pdc_pkt_footer(&qc->tf, pp->pkt, i);
break;
- case ATA_PROT_ATAPI:
+ case ATAPI_PROT_PIO:
pdc_fill_sg(qc);
break;
- case ATA_PROT_ATAPI_DMA:
+ case ATAPI_PROT_DMA:
pdc_fill_sg(qc);
/*FALLTHROUGH*/
- case ATA_PROT_ATAPI_NODATA:
+ case ATAPI_PROT_NODATA:
pdc_atapi_pkt(qc);
break;
}
}
+static int pdc_is_sataii_tx4(unsigned long flags)
+{
+ const unsigned long mask = PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS;
+ return (flags & mask) == mask;
+}
+
+static unsigned int pdc_port_no_to_ata_no(unsigned int port_no,
+ int is_sataii_tx4)
+{
+ static const unsigned char sataii_tx4_port_remap[4] = { 3, 1, 0, 2};
+ return is_sataii_tx4 ? sataii_tx4_port_remap[port_no] : port_no;
+}
+
+static unsigned int pdc_sata_nr_ports(const struct ata_port *ap)
+{
+ return (ap->flags & PDC_FLAG_4_PORTS) ? 4 : 2;
+}
+
+static unsigned int pdc_sata_ata_port_to_ata_no(const struct ata_port *ap)
+{
+ const struct ata_host *host = ap->host;
+ unsigned int nr_ports = pdc_sata_nr_ports(ap);
+ unsigned int i;
+
+ for(i = 0; i < nr_ports && host->ports[i] != ap; ++i)
+ ;
+ BUG_ON(i >= nr_ports);
+ return pdc_port_no_to_ata_no(i, pdc_is_sataii_tx4(ap->flags));
+}
+
+static unsigned int pdc_sata_hotplug_offset(const struct ata_port *ap)
+{
+ return (ap->flags & PDC_FLAG_GEN_II) ? PDC2_SATA_PLUG_CSR : PDC_SATA_PLUG_CSR;
+}
+
static void pdc_freeze(struct ata_port *ap)
{
void __iomem *mmio = ap->ioaddr.cmd_addr;
readl(mmio + PDC_CTLSTAT); /* flush */
}
+static void pdc_sata_freeze(struct ata_port *ap)
+{
+ struct ata_host *host = ap->host;
+ void __iomem *host_mmio = host->iomap[PDC_MMIO_BAR];
+ unsigned int hotplug_offset = pdc_sata_hotplug_offset(ap);
+ unsigned int ata_no = pdc_sata_ata_port_to_ata_no(ap);
+ u32 hotplug_status;
+
+ /* Disable hotplug events on this port.
+ *
+ * Locking:
+ * 1) hotplug register accesses must be serialised via host->lock
+ * 2) ap->lock == &ap->host->lock
+ * 3) ->freeze() and ->thaw() are called with ap->lock held
+ */
+ hotplug_status = readl(host_mmio + hotplug_offset);
+ hotplug_status |= 0x11 << (ata_no + 16);
+ writel(hotplug_status, host_mmio + hotplug_offset);
+ readl(host_mmio + hotplug_offset); /* flush */
+
+ pdc_freeze(ap);
+}
+
static void pdc_thaw(struct ata_port *ap)
{
void __iomem *mmio = ap->ioaddr.cmd_addr;
readl(mmio + PDC_CTLSTAT); /* flush */
}
-static void pdc_common_error_handler(struct ata_port *ap, ata_reset_fn_t hardreset)
+static void pdc_sata_thaw(struct ata_port *ap)
{
- if (!(ap->pflags & ATA_PFLAG_FROZEN))
- pdc_reset_port(ap);
+ struct ata_host *host = ap->host;
+ void __iomem *host_mmio = host->iomap[PDC_MMIO_BAR];
+ unsigned int hotplug_offset = pdc_sata_hotplug_offset(ap);
+ unsigned int ata_no = pdc_sata_ata_port_to_ata_no(ap);
+ u32 hotplug_status;
- /* perform recovery */
- ata_do_eh(ap, ata_std_prereset, ata_std_softreset, hardreset,
- ata_std_postreset);
-}
+ pdc_thaw(ap);
-static void pdc_pata_error_handler(struct ata_port *ap)
-{
- pdc_common_error_handler(ap, NULL);
+ /* Enable hotplug events on this port.
+ * Locking: see pdc_sata_freeze().
+ */
+ hotplug_status = readl(host_mmio + hotplug_offset);
+ hotplug_status |= 0x11 << ata_no;
+ hotplug_status &= ~(0x11 << (ata_no + 16));
+ writel(hotplug_status, host_mmio + hotplug_offset);
+ readl(host_mmio + hotplug_offset); /* flush */
}
-static void pdc_sata_error_handler(struct ata_port *ap)
+static void pdc_error_handler(struct ata_port *ap)
{
- pdc_common_error_handler(ap, sata_std_hardreset);
+ if (!(ap->pflags & ATA_PFLAG_FROZEN))
+ pdc_reset_port(ap);
+
+ ata_std_error_handler(ap);
}
static void pdc_post_internal_cmd(struct ata_queued_cmd *qc)
switch (qc->tf.protocol) {
case ATA_PROT_DMA:
case ATA_PROT_NODATA:
- case ATA_PROT_ATAPI_DMA:
- case ATA_PROT_ATAPI_NODATA:
+ case ATAPI_PROT_DMA:
+ case ATAPI_PROT_NODATA:
qc->err_mask |= ac_err_mask(ata_wait_idle(ap));
ata_qc_complete(qc);
handled = 1;
readl(mmio + PDC_INT_SEQMASK);
}
-static int pdc_is_sataii_tx4(unsigned long flags)
-{
- const unsigned long mask = PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS;
- return (flags & mask) == mask;
-}
-
-static unsigned int pdc_port_no_to_ata_no(unsigned int port_no,
- int is_sataii_tx4)
-{
- static const unsigned char sataii_tx4_port_remap[4] = { 3, 1, 0, 2};
- return is_sataii_tx4 ? sataii_tx4_port_remap[port_no] : port_no;
-}
-
static irqreturn_t pdc_interrupt(int irq, void *dev_instance)
{
struct ata_host *host = dev_instance;
mmio_base = host->iomap[PDC_MMIO_BAR];
+ spin_lock(&host->lock);
+
/* read and clear hotplug flags for all ports */
if (host->ports[0]->flags & PDC_FLAG_GEN_II)
hotplug_offset = PDC2_SATA_PLUG_CSR;
if (mask == 0xffffffff && hotplug_status == 0) {
VPRINTK("QUICK EXIT 2\n");
- return IRQ_NONE;
+ goto done_irq;
}
- spin_lock(&host->lock);
-
mask &= 0xffff; /* only 16 tags possible */
if (mask == 0 && hotplug_status == 0) {
VPRINTK("QUICK EXIT 3\n");
readl(ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); /* flush */
}
-static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
+static unsigned int pdc_qc_issue(struct ata_queued_cmd *qc)
{
switch (qc->tf.protocol) {
- case ATA_PROT_ATAPI_NODATA:
+ case ATAPI_PROT_NODATA:
if (qc->dev->flags & ATA_DFLAG_CDB_INTR)
break;
/*FALLTHROUGH*/
if (qc->tf.flags & ATA_TFLAG_POLLING)
break;
/*FALLTHROUGH*/
- case ATA_PROT_ATAPI_DMA:
+ case ATAPI_PROT_DMA:
case ATA_PROT_DMA:
pdc_packet_start(qc);
return 0;
break;
}
- return ata_qc_issue_prot(qc);
+ return ata_sff_qc_issue(qc);
}
static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
{
- WARN_ON(tf->protocol == ATA_PROT_DMA ||
- tf->protocol == ATA_PROT_ATAPI_DMA);
- ata_tf_load(ap, tf);
+ WARN_ON(tf->protocol == ATA_PROT_DMA || tf->protocol == ATAPI_PROT_DMA);
+ ata_sff_tf_load(ap, tf);
}
static void pdc_exec_command_mmio(struct ata_port *ap,
const struct ata_taskfile *tf)
{
- WARN_ON(tf->protocol == ATA_PROT_DMA ||
- tf->protocol == ATA_PROT_ATAPI_DMA);
- ata_exec_command(ap, tf);
+ WARN_ON(tf->protocol == ATA_PROT_DMA || tf->protocol == ATAPI_PROT_DMA);
+ ata_sff_exec_command(ap, tf);
}
static int pdc_check_atapi_dma(struct ata_queued_cmd *qc)