From nobody@FreeBSD.org  Thu Jun 19 06:10:29 2008
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 19707106564A
	for <freebsd-gnats-submit@FreeBSD.org>; Thu, 19 Jun 2008 06:10:29 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21])
	by mx1.freebsd.org (Postfix) with ESMTP id 118738FC20
	for <freebsd-gnats-submit@FreeBSD.org>; Thu, 19 Jun 2008 06:10:29 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.14.2/8.14.2) with ESMTP id m5J6ASdj009049
	for <freebsd-gnats-submit@FreeBSD.org>; Thu, 19 Jun 2008 06:10:28 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.14.2/8.14.1/Submit) id m5J6AScn009048;
	Thu, 19 Jun 2008 06:10:28 GMT
	(envelope-from nobody)
Message-Id: <200806190610.m5J6AScn009048@www.freebsd.org>
Date: Thu, 19 Jun 2008 06:10:28 GMT
From: Yuri Skripachov <y.skripachov@gmail.com>
To: freebsd-gnats-submit@FreeBSD.org
Subject: incorrect _BST result validation for Tosh Satellite P20
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         124744
>Category:       kern
>Synopsis:       [acpi] [patch] incorrect _BST result validation for Tosh Satellite P20
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    avg
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Jun 19 06:20:02 UTC 2008
>Closed-Date:    Fri Mar 11 18:03:39 UTC 2011
>Last-Modified:  Fri Mar 11 18:03:39 UTC 2011
>Originator:     Yuri Skripachov
>Release:        FreeBSD 7.0-STABLE
>Organization:
>Environment:
FreeBSD satellite.local 7.0-STABLE FreeBSD 7.0-STABLE #0: Wed Jun 18 13:50:25 MSD 2008  yvs@satellite.local:/usr/local/obj/usr/src/sys/SATELLITE i386
>Description:
"acpiconf -i 0" command does not show battery presence if notebook is AC
powered. that is because of extra bits used in _BST state by toshiba.
according to acpi specs the only wrong _BST state is (ACPI_BATT_STAT_CHARGING
| ACPI_BATT_STAT_DISCHARG). it seems that other bits in _BST have to be
ignored and arithmetic comparison is a wrong way to validate _BST state.
at least for my satellite :( i have been using this patch for 5.x, 6.x
and 7.0-stable.
>How-To-Repeat:
plug in AC adapter and type acpiconf -i 0.
>Fix:
patch for /usr/src/sys/dev/acpica/acpi_battery.c is attached.

Patch attached with submission follows:

--- acpi_battery.c.orig	2008-06-19 09:35:41.000000000 +0400
+++ acpi_battery.c	2008-06-19 09:36:05.000000000 +0400
@@ -101,8 +101,10 @@
 int
 acpi_battery_bst_valid(struct acpi_bst *bst)
 {
-    return (bst->state < ACPI_BATT_STAT_MAX && bst->cap != ACPI_BATT_UNKNOWN &&
-	bst->volt != ACPI_BATT_UNKNOWN);
+#define ACPI_BATT_STAT_IMPOSSIBLE (ACPI_BATT_STAT_CHARGING | ACPI_BATT_STAT_DISCHARG)
+    return ((bst->state & ACPI_BATT_STAT_IMPOSSIBLE) != ACPI_BATT_STAT_IMPOSSIBLE &&
+        bst->cap != ACPI_BATT_UNKNOWN && bst->volt != ACPI_BATT_UNKNOWN);
+#undef ACPI_BATT_STAT_IMPOSSIBLE
 }
 
 /* Check _BIF results for validity. */


>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->freebsd-acpi 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Thu Jun 19 21:05:29 UTC 2008 
Responsible-Changed-Why:  
Over to maintainer(s). 

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

From: Andriy Gapon <avg@freebsd.org>
To: bug-followup@freebsd.org, y.skripachov@gmail.com
Cc:  
Subject: Re: kern/124744: [acpi] [patch] incorrect _BST result validation
 for Tosh Satellite P20
Date: Sun, 05 Dec 2010 17:20:53 +0200

 Is this still an issue?
 If yes, I will try to review and commit your patch.
 Thanks!
 -- 
 Andriy Gapon
Responsible-Changed-From-To: freebsd-acpi->avg 
Responsible-Changed-By: avg 
Responsible-Changed-When: Tue Dec 14 18:34:21 UTC 2010 
Responsible-Changed-Why:  
I am taking a closer look at this report. 

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

From: Andriy Gapon <avg@icyb.net.ua>
To: bug-followup@FreeBSD.org, y.skripachov@gmail.com, freebsd-acpi@FreeBSD.org
Cc:  
Subject: Re: kern/124744: [acpi] [patch] incorrect _BST result validation
 for Tosh Satellite P20
Date: Thu, 16 Dec 2010 20:05:26 +0200

 I think that the patch is good and I have slightly extended it:
 http://people.freebsd.org/~avg/acpi-bat.diff
 
 Part of the problem is that the same definitions are used for interpreting status
 returned by _BST and for maintaining internal driver status.
 I have added a comment that explains this duality, retired now unused
 ACPI_BATT_STAT_MAX, added code for cleaning extended/undefined bits in _BST status
 and added a warning about charging+discharging bits being set at the same time.
 
 I'd appreciate reviews and testing.
 Thanks!
 
 -- 
 Andriy Gapon
State-Changed-From-To: open->patched 
State-Changed-By: avg 
State-Changed-When: Fri Dec 17 16:25:44 UTC 2010 
State-Changed-Why:  
The workaround is committed to head. 

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

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/124744: commit references a PR
Date: Fri, 17 Dec 2010 16:21:38 +0000 (UTC)

 Author: avg
 Date: Fri Dec 17 16:21:30 2010
 New Revision: 216503
 URL: http://svn.freebsd.org/changeset/base/216503
 
 Log:
   small cleanup of acpi battery status setting and checking
   
   This is based on the patch submitted by Yuri Skripachov.
   Overview of the changes:
   - clarify double-use of some ACPI_BATT_STAT_* definitions
   - clean up undefined/extended status bits returned by _BST
   - warn about charging+discharging bits being set at the same time
   
   PR:		kern/124744
   Submitted by:	Yuri Skripachov <y.skripachov@gmail.com>
   Tested by:	Yuri Skripachov <y.skripachov@gmail.com>
   MFC after:	2 weeks
 
 Modified:
   head/sys/dev/acpica/acpi_battery.c
   head/sys/dev/acpica/acpi_cmbat.c
   head/sys/dev/acpica/acpi_smbat.c
   head/sys/dev/acpica/acpiio.h
 
 Modified: head/sys/dev/acpica/acpi_battery.c
 ==============================================================================
 --- head/sys/dev/acpica/acpi_battery.c	Fri Dec 17 15:39:55 2010	(r216502)
 +++ head/sys/dev/acpica/acpi_battery.c	Fri Dec 17 16:21:30 2010	(r216503)
 @@ -102,8 +102,9 @@ acpi_battery_get_info_expire(void)
  int
  acpi_battery_bst_valid(struct acpi_bst *bst)
  {
 -    return (bst->state < ACPI_BATT_STAT_MAX && bst->cap != ACPI_BATT_UNKNOWN &&
 -	bst->volt != ACPI_BATT_UNKNOWN);
 +
 +    return (bst->state != ACPI_BATT_STAT_NOT_PRESENT &&
 +	bst->cap != ACPI_BATT_UNKNOWN && bst->volt != ACPI_BATT_UNKNOWN);
  }
  
  /* Check _BIF results for validity. */
 
 Modified: head/sys/dev/acpica/acpi_cmbat.c
 ==============================================================================
 --- head/sys/dev/acpica/acpi_cmbat.c	Fri Dec 17 15:39:55 2010	(r216502)
 +++ head/sys/dev/acpica/acpi_cmbat.c	Fri Dec 17 16:21:30 2010	(r216503)
 @@ -279,6 +279,12 @@ acpi_cmbat_get_bst(void *arg)
  	goto end;
      acpi_cmbat_info_updated(&sc->bst_lastupdated);
  
 +    /* Clear out undefined/extended bits that might be set by hardware. */
 +    sc->bst.state &= ACPI_BATT_STAT_BST_MASK;
 +    if ((sc->bst.state & ACPI_BATT_STAT_INVALID) == ACPI_BATT_STAT_INVALID)
 +	ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
 +	    "battery reports simultaneous charging and discharging\n");
 +
      /* XXX If all batteries are critical, perhaps we should suspend. */
      if (sc->bst.state & ACPI_BATT_STAT_CRITICAL) {
      	if ((sc->flags & ACPI_BATT_STAT_CRITICAL) == 0) {
 
 Modified: head/sys/dev/acpica/acpi_smbat.c
 ==============================================================================
 --- head/sys/dev/acpica/acpi_smbat.c	Fri Dec 17 15:39:55 2010	(r216502)
 +++ head/sys/dev/acpica/acpi_smbat.c	Fri Dec 17 16:21:30 2010	(r216503)
 @@ -390,6 +390,7 @@ acpi_smbat_get_bst(device_t dev, struct 
  
  	if (val > 0) {
  		sc->bst.rate = val * factor;
 +		sc->bst.state &= ~SMBATT_BS_DISCHARGING;
  		sc->bst.state |= ACPI_BATT_STAT_CHARGING;
  	} else if (val < 0)
  		sc->bst.rate = (-val) * factor;
 
 Modified: head/sys/dev/acpica/acpiio.h
 ==============================================================================
 --- head/sys/dev/acpica/acpiio.h	Fri Dec 17 15:39:55 2010	(r216502)
 +++ head/sys/dev/acpica/acpiio.h	Fri Dec 17 16:21:30 2010	(r216503)
 @@ -74,11 +74,22 @@ struct acpi_bst {
      uint32_t volt;			/* Present Voltage */
  };
  
 +/*
 + * Note that the following definitions represent status bits for internal
 + * driver state.  The first three of them (charging, discharging and critical)
 + * conveninetly conform to ACPI specification of status returned by _BST
 + * method.  Other definitions (not present, etc) are synthetic.
 + * Also note that according to the specification the charging and discharging
 + * status bits must not be set at the same time.
 + */
  #define ACPI_BATT_STAT_DISCHARG		0x0001
  #define ACPI_BATT_STAT_CHARGING		0x0002
  #define ACPI_BATT_STAT_CRITICAL		0x0004
 -#define ACPI_BATT_STAT_NOT_PRESENT	0x0007
 -#define ACPI_BATT_STAT_MAX		0x0007
 +#define ACPI_BATT_STAT_INVALID					\
 +    (ACPI_BATT_STAT_DISCHARG | ACPI_BATT_STAT_CHARGING)
 +#define ACPI_BATT_STAT_BST_MASK					\
 +    (ACPI_BATT_STAT_INVALID | ACPI_BATT_STAT_CRITICAL)
 +#define ACPI_BATT_STAT_NOT_PRESENT	ACPI_BATT_STAT_BST_MASK
  
  union acpi_battery_ioctl_arg {
      int			 unit;	/* Device unit or ACPI_BATTERY_ALL_UNITS. */
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/124744: commit references a PR
Date: Fri, 11 Mar 2011 16:43:59 +0000 (UTC)

 Author: avg
 Date: Fri Mar 11 16:43:39 2011
 New Revision: 219507
 URL: http://svn.freebsd.org/changeset/base/219507
 
 Log:
   MFC r216503: small cleanup of acpi battery status setting and checking
   
   PR:		kern/124744
 
 Modified:
   stable/8/sys/dev/acpica/acpi_battery.c
   stable/8/sys/dev/acpica/acpi_cmbat.c
   stable/8/sys/dev/acpica/acpi_smbat.c
   stable/8/sys/dev/acpica/acpiio.h
 Directory Properties:
   stable/8/sys/   (props changed)
   stable/8/sys/amd64/include/xen/   (props changed)
   stable/8/sys/cddl/contrib/opensolaris/   (props changed)
   stable/8/sys/contrib/dev/acpica/   (props changed)
   stable/8/sys/contrib/pf/   (props changed)
 
 Modified: stable/8/sys/dev/acpica/acpi_battery.c
 ==============================================================================
 --- stable/8/sys/dev/acpica/acpi_battery.c	Fri Mar 11 16:30:30 2011	(r219506)
 +++ stable/8/sys/dev/acpica/acpi_battery.c	Fri Mar 11 16:43:39 2011	(r219507)
 @@ -102,8 +102,9 @@ acpi_battery_get_info_expire(void)
  int
  acpi_battery_bst_valid(struct acpi_bst *bst)
  {
 -    return (bst->state < ACPI_BATT_STAT_MAX && bst->cap != ACPI_BATT_UNKNOWN &&
 -	bst->volt != ACPI_BATT_UNKNOWN);
 +
 +    return (bst->state != ACPI_BATT_STAT_NOT_PRESENT &&
 +	bst->cap != ACPI_BATT_UNKNOWN && bst->volt != ACPI_BATT_UNKNOWN);
  }
  
  /* Check _BIF results for validity. */
 
 Modified: stable/8/sys/dev/acpica/acpi_cmbat.c
 ==============================================================================
 --- stable/8/sys/dev/acpica/acpi_cmbat.c	Fri Mar 11 16:30:30 2011	(r219506)
 +++ stable/8/sys/dev/acpica/acpi_cmbat.c	Fri Mar 11 16:43:39 2011	(r219507)
 @@ -279,6 +279,12 @@ acpi_cmbat_get_bst(void *arg)
  	goto end;
      acpi_cmbat_info_updated(&sc->bst_lastupdated);
  
 +    /* Clear out undefined/extended bits that might be set by hardware. */
 +    sc->bst.state &= ACPI_BATT_STAT_BST_MASK;
 +    if ((sc->bst.state & ACPI_BATT_STAT_INVALID) == ACPI_BATT_STAT_INVALID)
 +	ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
 +	    "battery reports simultaneous charging and discharging\n");
 +
      /* XXX If all batteries are critical, perhaps we should suspend. */
      if (sc->bst.state & ACPI_BATT_STAT_CRITICAL) {
      	if ((sc->flags & ACPI_BATT_STAT_CRITICAL) == 0) {
 
 Modified: stable/8/sys/dev/acpica/acpi_smbat.c
 ==============================================================================
 --- stable/8/sys/dev/acpica/acpi_smbat.c	Fri Mar 11 16:30:30 2011	(r219506)
 +++ stable/8/sys/dev/acpica/acpi_smbat.c	Fri Mar 11 16:43:39 2011	(r219507)
 @@ -390,6 +390,7 @@ acpi_smbat_get_bst(device_t dev, struct 
  
  	if (val > 0) {
  		sc->bst.rate = val * factor;
 +		sc->bst.state &= ~SMBATT_BS_DISCHARGING;
  		sc->bst.state |= ACPI_BATT_STAT_CHARGING;
  	} else if (val < 0)
  		sc->bst.rate = (-val) * factor;
 
 Modified: stable/8/sys/dev/acpica/acpiio.h
 ==============================================================================
 --- stable/8/sys/dev/acpica/acpiio.h	Fri Mar 11 16:30:30 2011	(r219506)
 +++ stable/8/sys/dev/acpica/acpiio.h	Fri Mar 11 16:43:39 2011	(r219507)
 @@ -74,11 +74,22 @@ struct acpi_bst {
      uint32_t volt;			/* Present Voltage */
  };
  
 +/*
 + * Note that the following definitions represent status bits for internal
 + * driver state.  The first three of them (charging, discharging and critical)
 + * conveninetly conform to ACPI specification of status returned by _BST
 + * method.  Other definitions (not present, etc) are synthetic.
 + * Also note that according to the specification the charging and discharging
 + * status bits must not be set at the same time.
 + */
  #define ACPI_BATT_STAT_DISCHARG		0x0001
  #define ACPI_BATT_STAT_CHARGING		0x0002
  #define ACPI_BATT_STAT_CRITICAL		0x0004
 -#define ACPI_BATT_STAT_NOT_PRESENT	0x0007
 -#define ACPI_BATT_STAT_MAX		0x0007
 +#define ACPI_BATT_STAT_INVALID					\
 +    (ACPI_BATT_STAT_DISCHARG | ACPI_BATT_STAT_CHARGING)
 +#define ACPI_BATT_STAT_BST_MASK					\
 +    (ACPI_BATT_STAT_INVALID | ACPI_BATT_STAT_CRITICAL)
 +#define ACPI_BATT_STAT_NOT_PRESENT	ACPI_BATT_STAT_BST_MASK
  
  union acpi_battery_ioctl_arg {
      int			 unit;	/* Device unit or ACPI_BATTERY_ALL_UNITS. */
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/124744: commit references a PR
Date: Fri, 11 Mar 2011 17:12:54 +0000 (UTC)

 Author: avg
 Date: Fri Mar 11 17:12:39 2011
 New Revision: 219510
 URL: http://svn.freebsd.org/changeset/base/219510
 
 Log:
   MFC r216503: small cleanup of acpi battery status setting and checking
   
   PR:		kern/124744
 
 Modified:
   stable/7/sys/dev/acpica/acpi_battery.c
   stable/7/sys/dev/acpica/acpi_cmbat.c
   stable/7/sys/dev/acpica/acpi_smbat.c
   stable/7/sys/dev/acpica/acpiio.h
 Directory Properties:
   stable/7/sys/   (props changed)
   stable/7/sys/cddl/contrib/opensolaris/   (props changed)
   stable/7/sys/contrib/dev/acpica/   (props changed)
   stable/7/sys/contrib/pf/   (props changed)
 
 Modified: stable/7/sys/dev/acpica/acpi_battery.c
 ==============================================================================
 --- stable/7/sys/dev/acpica/acpi_battery.c	Fri Mar 11 17:01:14 2011	(r219509)
 +++ stable/7/sys/dev/acpica/acpi_battery.c	Fri Mar 11 17:12:39 2011	(r219510)
 @@ -101,8 +101,9 @@ acpi_battery_get_info_expire(void)
  int
  acpi_battery_bst_valid(struct acpi_bst *bst)
  {
 -    return (bst->state < ACPI_BATT_STAT_MAX && bst->cap != ACPI_BATT_UNKNOWN &&
 -	bst->volt != ACPI_BATT_UNKNOWN);
 +
 +    return (bst->state != ACPI_BATT_STAT_NOT_PRESENT &&
 +	bst->cap != ACPI_BATT_UNKNOWN && bst->volt != ACPI_BATT_UNKNOWN);
  }
  
  /* Check _BIF results for validity. */
 
 Modified: stable/7/sys/dev/acpica/acpi_cmbat.c
 ==============================================================================
 --- stable/7/sys/dev/acpica/acpi_cmbat.c	Fri Mar 11 17:01:14 2011	(r219509)
 +++ stable/7/sys/dev/acpica/acpi_cmbat.c	Fri Mar 11 17:12:39 2011	(r219510)
 @@ -278,6 +278,12 @@ acpi_cmbat_get_bst(void *arg)
  	goto end;
      acpi_cmbat_info_updated(&sc->bst_lastupdated);
  
 +    /* Clear out undefined/extended bits that might be set by hardware. */
 +    sc->bst.state &= ACPI_BATT_STAT_BST_MASK;
 +    if ((sc->bst.state & ACPI_BATT_STAT_INVALID) == ACPI_BATT_STAT_INVALID)
 +	ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev),
 +	    "battery reports simultaneous charging and discharging\n");
 +
      /* XXX If all batteries are critical, perhaps we should suspend. */
      if (sc->bst.state & ACPI_BATT_STAT_CRITICAL) {
      	if ((sc->flags & ACPI_BATT_STAT_CRITICAL) == 0) {
 
 Modified: stable/7/sys/dev/acpica/acpi_smbat.c
 ==============================================================================
 --- stable/7/sys/dev/acpica/acpi_smbat.c	Fri Mar 11 17:01:14 2011	(r219509)
 +++ stable/7/sys/dev/acpica/acpi_smbat.c	Fri Mar 11 17:12:39 2011	(r219510)
 @@ -389,6 +389,7 @@ acpi_smbat_get_bst(device_t dev, struct 
  
  	if (val > 0) {
  		sc->bst.rate = val * factor;
 +		sc->bst.state &= ~SMBATT_BS_DISCHARGING;
  		sc->bst.state |= ACPI_BATT_STAT_CHARGING;
  	} else if (val < 0)
  		sc->bst.rate = (-val) * factor;
 
 Modified: stable/7/sys/dev/acpica/acpiio.h
 ==============================================================================
 --- stable/7/sys/dev/acpica/acpiio.h	Fri Mar 11 17:01:14 2011	(r219509)
 +++ stable/7/sys/dev/acpica/acpiio.h	Fri Mar 11 17:12:39 2011	(r219510)
 @@ -74,11 +74,22 @@ struct acpi_bst {
      uint32_t volt;			/* Present Voltage */
  };
  
 +/*
 + * Note that the following definitions represent status bits for internal
 + * driver state.  The first three of them (charging, discharging and critical)
 + * conveninetly conform to ACPI specification of status returned by _BST
 + * method.  Other definitions (not present, etc) are synthetic.
 + * Also note that according to the specification the charging and discharging
 + * status bits must not be set at the same time.
 + */
  #define ACPI_BATT_STAT_DISCHARG		0x0001
  #define ACPI_BATT_STAT_CHARGING		0x0002
  #define ACPI_BATT_STAT_CRITICAL		0x0004
 -#define ACPI_BATT_STAT_NOT_PRESENT	0x0007
 -#define ACPI_BATT_STAT_MAX		0x0007
 +#define ACPI_BATT_STAT_INVALID					\
 +    (ACPI_BATT_STAT_DISCHARG | ACPI_BATT_STAT_CHARGING)
 +#define ACPI_BATT_STAT_BST_MASK					\
 +    (ACPI_BATT_STAT_INVALID | ACPI_BATT_STAT_CRITICAL)
 +#define ACPI_BATT_STAT_NOT_PRESENT	ACPI_BATT_STAT_BST_MASK
  
  union acpi_battery_ioctl_arg {
      int			 unit;	/* Device unit or ACPI_BATTERY_ALL_UNITS. */
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: patched->closed 
State-Changed-By: avg 
State-Changed-When: Fri Mar 11 18:03:12 UTC 2011 
State-Changed-Why:  
The fixed has been MFCed. 

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