linux-ide.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Albert Lee" <albertcc@tw.ibm.com>
To: Jeff Garzik <jgarzik@pobox.com>
Cc: IDE Linux <linux-ide@vger.kernel.org>, Doug Maxey <dwm@maxeymade.com>
Subject: [PATCH] libata-dev-2.6 -- pdc2027x timing register bug fix
Date: Fri, 21 Jan 2005 21:30:08 +0800	[thread overview]
Message-ID: <005e01c4ffbd$55c9b200$6401a8c0@tw.ibm.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 5554 bytes --]

Hi Jeff,

Attached please find the patch against libata-dev-2.6 for your review.

Changes:
1. Resubmit the pdc2027x ATAPI DMA bug fix.
2. Turn on prefetch only when the drive supports PIO mode only.
3. Minor debug message fix
4. Fix the incorrect timing register values automatically set by the hardware by
    setting timing registers again in ap->post_set_mode(). Problem detailed below:

   Promise pdc2027x hardware will look at the SET FEATURES and set the timing registers
   automatically. Under 133MHz PLL, the values set by the hardware is incorrect.
   Because ata_set_mode() set HBA timing registers before "SET FEATURES", 
   the correct value set by the software device driver is later overwritten
   by hardware when "SET FEATURES" seen by the hardware.
   So,  pdc2027x_post_set_mode() is added to set the correct timeing values back.

Albert

Signed-off-by: Albert Lee <albertcc@tw.ibm.com>
----------------------------------------------------------------------------------------------
--- libata-2.6/drivers/scsi/pata_pdc2027x.c 2005-01-21 20:00:52.000000000 +0800
+++ libata-2.6-mod/drivers/scsi/pata_pdc2027x.c 2005-01-21 21:03:26.868787243 +0800
@@ -29,7 +29,7 @@
 #include <asm/io.h>
 
 #define DRV_NAME "pata_pdc2027x"
-#define DRV_VERSION "0.53"
+#define DRV_VERSION "0.55"
 #undef PDC_DEBUG
 
 #ifdef PDC_DEBUG
@@ -51,6 +51,8 @@
 static void pdc2027x_phy_reset(struct ata_port *ap);
 static void pdc2027x_set_piomode(struct ata_port *ap, struct ata_device *adev);
 static void pdc2027x_set_dmamode(struct ata_port *ap, struct ata_device *adev);
+static void pdc2027x_post_set_mode(struct ata_port *ap);
+static int pdc2027x_check_atapi_dma(struct ata_queued_cmd *qc);
 
 /* 
  * ATA Timing Tables based on 133MHz controller clock.
@@ -140,15 +142,17 @@
  .dev_select  = ata_std_dev_select,
 
  .phy_reset  = pdc2027x_phy_reset,   
+ .post_set_mode  = pdc2027x_post_set_mode,
 
- .bmdma_setup            = ata_bmdma_setup,
- .bmdma_start            = ata_bmdma_start,
+ .check_atapi_dma = pdc2027x_check_atapi_dma,
+ .bmdma_setup  = ata_bmdma_setup,
+ .bmdma_start  = ata_bmdma_start,
  .qc_prep  = ata_qc_prep,
  .qc_issue  = ata_qc_issue_prot,
  .eng_timeout  = ata_eng_timeout,
 
  .irq_handler  = ata_interrupt,
- .irq_clear              = ata_bmdma_irq_clear,
+ .irq_clear  = ata_bmdma_irq_clear,
 
  .port_start  = ata_port_start,
  .port_stop  = ata_port_stop,
@@ -284,8 +288,6 @@
  unsigned int pio      = adev->pio_mode - XFER_PIO_0;
  unsigned int drive_dn = (ap->port_no ? 2 : 0) + adev->devno;
  u8 adj        = (drive_dn%2) ? 0x08 : 0x00;
- u8 tmp8;
-
 
  PDPRINTK("adev->pio_mode[%X]\n", adev->pio_mode);
 
@@ -305,20 +307,7 @@
 
  PDPRINTK("Set pio regs done\n");
 
- /*
-  *  Check whether the device supports turning off IORDY.
-  * For PIO3 and above, the device must support IORDY and set bit 10 
-  */
- if (adev->id[49] & 0x400) { 
-  /* IORDY_EN & PREFETCH_EN */
-  /* Turn on Prefetch */
-  tmp8 = pdc_get_indexed_reg(ap, 0x13 + adj);
-  pdc_set_indexed_reg(ap, 0x13 + adj, tmp8 | 0x03);
-
-  PDPRINTK("Turn on prefetch\n");
- }
-
- printk(KERN_INFO DRV_NAME ": Set to pio mode[%u] \n", pio);
+ PDPRINTK("Set to pio mode[%u] \n", pio);
 }
 /**
  * pdc2027x_set_dmamode - Initialize host controller PATA UDMA timings
@@ -359,7 +348,7 @@
   pdc_set_indexed_reg(ap, 0x12 + adj, pdc2027x_udma_timing_tbl[udma_mode].value2);
   PDPRINTK("Set udma regs done\n");
   
-  printk(KERN_INFO DRV_NAME ": Set to udma mode[%u] \n", udma_mode);
+  PDPRINTK("Set to udma mode[%u] \n", udma_mode);
 
  } else  if((dma_mode >= XFER_MW_DMA_0) && 
      (dma_mode <= XFER_MW_DMA_2)) {
@@ -371,11 +360,70 @@
   pdc_set_indexed_reg(ap, 0x0f + adj, pdc2027x_mdma_timing_tbl[mdma_mode].value1);
   PDPRINTK("Set mdma regs done\n");
   
-  printk(KERN_INFO DRV_NAME ": Set to mdma mode[%u] \n", mdma_mode);
+  PDPRINTK("Set to mdma mode[%u] \n", mdma_mode);
  } else {
   printk(KERN_ERR DRV_NAME ": Unknown dma mode [%u] ignored\n", dma_mode);
  }
 }
+
+/**
+ * pdc2027x_post_set_mode - Set the timing registers back to correct values.
+ * @ap: Port to configure
+ * 
+ * The pdc2027x hardware will look at "SET FEATURES" and change the timing registers 
+ * automatically. The values set by the hardware might be incorrect, under 133Mhz PLL.
+ * This function overwrites the possibly incorrect values set by the hardware to be correct.
+ */
+static void pdc2027x_post_set_mode(struct ata_port *ap)
+{
+ int i;
+
+ for (i = 0; i < ATA_MAX_DEVICES; i++) {
+  struct ata_device *dev = &ap->device[i];
+
+  if (ata_dev_present(dev)) {
+   u8 adj = (i % 2) ? 0x08 : 0x00;
+   u8 tmp8;
+   
+   pdc2027x_set_piomode(ap, dev);
+
+   /*
+    * Enable prefetch if the device support PIO only.
+    */
+   if (dev->xfer_shift == ATA_SHIFT_PIO) { 
+    tmp8 = pdc_get_indexed_reg(ap, 0x13 + adj);
+    pdc_set_indexed_reg(ap, 0x13 + adj, tmp8 | 0x02);
+    
+    PDPRINTK("Turn on prefetch\n");
+   } else {
+    pdc2027x_set_dmamode(ap, dev);
+   }
+  }
+ }
+}
+
+/**
+ * pdc2027x_check_atapi_dma - Check whether ATAPI DMA can be supported for this command
+ * @qc: Metadata associated with taskfile to check
+ *
+ * LOCKING:
+ * None (inherited from caller).
+ *
+ * RETURNS: 0 when ATAPI DMA can be used
+ *   1 otherwise
+ */
+static int pdc2027x_check_atapi_dma(struct ata_queued_cmd *qc)
+{
+ struct scsi_cmnd *cmd = qc->scsicmd;
+ int rc = 0;
+
+ /* pdc2027x can only do ATAPI DMA for specific buffer size */
+ if (cmd->request_bufflen % 256)
+  rc = 1;
+
+ return rc;
+}
+
 /**
  * adjust_pll - Adjust the PLL input clock in Hz.
  *

[-- Attachment #2: pdc2027x_055.patch --]
[-- Type: application/octet-stream, Size: 4705 bytes --]

--- libata-2.6/drivers/scsi/pata_pdc2027x.c	2005-01-21 20:00:52.000000000 +0800
+++ libata-2.6-mod/drivers/scsi/pata_pdc2027x.c	2005-01-21 21:03:26.868787243 +0800
@@ -29,7 +29,7 @@
 #include <asm/io.h>
 
 #define DRV_NAME	"pata_pdc2027x"
-#define DRV_VERSION	"0.53"
+#define DRV_VERSION	"0.55"
 #undef PDC_DEBUG
 
 #ifdef PDC_DEBUG
@@ -51,6 +51,8 @@
 static void pdc2027x_phy_reset(struct ata_port *ap);
 static void pdc2027x_set_piomode(struct ata_port *ap, struct ata_device *adev);
 static void pdc2027x_set_dmamode(struct ata_port *ap, struct ata_device *adev);
+static void pdc2027x_post_set_mode(struct ata_port *ap);
+static int pdc2027x_check_atapi_dma(struct ata_queued_cmd *qc);
 
 /* 
  * ATA Timing Tables based on 133MHz controller clock.
@@ -140,15 +142,17 @@
 	.dev_select		= ata_std_dev_select,
 
 	.phy_reset		= pdc2027x_phy_reset,   
+	.post_set_mode		= pdc2027x_post_set_mode,
 
-	.bmdma_setup            = ata_bmdma_setup,
-	.bmdma_start            = ata_bmdma_start,
+	.check_atapi_dma	= pdc2027x_check_atapi_dma,
+	.bmdma_setup		= ata_bmdma_setup,
+	.bmdma_start		= ata_bmdma_start,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
 	.eng_timeout		= ata_eng_timeout,
 
 	.irq_handler		= ata_interrupt,
-	.irq_clear              = ata_bmdma_irq_clear,
+	.irq_clear		= ata_bmdma_irq_clear,
 
 	.port_start		= ata_port_start,
 	.port_stop		= ata_port_stop,
@@ -284,8 +288,6 @@
 	unsigned int pio      = adev->pio_mode - XFER_PIO_0;
 	unsigned int drive_dn = (ap->port_no ? 2 : 0) + adev->devno;
 	u8 adj		      = (drive_dn%2) ? 0x08 : 0x00;
-	u8 tmp8;
-
 
 	PDPRINTK("adev->pio_mode[%X]\n", adev->pio_mode);
 
@@ -305,20 +307,7 @@
 
 	PDPRINTK("Set pio regs done\n");
 
-	/*
-	 *  Check whether the device supports turning off IORDY.
-	 * For PIO3 and above, the device must support IORDY and set bit 10 
-	 */
-	if (adev->id[49] & 0x400) { 
-		/* IORDY_EN & PREFETCH_EN */
-		/* Turn on Prefetch */
-		tmp8 = pdc_get_indexed_reg(ap, 0x13 + adj);
-		pdc_set_indexed_reg(ap, 0x13 + adj, tmp8 | 0x03);
-
-		PDPRINTK("Turn on prefetch\n");
-	}
-
-	printk(KERN_INFO DRV_NAME ": Set to pio mode[%u] \n", pio);
+	PDPRINTK("Set to pio mode[%u] \n", pio);
 }
 /**
  *	pdc2027x_set_dmamode - Initialize host controller PATA UDMA timings
@@ -359,7 +348,7 @@
 		pdc_set_indexed_reg(ap, 0x12 + adj, pdc2027x_udma_timing_tbl[udma_mode].value2);
 		PDPRINTK("Set udma regs done\n");
 		
-		printk(KERN_INFO DRV_NAME ": Set to udma mode[%u] \n", udma_mode);
+		PDPRINTK("Set to udma mode[%u] \n", udma_mode);
 
 	} else  if((dma_mode >= XFER_MW_DMA_0) && 
 		   (dma_mode <= XFER_MW_DMA_2)) {
@@ -371,11 +360,70 @@
 		pdc_set_indexed_reg(ap, 0x0f + adj, pdc2027x_mdma_timing_tbl[mdma_mode].value1);
 		PDPRINTK("Set mdma regs done\n");
 		
-		printk(KERN_INFO DRV_NAME ": Set to mdma mode[%u] \n", mdma_mode);
+		PDPRINTK("Set to mdma mode[%u] \n", mdma_mode);
 	} else {
 		printk(KERN_ERR DRV_NAME ": Unknown dma mode [%u] ignored\n", dma_mode);
 	}
 }
+
+/**
+ *	pdc2027x_post_set_mode - Set the timing registers back to correct values.
+ *	@ap: Port to configure
+ *	
+ *	The pdc2027x hardware will look at "SET FEATURES" and change the timing registers 
+ *	automatically. The values set by the hardware might be incorrect, under 133Mhz PLL.
+ *	This function overwrites the possibly incorrect values set by the hardware to be correct.
+ */
+static void pdc2027x_post_set_mode(struct ata_port *ap)
+{
+	int i;
+
+	for (i = 0; i < ATA_MAX_DEVICES; i++) {
+		struct ata_device *dev = &ap->device[i];
+
+		if (ata_dev_present(dev)) {
+			u8 adj = (i % 2) ? 0x08 : 0x00;
+			u8 tmp8;
+			
+			pdc2027x_set_piomode(ap, dev);
+
+			/*
+			 * Enable prefetch if the device support PIO only.
+			 */
+			if (dev->xfer_shift == ATA_SHIFT_PIO) { 
+				tmp8 = pdc_get_indexed_reg(ap, 0x13 + adj);
+				pdc_set_indexed_reg(ap, 0x13 + adj, tmp8 | 0x02);
+				
+				PDPRINTK("Turn on prefetch\n");
+			} else {
+				pdc2027x_set_dmamode(ap, dev);
+			}
+		}
+	}
+}
+
+/**
+ *	pdc2027x_check_atapi_dma - Check whether ATAPI DMA can be supported for this command
+ *	@qc: Metadata associated with taskfile to check
+ *
+ *	LOCKING:
+ *	None (inherited from caller).
+ *
+ *	RETURNS: 0 when ATAPI DMA can be used
+ *		 1 otherwise
+ */
+static int pdc2027x_check_atapi_dma(struct ata_queued_cmd *qc)
+{
+	struct scsi_cmnd *cmd = qc->scsicmd;
+	int rc = 0;
+
+	/* pdc2027x can only do ATAPI DMA for specific buffer size */
+	if (cmd->request_bufflen % 256)
+		rc = 1;
+
+	return rc;
+}
+
 /**
  * adjust_pll - Adjust the PLL input clock in Hz.
  *

             reply	other threads:[~2005-01-21 13:30 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-01-21 13:30 Albert Lee [this message]
2005-01-27 22:23 ` [PATCH] libata-dev-2.6 -- pdc2027x timing register bug fix Jeff Garzik

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='005e01c4ffbd$55c9b200$6401a8c0@tw.ibm.com' \
    --to=albertcc@tw.ibm.com \
    --cc=dwm@maxeymade.com \
    --cc=jgarzik@pobox.com \
    --cc=linux-ide@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).