Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 19 Jan 1999 22:18:03 -0500
From:      Andrew Sherrod <yaldabaoth@geocities.com>
To:        Bruce Evans <bde@zeta.org.au>
Cc:        freebsd-bugs@FreeBSD.ORG, ixkatl@yahoo.com
Subject:   Re: [Modified Patch] Re: i386/9431: wd.c Does nto recognize certain LBA disks [patch attached]
Message-ID:  <36A54AEA.81B56C88@geocities.com>
References:  <199901121651.DAA10604@godzilla.zeta.org.au>

next in thread | previous in thread | raw e-mail | index | archive | help

     I am afraid my initial posting to GNATS / bugs@FreeBSD.org was unclear.
Judging from your response I assume you thought I was reporting a problem with LBA
support. However, what I am reporting is not an LBA issue but an issue with disk
geometry.
     However, as several postings to -bugs and -current have passed without
comment, I will assume that others have also decided that this patch is not worth
considering. I can see only three reasons for this:
          1. They consider the problem unimportant.
          2. They do not think the patch works.
          3. They worry the patch will break existing code.
Thus, I have decided to address these three points and, hopefully, in the process,
show that the two attached changes to existing code are worth making.

1. Background

     For those unfamiliar with the wd.c code, I will present a short description of
how FreeBSD handles disk geometry.
     If a disk partition table (either DOS or FreeBSD) exists, the kernel will
accept the reported number of cylinders heads and sectors ("CHS geometry").
Otherwise, the drive will be polled and return a lengthy structure as specified in
"Information Technology - AT Attachment Interface with Extensions (ATA-2) Working
Draft" (ASC X3T10 Revision 4c Mar. 18 1996) ("ATA-2"). This structure, among other
things, defines the CHS geometry of the disk (words 1,3,and 6) , returning the
number of cylinders, heads, and sectors.
     This structure also contains a set of flags (word 49) showing disk
capabilities (wdp_capability in wd.c's wdparam structure), including whether DMA
and LBA are supported. In both 2.2.8 and 3.0 these flags are ignored.
     A third part of the structure returns the "LBA size" (words 60-61) which is
used by LBA to determine disk size.  This value is used by FreeBSD under a few
specific circumstances:
            1. In 3.0 ONLY, if the user specifies LBA mode, and the product
obtained by multiplying C*H*S is less than lba_size, then lba_size is used.
           2. In both 2.2.8 and 3.0, if the number of cylinders is 16383 and
lba_size is greater than the CHS product, then lba_size is used.
      If user LBA is not defined, and number of reported cylinders is not 16383, a
disk without a partition table will be seen by FreeBSD to have a size defined by:

         Sectors(total) = ( (Cylinders * Heads/Cylinder) * Sectors/ Head)

     There is one problem with this model, however. (And I know this is a point
which some will debate). Certain BIOSes (in my case Award Modular BIOS v 4.51PG ),
do not return a Cylinder count of 16383 for disks smaller than 8 GB, nor do they
return a cylinder value which makes the CHS size match the LBA size. Instead, these
BIOSes return a fictitious Cylinder count (in my case, and at least one other in
the mailing list archives, 4092).
     It is this problem I hope to correct with the attached patches..

2. Why This Problem Should Be Corrected

     Even a cursory examination of GNATS and the mailing list archives will show
that incorrect disk geometry is one of the most prevalent complaints during a
FreeBSD installation. Complaints about drives reporting 4092 cylinders, not
recognizing disks over 8GB, producing false CHS geometries when using "dangerously
dedicated" disks, and others are numerous. The problem is so common, that the
"solution" of creating a temporary DOS partition has made its way into the
handbook, FAQs, and Mr. Lehey's manual.
     And it IS a problem. How popular would Microsoft products be, if every new
user was told, "Oh, we can recognize several drives, and if we can't, just put a
Linux file system on the disk"? I speak from experience. I almost gave up on my
first FreeBSD installation because it had lopped almost 2 GB of space off each of
two disk drives. If it is our hope to attract new (read "novice") users, we cannot
afford such user unfriendliness during their first encounter with the system.
Installation is intimidating enough without the added headache of sifting through
the FAQs only to discover they must stop and add a superfluous DOS partition just
to get the use of all their disk space.
      I know at this point many readers are thinking, "But how often do you install
the system?" And that is true. In fact, I think it may explain why I received so
little response. My readers are already proficient. They already have  a system up
and running. They have disks which are configured correctly. They haven't seen an
fresh install in quite some time. And even if they have, they know exactly how to
fix the problem. Even the DOS work-around is an old familiar practice. They don't
think of it as a problem.
     But to the new user, this is not the case. Most people come to UN*X systems
because they have complaints against Microsoft, and to be told that we rely upon
Microsoft for our disk partitioning reduces our credibility quite a bit. (To be
fair at this point, we are not alone in this problem. Three different Linux systems
gave the same incorrect geometries. But that does not excuse us from trying to fix
the problem.) We often talk about publicity, and expanding the user base. Yet we do
not take simple steps to make the new user's first encounter less intimidating. Too
often we take a reasonable question and brush it off with "RTFM". And all too often
it is a problem which could be easily fixed, but which is not interesting enough to
attract a developer, or else it is a problem only encountered by newbies who don't
have enough experience to fix it, and is thus unknown to, because it does not
effect, those with more experience.
     This is such a problem. Fortunately, it annoyed me enough that I spent some
time (and made quite a few false starts, as my GNATS PR will show) and found a
relatively simple solution.

3. Do the Patches Work

     Well, the simplest answer is to show my dmesg output before and after the fix.

     My system has 3 drives. Wd0 is an 8 GB Quantum Fireball. Wd1 is a 3 GB Western
Digital. Wd2 is a 4.1 GB Maxtor.

    The dmesg before the patch (same output for both 2.2.8 and 3.0) edited to show
only the relevant portions:

      fdc0 at 0x3f0-0x3f7 irq 6 drq 2 on isa
      fdc0: FIFO enabled, 8 bytes threshold
      fd0: 1.44MB 3.5in
      wdc0 at 0x1f0-0x1f7 irq 14 on isa
      wdc0: unit 0 (wd0): <QUANTUM FIREBALL SE8.4A>
      wd0: 8063MB (16514064 sectors), 16383 cyls, 16 heads, 63 S/T, 512 B/S
      wdc0: unit 1 (wd1): <WDC AC33100H>
      wd1: 2014MB (4124736 sectors), 4092 cyls, 16 heads, 63 S/T, 512 B/S
      wdc1 at 0x170-0x177 irq 15 on isa
      wdc1: unit 0 (wd2): <Maxtor 84320D4>
      wd2: 1888MB (3866940 sectors), 4092 cyls, 15 heads, 63 S/T, 512 B/S
      wdc1: unit 1 (atapi): <FX322M/w03>, removable, intr, dma, iordis
      wcd0: 5512KB/sec, 256KB cache, audio play, 255 volume levels, ejectable tray
      wcd0: no disc inside, unlocked

    As you can see,  wd1 and wd2 are both reported to be much smaller than they
really are. And both are also reporting 4092 cylinders.

    Here is dmesg after the patch.(Once again 2.2.8 and 3.0 showed the same
results).

      fdc0 at 0x3f0-0x3f7 irq 6 drq 2 on isa
      fdc0: FIFO enabled, 8 bytes threshold
      fd0: 1.44MB 3.5in
      wdc0 at 0x1f0-0x1f7 irq 14 on isa
      wdc0: unit 0 (wd0): <QUANTUM FIREBALL SE8.4A>
      wd0: 8063MB (16514064 sectors), 16383 cyls, 16 heads, 63 S/T, 512 B/S
      wdc0: unit 1 (wd1): <WDC AC33100H>
      wd1: 3020MB (6185088 sectors), 6136 cyls, 16 heads, 63 S/T, 512 B/S
      wdc1 at 0x170-0x177 irq 15 on isa
      wdc1: unit 0 (wd2): <Maxtor 84320D4>
      wd2: 4120MB (8439184 sectors), 8930 cyls, 15 heads, 63 S/T, 512 B/S
      wdc1: unit 1 (atapi): <FX322M/w03>, removable, intr, dma, iordis
      wcd0: 5512KB/sec, 256KB cache, audio play, 255 volume levels, ejectable tray
      wcd0: no disc inside, unlocked

     Once the patch is applied, wd1 and wd2 both show the correct size.
     In addition, to prove that the pacth works for system installtion, I ran
/stand./sysinstall for 3.0 (Release) from both the CD and from the hard-drive
(using the patched kernel). After removing the partition table from the two smaller
disks, I tried the CD install. The kernel reported the incorrect size for both wd1
and wd2. I tried to enter the correct geometry on the "slice" page, but when I
selected "A" to use the whole disk, it returned to the incorrect geometry. I then
completed installation. After installation df and fdisk both showed the same
incorrect geometry.
     I then cleared the disk partitions again from wd1 and wd2 (both '/usr' and '/'
are on wd0), installed my 3.0 patch, and ran /stand/sysinstall from the hard drive.
This time the installation "slice" screen showed the correct geometry for all 3
disks. After a minimal install (just to commit the changes), df, fdisk and dmesg
all reported the correct geometries.

      For anyone who has followed my lengthy trail of patches, I admit my first few
attempts had some unwanted side effects, but I shall defer those to the next
section.
      Why does this patch work? Basically, the patch checks word 49 (the
LBA/DMA/etc. flags) returned by the BIOS and, if the LBA bit is set and lba_size is
greater than the CHS product, uses the lba_size. This is supported by the ATA-2
standard. Page 40 states (regarding the LBA bit) "If this bit is set, words 60-61
[lba_size] shall be valid." Thus, if the LBA bit is active, then the LBA size gives
an accurate measurement of the disk size. if this size is larger than the CHS
geometry indicates, the CHS geometry must be in error.  (To forestall any
objections that pre-ATA-2 drives may give incorrect values for both capabilities
and lba_size, I shall address that objection in the following section as well.)

4. Does the Patch break Existing Code

     I will be the first to admit that my first few attempts resulted in unwanted
side effects. My initial attempts actually forced DMA and LBA on if they were
supported, whether the user activated them or not. However, I think the current
patch avoids any such problems. I have run it on both a 2.2.8 and a 3.0 (Release)
system, with no consequences.
    The only valid objection I have heard raised to my patches is that certain
older disks and BIOSes may incorrectly return an LBA flag and garbage data in the
lba_size. However, as I have said before, this raises the question whether we want
to support the bugs of older disks or the bugs of newer BIOSes. Those using the
older hardware are usually more experienced and sometimes are contributors
themselves, thus, we have a tendency to support old bugs rather than new. However,
in this case, I think supporting new bugs is preferable. Disks wear out faster than
motherboards, and Award isn't likely to fix this bug any time soon. And, since
ATA-2 came into effect in the mid 1990's, noncompliant disks are likely to vanish
as time goes on, while Award is not violating any standards in their somewhat buggy
BIOS, so they have little reason to change. (And, since it doesn't cause any
problems for Microsoft products, which are by far their largest market, they have
no financial incentive to change.) Those using old non-ATA-2 compliant disks are
likely to be a small minority growing ever smaller as those disks wear out or are
replaced, while those using newer Award BIOSes is a group likely to grow. Thus, it
seems that this patch likely fixes more problems than it creates, and this is even
more true in the future than it is now.

Well, having addressed all your concerns (I hope) I ask that anyone who has an
objection or finds a problem with this code to please send it to me at
ixkatl@yahoo.com . I do not believe this patch causes any major problems, but I
welcome any comment or criticism.

Thanks.

Andrew Sherrod

--------------------------------------------------------------------------------------------------------

DIFFS:
--------------------------------------------------------------------------------------------------------

--------------------------------------------------------------------------------------------------------

3.0 Release
--------------------------------------------------------------------------------------------------------

*** wd.c Mon Jan 18 19:39:22 1999
--- wd.c.original Mon Jan 18 18:24:14 1999
***************
*** 120,131 ****
  #define WDOPT_MULTIMASK 0x00ff

  /*
- * This define is used to determine if the drive is LBA capable
- */
-
- #define WDCAP_LBA 0x02
-
- /*
   * This biotab field doubles as a field for the physical unit number on
   * the controller.
   */
--- 120,125 ----
***************
*** 1940,1960 ****
     du->dk_dd.d_ntracks * du->dk_dd.d_nsectors;
    du->dk_dd.d_secperunit =
     du->dk_dd.d_secpercyl * du->dk_dd.d_ncylinders;
!
!   /*
!   * tThe following change determines if the disk
!   * is LBA capable. If it is, and the lba size is
!   * larger than the CHS size, use the LBA size.
!   * This should allow certain difficult BIOSES
!   * (eg. Award) which do not report the correct
!   * CHS size to still give an accurate measure
!   * of disk size,w ithout forcing the user to
!   * enable LBA mode.
!   * A. Sherrod (01/18/1999)
!   */
!
!   if ( ( (wp->wdp_capability & WDCAP_LBA) ||
!         (wp->wdp_cylinders == 16383) ) &&
        du->dk_dd.d_secperunit < wp->wdp_lbasize) {
     du->dk_dd.d_secperunit = wp->wdp_lbasize;
     du->dk_dd.d_ncylinders =
--- 1932,1938 ----
     du->dk_dd.d_ntracks * du->dk_dd.d_nsectors;
    du->dk_dd.d_secperunit =
     du->dk_dd.d_secpercyl * du->dk_dd.d_ncylinders;
!   if (wp->wdp_cylinders == 16383 &&
        du->dk_dd.d_secperunit < wp->wdp_lbasize) {
     du->dk_dd.d_secperunit = wp->wdp_lbasize;
     du->dk_dd.d_ncylinders =

--------------------------------------------------------------------------------------------------------

2.2.8
--------------------------------------------------------------------------------------------------------

*** wd.c.2_2_8 Wed Jan 13 21:07:30 1999
--- wd.c.original.2_2_8 Wed Jan 13 21:08:24 1999
***************
*** 113,122 ****
  #define WDOPT_FORCEHD(x) (((x)&0x0f00)>>8)
  #define WDOPT_MULTIMASK 0x00ff

- /* This bit mask is used to determine if the drive supports LBA addressing. */
-
- #define WDCAP_LBA  0x02
-
  /*
   * This biotab field doubles as a field for the physical unit number on
   * the controller.
--- 113,118 ----
***************
*** 1731,1745 ****
   du->dk_dd.d_nsectors = wp->wdp_sectors;
   du->dk_dd.d_secpercyl = du->dk_dd.d_ntracks * du->dk_dd.d_nsectors;
   du->dk_dd.d_secperunit = du->dk_dd.d_secpercyl * du->dk_dd.d_ncylinders;
!
!        /* Check for BIOS LBA flag. This should allow kernel to determine
!     actual disk geometry for diffiuclt BIOSes.
!      This will likely only be of use during initial installation, or
!      perhaps when configuring a new drive. Otherwise, the disk geometry
!      should already be known. -A. Sherrod 01/13/1999*/
!
!  if ( ( (wp->wdp_capability & WDCAP_LBA) ||
!            (wp->wdp_cylinders == 16383 ) ) &&
              du->dk_dd.d_secperunit < wp->wdp_lbasize) {
           du->dk_dd.d_secperunit = wp->wdp_lbasize;
           du->dk_dd.d_ncylinders =
--- 1727,1733 ----
   du->dk_dd.d_nsectors = wp->wdp_sectors;
   du->dk_dd.d_secpercyl = du->dk_dd.d_ntracks * du->dk_dd.d_nsectors;
   du->dk_dd.d_secperunit = du->dk_dd.d_secpercyl * du->dk_dd.d_ncylinders;
!  if (wp->wdp_cylinders == 16383 &&
              du->dk_dd.d_secperunit < wp->wdp_lbasize) {
           du->dk_dd.d_secperunit = wp->wdp_lbasize;
           du->dk_dd.d_ncylinders =

--------------------------------------------------------------------------------------------------------



> (I could really use the input of some disk gurus here. Any idea why the
> Award BIOS would NOT return
> any flags?

The driver ignores the BIOS.  The flags are whatever you set them to be
in the FreeBSD configuration of the driver.

> And, more important, if LBA is not enabled, will any lba_size
> value be returned?Or if LBA is off
> is a null or 0 returned?)

Support for LBA mode is nonexistent in 2.2.8 and dangerously incomplete
in 3.0 (if it is used, then kernel dumps may trash filesystems).  There
is no reason to use it because all known disks (except possibly yours :-)
support CHS mode.

> *** wd.c.3_0  Mon Jan 11 21:01:30 1999
> --- wd.c.original.3_0 Sun Jan 10 21:27:22 1999
> ***************
> *** 1949,1964 ****
>                       du->dk_dd.d_ntracks * du->dk_dd.d_nsectors;
>               du->dk_dd.d_secperunit =
>                       du->dk_dd.d_secpercyl * du->dk_dd.d_ncylinders;
> !
> !             /* It appears that certain Award BIOSes (newer versions
> !                apparently) do not return LBA flags when LBA is
> !               active. Hwoever, as LBA size should not be returned
> !               when LBA is off, this hack should be safe.
> !
> !               A. Sherrod 01/11/1998   */
> !
> !
> !             if(du->dk_dd.d_secperunit < wp->wdp_lbasize) {
>                       du->dk_dd.d_secperunit = wp->wdp_lbasize;
>                       du->dk_dd.d_ncylinders =
>                               du->dk_dd.d_secperunit / du->dk_dd.d_secpercyl;
> --- 1949,1956 ----
>                       du->dk_dd.d_ntracks * du->dk_dd.d_nsectors;
>               du->dk_dd.d_secperunit =
>                       du->dk_dd.d_secpercyl * du->dk_dd.d_ncylinders;
> !             if (wp->wdp_cylinders == 16383 &&
> !                 du->dk_dd.d_secperunit < wp->wdp_lbasize) {
>                       du->dk_dd.d_secperunit = wp->wdp_lbasize;
>                       du->dk_dd.d_ncylinders =
>                               du->dk_dd.d_secperunit / du->dk_dd.d_secpercyl;
>

The magic number 16383 is tested because the current ATA (draft?) standard
specifies that CHS mode is specially broken for drives with more than
1024*255*63 sectors.  Such drives are supposed to have a C/H/S geometry of
16383/16/63 (or something like that) for their default translation mode
so that they work as least unwell as possible with old, broken BIOSes.
Previous versions of the standard permitted the default geometry to
have up to 65535 cylinders, and we know that drives with more than 32767
cylinders used to be made because the driver used to have sign extension
bugs for them.

The driver multiplies out the CHS values to get the number of sectors
unless the drive appears to have specially broken CHS.  It doesn't
trust the wdp_lbasize value otherwise because wdp_lbasize may be
garbage for old drives.  Drives with 16383 cylinders are presumably
new enough to have a valid wdp_lbasize.

Bruce


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?36A54AEA.81B56C88>