aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Cox <alan@lxorguk.ukuu.org.uk>2006-03-21 15:59:57 +0000
committerJeff Garzik <jeff@garzik.org>2006-03-21 21:21:32 -0500
commitd33d44facc8673388979297c9836b4bf590f7388 (patch)
tree69cdb3ef82191ba66ec79bcc2ad1702f84951f83
parent41bbc8bf1ab0e3e7cda1a0334176a9aa3986cd30 (diff)
[PATCH] libata: two new PCI helpers
The first performs the simplex clearing relevant to some chipsets that report simplex by default but can in fact do more if poked. The second is used to strip DMA modes from a PCI control with no BAR4 allocation. Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r--drivers/scsi/libata-bmdma.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/drivers/scsi/libata-bmdma.c b/drivers/scsi/libata-bmdma.c
index a89e44b21f4..999725ca8d0 100644
--- a/drivers/scsi/libata-bmdma.c
+++ b/drivers/scsi/libata-bmdma.c
@@ -700,5 +700,41 @@ err_out:
return rc;
}
+/**
+ * ata_pci_clear_simplex - attempt to kick device out of simplex
+ * @pdev: PCI device
+ *
+ * Some PCI ATA devices report simplex mode but in fact can be told to
+ * enter non simplex mode. This implements the neccessary logic to
+ * perform the task on such devices. Calling it on other devices will
+ * have -undefined- behaviour.
+ */
+
+int ata_pci_clear_simplex(struct pci_dev *pdev)
+{
+ unsigned long bmdma = pci_resource_start(pdev, 4);
+ u8 simplex;
+
+ if (bmdma == 0)
+ return -ENOENT;
+
+ simplex = inb(bmdma + 0x02);
+ outb(simplex & 0x60, bmdma + 0x02);
+ simplex = inb(bmdma + 0x02);
+ if (simplex & 0x80)
+ return -EOPNOTSUPP;
+ return 0;
+}
+
+unsigned long ata_pci_default_filter(const struct ata_port *ap, struct ata_device *adev, unsigned long xfer_mask)
+{
+ /* Filter out DMA modes if the device has been configured by
+ the BIOS as PIO only */
+
+ if (ap->ioaddr.bmdma_addr == 0)
+ xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA);
+ return xfer_mask;
+}
+
#endif /* CONFIG_PCI */