|
@@ -4102,6 +4102,68 @@ static void ata_fill_sg(struct ata_queued_cmd *qc)
|
|
|
ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * ata_fill_sg_dumb - Fill PCI IDE PRD table
|
|
|
+ * @qc: Metadata associated with taskfile to be transferred
|
|
|
+ *
|
|
|
+ * Fill PCI IDE PRD (scatter-gather) table with segments
|
|
|
+ * associated with the current disk command. Perform the fill
|
|
|
+ * so that we avoid writing any length 64K records for
|
|
|
+ * controllers that don't follow the spec.
|
|
|
+ *
|
|
|
+ * LOCKING:
|
|
|
+ * spin_lock_irqsave(host lock)
|
|
|
+ *
|
|
|
+ */
|
|
|
+static void ata_fill_sg_dumb(struct ata_queued_cmd *qc)
|
|
|
+{
|
|
|
+ struct ata_port *ap = qc->ap;
|
|
|
+ struct scatterlist *sg;
|
|
|
+ unsigned int idx;
|
|
|
+
|
|
|
+ WARN_ON(qc->__sg == NULL);
|
|
|
+ WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
|
|
|
+
|
|
|
+ idx = 0;
|
|
|
+ ata_for_each_sg(sg, qc) {
|
|
|
+ u32 addr, offset;
|
|
|
+ u32 sg_len, len, blen;
|
|
|
+
|
|
|
+ /* determine if physical DMA addr spans 64K boundary.
|
|
|
+ * Note h/w doesn't support 64-bit, so we unconditionally
|
|
|
+ * truncate dma_addr_t to u32.
|
|
|
+ */
|
|
|
+ addr = (u32) sg_dma_address(sg);
|
|
|
+ sg_len = sg_dma_len(sg);
|
|
|
+
|
|
|
+ while (sg_len) {
|
|
|
+ offset = addr & 0xffff;
|
|
|
+ len = sg_len;
|
|
|
+ if ((offset + sg_len) > 0x10000)
|
|
|
+ len = 0x10000 - offset;
|
|
|
+
|
|
|
+ blen = len & 0xffff;
|
|
|
+ ap->prd[idx].addr = cpu_to_le32(addr);
|
|
|
+ if (blen == 0) {
|
|
|
+ /* Some PATA chipsets like the CS5530 can't
|
|
|
+ cope with 0x0000 meaning 64K as the spec says */
|
|
|
+ ap->prd[idx].flags_len = cpu_to_le32(0x8000);
|
|
|
+ blen = 0x8000;
|
|
|
+ ap->prd[++idx].addr = cpu_to_le32(addr + 0x8000);
|
|
|
+ }
|
|
|
+ ap->prd[idx].flags_len = cpu_to_le32(blen);
|
|
|
+ VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len);
|
|
|
+
|
|
|
+ idx++;
|
|
|
+ sg_len -= len;
|
|
|
+ addr += len;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (idx)
|
|
|
+ ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* ata_check_atapi_dma - Check whether ATAPI DMA can be supported
|
|
|
* @qc: Metadata associated with taskfile to check
|
|
@@ -4149,6 +4211,23 @@ void ata_qc_prep(struct ata_queued_cmd *qc)
|
|
|
ata_fill_sg(qc);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * ata_dumb_qc_prep - Prepare taskfile for submission
|
|
|
+ * @qc: Metadata associated with taskfile to be prepared
|
|
|
+ *
|
|
|
+ * Prepare ATA taskfile for submission.
|
|
|
+ *
|
|
|
+ * LOCKING:
|
|
|
+ * spin_lock_irqsave(host lock)
|
|
|
+ */
|
|
|
+void ata_dumb_qc_prep(struct ata_queued_cmd *qc)
|
|
|
+{
|
|
|
+ if (!(qc->flags & ATA_QCFLAG_DMAMAP))
|
|
|
+ return;
|
|
|
+
|
|
|
+ ata_fill_sg_dumb(qc);
|
|
|
+}
|
|
|
+
|
|
|
void ata_noop_qc_prep(struct ata_queued_cmd *qc) { }
|
|
|
|
|
|
/**
|
|
@@ -6821,6 +6900,7 @@ EXPORT_SYMBOL_GPL(ata_do_set_mode);
|
|
|
EXPORT_SYMBOL_GPL(ata_data_xfer);
|
|
|
EXPORT_SYMBOL_GPL(ata_data_xfer_noirq);
|
|
|
EXPORT_SYMBOL_GPL(ata_qc_prep);
|
|
|
+EXPORT_SYMBOL_GPL(ata_dumb_qc_prep);
|
|
|
EXPORT_SYMBOL_GPL(ata_noop_qc_prep);
|
|
|
EXPORT_SYMBOL_GPL(ata_bmdma_setup);
|
|
|
EXPORT_SYMBOL_GPL(ata_bmdma_start);
|