Abstract: This article is mainly to discuss another topic of system-level C language program: the read and write operation of large-capacity hard drives. The article first introduces the physical structure of the hard disk, then briefly explains the cause of capacity restrictions, and finally gives a problem-solving method, and implements reading and writing and testing of large-capacity hard drives with C language. The article will involve some content related to computer data storage and interrupt calls. If you want to know more about the readers of these contents, you can refer to the "System-level C language program design (write-to-date)" or related information written by the author.
Key words: cylindrical, magnetic head, sector, hard disk adding mode, CHS, LBA, ATA interface, int 13 interface, extended INT 13 interrupt, hard disk capacity, standard formatting
When tracking the hard disk partition table, you can find a problem: For a 4.3GB hard disk, you can find all its logical partitions correctly, and for a 10.3GB hard drive, we can only find logical partitions within the near 8GB range. . Similarly, when the hard disk is programmed to obtain a hard disk parameter, if the hard disk is 4.3GB, it can get the correct result, but if the hard disk is 10.3GB or more, the program is like "myopia", only " See "8.4GB of capacity. Why is this?
In order to solve this problem, you should first understand the physical structure of the hard disk. We can see the hard disk as a cylinder, then cut the cylinder into a plurality of thin wafings in the direction perpendicular to the central axis, for a circle, it has two sides, there are multiple concentric circles on each side, each The concentric circle can be divided into a sector area equal to the number, and the data is stored in these sector regions. We called a "magnetic head" (magnetic surface) in different upper and lower sides, and the label started from 0, called these concentric circles (track), the label started from 0, and called the sector area "sector", The label starts from 1. For standards formatted disks, each sector is a total of 512 bytes, so the capacity of the hard disk can be calculated:
Capacity = cylindrical * magnetic head number * (sector number / cylinder) * 512 (byte / sector)
In fact, for all standards formatted, the above formula is established. For example, for a floppy disk, a total of 2 heads (magnetic surfaces), 80 tracks per magnetic head, 18 sectors per track, so the capacity is:
2 * 80 * 18 * 512 = 1.44MB
After understanding the physical structure of the hard disk, come back to briefly talk about the ATA interface and INT 13 interface. The ATA interface is a register-driven parallel bus, and when the data is transmitted, the BIOS first writes the start address and length of the data in the ATA, and then writes the corresponding read and write or the like to a specific register, complete the corresponding operation; int 13 interface is actually Also driven by register, first set all parameters including data address or the like (assignment to register), and then call the INT 13 interrupt completion operation.
For the ATA interface, the register is defined as follows:
Cylindrical low register 8bit
Cylindrical high register 8bit
Sector register 8bit
Device head register 4bit
If you use traditional Chs (Cylinder head sector) addressing, its maximum addressing capacity is:
2 (8 8) * (28-1) * 24 * 512 = 65536 * 255 * 16 * 512 = 136.9GB
If the LBA (Logic Block Addressing) is used, its maximum addressing capacity is: 2 (8 8) * 28 * 24 * 512 = 65536 * 256 * 16 * 512 = 137.4GB
For the INT 13 interface, the register is defined as follows:
Cylindrical status register 8bit
Cylindrical high / sector register 2bit / 6bit
Code register 8bit
If you use traditional Chs (Cylinder head sector) addressing, the maximum addressing capacity is:
210 * (26-1) * 28 * 512 = 8.456GB
If you are addressed by LBA (Logic Block Addressing), the maximum addressing capacity is:
210 * 26 * 28 * 512 = 8.590GB
Note: The calculation formula of the two addressing methods is because the sector first address of the CHS addressing method starts from 1, while the sector first address of the LBA addressing is starting from 0.
At this point, the reason why 8.4GB capacity restrictions have been clear. In summary, there are two aspects: on the one hand, the BIOS program of the motherboard is too old, and the large-capacity hard disk cannot be supported. The parameter to the operating system does not have reliability, and the method of solving this problem is to refresh the BIOS. Method upgrade BIOS; on the other hand because the INT 13 is limited. In order to solve this soft problem, people have defined new extension INTs in turn, and they no longer pass the hard disk parameters using the register of the operating system, but use the address stored in the operating system memory to save the address of the 64-bit LBA address. package. If the hard disk supports ATA, pass the address package low to the ATA interface, otherwise it will be converted to a CHS parameter and then pass it to the ATA interface. From this, the expansion INT 13 can make the maximum addressing capacity reaches around 137GB.
Now start study how to use extended int 13 in C language to operate large-capacity hard drives. In order to make the description, it will only be read, write, and obtain three implementation methods of hard disk parameters. Other operations such as "test hard disk sectors", etc., readers should read the relevant information.
For extended INT 13 interrupts, parameters are as follows:
Interrupt number
Features
Call register
Return register
Note
INT 13
AH = 41h
Detect whether the expansion interrupt function is installed
AH = 41h
BX = 55aah
DL = drive letter
(80h to FFH)
Failure: AH = 1
CF set
Success: ah = version number
Cf = 0 bx = aa55h
INT 13
AH = 42h
Disk extension read operation
AH = 42h
DL = drive letter
DS: Si = pointer to the LBA address package
Failure: AH = error number
CF set
Success: ah = 0
Cf = 0
Address package definition:
Offset size description
00h byte address package size
01H byte retention (0)
02H word transmission package
04h double word pointing data pointer
08h 4 word start addresses
Where LBA = ((Cylinder * head / cylinder magnetic head) * sector / cylinder) sector -1
INT 13
AH = 43H disk expansion write operation
AH = 43h
Al = write logo
DL = drive letter
DS: Si = pointer to the LBA address package
Failure: AH = error number
CF set
Success: ah = 0
Cf = 0
Equally
INT 13
AH = 48h
Get disk parameters
AH = 48h
DL = drive letter
DS: Si = Pointer to the Save Parameter Buffer
Failure: AH = error number
CF set
Success: ah = 0
Cf = 0
Parameter buffer definition:
Offset size description
00H word buffer size
02H word information logo
04H double word physical cylindrical number
08h double word physical head number
0CH double word physics per column number number
10h 4-word sector total
18H word per segment number
With the above parameters, we can easily write programs to operate large-capacity hard drives. Here, several examples show how to write programs implementation operations in the C language. The C language that the author is the compiler of Borland C 3.1.
[Program 1] Detecting the extended INT 13 installation
#include
#include
void main ()
{
Regs regs;
Sregs Sregs;
Regs.h.ah = 0x41; regs.x.bx = 0x55AA; / * Setting register * /
Regs.h.dl = 0x80;
INT86X (0x13, & Regs, & Regs, & Sregs); / * Call interrupt * /
IF (regs.x.bx = = 0xAa55) / * Judgment on the results * /
Printf ("INT 13 EXTENSIONS INSTALLED! / N");
Else
Printf ("INT 13 EXTENSIONS Not Installed! / N");
}
Before using the extended INT 13 interrupt, it is best to use the above program to judge whether the BIOS supports the expansion INT13 so that you can guarantee that your program is correct. Generally, the new DOS7 operating system that supports the LBA mode of the LBA mode and the WIN98 self-contained DOS7 operating system supports extended INT 13.
[Program 2] Get hard disk physical parameters
#include
#include
#include
Typedef unsigned char BYTE; / * Define byte data type name * /
Typedef unsigned short word; / * Define word data type name * /
Typedef unsigned long dword; / * Defines the double word type name * /
void main ()
{
Union regs regs;
Struct Sregs Sregs;
Struct {
Word size; / * address package size * /
Word Inforflags; / * Information Sign * /
DWORD CYLNS; / * Number of physical cylinders * /
DWORD heads; / * Physical head number * /
DWORD SECTS; / * Physics per column sector number * /
DWORD TSLOW; / * The total number of sectors is low * /
DWORD TSHI; / * The total number of sectors is high * /
Word bps; / * Number of fields per channel * /
} package; / * LBA address package definition * /
Regs.h.ah = 0x48;
Regs.h.dl = 0x80;
Sregs.ds = fp_seg (& package); / * Get package address of Package * / regs.x.si = fp_off (& package); / * Get package offset * /
INT86X (0x13, & Regs, & Regs, & Sregs); / * Call interrupt * /
Printf ("Total Cylinders in this Disk is:% ld / n", package.cylns; / * Output information * /
Printf ("Total Heads in this Disk IS:% LD / N", package.heads;
Printf ("TOTAL SECT / CYLN IN THIS DIS:% LD / N", package.sects;
Printf ("Low Bit of Total Sectors IS:% LD / N", package.tslow;
Printf ("High Bit of Total Sectors IS:% LD / N", Package.tshi;
Printf ("BYTES Per Sector of the Disk IS:% D / N", package.bps;
Printf ("Total Space Amount By L-Bit IS:%
.1f
GB / N ", (double) (Package.tslow * 512.0 / POW (10, 9)));
}
For the above programs, the reader can compare it and the parameters of the above table, which can understand the meaning of the various parameters of the table, or better understand this program. The reader can also convert the above program into a function, and then call directly when necessary.
[Program three-disk extension read and write operation]
#include
#include
#define extra_read 0x42
#define ext_write 0x43
#define HDD 0x80
Unsigned long cylinders, heads, sectors;
TYPEDEF UNSIGNED CHAR BYTE
Typedef unsigned short word;
Typedef unsigned long dword;
INT GET_PARAMETER (INT Drive) / * Reads hard disk parameters to calculate LBA data * /
{
Union regs regs;
Struct Sregs Sregs;
Struct {
Word size;
Word inforflags;
DWORD CYLNS;
DWORD heads;
DWORD SECTS;
DWORD TSLOW;
DWORD TSHI;
Word BPS;
} package;
Regs.h.ah = 0x48;
Regs.h.dl = drive;
Sregs.ds = fp_seg (& package);
Regs.x.si = fp_off (& package);
INT86X (0x13, & Regs, & Regs, & Sregs);
Cylinders = package.cylns; / * Assignped the data to the global variable * /
Heads = package.heads;
Sectors = package.sects;
IF (regs.h.ah) return (regs.h.ah);
Else Return 0;
}
Int Iodisk (Unsigned Char DRV, UNSIGNED Char CMD, Unsigned Char * Buffer,
Unsigned long startlow, unsigned long startblk {
Union regs regs;
Struct Sregs Sregs;
Struct {
Unsigned char ging; / * package size * /
Unsigned char res; / * Reserved byte * /
Unsigned short nob; / * package number * /
Unsigned short bufoff; / * Data buffer offset * /
UNSIGNED short bufseg; / * Data buffer address * /
Unsigned long Slow; / * Sector start address low * /
Unsigned long shi; / * sector start address high * /
} package;
Package.len = Sizeof (package);
Package.RES = 0;
Package.nob = CopyBLK;
Package.bufoff = fp_off (buffer);
Package.bufseg = fp_seg (buffer);
Package.slow = startload;
Package.shi = starthi;
Regs.h.ah = cmd;
Regs.h.dl = DRV;
Regs.h.al = 0;
Sregs.ds = fp_seg (& package);
Regs.x.si = fp_off (& package);
INT86X (0x13, & Regs, & Regs, & Sregs);
IF (regs.h.ah) return (regs.h.ah);
Else Return (0);
}
Int iosecTorex (unsigned char DRV, UNSIGNED Char CMD, unsigned long, unsigned long sector, unsigned long copyspace, unsigned char * buffer)
{
Int Err;
UNSIGNED Long LBA;
LBA = (CYLINDER * HEADS Head) * Sectors) Sector - 1; / * Transform the CHS address to the LBA sector address * /
Err = IODISK (DRV, CMD, Buffer, LBA, 0, COPYS); / * Call function readout sector * /
Return ERR;
}
void main ()
{
Unsigned char buffer [512]; / * Define sector data area * /
GET_PARAMETER (HDD); / * Call function to get a hard disk parameter * /
Iosectorex (HDD, EXT_READ, 0, 0, 1, 1, BUFFER); / * Call function read 0 cylindrical 0 head 1 sector content * /
Printf ("% x / n", buffer [511]); / * The last byte of the read sector * /
}
Three call functions are defined in [Program 3] above, and the GET_PARAMETER () function is a function of reading hard disk physical parameters by extending INT 13, and setting this function is mainly for more convenient calculation of the value of the LBA sector address; IODisk () is the most universal sector read and write operation function, which can use the address of the LBA sector to operate sectors directly; the iosectorex () function is to operate the sector using the way to provide a CHS parameter, and the middle is a conversion process.
If you need it, you can use the above functions in your program. For other disk operation functions of extending INT 13, it will not be described here. references
"The Capacity Limit of the Ide Ide Hard Disk" (http://www.pchome.net/), dwell