svn commit: r216269 - head/sys/geom/part

Bruce Cran bruce at cran.org.uk
Wed Dec 8 22:52:44 UTC 2010


On Wed, 8 Dec 2010 16:46:17 +1100 (EST)
Bruce Evans <brde at optusnet.com.au> wrote:

> - for ATA drives, it uses the "firmware" geometry supplied by the
> drive firmware.  The ATA standard specifies this to be H=16/S=63 for
> all drives larger than a certain size (IIRC, about 8GB, which is the
> size at which the better default fake of H=255/S=63 generated by
>    cam_calc_geometry() for drives larger than 1GB, stops working for
>    systems that can't handle more than 1024 fake cylinders.  The magic
>    1GB is the size at which the even better default fake of H=64/S=32
>    stops working with more than 1024 fake cylinders.
> cam_calc_geometry() has no comment about this either).  Since all
> modern ATA drives are larger than 8GB, H=16/S=63 is almost hard-coded
> for ATA.

I've put together a patch which will hopefully improve the reporting of
geometry, though as you say nothing actually uses it nowadays - we
don't even appear to support CHS addressing in the disk drivers.
ata_da.c now calls cam_calc_geometry() which is updated to clip the
number of cylinders to 65535.  This introduces a problem because the
calculated geometry will no longer match the disklabel: however, since
CHS isn't used I don't know if we need to warn if the geometries don't
match? Since it appears superfluous I've removed the warning in the
patch.

atacontrol and camcontrol are updated to only display CHS
parameters from the drive if the disk conforms to ATA-5 or before. 

The patch is also available at
http://www.cran.org.uk/~brucec/freebsd/chs_deprecate.diff.txt in case
the attachment gets lost.

-- 
Bruce Cran
-------------- next part --------------
Index: sbin/atacontrol/atacontrol.c
===================================================================
--- sbin/atacontrol/atacontrol.c	(revision 216266)
+++ sbin/atacontrol/atacontrol.c	(working copy)
@@ -161,6 +161,7 @@
 static void
 cap_print(struct ata_params *parm)
 {
+	int ataver;
 	u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
 				((u_int32_t)parm->lba_size_2 << 16);
 
@@ -169,6 +170,8 @@
 				((u_int64_t)parm->lba_size48_3 << 32) |
 				((u_int64_t)parm->lba_size48_4 << 48);
 
+	ataver = version(parm->version_major);
+
 	printf("\n");
 	printf("Protocol              ");
 	if (parm->satacapabilities && parm->satacapabilities != 0xffff) {
@@ -180,14 +183,16 @@
 			printf("Unknown SATA revision\n");
 	}
 	else
-		printf("ATA/ATAPI revision %d\n", version(parm->version_major));
+		printf("ATA/ATAPI revision %d\n", ataver);
 	printf("device model          %.40s\n", parm->model);
 	printf("serial number         %.20s\n", parm->serial);
 	printf("firmware revision     %.8s\n", parm->revision);
 
-	printf("cylinders             %d\n", parm->cylinders);
-	printf("heads                 %d\n", parm->heads);
-	printf("sectors/track         %d\n", parm->sectors);
+	if (ataver <= 5) {
+		printf("cylinders             %d\n", parm->cylinders);
+		printf("heads                 %d\n", parm->heads);
+		printf("sectors/track         %d\n", parm->sectors);
+	}
 
 	if (parm->config == ATA_PROTO_CFA ||
 	    (parm->support.command2 & ATA_SUPPORT_CFA))
Index: sbin/camcontrol/camcontrol.c
===================================================================
--- sbin/camcontrol/camcontrol.c	(revision 216266)
+++ sbin/camcontrol/camcontrol.c	(working copy)
@@ -1104,6 +1104,7 @@
 static void
 atacapprint(struct ata_params *parm)
 {
+	int ataver;
 	u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
 				((u_int32_t)parm->lba_size_2 << 16);
 
@@ -1112,9 +1113,11 @@
 				((u_int64_t)parm->lba_size48_3 << 32) |
 				((u_int64_t)parm->lba_size48_4 << 48);
 
+	ataver = ata_version(parm->version_major);
+
 	printf("\n");
 	printf("protocol              ");
-	printf("ATA/ATAPI-%d", ata_version(parm->version_major));
+	printf("ATA/ATAPI-%d", ataver);
 	if (parm->satacapabilities && parm->satacapabilities != 0xffff) {
 		if (parm->satacapabilities & ATA_SATA_GEN3)
 			printf(" SATA 3.x\n");
@@ -1139,9 +1142,11 @@
 		    parm->media_serial);
 	}
 
-	printf("cylinders             %d\n", parm->cylinders);
-	printf("heads                 %d\n", parm->heads);
-	printf("sectors/track         %d\n", parm->sectors);
+	if (ataver <= 5) {
+		printf("cylinders             %d\n", parm->cylinders);
+		printf("heads                 %d\n", parm->heads);
+		printf("sectors/track         %d\n", parm->sectors);
+	}
 	printf("sector size           logical %u, physical %lu, offset %lu\n",
 	    ata_logical_sector_size(parm),
 	    (unsigned long)ata_physical_sector_size(parm),
Index: sys/cam/cam.c
===================================================================
--- sys/cam/cam.c	(revision 216266)
+++ sys/cam/cam.c	(working copy)
@@ -468,5 +468,8 @@
 		return;
 	}
 	ccg->cylinders = ccg->volume_size / secs_per_cylinder;
+	if (ccg->cylinders > 65535)
+		ccg->cylinders = 65535;
+
 	ccg->ccb_h.status = CAM_REQ_CMP;
 }
Index: sys/cam/ata/ata_da.c
===================================================================
--- sys/cam/ata/ata_da.c	(revision 216266)
+++ sys/cam/ata/ata_da.c	(working copy)
@@ -1129,27 +1129,14 @@
 	struct disk_params *dp = &softc->params;
 	u_int64_t lbasize48;
 	u_int32_t lbasize;
+	struct ccb_calc_geometry cg;
 
 	dp->secsize = ata_logical_sector_size(&cgd->ident_data);
-	if ((cgd->ident_data.atavalid & ATA_FLAG_54_58) &&
-		cgd->ident_data.current_heads && cgd->ident_data.current_sectors) {
-		dp->heads = cgd->ident_data.current_heads;
-		dp->secs_per_track = cgd->ident_data.current_sectors;
-		dp->cylinders = cgd->ident_data.cylinders;
-		dp->sectors = (u_int32_t)cgd->ident_data.current_size_1 |
-			  ((u_int32_t)cgd->ident_data.current_size_2 << 16);
-	} else {
-		dp->heads = cgd->ident_data.heads;
-		dp->secs_per_track = cgd->ident_data.sectors;
-		dp->cylinders = cgd->ident_data.cylinders;
-		dp->sectors = cgd->ident_data.cylinders * dp->heads * dp->secs_per_track;  
-	}
+
 	lbasize = (u_int32_t)cgd->ident_data.lba_size_1 |
 		  ((u_int32_t)cgd->ident_data.lba_size_2 << 16);
 
-	/* use the 28bit LBA size if valid or bigger than the CHS mapping */
-	if (cgd->ident_data.cylinders == 16383 || dp->sectors < lbasize)
-		dp->sectors = lbasize;
+	dp->sectors = lbasize;
 
 	/* use the 48bit LBA size if valid */
 	lbasize48 = ((u_int64_t)cgd->ident_data.lba_size48_1) |
@@ -1159,6 +1146,14 @@
 	if ((cgd->ident_data.support.command2 & ATA_SUPPORT_ADDRESS48) &&
 	    lbasize48 > ATA_MAX_28BIT_LBA)
 		dp->sectors = lbasize48;
+
+	cg.block_size = dp->secsize;
+	cg.volume_size = dp->sectors * dp->secsize;
+	cam_calc_geometry(&cg, 1);
+
+	dp->heads = cg.heads;
+	dp->secs_per_track = cg.secs_per_track;
+	dp->cylinders = cg.cylinders;
 }
 
 static void
Index: sys/geom/part/g_part.h
===================================================================
--- sys/geom/part/g_part.h	(revision 216266)
+++ sys/geom/part/g_part.h	(working copy)
@@ -114,12 +114,12 @@
 	uint32_t	gpt_smhead;
 	uint32_t	gpt_smtail;
 	/*
-	 * gpt_sectors and gpt_heads are the fixed or synchesized number
+	 * gpt_sectors and gpt_heads are the fixed or synthesized number
 	 * of sectors per track and heads (resp) that make up a disks
 	 * geometry. This is to support partitioning schemes as well as
 	 * file systems that work on a geometry. The MBR scheme and the
 	 * MS-DOS (FAT) file system come to mind.
-	 * We keep track of whether the geometry is fixed or synchesized
+	 * We keep track of whether the geometry is fixed or synthesized
 	 * so that a partitioning scheme can correct the synthesized
 	 * geometry, based on the on-disk metadata.
 	 */
Index: sys/geom/part/g_part_bsd.c
===================================================================
--- sys/geom/part/g_part_bsd.c	(revision 216266)
+++ sys/geom/part/g_part_bsd.c	(working copy)
@@ -387,10 +387,6 @@
 		goto invalid_label;
 	if (heads != basetable->gpt_heads && !basetable->gpt_fixgeom)
 		basetable->gpt_heads = heads;
-	if (sectors != basetable->gpt_sectors || heads != basetable->gpt_heads)
-		printf("GEOM: %s: geometry does not match label"
-		    " (%uh,%us != %uh,%us).\n", pp->name, heads, sectors,
-		    basetable->gpt_heads, basetable->gpt_sectors);
 
 	chs = le32dec(buf + 60);
 	if (chs < 1)
Index: sys/geom/part/g_part.c
===================================================================
--- sys/geom/part/g_part.c	(revision 216266)
+++ sys/geom/part/g_part.c	(working copy)
@@ -203,7 +203,7 @@
 				continue;
 			/*
 			 * Prefer a geometry with sectors > 1, but only if
-			 * it doesn't bump down the numbver of heads to 1.
+			 * it doesn't bump down the number of heads to 1.
 			 */
 			if (chs > bestchs || (chs == bestchs && heads > 1 &&
 			    table->gpt_sectors == 1)) {


More information about the svn-src-head mailing list