lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <20080610154829.6f2cec75@core>
Date:	Tue, 10 Jun 2008 15:48:29 +0100
From:	Alan Cox <alan@...rguk.ukuu.org.uk>
To:	linux-kernel@...r.kernel.org, linux-ide@...r.kernel.org
Subject: [PATCH] pata_amd: (TEST) See if the ATAPI reports of problems are
 related to the FIFO

Please try the following if you are still seeing problems with the AMD PATA and
ATAPI devices (CD/DVD etc).

From: Alan Cox <alan@...hat.com>

The AMD documentation says the FIFO is only valid when we have 32bit wide transfers
running. That is not reliably the case with ATAPI. As we get some people reporting
problems with ATAPI on this controller lets see if this cures it.

I've not touched the Nvidia side. We have no documentation for nVidia stuff as
usual so if they need FIFO management someone from nVidia will just have to
fix it...

Alan
---

 drivers/ata/pata_amd.c |   77 ++++++++++++++++++++++++++++++++++++------------
 1 files changed, 58 insertions(+), 19 deletions(-)


diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c
index 57dd00f..5588ba9 100644
--- a/drivers/ata/pata_amd.c
+++ b/drivers/ata/pata_amd.c
@@ -25,7 +25,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_amd"
-#define DRV_VERSION "0.3.10"
+#define DRV_VERSION "0.4.1"
 
 /**
  *	timing_setup		-	shared timing computation and load
@@ -34,14 +34,18 @@
  *	@offset: port offset
  *	@speed: target speed
  *	@clock: clock multiplier (number of times 33MHz for this part)
+ *	@fifo: true if we can touch the FIFO
  *
  *	Perform the actual timing set up for Nvidia or AMD PATA devices.
  *	The actual devices vary so they all call into this helper function
  *	providing the clock multipler and offset (because AMD and Nvidia put
  *	the ports at different locations).
+ *
+ *	FIXME: We could share a lot of this logic with the VIA driver.
  */
 
-static void timing_setup(struct ata_port *ap, struct ata_device *adev, int offset, int speed, int clock)
+static void timing_setup(struct ata_port *ap, struct ata_device *adev,
+				int offset, int speed, int clock, int fifo)
 {
 	static const unsigned char amd_cyc2udma[] = {
 		6, 6, 5, 4, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 7
@@ -54,6 +58,8 @@ static void timing_setup(struct ata_port *ap, struct ata_device *adev, int offse
 	int T, UT;
 	const int amd_clock = 33333;	/* KHz. */
 	u8 t;
+	u8 ccr;
+	int drive = (3 - dn);
 
 	T = 1000000000 / amd_clock;
 	UT = T;
@@ -84,15 +90,15 @@ static void timing_setup(struct ata_port *ap, struct ata_device *adev, int offse
 
 	/* Configure the address set up timing */
 	pci_read_config_byte(pdev, offset + 0x0C, &t);
-	t = (t & ~(3 << ((3 - dn) << 1))) | ((clamp_val(at.setup, 1, 4) - 1) << ((3 - dn) << 1));
+	t = (t & ~(3 << (drive << 1))) | ((clamp_val(at.setup, 1, 4) - 1) << (drive << 1));
 	pci_write_config_byte(pdev, offset + 0x0C , t);
 
 	/* Configure the 8bit I/O timing */
-	pci_write_config_byte(pdev, offset + 0x0E + (1 - (dn >> 1)),
+	pci_write_config_byte(pdev, offset + 0x0F - ap->port_no,
 		((clamp_val(at.act8b, 1, 16) - 1) << 4) | (clamp_val(at.rec8b, 1, 16) - 1));
 
 	/* Drive timing */
-	pci_write_config_byte(pdev, offset + 0x08 + (3 - dn),
+	pci_write_config_byte(pdev, offset + 0x08 + drive,
 		((clamp_val(at.active, 1, 16) - 1) << 4) | (clamp_val(at.recover, 1, 16) - 1));
 
 	switch (clock) {
@@ -118,7 +124,20 @@ static void timing_setup(struct ata_port *ap, struct ata_device *adev, int offse
 
 	/* UDMA timing */
 	if (at.udma)
-		pci_write_config_byte(pdev, offset + 0x10 + (3 - dn), t);
+		pci_write_config_byte(pdev, offset + 0x10 + drive, t);
+	
+	if (fifo) {
+		/* Disable the FIFO in ATAPI mode as it only works for
+		   32bit wide transfer blocks */
+		int bit = ap->port_no ? 0x10: 0x40;
+		pci_read_config_byte(pdev, offset + 0x01, &ccr);
+		ccr &= ~bit;
+		if (adev->class == ATA_DEV_ATA &&
+			(peer == NULL || peer->class == ATA_DEV_ATA))
+			ccr |= bit;
+		pci_write_config_byte(pdev, offset + 0x01, ccr);
+		
+	}
 }
 
 /**
@@ -168,22 +187,28 @@ static int amd_cable_detect(struct ata_port *ap)
 
 static void amd33_set_piomode(struct ata_port *ap, struct ata_device *adev)
 {
-	timing_setup(ap, adev, 0x40, adev->pio_mode, 1);
+	timing_setup(ap, adev, 0x40, adev->pio_mode, 1, 1);
 }
 
 static void amd66_set_piomode(struct ata_port *ap, struct ata_device *adev)
 {
-	timing_setup(ap, adev, 0x40, adev->pio_mode, 2);
+	timing_setup(ap, adev, 0x40, adev->pio_mode, 2, 1);
 }
 
 static void amd100_set_piomode(struct ata_port *ap, struct ata_device *adev)
 {
-	timing_setup(ap, adev, 0x40, adev->pio_mode, 3);
+	timing_setup(ap, adev, 0x40, adev->pio_mode, 3, 1);
+}
+
+static void amd100_set_piomode_nofifo(struct ata_port *ap,
+						struct ata_device *adev)
+{
+	timing_setup(ap, adev, 0x40, adev->pio_mode, 3, 0);
 }
 
 static void amd133_set_piomode(struct ata_port *ap, struct ata_device *adev)
 {
-	timing_setup(ap, adev, 0x40, adev->pio_mode, 4);
+	timing_setup(ap, adev, 0x40, adev->pio_mode, 4, 1);
 }
 
 /**
@@ -197,22 +222,28 @@ static void amd133_set_piomode(struct ata_port *ap, struct ata_device *adev)
 
 static void amd33_set_dmamode(struct ata_port *ap, struct ata_device *adev)
 {
-	timing_setup(ap, adev, 0x40, adev->dma_mode, 1);
+	timing_setup(ap, adev, 0x40, adev->dma_mode, 1, 1);
 }
 
 static void amd66_set_dmamode(struct ata_port *ap, struct ata_device *adev)
 {
-	timing_setup(ap, adev, 0x40, adev->dma_mode, 2);
+	timing_setup(ap, adev, 0x40, adev->dma_mode, 2, 1);
 }
 
 static void amd100_set_dmamode(struct ata_port *ap, struct ata_device *adev)
 {
-	timing_setup(ap, adev, 0x40, adev->dma_mode, 3);
+	timing_setup(ap, adev, 0x40, adev->dma_mode, 3, 1);
+}
+
+static void amd100_set_dmamode_nofifo(struct ata_port *ap,
+						struct ata_device *adev)
+{
+	timing_setup(ap, adev, 0x40, adev->dma_mode, 3, 0);
 }
 
 static void amd133_set_dmamode(struct ata_port *ap, struct ata_device *adev)
 {
-	timing_setup(ap, adev, 0x40, adev->dma_mode, 4);
+	timing_setup(ap, adev, 0x40, adev->dma_mode, 4, 1);
 }
 
 /* Both host-side and drive-side detection results are worthless on NV
@@ -306,12 +337,12 @@ static int nv_pre_reset(struct ata_link *link, unsigned long deadline)
 
 static void nv100_set_piomode(struct ata_port *ap, struct ata_device *adev)
 {
-	timing_setup(ap, adev, 0x50, adev->pio_mode, 3);
+	timing_setup(ap, adev, 0x50, adev->pio_mode, 3, 0);
 }
 
 static void nv133_set_piomode(struct ata_port *ap, struct ata_device *adev)
 {
-	timing_setup(ap, adev, 0x50, adev->pio_mode, 4);
+	timing_setup(ap, adev, 0x50, adev->pio_mode, 4, 0);
 }
 
 /**
@@ -325,12 +356,13 @@ static void nv133_set_piomode(struct ata_port *ap, struct ata_device *adev)
 
 static void nv100_set_dmamode(struct ata_port *ap, struct ata_device *adev)
 {
-	timing_setup(ap, adev, 0x50, adev->dma_mode, 3);
+	timing_setup(ap, adev, 0x50, adev->dma_mode, 3, 0
+	);
 }
 
 static void nv133_set_dmamode(struct ata_port *ap, struct ata_device *adev)
 {
-	timing_setup(ap, adev, 0x50, adev->dma_mode, 4);
+	timing_setup(ap, adev, 0x50, adev->dma_mode, 4, 0);
 }
 
 static void nv_host_stop(struct ata_host *host)
@@ -371,6 +403,13 @@ static struct ata_port_operations amd100_port_ops = {
 	.set_dmamode	= amd100_set_dmamode,
 };
 
+static struct ata_port_operations amd100_port_nofifo_ops = {
+	.inherits	= &amd_base_port_ops,
+	.cable_detect	= ata_cable_unknown,
+	.set_piomode	= amd100_set_piomode_nofifo,
+	.set_dmamode	= amd100_set_dmamode_nofifo,
+};
+
 static struct ata_port_operations amd133_port_ops = {
 	.inherits	= &amd_base_port_ops,
 	.cable_detect	= amd_cable_detect,
@@ -427,7 +466,7 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 			.pio_mask = 0x1f,
 			.mwdma_mask = 0x07,
 			.udma_mask = ATA_UDMA5,	/* UDMA 100 */
-			.port_ops = &amd100_port_ops
+			.port_ops = &amd100_port_nofifo_ops
 		},
 		{	/* 4: AMD 7441 */
 			.flags = ATA_FLAG_SLAVE_POSS,
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ