The HDIO_GETGEO
ioctl returns the number of cylinders in a short.
This means that if you have more than 65535 cylinders, the number is
truncated, and (for a typical SCSI setup with 1 MiB cylinders)
a 80 GiB disk may appear as a 16 GiB one.
Once one recognizes what the problem is, it is easily avoided.
(The programming convention is to use the BLKGETSIZE
ioctl
to get total size, and HDIO_GETGEO
to get number of heads and
sectors/track, and, if needed, get C by C = size/(H*S).)
(Below a discussion of Linux kernel problems. BIOS problems and jumpers that clip capacity were discussed above.)
Drives larger than 33.8 GB will not work with kernels older than 2.2.14 / 2.3.21. The details are as follows. Suppose you bought a new IBM-DPTA-373420 disk with a capacity of 66835440 sectors (34.2 GB). Pre-2.3.21 kernels will tell you that the size is 769*16*63 = 775152 sectors (0.4 GB), which is a bit disappointing. And giving command line parameters hdc=4160,255,63 doesn't help at all - these are just ignored. What happens? The routine idedisk_setup() retrieves the geometry reported by the disk (which is 16383/16/63) and overwrites what the user specified on the command line, so that the user data is used only for the BIOS geometry. The routine current_capacity() or idedisk_capacity() recomputes the cylinder number as 66835440/(16*63)=66305, but since this is stored in a short, it becomes 769. Since lba_capacity_is_ok() destroyed id->cyls, every following call to it will return false, so that the disk capacity becomes 769*16*63. For several kernels a patch is available. A patch for 2.0.38 can be found at ftp.kernel.org. A patch for 2.2.12 can be found at www.uwsg.indiana.edu (some editing may be required to get rid of the html markup). The 2.2.14 kernels do support these disks. In the 2.3.* kernel series, there is support for these disks since 2.3.21. One can also `solve' the problem in hardware by using a jumper to clip the size to 33.8 GB. In many cases a BIOS upgrade will be required if one wants to boot from the disk.