Subject: kern/9864: wd driver reports cylinders incorrectly on some drives
To: None <gnats-bugs@gnats.netbsd.org>
From: None <thorpej@zembu.com>
List: netbsd-bugs
Date: 04/12/2000 11:45:10
>Number:         9864
>Category:       kern
>Synopsis:       wd driver reports cylinders incorrectly on some drives
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Apr 12 11:46:01 PDT 2000
>Closed-Date:
>Last-Modified:
>Originator:     Jason R. Thorpe
>Release:        NetBSD 1.4X, March 31, 2000
>Organization:
Zembu Labs, Inc.
>Environment:
	
NetBSD 1.4X on Intel server hardware.

>Description:
	The wd driver reports the incorrect number of cylinders on
	some drives, specifically drives that report the magic number
	16383, which apparently indicates that LBA is the only way the
	drive can be addressed.

	This causes programs like disklabel(8) do bounds-check incorrectly.

>How-To-Repeat:
	This bug was found while testing a highly customized automated
	installation program.

>Fix:
	The following patch fixes the bug by recognizing the magic
	cylinder count and then recomputing it based on the capacity
	and the reported number of heads and sectors/track.

Index: wd.c
===================================================================
RCS file: /home/cvsfiles/netbsd/src/sys/dev/ata/wd.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -c -r1.1 -r1.2
*** wd.c	2000/03/31 20:00:16	1.1
--- wd.c	2000/04/11 19:19:47	1.2
***************
*** 846,852 ****
  	lp->d_secsize = DEV_BSIZE;
  	lp->d_ntracks = wd->sc_params.atap_heads;
  	lp->d_nsectors = wd->sc_params.atap_sectors;
! 	lp->d_ncylinders = wd->sc_params.atap_cylinders;
  	lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
  
  	if (strcmp(wd->sc_params.atap_model, "ST506") == 0)
--- 846,862 ----
  	lp->d_secsize = DEV_BSIZE;
  	lp->d_ntracks = wd->sc_params.atap_heads;
  	lp->d_nsectors = wd->sc_params.atap_sectors;
! 	if (wd->sc_params.atap_cylinders == ATAP_CYLINDERS_LBA_ONLY) {
! 		/*
! 		 * If we get the magic "LBA is the only reliably way"
! 		 * value for ncylinders, compute the `actual' number
! 		 * of cylinders that would correspond to our capacity
! 		 * and reported number of heads and sectors per track.
! 		 */
! 		lp->d_ncylinders = wd->sc_capacity /
! 		    lp->d_ntracks / lp->d_nsectors;
! 	} else
! 		lp->d_ncylinders = wd->sc_params.atap_cylinders;
  	lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
  
  	if (strcmp(wd->sc_params.atap_model, "ST506") == 0)
Index: atareg.h
===================================================================
RCS file: /home/cvsfiles/netbsd/src/sys/dev/ata/atareg.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -c -r1.1 -r1.2
*** atareg.h	2000/03/31 20:00:16	1.1
--- atareg.h	2000/04/11 19:19:47	1.2
***************
*** 25,30 ****
--- 25,31 ----
  #define ATAPI_CFG_CMD_16	0x0001
  /* words 1-9 are ATA only */
      u_int16_t	atap_cylinders;		/* 1: # of non-removable cylinders */
+ #define	ATAP_CYLINDERS_LBA_ONLY	16383	/* Stupid Evil ATA Crap */
      u_int16_t	__reserved1;
      u_int16_t	atap_heads;		/* 3: # of heads */
      u_int16_t	__retired1[2];		/* 4-5: # of unform. bytes/track */
>Release-Note:
>Audit-Trail:
>Unformatted: