aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-core.c
diff options
context:
space:
mode:
authorAlan Cox <alan@lxorguk.ukuu.org.uk>2007-07-06 19:13:52 -0400
committerJeff Garzik <jeff@garzik.org>2007-07-09 12:17:35 -0400
commitd26fc9551a15fdad0d5de8376a78816b8af44f00 (patch)
tree5c829c1baf499ad1f31ed4b8b41e766b290a6306 /drivers/ata/libata-core.c
parentc1e6f28cc5de37dcd113b9668a185c0b9334ba8a (diff)
libata: Support chips with 64K PRD quirk
Add ata_dumb_qc_prep and supporting logic so that a driver can just specify it needs to be helped in this area. 64K entries are split as with drivers/ide. Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata/libata-core.c')
-rw-r--r--drivers/ata/libata-core.c80
1 files changed, 80 insertions, 0 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 74c4cd9ad82..5b25311ba88 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -4103,6 +4103,68 @@ static void ata_fill_sg(struct ata_queued_cmd *qc)
4103} 4103}
4104 4104
4105/** 4105/**
4106 * ata_fill_sg_dumb - Fill PCI IDE PRD table
4107 * @qc: Metadata associated with taskfile to be transferred
4108 *
4109 * Fill PCI IDE PRD (scatter-gather) table with segments
4110 * associated with the current disk command. Perform the fill
4111 * so that we avoid writing any length 64K records for
4112 * controllers that don't follow the spec.
4113 *
4114 * LOCKING:
4115 * spin_lock_irqsave(host lock)
4116 *
4117 */
4118static void ata_fill_sg_dumb(struct ata_queued_cmd *qc)
4119{
4120 struct ata_port *ap = qc->ap;
4121 struct scatterlist *sg;
4122 unsigned int idx;
4123
4124 WARN_ON(qc->__sg == NULL);
4125 WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
4126
4127 idx = 0;
4128 ata_for_each_sg(sg, qc) {
4129 u32 addr, offset;
4130 u32 sg_len, len, blen;
4131
4132 /* determine if physical DMA addr spans 64K boundary.
4133 * Note h/w doesn't support 64-bit, so we unconditionally
4134 * truncate dma_addr_t to u32.
4135 */
4136 addr = (u32) sg_dma_address(sg);
4137 sg_len = sg_dma_len(sg);
4138
4139 while (sg_len) {
4140 offset = addr & 0xffff;
4141 len = sg_len;
4142 if ((offset + sg_len) > 0x10000)
4143 len = 0x10000 - offset;
4144
4145 blen = len & 0xffff;
4146 ap->prd[idx].addr = cpu_to_le32(addr);
4147 if (blen == 0) {
4148 /* Some PATA chipsets like the CS5530 can't
4149 cope with 0x0000 meaning 64K as the spec says */
4150 ap->prd[idx].flags_len = cpu_to_le32(0x8000);
4151 blen = 0x8000;
4152 ap->prd[++idx].addr = cpu_to_le32(addr + 0x8000);
4153 }
4154 ap->prd[idx].flags_len = cpu_to_le32(blen);
4155 VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len);
4156
4157 idx++;
4158 sg_len -= len;
4159 addr += len;
4160 }
4161 }
4162
4163 if (idx)
4164 ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
4165}
4166
4167/**
4106 * ata_check_atapi_dma - Check whether ATAPI DMA can be supported 4168 * ata_check_atapi_dma - Check whether ATAPI DMA can be supported
4107 * @qc: Metadata associated with taskfile to check 4169 * @qc: Metadata associated with taskfile to check
4108 * 4170 *
@@ -4149,6 +4211,23 @@ void ata_qc_prep(struct ata_queued_cmd *qc)
4149 ata_fill_sg(qc); 4211 ata_fill_sg(qc);
4150} 4212}
4151 4213
4214/**
4215 * ata_dumb_qc_prep - Prepare taskfile for submission
4216 * @qc: Metadata associated with taskfile to be prepared
4217 *
4218 * Prepare ATA taskfile for submission.
4219 *
4220 * LOCKING:
4221 * spin_lock_irqsave(host lock)
4222 */
4223void ata_dumb_qc_prep(struct ata_queued_cmd *qc)
4224{
4225 if (!(qc->flags & ATA_QCFLAG_DMAMAP))
4226 return;
4227
4228 ata_fill_sg_dumb(qc);
4229}
4230
4152void ata_noop_qc_prep(struct ata_queued_cmd *qc) { } 4231void ata_noop_qc_prep(struct ata_queued_cmd *qc) { }
4153 4232
4154/** 4233/**
@@ -6821,6 +6900,7 @@ EXPORT_SYMBOL_GPL(ata_do_set_mode);
6821EXPORT_SYMBOL_GPL(ata_data_xfer); 6900EXPORT_SYMBOL_GPL(ata_data_xfer);
6822EXPORT_SYMBOL_GPL(ata_data_xfer_noirq); 6901EXPORT_SYMBOL_GPL(ata_data_xfer_noirq);
6823EXPORT_SYMBOL_GPL(ata_qc_prep); 6902EXPORT_SYMBOL_GPL(ata_qc_prep);
6903EXPORT_SYMBOL_GPL(ata_dumb_qc_prep);
6824EXPORT_SYMBOL_GPL(ata_noop_qc_prep); 6904EXPORT_SYMBOL_GPL(ata_noop_qc_prep);
6825EXPORT_SYMBOL_GPL(ata_bmdma_setup); 6905EXPORT_SYMBOL_GPL(ata_bmdma_setup);
6826EXPORT_SYMBOL_GPL(ata_bmdma_start); 6906EXPORT_SYMBOL_GPL(ata_bmdma_start);