Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 16 Mar 1997 13:55:38 -0700 (MST)
From:      Don Yuniskis <dgy@rtd.com>
To:        freebsd-hackers@freefall.FreeBSD.org (FreeBSD hackers)
Cc:        joerg_wunsch@uriah.heep.sax.de (Joerg Wunsch), bde@zeta.org.au (Bruce Evans)
Subject:   wd and funky geometry (understood?)
Message-ID:  <199703162055.NAA23944@seagull.rtd.com>

next in thread | raw e-mail | index | archive | help
Greetings!

      I *think* I've located the source of the geometry foul-ups I've
seen with IDE drives...

[apologies that the code fragments herein are quoted from a 2.1R
system -- I've just dismantled the 2.1.7R system to reprogram the
system ROMs  :-(   The code is essentially the same.  Liberal snipping
employed throughout for readability...]

      This problem appears to have been in the system since at least
Aug 94 (by my notes).

      The problem appears to an inconsistent use of geometry information
for each drive.  During IPL, the drive is INITed with parameters from the
BIOS's disk parameter table.  This makes sense as I can't imagine any
*other* place from which to get the disk geometry (reliably).  From
boot() in /usr/src/sys/i386/boot/biosboot/boot.c:

///////////////////////////////////////////////////////////////////
#include <machine/bootinfo.h>
struct bootinfo bootinfo;

	/* Pick up the story from the Bios on geometry of disks */
	for(ret = 0; ret < N_BIOS_GEOM; ret ++)
		bootinfo.bi_bios_geom[ret] = get_diskinfo(ret + 0x80);
///////////////////////////////////////////////////////////////////

[get_diskinfo() system call basically does an INT 13, AH=8 (Read Drive
Parameters) -- see /usr/src/sys/i386/boot/biosboot/bios.S]

     Since the system ROM's have already INITed the drive, the geometry
reflected in bootinfo.bi_bios_geom[] will reflect the current geometries
of each of these INITed drives.

     However, in wdattach(), wdgetctlr() is invoked to get the drive's
geometry.  It does this by issuing an IDENTIFY command (i.e. READP)
to the drive.  The data returned by the command is interpreted as
a wdparams structure:

///////////////////////////////////////////////////////////////////
/*
 * read parameters command returns this:
 */
struct wdparams {
	/* drive info */
	short	wdp_config;		/* general configuration */
	short	wdp_fixedcyl;		/* number of non-removable cylinders */
	short	wdp_removcyl;		/* number of removable cylinders */
	short	wdp_heads;		/* number of heads */
	short	wdp_unfbytespertrk;	/* number of unformatted bytes/track */
	short	wdp_unfbytes;		/* number of unformatted bytes/sector */
	short	wdp_sectors;		/* number of sectors */
	short	wdp_minisg;		/* minimum bytes in inter-sector gap*/
	short	wdp_minplo;		/* minimum bytes in postamble */
	short	wdp_vendstat;		/* number of words of vendor status */
	/* controller info */
	char	wdp_cnsn[20];		/* controller serial number */
	short	wdp_cntype;		/* controller type */
#define	WDTYPE_SINGLEPORTSECTOR	1	 /* single port, single sector buffer */
#define	WDTYPE_DUALPORTMULTI	2	 /* dual port, multiple sector buffer */
#define	WDTYPE_DUALPORTMULTICACHE 3	 /* above plus track cache */
	short	wdp_cnsbsz;		/* sector buffer size, in sectors */
	short	wdp_necc;		/* ecc bytes appended */
	char	wdp_rev[8];		/* firmware revision */
	char	wdp_model[40];		/* model name */
	short	wdp_nsecperint;		/* sectors per interrupt */
	short	wdp_usedmovsd;		/* can use double word read/write? */
};
///////////////////////////////////////////////////////////////////

The drive's geometry is deduced from the wdp_fixedcyl, wdp_removcyl, wdp_heads
and wdp_sectors members thereof.  This information is reported in the probe
(actually, the attach) on the console as the device's geometry.  The drive is
then reINITed with these parameters by wdsetctlr() when the device is opened
or an error is detected.

Herein lies the problem:  these parameters reflect "the default geometry of
the device" (paraphrased from the ATA specification).  However, the BIOS's
geometry may *NOT* agree with the drives "default geometry".  For example,
the probe of my IDE drives yields:

	wdc0 at 0x1f0-0x1f7 irq 14 on isa
	wdc0: unit 0 (wd0): <Maxtor 7345 AT>
	wd0: 329MB (675450 sectors), 790 cyls, 15 heads, 57 S/T, 512 B/S
	wdc0: unit 1 (wd1): <MAXTOR  LXT-340A>
	wd1: 321MB (659232 sectors), 654 cyls, 16 heads, 63 S/T, 512 B/S

However, *both* drives have a BIOS geometry of 611/16/63.  (Sorry,
my ancient BIOS does not support "user configurable" geometries
so this was the closest geometry I could find -- hence the reason
I have disassembled the 2.1.7R system to reprogram the system ROMs!
The drives will automatically adapt to whatever geometry they are
INITed with so it doesn't pose a problem).

I haven't delved into how the geometry contained within the disklabel
written to the drive factors into all this.

Why is all this a problem?  I don't *think* it causes any problems
during IPL -- since the drive is INITed with the BIOS geometry
during the boot and then switched to the "default geometry"
during the attach/open.  I think that the image loaded from the
disk during boot is small enough that changes to the size/shape
of the first track are safely ignored.  (though, on second thought,
I suspect this *can* screw you if your FBSD partition does not
begin at the start of the disk!  Comments?)

However, sharing a partition might be a problem since DOS's
FDISK (which you used to create the DOS partition) will talk
to a disk shaped per the BIOS geometry.  When FBSD takes over,
the geometry of the disk is changed and track/cylinder boundaries
can "move"  (e.g., consider my case with a default geometry
of 57 S/C vs. the BIOS's 63 S/C).

And, switching to/from DOS can screw you.  Consider DOS and
FBSD sharing wd0.  FBSD reINITs the drive to use it's default
geometry.  Then, you mount a DOS partition FROM THE SAME DRIVE!
The layout of the DOS partition expected the BIOS geometry
yet the disk is now accessed using the FBSD geometry.

I suspect that LBA *could* be a redeeming grace.  However, I don't
know enough about the *guarantees* within the drive to determine
if a particular sector address will *allways* map to the same
(PHYSICALLY EQUIVALENT) sector regardless of geometry (i.e.,
will sector "97" in a 611/16/63 geometry correspond to the
exactl same physical sector when the drive is configured for
790/15/57??)

[someone who really *knows* what they are talking about could probably
determine the *real* effects of all this  :-( ]

I was initially thinking a good hack to fix this would be to simply 
copy the "apparent" disk geometry from the results of the IDENTIFY
command (i.e. from the shorts at parameters[54] through [56]) into
the "default" disk geometry parameters (i.e., the shorts at 
parameters[1], [4] and [6]).  That seemed easier than changing
the wdparams structure to include thes other fields and then *use*
those fields instead of wdp_ncylinders, wdp_heads, etc.  But, I'm
a bit nervous about just making that change and "hoping" it
doesn't break something else  :>

I don't claim to know what the hell I'm talking about :>  so if
someone would like to enlighten me as to the errors in my
analysis/assumptions, I'd be *thrilled*!  :>

But, right now I have to try and tweek the geometries in these
system ROMs to match the geometries of my drives (and forget
all these other -- more interesting --  issues!  :>)

Thanks!
--don



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199703162055.NAA23944>