From nobody@FreeBSD.org  Mon Jul 17 08:41:46 2006
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id D29FB16A4DD
	for <freebsd-gnats-submit@FreeBSD.org>; Mon, 17 Jul 2006 08:41:46 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [216.136.204.117])
	by mx1.FreeBSD.org (Postfix) with ESMTP id 84E5E43D46
	for <freebsd-gnats-submit@FreeBSD.org>; Mon, 17 Jul 2006 08:41:46 +0000 (GMT)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.13.1/8.13.1) with ESMTP id k6H8fklH075645
	for <freebsd-gnats-submit@FreeBSD.org>; Mon, 17 Jul 2006 08:41:46 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.13.1/8.13.1/Submit) id k6H8fkd3075644;
	Mon, 17 Jul 2006 08:41:46 GMT
	(envelope-from nobody)
Message-Id: <200607170841.k6H8fkd3075644@www.freebsd.org>
Date: Mon, 17 Jul 2006 08:41:46 GMT
From: Karsten Brandt <spam_schlucker@web.de>
To: freebsd-gnats-submit@FreeBSD.org
Subject: no WDMA mode available for ATAPI drives
X-Send-Pr-Version: www-2.3

>Number:         100428
>Category:       kern
>Synopsis:       [ata] [patch] no WDMA mode available for ATAPI drives
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    sos
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Jul 17 08:50:17 GMT 2006
>Closed-Date:    Wed Sep 13 09:07:55 GMT 2006
>Last-Modified:  Wed Sep 13 09:07:55 GMT 2006
>Originator:     Karsten Brandt
>Release:        FreeBSD 6.1-STABLE
>Organization:
>Environment:
FreeBSD Pegasus.mai.de.internal 6.1-STABLE FreeBSD 6.1-STABLE #67: Mon Jul 17 07:43:10 UTC 2006     root@Pegasus.mai.de.internal:/usr/obj/usr/src/sys/PEGASUS  i386
>Description:
I've tested video playback with vlc and ogle on my machine.
But all what I could see was a spluttered video output.
Therefore I've searched the reason for that.
After some hours I've found the reason in the ATA source.

For ATAPI devices is the WDMA mode unused. After this correction the video
playback runs without spluttering.

Now I've created a patch for this problem and I'v added this to the Fix section.

This patch is build for the following file in the source tree:

/usr/src/dev/ata/ata-all.c

The __FBSDID of the original source file is:

__FBSDID("$FreeBSD: src/sys/dev/ata/ata-all.c,v 1.252.2.9 2006/04/04 16:07:42 sos Exp $"); 

The changes are:
----------------

- use of WDMA-Modes for ATAPI-Devices in the ata_getparam() function
- remove magic numbers in the ata_getparam() function

>How-To-Repeat:
Play video DVD's on an ATAPI drive, which only have WDMA support.
>Fix:
*** /usr/src_org/sys/dev/ata/ata-all.c	Fri Jul 14 08:30:53 2006
--- /usr/src/sys/dev/ata/ata-all.c	Mon Jul 17 06:53:06 2006
***************
*** 640,655 ****
  	    sprintf(buffer, "%.40s/%.8s", atacap->model, atacap->revision);
  	    device_set_desc_copy(atadev->dev, buffer);
  	    if (atadev->param.config & ATA_PROTO_ATAPI) {
! 		if (atapi_dma && ch->dma &&
! 		    (atadev->param.config & ATA_DRQ_MASK) != ATA_DRQ_INTR &&
! 		    ata_umode(&atadev->param) >= ATA_UDMA2)
! 		    atadev->mode = ATA_DMA_MAX;
  	    }
  	    else {
  		if (ata_dma && ch->dma &&
! 		    (ata_umode(&atadev->param) > 0 ||
! 		     ata_wmode(&atadev->param) > 0))
  		    atadev->mode = ATA_DMA_MAX;
  	    }
  	}
      }
--- 640,661 ----
  	    sprintf(buffer, "%.40s/%.8s", atacap->model, atacap->revision);
  	    device_set_desc_copy(atadev->dev, buffer);
  	    if (atadev->param.config & ATA_PROTO_ATAPI) {
! 		if( atapi_dma && ch->dma && (atadev->param.config & ATA_DRQ_MASK) != ATA_DRQ_INTR ){
! 		    if( ( ata_umode(&atadev->param) < ATA_UDMA0 &&
! 			  ata_wmode(&atadev->param) >= ATA_WDMA0 ) ||
! 			( ata_umode(&atadev->param) >= ATA_UDMA2 ) )
! 		    {
! 		    	atadev->mode = ATA_DMA_MAX;
! 		    }
! 		}
  	    }
  	    else {
  		if (ata_dma && ch->dma &&
! 		    (ata_umode(&atadev->param) >= ATA_UDMA0 ||
! 		     ata_wmode(&atadev->param) >= ATA_WDMA0))
! 		{
  		    atadev->mode = ATA_DMA_MAX;
+ 		}
  	    }
  	}
      }

>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->sos 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Mon Jul 17 08:52:29 UTC 2006 
Responsible-Changed-Why:  
Over to maintainer. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=100428 

From: Jung-uk Kim <jkim@FreeBSD.org>
To: bug-followup@FreeBSD.org, spam_schlucker@web.de
Cc:  
Subject: Re: kern/100428: [ata] [patch] no WDMA mode available for ATAPI drives
Date: Wed, 6 Sep 2006 19:51:53 -0400

 --Boundary-00=_e81/E7OXYtYD3YB
 Content-Type: text/plain;
   charset="iso-8859-1"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: inline
 
 I have had the same issue with CompactFlash disks, which usually does 
 not support UDMA but does WDMA.  In fact, it is a serious issue with 
 small embedded systems.  I know we can use atacontrol(8) to set it 
 manually but it is very inconvenient if you have large scale 
 deployment.
 Here's my version of the patch.  Please note that I didn't remove the 
 'magic number' because it is actually correct, i.e., ata_umode() and 
 ata_wmode() return -1 when supported mode is not found.  I believe 
 turning on WDMA for ATAPI devices by default is okay because 
 multiword DMA support is mandatory for ATAPI devices, AFAIK.
 Of course, I know there are broken ATA controllers, e.g., some (all?) 
 Intel ICHs have broken MWDMA mode 1 support but these must be handled 
 by chipset-specific code, I believe.  I have no idea why UDMA0 and 
 UDMA1 are not enabled by default though but I am sure sos@ has his 
 reasons. ;-)
 
 Thanks,
 
 Jung-uk Kim
 
 --Boundary-00=_e81/E7OXYtYD3YB
 Content-Type: text/x-diff;
   charset="iso-8859-1";
   name="ata-all.diff"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: attachment;
 	filename="ata-all.diff"
 
 Index: ata-all.c
 ===================================================================
 RCS file: /home/ncvs/src/sys/dev/ata/ata-all.c,v
 retrieving revision 1.273
 diff -u -r1.273 ata-all.c
 --- ata-all.c	12 May 2006 05:04:40 -0000	1.273
 +++ ata-all.c	6 Sep 2006 23:19:05 -0000
 @@ -570,6 +570,7 @@
      struct ata_request *request;
      u_int8_t command = 0;
      int error = ENOMEM, retries = 2;
 +    int umode, wmode;
  
      if (ch->devices &
  	(atadev->unit == ATA_MASTER ? ATA_ATA_MASTER : ATA_ATA_SLAVE))
 @@ -636,17 +637,19 @@
  	if (init) {
  	    sprintf(buffer, "%.40s/%.8s", atacap->model, atacap->revision);
  	    device_set_desc_copy(atadev->dev, buffer);
 -	    if (atadev->param.config & ATA_PROTO_ATAPI) {
 -		if (atapi_dma && ch->dma &&
 -		    (atadev->param.config & ATA_DRQ_MASK) != ATA_DRQ_INTR &&
 -		    ata_umode(&atadev->param) >= ATA_UDMA2)
 -		    atadev->mode = ATA_DMA_MAX;
 -	    }
 -	    else {
 -		if (ata_dma && ch->dma &&
 -		    (ata_umode(&atadev->param) > 0 ||
 -		     ata_wmode(&atadev->param) > 0))
 +	    umode = ata_umode(&atadev->param);
 +	    wmode = ata_wmode(&atadev->param);
 +	    if (ch->dma && (umode > 0 || wmode > 0)) {
 +	        if (atadev->param.config & ATA_PROTO_ATAPI) {
 +		    if (atapi_dma &&
 +			(atadev->param.config & ATA_DRQ_MASK) != ATA_DRQ_INTR &&
 +			(umode < 0 || umode >= ATA_UDMA2)) {
 +		    	atadev->mode = ATA_DMA_MAX;
 +		    }
 +		}
 +		else if (ata_dma) {
  		    atadev->mode = ATA_DMA_MAX;
 +		}
  	    }
  	}
      }
 
 --Boundary-00=_e81/E7OXYtYD3YB--

From: Jung-uk Kim <jkim@FreeBSD.org>
To: bug-followup@FreeBSD.org
Cc: spam_schlucker@web.de
Subject: Re: kern/100428: [ata] [patch] no WDMA mode available for ATAPI drives
Date: Wed, 6 Sep 2006 21:26:56 -0400

 --Boundary-00=_kV3/Ec9/OXlJfgJ
 Content-Type: text/plain;
   charset="iso-8859-1"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: inline
 
 I believe the attached patch is more closer to sos's coding style. :-)
 
 Jung-uk Kim
 
 --Boundary-00=_kV3/Ec9/OXlJfgJ
 Content-Type: text/x-diff;
   charset="iso-8859-1";
   name="ata-all.diff"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: attachment;
 	filename="ata-all.diff"
 
 Index: ata-all.c
 ===================================================================
 RCS file: /home/ncvs/src/sys/dev/ata/ata-all.c,v
 retrieving revision 1.273
 diff -u -r1.273 ata-all.c
 --- ata-all.c	12 May 2006 05:04:40 -0000	1.273
 +++ ata-all.c	7 Sep 2006 01:18:45 -0000
 @@ -570,6 +570,7 @@
      struct ata_request *request;
      u_int8_t command = 0;
      int error = ENOMEM, retries = 2;
 +    int umode = -1, wmode = -1;
  
      if (ch->devices &
  	(atadev->unit == ATA_MASTER ? ATA_ATA_MASTER : ATA_ATA_SLAVE))
 @@ -636,17 +637,21 @@
  	if (init) {
  	    sprintf(buffer, "%.40s/%.8s", atacap->model, atacap->revision);
  	    device_set_desc_copy(atadev->dev, buffer);
 -	    if (atadev->param.config & ATA_PROTO_ATAPI) {
 -		if (atapi_dma && ch->dma &&
 -		    (atadev->param.config & ATA_DRQ_MASK) != ATA_DRQ_INTR &&
 -		    ata_umode(&atadev->param) >= ATA_UDMA2)
 -		    atadev->mode = ATA_DMA_MAX;
 +	    if (ch->dma) {
 +		umode = ata_umode(&atadev->param);
 +		wmode = ata_wmode(&atadev->param);
  	    }
 -	    else {
 -		if (ata_dma && ch->dma &&
 -		    (ata_umode(&atadev->param) > 0 ||
 -		     ata_wmode(&atadev->param) > 0))
 -		    atadev->mode = ATA_DMA_MAX;
 +	    if (umode > 0 || wmode > 0) {
 +	        if (atadev->param.config & ATA_PROTO_ATAPI) {
 +		    if (atapi_dma &&
 +			(atadev->param.config & ATA_DRQ_MASK) != ATA_DRQ_INTR &&
 +			(umode < 0 || umode >= ATA_UDMA2))
 +		    	atadev->mode = ATA_DMA_MAX;
 +		}
 +		else {
 +		    if (ata_dma)
 +			atadev->mode = ATA_DMA_MAX;
 +		}
  	    }
  	}
      }
 
 --Boundary-00=_kV3/Ec9/OXlJfgJ--

From: * <spam_schlucker@web.de>
To: bug-followup@FreeBSD.org
Cc: jkim@FreeBSD.org
Subject: Re: kern/100428: [ata] [patch] no WDMA mode available for ATAPI drives
Date: Sat, 09 Sep 2006 22:57:24 +0200

 Hello Jung-uk Kim,
 Hello Sren Schmidt,
 
 I like symbols more than magic numbers, because the code is more readable.
 But this is only my coding style and we can ignore this.
 Because this isn't a performance issue, we can reduce the needed changes 
 to 1 line.
 See the following patch.
 
 Thank's
 
 Karsten Brandt
 
 --- src/sys/dev/ata/ata-all.c    Fri Sep  8 22:34:14 2006
 +++ src_contrib/sys/dev/ata/ata-all.c    Fri Sep  8 23:17:49 2006
 @@ -642,7 +642,8 @@
          if (atadev->param.config & ATA_PROTO_ATAPI) {
          if (atapi_dma && ch->dma &&
              (atadev->param.config & ATA_DRQ_MASK) != ATA_DRQ_INTR &&
 -            ata_umode(&atadev->param) >= ATA_UDMA2)
 +             ((ata_umode(&atadev->param) < ATA_UDMA0 && 
 ata_wmode(&atadev->param) >= ATA_WDMA0 ) ||
 +              ata_umode(&atadev->param) >= ATA_UDMA2))
              atadev->mode = ATA_DMA_MAX;
          }
          else {
 

From: Jung-uk Kim <jkim@FreeBSD.org>
To: spam_schlucker@web.de
Cc: bug-followup@FreeBSD.org
Subject: Re: kern/100428: [ata] [patch] no WDMA mode available for ATAPI drives
Date: Mon, 11 Sep 2006 15:14:51 -0400

 I had very long discussion with sos@.  He said the issue was discussed 
 many times already and it was decided for the best.  He also said 
 ATAPI CD-ROM drive with WDMA2 is most problematic.  It was even 
 documented in ata(4):
 
 http://www.freebsd.org/cgi/man.cgi?query=ata&manpath=FreeBSD+6.1-RELEASE&format=html
 
 'Unknown ATAPI devices are initialized to DMA mode if the 
 hw.ata.atapi_dma tunable is set to 1 and they support at least UDMA33 
 transfers. Otherwise they are set to PIO mode because severe DMA 
 problems are common even if the device capabilities indicate support. 
 You can always try to set DMA mode on an ATAPI device using 
 atacontrol(8), but be aware that your hardware might not support it 
 and can potentially hang the entire system causing data loss.'
 
 Please close this PR because it was design choice, not a bug.
 
 Thanks!
 
 Jung-uk Kim
State-Changed-From-To: open->closed 
State-Changed-By: linimon 
State-Changed-When: Wed Sep 13 09:07:23 UTC 2006 
State-Changed-Why:  
Closed per misfiled followup, now included in this PR. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=100428 
>Unformatted:
