Chapter – 8
Disk-BIOS Functions and Interrupts Handling With C
Introduction
In this chapter we shall discuss the important Disk-BIOS functions and other important functions which give us the freedom to uses and handle interrupts in our program with C, with the easy and short method. These functions are the back – bone of the data recovery and disk troubleshooting programming. These are the functions that make The C language a “High – level Assembly Language”.
biosdisk and _bios_disk Functions
These two functions are the most important function for our purpose of data recovery and disk troubleshooting programming. We’ll use these functions most of the time.
These two are the BIOS disk drive services and have been defined in bios.h where biosdisk operates below the level of files on raw sectors. If these functions are used even in a little bit lack of care, it can destroy the file contents and directories on a hard disk. Both biosdisk and _bios_disk functions, use interrupt 0x13 to issue disk operations directly to the BIOS. The _bios_disk function is declared in the program in the following manner:
unsigned _bios_disk(unsigned cmd, struct diskinfo_t *dinfo);
And the declaration for the bios disk function is as follows:
int biosdisk(int cmd, int drive, int head, int track,
int sector, int nsects, void *buffer);
The meaning of these parameters has been described in the following table:
Parameter |
Function |
What It Is or what it does |
cmd |
Both |
Indicates the operation to perform such as read, write, verify etc.(See the description of cmd, given next) |
dinfo |
_bios_disk |
Points to a diskinfo_t structure that contains the remaining Parameters required by the operation.(see the description of diskinfo_t structure, given next) |
drive |
biosdisk |
Specifies which disk drive is to be used(0 for a:, 1for b: and 0x80 for first physical hard disk, 0x81 for second and so on.) |
head
track
sector |
biosdisk |
These specify the starting sector location from which the Operation is to be started. |
nsects |
biosdisk |
Number of sectors to read, write, verify etc. |
buffer |
biosdisk |
Memory address where data is to be read or written |
In both of these functions, the data is read into and written from buffer at 512 bytes per sector that is the logical size of sector of a hard disk and the value returned by both functions is the value of the AX register set by the INT 0x13H BIOS call.
If the function is successful, High byte = 0, that means the successful completion and low byte contains the number of sectors read, written or verified and so on.
But if there is any error and function is not successful, the value of High byte will be one of the following error codes which are described in the following table:
Value |
Description |
0x00 |
Successful completion (Not an Error!!) |
0x01 |
Bad command |
0x02 |
Address mark not found |
0x03 |
Attempt to write to write-protected disk |
0x04 |
Sector not found |
0x05 |
Reset failed (hard disk) |
0x06 |
Disk changed since last operation |
0x07 |
Drive parameter activity failed |
0x08 |
Direct memory access (DMA) overrun |
0x09 |
Attempt to perform DMA across 64K boundary
(data Boundary error or >80H sectors) |
0x0A |
Bad sector detected |
0x0B |
Bad track detected |
0x0C |
Unsupported track |
0x0D |
Invalid number of sectors on format (PS/2 hard disk) |
0x0E |
Control data address mark detected (hard disk) |
0x0F |
DMA arbitration level out of range (hard disk) |
0x10 |
Bad CRC/ECC on disk read |
0x11 |
CRC/ECC corrected data error (Not an error actually) |
0x20 |
Controller has failed |
0x31 |
No media in drive (IBM/MS INT 13 extensions) |
0x32 |
Incorrect drive type stored in CMOS (Compaq) |
0x40 |
Seek operation failed |
0x80 |
Attachment failed to respond |
0xAA |
Drive not ready (hard disk only) |
0xB0 |
Volume not locked in drive (INT 13 extensions) |
0xB1 |
Volume locked in drive (INT 13 extensions) |
0xB2 |
Volume not removable (INT 13 extensions) |
0xB3 |
Volume in use (INT 13 extensions) |
0xB4 |
Lock count exceeded (INT 13 extensions) |
0xB5 |
Valid eject request failed (INT 13 extensions) |
0xBB |
Undefined error occurred (hard disk only) |
0xCC |
Write fault occurred |
0xE0 |
Status register error |
0xFF |
Sense operation failed |
The table given next represents the operation commands to be performed by cmd parameter. First of all we shall see the common operations of both the functions.
biosdisk |
_bios_disk |
What it does |
0 |
_DISK_RESET |
Resets disk system, forcing the drive controller to do a hard reset. Ignore all other parameters |
1 |
_DISK_STATUS |
Returns the status of the last disk operation. Ignores all other parameters |
2 |
_DISK_READ |
Reads one or more disk sectors into memory |
3 |
_DISK_WRITE |
Writes one or more disk sectors from memory |
4 |
_DISK_VERIFY |
Verifies one or more sectors |
5 |
_DISK_FORMAT |
Formats a track |
Though you are free to use either cmd = 0, 1, 2, 3, 4,5 or cmd = _DISK_RESET, _DISK_STATUS, _DISK_READ, _DISK_WRITE, _DISK_VARIFY, _DISK_FORMAT and both the options have the same effect, but it is recommended that you should have a habit to use words option such as cmd = _DISK_FORMAT instead of cmd = 5 because it may help you to avoid errors that may take place if you have typed a wrong command number for cmd.
In the declaration of biosdisk or _bios_disk function if we give the cmd = _DISK_RESET the function reset the disk system by ignoring the all other parameters and _DISK_STATUS returns the status of the last disk operation, ignoring the all other parameters
For cmd =_DISK_READ, _DISK_WRITE, or _DISK_VERIFY (2, 3 or 4), biosdisk and _bios_disk functions also use other parameters shown below:
Parameter |
What It Does |
head
track
sector |
These three specify the location of starting sector for the specified operation. (minimum possible values may be head = 0, track = 0 and sector =1) |
nsectors |
This specifies the number of sectors to read or write |
buffer |
It points to the buffer where data is to be read and written |
If the value of cmd is = 5 (_DISK_FORMAT), biosdisk and _bios_disk use the following parameters as according to the description in the table. It is always recommended that you should take care while you are using _DISK_FORMAT and you should know what you are going to with. Lack of knowledge or even a small mistake may make you to face a big loss of data.
Parameter |
What It Does |
head
track |
These specify the location of the track to format |
buffer |
It points to a table of sector headers to be written on the named track |
There are some additional values of cmd which are used only by biosdisk functions. These values of cmd are allowed only for the XT, AT, PS/2, and compatibles. Values have been described in the table given next:
cmd |
What it does |
6 |
Formats a track and sets bad sector flags |
7 |
Formats the drive beginning at a specific track |
8 |
Returns the current drive parameters in first 4 bytes of buffer |
9 |
Initializes drive-pair characteristics |
10 |
Does a long read (512 plus 4 extra bytes per sector) |
11 |
Does a long write (512 plus 4 extra bytes per sector) |
12 |
Does a disk seek |
13 |
Alternates disk reset |
14 |
Reads sector buffer |
15 |
Writes sector buffer |
16 |
Tests whether the named drive is ready |
17 |
Recalibrates the drive |
18 |
Controller RAM diagnostic |
19 |
Drive diagnostic |
20 |
Controller internal diagnostic |
diskinfo_t Structure
diskinfo_t structure is used by _bios_disk function. The description of the structure is as follows:
struct diskinfo_t {
unsigned drive, head, track, sector, nsectors;
void far *buffer;
};
Where drive specifies the disk drive which is to be used. Always remember that for the hard disks, the physical drive is specified, not the disk partition. If you want to operate partitions, the application program must also interpret the partition table information of that disk itself.
The value of head, track and sector specify the location of the starting sector for the operation. nsectors specifies the number of sectors to be read or written and buffer points to the buffer where data is read and written. Depending on the value of cmd, the other parameters in the diskinfo_t structure might or might not be needed.
The value for the specification of disk drive to be used in the biosdisk and _bios_disk functions has been given in the following table:
drive Value |
Disk drive to use |
0 |
First floppy-disk drive |
1 |
Second floppy-disk drive |
2 |
Third floppy-disk drive |
.... |
(and so on) |
0x80 |
First hard-disk drive |
0x81 |
Second hard-disk drive |
0x82 |
Third hard-disk drive |
.... |
(and so on) |
Enough theory! Now let us see some practical things and some example of these functions. The following example reads the sectors of the both sides of four tracks of the floppy and stores the contents to the file, specified by the user. It does not matter, if you have deleted the files from your disk because the program is directly reading the surface of the disk.
To see the deleted data, it is a better ideal that you take a fully formatted floppy disk and copy some text files such as your .c programs coding or other text files ( so that you can understand the contents of the files) occupying approximately 73KB(data stored in four tracks, two sides and 18 sectors in each track. Each sector is of 512bytes). The program has been developed to demonstrate the example. However you can alter and develop it to ready torecover data.
/* Program to read 4 tracks (0, 1, 2 and 3) of a floppy and write the contents to specified file */
#include <bios.h>
#include <stdio.h>
#include<conio.h>
void main(void)
{
int head,track;
int result,i,sector;
char filename[80];
char *buffer;
struct diskinfo_t dinfo;
static char dbuf[512];
FILE *tt;
clrscr();
/// Check if drive is Ready or Not \\\
if(!(biosdisk(4,0,0,0,0,1,buffer) & 0x02))
{
printf(" Drive A: Not Ready:\n Insert disk into Drive A:
and press any key\n");
getch();
}
/* Get the file name to store the data of the Sectors of
the disk */
printf("\nEnter the Destination File name with full Path
to store the data \n\n >");
gets(filename);
if((tt= fopen(filename, "wb"))==NULL)
{
printf("Could not open the File!!!");
getch();
}
for(track=0;track<4;track++)
{
for(head=0; head<=1;head++)
{
for(sector=1;sector<=18;sector++)
{
dinfo.drive = 0; /* drive number for A: */
dinfo.head = head; /* disk head number */
dinfo.track = track; /* track number */
dinfo.sector = sector; /* sector number */
dinfo.nsectors = 1; /* sector count */
dinfo.buffer = dbuf; /* data buffer */
/// Show the Status \\\
gotoxy(10,10); printf("Reading Data from: Head=%d
Track=%d Sector=%d",
head, track, sector);
fprintf(tt,"\n Data read from: Head=%d Track=%d Sector=%d\n",
head, track, sector);
/// Read the Specified Sectors \\\
result = _bios_disk(_DISK_READ, &dinfo);
/// Store the contents in the Specified file \\\
if ((result & 0xff00) == 0)
{
for(i=0;i<512;i++)
fprintf(tt,"%c",dbuf[i] & 0xff);
}
/* Print Error message on screen and in file for Error while Reading a sector */
else
{
printf("\n Can not read at Head= %d Track= %d
Sector= %d\n",head,track,sector);
fprintf(tt,"\n Can not read at Head= %d Track= %d
Sector =%d\n",head,track,sector);
}
}
}
}
fclose(tt);
}
The example shows the use of the functions, biosdisk and _bios_disk. The biosdisk function check if the disk is ready or not and address mark is found. The _bios_disk function reads the sectors of the both sides up to four tracks.
The sequence of reading (or writing) at the surface of the disk should be as follows:
absread and abswrite Functions
These Functions have been defined in Dos.h. The absread function reads absolute disk sectors and the abswrite function writes absolute disk sectors. The function absread uses DOS interrupt 0x25 to read specific disk sectors and the function abswrite uses DOS interrupt 0x26 to write specific disk sectors.
Absolute read or write operations proceeds in sequential manner by incrementing sector(s) step by step and are completely free of the head and track numbers etc. it is the job of BIOS of the computer to translate the absolute sectors to the respective track, Head and Sector numbers.
Absolute read and write operations are recommended in such programs where we are going to perform read/write operation on the entire disk and we want to avoid extra coding and looping in our program to increase the speed of the program to fastest.
Both of the functions absread and abswrite, ignore the logical structure of a disk and pay no attention to files, FATs, or directories. These functions directly perform absolute read and absolute write operation on the surface of the disk, This is the reason that if used improperly, abswrite can overwrite files, directories, and FATs.
The declaration of the absread function is as follows:
int absread(int drive, int nsects, long lsect,
void *buffer);
and the abswrite function is declared as follows:
int abswrite(int drive, int nsects, long lsect,
void *buffer);
Where the meaning of parameters is as follows:
Param. |
What It Is/Does |
drive |
Drive number to read (or write): 0 = A, 1 = B, etc. |
nsects |
Number of sectors to read (or write) |
lsect |
Beginning logical sector number |
buffer |
Memory address where the data is to be read (or written) |
On success, both of the functions return 0. When there is any error, both return -1 and set error no. to the value of the AX register returned by the system call.
The number of sectors for read or write operation is limited to 64K or the size of the buffer, whichever is smaller. However we will learn the use of Huge memory in next chapters to exceed out of the memory limit 64K, to develop a very fast program.
|
Interrupt Handling with C
C is sometimes called a high level assembly language because it can call the different interrupts using some of its some defined functions. Some important functions are as follows:
- int86: Invokes MS-DOS interrupts.
- int86x: Invokes MS-DOS interrupt with segment register values.
- intdos: invokes MS-DOS service using registers other than DX and AL
- intdosx: invokes MS-DOS service with segment register values.
- segread: Reads Segment registers
We shall discuss these functions in detail. First of all we discuss some predefined structure and unions that are frequently or necessarily used with these functions.
SREGS Structure
This structure has been defined in dos.h and it is a structure of the segment registers passed to and filled in by the functions, int86x, intdosx and segread. The declaration of the structure is as follows:
struct SREGS {
unsigned int es;
unsigned int cs;
unsigned int ss;
unsigned int ds;
};
REGS union
REGS is the union of two structures. The union REGS has been defined dos.h and it is used to pass information to and from the functions, int86, int86x, intdos and intdosx. The declaration of the union is as follows:
union REGS {
struct WORDREGS x;
struct BYTEREGS h;
};
BYTEREGS and WORDREGS Structures
The BYTEREGES and WORDREGS structures have been defined in dos.h and these are used for storing byte and word registers. The WORGREGS structure allows the user to access the registers of CPU as 16-bit quantities where BYTEREGES structure gives the access to the individual 8-bit registers.
The BITEREGS structure is declared as follows:
struct BYTEREGS {
unsigned char al, ah, bl, bh;
unsigned char cl, ch, dl, dh;
};
And the WORDREGS structure is declared as follows:
struct WORDREGS {
unsigned int ax, bx, cx, dx;
unsigned int si, di, cflag, flags;
};
int86 and int86x functions
These functions are the general 8086 software interrupt interfaces defined in dos.h. Registers are set to the desired values and these functions are called to invoke the MS-DOS interrupts. The declaration of the int86 function is as follows:
int int86(int intno, union REGS *inregs,
union REGS *outregs);
int86x is the variation of int86 function. It is declared as follows:
int int86x(int intno, union REGS *inregs,
union REGS *outregs, struct SREGS *segregs);
Both the functions int86 and int86x execute an 8086 software interrupt specified by the argument intno Or we can say interrupt to generate is specified by intno.
With int86x function access is possible only to ES and DS and not to CS and SS so you can invoke an 8086 software interrupt that takes a value of DS different from the default data segment and/or takes an argument in ES.
These functions copy register values from inregs into the registers before execution of the software interrupt. The function int86x also copies the segregs->ds and segregs->es values into the corresponding registers before executing the software interrupt. This feature allows programs that use far pointers or a large data memory model to specify which segment is to be used for the software interrupt.
The functions copy the current register values to outregs, status of the carry flag to the x.cflag field in outregs and the value of the 8086 flags register to the x.flags field in outregs, after the software interrupt returns. The function int86x also restores DS and sets the segregs->es and segregs->ds fields to the values of the corresponding segment registers.
In both functions inregs and outregs can point to the same structure and both functions return the value of AX after completion of the software interrupt. If the carry flag is set, it usually indicates that an error has occurred.
The REGS union elements used in C, equivalent to Assembly language have been in the table given next:
16-bit |
8-bit |
C language |
Assembly language |
C language |
Assembly language |
inregs.x.ax |
AX |
inregs.h.al |
AL |
|
|
inregs.h.ah |
AH |
inregs.x.bx |
BX |
inregs.h.bl |
BL |
|
|
inregs.h.bh |
BH |
inregs.x.cx |
CX |
inregs.h.cl |
CL |
|
|
inregs.h.ch |
CH |
inregs.x.dx |
DX |
inregs.h.dl |
DL |
|
|
inregs.h.dh |
DH |
inregs.x.si |
SI |
|
|
inregs.x.di |
DI |
|
|
inregs.x.cflag |
CF |
|
|
Let us see the examples of int86 and int86x functions. The Following Program Scans the every sector of the floppy disk and prints the status of every sector on the screen.
/* Program To Scan Every Sector Of The Floppy Disk and Print the Status */
#include<dos.h>
#include<conio.h>
void main()
{
int head,track,sector,i;
char *buf;
union REGS inregs, outregs;
struct SREGS sregs;
clrscr();
/// Initializing Disk By Resetting Disk System \\\
gotoxy(10,2); printf("Initializing The Disk...");
for(i=0;i<3;i++)
{
inregs.h.ah=0x00; // Function Number
inregs.h.dl=0x00; // Floppy Disk
int86(0x13,&inregs,&outregs);
}
gotoxy(10,2); printf("The Status of the Disk is as....\n");
/* Scan the Floppy Disk from 0 to 79 Tracks (Total Tracks 80) */
for(track=0;track<=79;track++)
for(head=0;head<=1;head++)
for(sector=1;sector<=18;sector++)
{
inregs.h.ah = 0x04; /// function Number
inregs.h.al = 1; /// Number of sectors
inregs.h.dl = 0x00; /// Floppy Disk
inregs.h.ch = track;
inregs.h.dh = head;
inregs.h.cl = sector;
inregs.x.bx = FP_OFF(buf);
sregs.es = FP_SEG(buf);
int86x(0x13,&inregs,&outregs,&sregs);
//// Print The Status of the Scanned Sector \\\\
switch(outregs.h.ah)
{
case 0x00:
cprintf("STATUS: No Error!!");
break;
case 0x01:
cprintf("STATUS: Bad command");
break;
case 0x02:
cprintf("STATUS: Address mark not found");
break;
case 0x03:
cprintf("STATUS: Attempt to write to
write-protected disk");
break;
case 0x04:
cprintf("STATUS: Sector not found");
break;
case 0x05:
cprintf("STATUS: Reset failed (hard disk)");
break;
case 0x06:
cprintf("STATUS: Disk changed since last
operation");
break;
case 0x07:
cprintf("STATUS: Drive parameter activity
failed");
break;
case 0x08:
cprintf("STATUS: Direct memory access (DMA)
overrun");
break;
case 0x09:
cprintf("STATUS: Attempt to perform DMA across
64K boundary");
break;
case 0x0A:
cprintf("STATUS: Bad sector detected");
break;
case 0x0B:
cprintf("STATUS: Bad track detected");
break;
case 0x0C:
cprintf("STATUS: Media type not found");
break;
case 0x0D:
cprintf("STATUS: Invalid number of sectors on
format (hard disk)");
break;
case 0x0E:
cprintf("STATUS: Control data address mark
detected (hard disk)");
break;
case 0x0F:
cprintf("STATUS: DMA arbitration level out of
range (hard disk)");
break;
case 0x10:
cprintf("STATUS: Bad CRC/ECC on disk read");
break;
case 0x11:
cprintf("STATUS: CRC/ECC corrected data error");
break;
case 0x20:
cprintf("STATUS: Controller has failed");
break;
case 0x31:
cprintf("STATUS: No media in drive (IBM/MS INT 13H
extensions)");
break;
case 0x32:
cprintf("STATUS: Incorrect drive type stored in
CMOS (Compaq)");
break;
case 0x40:
cprintf("STATUS: Seek operation failed");
break;
case 0x80:
cprintf("STATUS: Attachment failed to respond
(Disk Timed-out)");
break;
case 0xAA:
cprintf("STATUS: Drive not ready (hard disk
only)");
break;
case 0xB0:
cprintf("STATUS: Volume not locked in drive (INT
13H extensions)");
break;
case 0xB1:
cprintf("STATUS: Volume locked in drive (INT 13H extensions)");
break;
case 0xB2:
cprintf("STATUS: Volume not removable (INT 13H
extensions)");
break;
case 0xB3:
cprintf("STATUS: Volume in use (INT 13H
extensions)");
break;
case 0xB4:
cprintf("STATUS: Lock count exceeded (INT 13H
extensions)");
break;
case 0xB5:
cprintf("STATUS: Valid eject request failed (INT
13H extensions)");
break;
case 0xBB:
cprintf("STATUS: Undefined error occurred (hard
disk only)");
break;
case 0xCC:
cprintf("STATUS: Write fault occurred");
break;
case 0xE0:
cprintf("STATUS: Status register error");
break;
case 0xFF:
cprintf("STATUS: Sense operation failed");
break;
default: cprintf("STATUS: UNKNOWN Status CODE");
}
printf("\nCurrent position= Track:%d Head:%d Sector:%d \n",
track,head,sector);
}
gotoxy(10,24);printf("Scanning Completed!! Press Any Key TO
Exit..");
getch();
}
The program shows the example of use of functions int86 and int86x functions. In this Program the int86 function is initializing the disk by resetting the disk system, using function 00H of INT 13H. The int86x function is verifying every sector of the floppy (1.44Mb, 3½ floppy disk) from both sides, up to 0 to 79 tracks ( total 80 tracks) using the function 04H of INT 13H.
segread Function
This function has been defined in dos.h. This function reads the segment registers. The declaration of the function is as follows:
void segread(struct SREGS *segp);
where segread puts the current values of the segment registers into the structure *segp. Nothing is returned by the function and the call is intended for use with intdosx and int86x. let us see an example
#include <stdio.h>
#include <dos.h>
void main()
{
struct SREGS segs;
segread(&segs);
printf("Current segment register settings\n\n");
printf("CS: %X DS: %X\n", segs.cs, segs.ds);
printf("ES: %X SS: %X\n", segs.es, segs.ss);
getch();
}
And the output of the program will be something like this:
Current segment register settings
CS: EED DS: 10BA
ES: 10BA SS: 10BA
intdos and intdosx Functions
These functions have been defined in dos.h. These are the general DOS interrupt interfaces. The function intdos invokes MS-DOS service registers then DX and AL where the function intdosx invokes MS-DOS service with segment register values.
The Declaration of the intdos function is as follows:
int intdos(union REGS *inregs, union REGS *outregs);
and the declaration of intdosx function is as:
int intdosx(union REGS *inregs, union REGS *outregs,
struct SREGS *segregs);
The functions intdos and intdosx execute DOS interrupt 0x21 to invoke a specified DOS function. The value of inregs->h.ah specifies the DOS function to be invoked. The function intdosx also copies the segregs ->ds and segregs ->es values into the corresponding registers before invoking the DOS function and then restores DS.
This feature of the functions allows the programs that use far pointers or a large data memory model specify which segment is to be used for the function execution. With intdosx function you can invoke a DOS function that takes a value of DS different from the default data segment and/or takes an argument in ES.
Both the functions return the value of AX after completion of the DOS function call and if the carry flag is set (outregs -> x.cflag != 0), it indicates that an error occurred.
After the interrupt 0x21 returns the functions copy the current register values to outregs, status of the carry flag to the x.cflag field in outregs and value of the 8086 flags register to the x.flags field in outregs. Both inregs and outregs can point to the same structure. Let us see the examples of these functions.
The example of the use of intdos function has been given below. This program obtains the selected information about the floppy (1.44Mb, 3½ inch floppy disk) disk drive. This program provides the allocation information of a floppy disk.
/* The get drive allocation information for disk usage */
#include <dos.h> /* for intdos() and union REGS */
#include <stdio.h> /* for printf() */
union REGS inregs, outregs;
void main()
{
inregs.h.ah = 0x36; /* get disk free space
function number */
inregs.h.dl = 0x01; /* drive A: */
intdos(&inregs, &outregs);
printf("%d sectors/cluster,\n%d clusters,\n%d bytes/sector,
\n%d total clusters",
outregs.x.ax,outregs.x.bx,
outregs.x.cx, outregs.x.dx);
getch();
}
And output of the program will be like this:
1 sectors/cluster,
1933 clusters,
512 bytes/sector,
2843 total clusters
Now let us see an example of the function intdosx. The following example shows the use of intdosx function. The program outputs a string to the standard output.
/* The program to output 'string' to the standard
output. */
#include <dos.h>
union REGS inregs, outregs;
struct SREGS segregs;
char far *string = "this string is not in the
default data segment$";
void main()
{
inregs.h.ah = 0x09; /* function number */
inregs.x.dx = FP_OFF(string);/*DS:DX is far
address of 'string */
segregs.ds = FP_SEG(string);
intdosx(&inregs, &outregs, &segregs);
getch();
}
And the output of the program will be as follows:
this string is not in the default data segment |
Here we are printing the given string with the function intdosx, by function 09H of INT 21H. It should always be kept in mind that the given string should always end with the character “$”.
How to know the Physical Hard Drive Number
The physical hard drive number is a very important thing and should be written exact. The illegal drive specification may cause a major data loss. We must be confident about the drive number during the data recovery or disk troubleshooting programming. How to know the drive number of any disk with different arrangements of disks can be estimated by the examples given next.
According to a most generalized Myth, The physical drive numbers are provided according to the attachment status of the disk however in some or special cases it may be dependent for your Operating system’s Boot procedure or boot settings.
The most generalized idea for the Physical drive number provided by BIOS has been given here but even then you must confirm with the help of any disk editing tool or with the programs given in the next chapters, about the configuration of the disk. After being sure you should take any decision about running such programs which may corrupt or harm the data, if used illegally or in lack of knowledge.
Generally, If the two disks are attached to the system, one is primary master and another is secondary master, the first preference will be given to the primary master (and then to primary slave if available) and then to secondary master (and then to secondary slave if available and so on) and the physical number will be given according to their preferences.
Let us assume that your system supports the maximum four hard disks at a time. The all four hard disks may be connected as given Next:
Primary Master |
Primary Slave |
Secondary Master |
Secondary Slave |
Now let us consider some cases for drive number of physical drives. Here I assume that you have connected the disks with proper jumper settings as mentioned by the disk manufacturer, and in proper Master–Slave settings:
- If all four Hard Disks are connected to the system: if all four disks are connected to the system the physical drive numbers will be as follows:
Primary/Secondary (Master/Slave) |
Status |
Physical Drive Number and Description |
Primary Master |
Disk is Present |
Physical Drive Number will be 80H. In this case the Hard Disk is called the First Hard Disk. |
Primary Slave |
Disk is Present |
Physical Drive Number will be 81H. In this case the Hard Disk is called the Second Hard Disk. |
Secondary Master |
Disk is Present |
Physical Drive Number will be 82H. In this case the Hard Disk is called the Third Hard Disk. |
Secondary Slave |
Disk is Present |
Physical Drive Number will be 83H. In this case the Hard Disk is called the Fourth Hard Disk. |
- If three Hard Disks are connected to the system: if three Hard Disks are connected to the system the physical drive numbers will be as according to their attachment preferences. The following examples represent some of the arrangements:
Primary/Secondary (Master/Slave) |
Status |
Physical Drive Number and Description |
Primary Master |
Disk is Present |
Physical Drive Number will be 80H. In this case the Hard Disk is called the First Hard Disk. |
Primary Slave |
Disk is Present |
Physical Drive Number will be 81H. In this case the Hard Disk is called the Second Hard Disk. |
Secondary Master |
Disk is Present |
Physical Drive Number will be 82H. In this case the Hard Disk is called the Third Hard Disk. |
Secondary Slave |
Disk Not Present |
------------------- |
Primary/Secondary (Master/Slave) |
Status |
Physical Drive Number and Description |
Primary Master |
Disk Not Present |
------------------- |
Primary Slave |
Disk is Present |
Physical Drive Number will be 80H. In this case the Hard Disk is called the First Hard Disk. |
Secondary Master |
Disk is Present |
Physical Drive Number will be 81H. In this case the Hard Disk is called the Second Hard Disk. |
Secondary Slave |
Disk is Present |
Physical Drive Number will be 82H. In this case the Hard Disk is called the Third Hard Disk. |
Primary/Secondary (Master/Slave) |
Status |
Physical Drive Number and Description |
Primary Master |
Disk is Present |
Physical Drive Number will be 80H. In this case the Hard Disk is called the First Hard Disk. |
Primary Slave |
Disk Not Present |
------------------- |
Secondary Master |
Disk is Present |
Physical Drive Number will be 81H. In this case the Hard Disk is called the Second Hard Disk. |
Secondary Slave |
Disk is Present |
Physical Drive Number will be 82H. In this case the Hard Disk is called the Third Hard Disk. |
Primary/Secondary (Master/Slave) |
Status |
Physical Drive Number and Description |
Primary Master |
Disk is Present |
Physical Drive Number will be 80H. In this case the Hard Disk is called the First Hard Disk. |
Primary Slave |
Disk is Present |
Physical Drive Number will be 81H. In this case the Hard Disk is called the Second Hard Disk. |
Secondary Master |
Disk Not Present |
------------------- |
Secondary Slave |
Disk is Present |
Physical Drive Number will be 82H. In this case the Hard Disk is called the Third Hard Disk. |
- If two Hard Disks are connected to the system: Similarly, if two Hard Disks are connected to the system the physical drive numbers will be as according to their attachment preferences. Following example illustrates it:
Primary/Secondary (Master/Slave) |
Status |
Physical Drive Number and Description |
Primary Master |
Disk is Present |
Physical Drive Number will be 80H. In this case the Hard Disk is called the First Hard Disk. |
Primary Slave |
Disk Not Present |
------------------- |
Secondary Master |
Disk Not Present |
------------------- |
Secondary Slave |
Disk is Present |
Physical Drive Number will be 81H. In this case the Hard Disk is called the Second Hard Disk. |
- If Single Hard Disk is connected to the system: Need not to think, if there is only one disk available, the physical drive number will be 80H.
Interrupt 13H (INT 13H), ROM BIOS Disk Driver Functions
The description of INT 13H functions has been given here. These functions should be learnt with care, as the misuse of these functions or use in lack of care or lack of knowledge, may cause big loss of data or many other problems. However if used in a appropriate and proper way these functions help to minimize the coding of your program and to make your programming simple and easy as well as.
INT 13H (0x13)
Function 00H (0x00) Reset disk system
Call with AH = 00H
DL = drive
00H-7FH floppy disk
80H-FFH fixed disk
Returns: If function is successful
Carry flag = clear
AH = 00H
If function is unsuccessful
Carry flag = set
AH = status
Comments:
Reset the disk controller, recalibrates its attached drives. The read/write arm is moved to cylinder 0 and prepares for the disk I/O.
This function should be called after a failed floppy disk Read, write, Verify, or Format request before retrying the operation. If the function is called with a fixed disk drive (i.e. selecting DL>=80H), the floppy disk controller and then the fixed disk controller are reset.
INT 13H (0x13)
Function 01H (0x01) Get disk system status
Call with: AH = 01H
DL = drive
00H-7FH floppy disk
80H-FFH fixed disk
Returns: AH = 00H
AL = status of previous disk operation
(See the table given before for error
and status codes description).
Comments:
Returns the status of the most recent disk operation
INT 13H (0x13)
Function 02H (0x02) Read sector
Call with: AH = 02H
AL = number of sectors
CH = cylinder
CL = sector
DH = head
DL = drive
00H-7FH floppy disk
80H-FFH fixed disk
ES:BX = segment: offset of buffer
Returns: If function successful
Carry flag = clear
AH = 00H
AL = number of sectors transferred
If function unsuccessful
Carry flag = set
AH = status
Comments:
This function reads one or more sectors from disk into memory. On fixed disks, the upper 2 bits of the 10-bit cylinder number are placed in the upper 2 bits of register CL.
INT 13H (0x13)
Function 03H (0x03) Write sector
Call with: AH = 03H
AL = number of sectors
CH = cylinder
CL = sector
DH = head
DL = drive
00H-7FH floppy disk
80H-FFH fixed disk
ES: BX = segment: offset of buffer
Returns: If function successful
Carry flag = clear
AH = 00H
AL = number of sector transferred
If function unsuccessful
Carry flag = set
AH = status
Comments:
This function writes one or more sectors from memory to disk. On fixed disks, the upper 2 bits of the 10-bit cylinder number are placed in the upper 2 bits of register CL.
INT 13H (0x13)
Function 04H (0x04) >> Verify sector
Call with: AH = 04H
AL = number of sectors
CH = cylinder
CL = sector
DH = drive
00H-7FH floppy disk
80H-FFH fixed drive
ES: BX = segment: offset of buffer
Returns: If function is successful
Carry flag = clear
AH = 00H
AL = number of sectors verified
If function is unsuccessful
Carry flag = set
AH = status
Comments:
This function verifies the address fields of one or more sectors. No data is transferred to or from memory by this operation. On fixed disks, the upper 2 bits of the 10-bit cylinder number re placed in the upper 2 bits of register CL.
This function can be used to test whether a readable media is in a floppy disk drive. The requesting program should reset the floppy disk system (INT 13H Function 00H) and retry the operation three times before assuming that a readable floppy disk is not present. It is recommended in most of the floppy initialization operations.
INT 13H (0x13)
Function 05H (0x05) >> Format track
Call with: AH = 05H
AL = interleave (PC/XT fixed disks)
CH = cylinder
DH = head
DL = drive
00H-7FH floppy disk
80H-FFH fixed disk
ES: BX = segment: offset of address field list
(Except PC/XT fixed disk)
Returns: If function successful
Carry flag = clear
AH = 00H
If function unsuccessful
Carry flag = set
AH = status (see the status table given
earlier)
Comments:
Initialize disk sector and tracks address fields on the specified track. On floppy disks, the address field list consists of a series of 4-byte entries, one entry per sector. The Format has been given in the following table.
On fixed disks, the upper 2-bits of the 10-bits cylinder number are placed in the upper 2 bits of register CL.
Byte |
Contents |
0 |
Cylinder |
1 |
Head |
2 |
Sector |
3
|
Sector-size code
Value |
Description |
00H |
128 Byte per sector |
01H |
256 Byte per sector |
02H |
512 Byte per sector |
03H |
1024 Byte per sector |
|
INT 13H (0x13)
Function 06H (0x06) >> Format bad track
Call with: AH = 06H
AL = interleave
CH = cylinder
DH = head
DL = drive
80H-FFH fixed disk
Returns:If function successful
Carry flag = clear
AH = 00H
If function unsuccessful
Carry flag = set
AH = status
Comments:
This function is defined for PC/XT fixed disk drives only. It initializes a track, writing disk address fields and data sectors and setting bad sector flags.
INT 13H (0x13)
Function 07H (0x07) >> Format drive
Call with: AH = 07H
AL = interleave
CH = cylinder
DL = drive
80H-FFH fixed disk
Returns: If function successful
Carry flag = clear
AH = 00H
If function unsuccessful
Carry flag = set
AH = status (see the status table given
earlier)
Comments:
This function is defined for PC/XT fixed disk drives only. It formats the entire drive, writing disk address fields and data sectors, starting at the specified cylinder.
INT 13H (0x13)
Function 08H (0x08) >> Get drive parameters
Call with: AH = 08H
DL = drive
00H-7FH floppy disk
80H-FFH fixed disk
Returns: If function successful
Carry flag = clear
BL = drive type (PC/AT and PS/2 floppy
disk)
Value |
Description |
01H |
360KB, 40 track, 5.25” |
02H |
1.2MB, 80 track, 5.25” |
03H |
720KB, 80 track, 3.5” |
04H |
1.44MB, 80 track, 3.5” |
CH = low 8 bits of maximum cylinder
number
CL = bits 6-7 high order 2 bits of maximum
cylinder number bits 0-5 maximum
sector number
DH = maximum head number
DL = number of drives
ES: DI = segment: offset of disk drive
parameter table
If function unsuccessful
Carry flag = set
AH = status
Comments:
This function returns various parameters for the specified drive. The value returned in register DL reflects the true number of physical drives attached to the adapter for the requested drive.
INT 13H (0x13)
Function 09H (0x09) >> Initialize fixed disk characteristics
Call with: AH = 09H
DL = drive
80H-FFH fixed disk
On the PC/XT Vector for INT 41H
must point to disk parameter block or, on the PC/AT and PS/2
Vector for INT 41H must point to disk
parameter block for drive 0
Vector for INT 46H must point to disk
parameter block for drive 1
Returns: If function successful
Carry flag = clear
AH = 00H
If function unsuccessful
Carry flag = set
AH = status
Comments:
This function initializes the fixed disk controller for subsequent I/O operations, using the values found in the ROM BIOS disk parameter block(s). The function is supported on fixed disk only. The parameter block format for PC and PC/XT fixed disks is as follows:
Byte(s) |
Contents |
00H-01H |
Maximum number of cylinders |
02H |
Maximum number of heads |
03H-04H |
Starting reduced write current cylinder |
05H-06H |
Starting write pre compensation cylinder |
07H |
Maximum ECC burst length |
08H
|
Drive option
Bit(s) |
Significance (if set) |
0 – 2 |
drive option |
3 – 5 |
reserved (0) |
6 |
disable ECC entries |
7 |
disable disk-access retries |
|
09H |
Standard time-out value |
0AH |
Time-out value for format drive |
0BH |
Time-out value for check drive |
0CH-0FH |
Reserved |
The parameter block format for PC/AT and PS/2 fixed disks is as follows:
Byte(s) |
Contents |
00H_01H |
maximum number of cylinders |
02H |
maximum number of heads |
03H-04H |
Reserved |
05H-06H |
starting write pre compensation cylinder |
07H |
maximum ECC burst length |
08H |
Drive options
Bit(s) |
Significance (if set) |
0 – 2 |
not used |
3 |
more than 8 heads |
4 |
not used |
5 |
manufacturer’s defect map present at
maximum cylinder +1 |
6 – 8 |
nonzero (10, 01,or 11) if retries disabled |
|
09H-0BH |
Reserved |
0CH-0DH |
landing zone cylinder |
0EH |
sector per track |
0FH |
Reserved |
INT 13H (0x13)
Function 0A H (0x0A or 10) >> Read sector long
Call with: AH = 0AH
AL = number of sectors
CH = cylinder
CL = sector
DH = head
DL = drive
80H-FFH fixed disk
ES: BX = segment: offset of buffer
Returns:If function successful
Carry flag = clear
AH = 00H
AL = number of sectors transferred
If function unsuccessful
Carry flag = set
AH = status
Comments:
This function reads a sector or sectors from disk into memory along with a 4 byte Error Correcting Code (ECC) code for each sector. Unlike the normal Read sector function (INT 13H (0x13) Function 02H), ECC errors are not automatically corrected. Multi sector transfers are terminated after any sector with a read error.
This function is supported on fixed disks only. The upper 2 bits of the 10-bit cylinder number are placed in the upper 2 bits of register CL.
INT 13H (0x13)
Function 0BH (0x0B or 11) >> Write sector long
Call with:AH = 0BH
AL = number of sectors
CH = cylinder
CL = sector
DH = head
DL = drive
80H-FFH fixed disk
ES: BX = segment: offset of buffer
Returns:If function successful
Carry flag = clear
AH = 00H
AL = number of sectors transferred
If function unsuccessful
Carry flag = set
AH = status
Comments:
This function writes a sector(s) from memory to disk. Each sector’s worth of data must be followed by its 4-byte ECC code. The upper 2 bits of the 10-bit cylinder number are placed in the upper 2 bits of register CL. This function is supported on fixed disks only.
INT 13H (0x13)
Function 0CH (0x0C or 12) >> Seek
Call with:AH = 0CH
CH = lower 8 bits of cylinder
CL = upper 2 bits of cylinder in bits 6-7
DH = head
DL = drive
80H-FFH fixed disk
Returns:If function successful
Carry flag = clear
AH = 00H
If function unsuccessful
Carry flag = set
AH = status
Comments:
This function positions the disk read/write heads to the specified cylinder without transferring any data. The upper 2 bits of the cylinder number are placed in the upper 2 bits of register CL. This function is supported on fixed disks only.
INT 13H (0x13)
Function 0DH (0x0D or 13) >> Reset fixed disk system
Call with:AH = 0DH
DL = drive
80H-FFH fixed disk
Returns:If function successful
Carry flag = clear
AH = 00H
If function unsuccessful
Carry flag = set
AH = status (see INT 13H Function 01H)
Comments:
This function resets the fixed disk controller, recalibrates attached drives, moves the read/write arm to cylinder 0, and prepares for subsequent disk I/O.
INT 13H (0x13)
Function 0EH (0x0E or 14) >> Read sector buffer
Call with:AH = 0EH
ES: BX = segment: offset of buffer
Returns:If function successful
Carry flag = clear
If function unsuccessful
Carry flag = set
AH = status
Comments:
This function transfers the contents of the internal sector buffer of the fixed disk adapter to the system memory. No data is read from the physical disk drive.
INT 13H (0x13)
Function 0FH (0x0F or 15) >> Write sector buffer
Call with:AH = 0FH
ES: BX = segment: offset of buffer
Returns:If function successful
Carry flag = clear
If function unsuccessful
Carry flag = set
AH = status
Comments:
This function transfers data from system memory to internal sector buffer of the fixed adapter. No data is written to the physical disk drive. This function should be called to initialize the contents of the sector buffer before formatting the drive with INT 13H Function 05H.
INT 13H (0x13)
Function 10H (0x10 or 16) >> Get drive status
Call with:AH = 10H
DL = drive
80H-FFH fixed disk
Returns:If function successful
Carry flag = clear
AH = 00H
If function unsuccessful
Carry flag = set
AH = status
Comments:
This function tests whether the specified fixed disk drive is operational and returns the drive’s status. This function is supported on fixed disks only.
INT 13H (0x13)
Function 11H (0x11 or 17) >> Recalibrate drive
Call with:AH =11H
DL = drive
80H-FFH fixed disk
Returns:If function successful
Carry flag = clear
AH = 00H
If function unsuccessful
Carry flag = set
AH = status
Comments:
This function causes the fixed disk adapter to recalibrate itself for the specified drive, positioning the read/write arm to cylinder 0, and returns the drive’s status. This function is supported on fixed disks only.
INT 13H (0x13)
Function 12H (0x12 or 18) >> Controller RAM
diagnostic
Call with:AH = 12H
Returns:If function successful
Carry flag = clear
If function unsuccessful
Carry flag = set
AH = status
Comments:
This function causes the fixed disk adapter to carry out a built-in diagnostic test on its internal sector buffer, indicating whether the test was passed by the returned status.
INT 13H (0x13)
Function 13H (0x13 or 19) >> Controller drive diagnostic
Call with:AH = 13H
Returns:If function successful
Carry flag = clear
If function unsuccessful
Carry flag = set
AH = status
Comments:
This function causes the fixed adapter to run internal diagnostic tests of the attached drive, indicating whether the test was passed by the returned status.
INT 13H (0x13)
Function 14H (0x14 or 20) >> Controller internal
diagnostic
Call with:AH = 14H
Returns:If function successful
Carry flag = clear
AH = 00H
If function unsuccessful
Carry flag = set
AH = status
Comments:
This function causes the fixed disk adapter to carry out a built-in diagnostic self-test, indicating whether the test was passed by the returned status.
INT 13H (0x13)
Function 15H (0x15 or 21) >> Get disk type
Call with:AH = 15H
DL = drive
00H-7FH floppy disk
80H-FFH fixed disk
Returns:If function successful
Carry flag = clear
AH = drive type code
00H if no drive present
01H if floppy disk drive without change-line support
02H if floppy disk drive with change-line support
03H if fixed disk
|
And, if fixed disk (AH =03H)
CX: DX = number of 512-byte sectors
If function unsuccessful
Carry flag = set
AH = status
Comments:
This function returns a code indicating the type of floppy or fixed disk referenced by the specified drive code.
INT 13H (0x13)
Function 16H (0x16 or 22) >> Get disk change
status
Call with: AH = 16H
DL = drive
00H-7FH floppy disk
Returns:If change line inactive and disk has not been changed
Carry flag = clear
AH = 00H
If change line active and disk may have been changed
Carry flag = set
AH = 06H
Comments:
This function returns the status of the change line, indicating whether the disk in the drive may have been replaced since the last disk access. If this function returns with the carry flag set, the disk has not necessarily been changed and the change line can be activated by simply unlocking and locking the disk drive door without removing the floppy disk.
INT 13H (0x13)
Function 17H (0x17 or 23) >> Set disk type
Call with: AH = 17H
AL = floppy disk type code
Value |
Description |
00H |
Not used |
01H |
320/360 KB floppy disk in 360 KB drive |
02H |
320/360 KB floppy disk in 1.2 MB drive |
03H |
1.2 MB floppy disk in 1.2 MB drive |
04H |
720 KB floppy disk in 720 KB drive |
SL = drive
00H-7FH floppy disk
Returns: If function successful
Carry flag = clear
AH = 00H
If function unsuccessful
Carry flag = set
AH = status
Comments:
This function selects a floppy disk type for the specified drive.
INT 13H (0x13)
Function 18H (0x18 or 24) >> Set media type for format
Call with: AH = 18H
CH = number of cylinders
CL = sector per track
DL = drive
00H-7FH floppy disk
Returns: If function successful
Carry flag = clear
AH = 00H
ES: DI = segment: offset of disk
parameter table for media type
If function unsuccessful
Carry flag = set
AH = status
Comments:
This function selects media characteristics for the specified drive therefore A floppy disk must be present in the drive.
INT 13H (0x13)
Function 19H (0x19 or 25) >> Park heads
Call with: AH = 19H
DL = drive
80H-FFH fixed disk
Returns: If function successful
Carry flag = clear
AH = 00H
If function unsuccessful
Carry flag = set
AH = status
Comments:
This function moves the read/write arm to a track that is not used for data storage, so that data will not be damaged when the drive is turned off.
INT 13H (0x13)
Function 1AH (0x1A or 26) >> Format ESDI drive
Call with: AH = 1AH
AL = Relative Block Address (RBA)
defect table count
0, if no RBA table
>0, if RBA table used
CL = format modifier bits
Bit(s) |
Significance (if set) |
0 |
Ignore primary defect map |
1 |
Ignore secondary defect map |
2 |
Update secondary defect map |
3 |
Perform extended surface analysis |
4 |
Generate periodic interrupt |
5-7 |
Reserved (must be 0) |
DL = drive
80H-FFH fixed disk
ES: BX = segment: offset of RBA table
Returns: If function successfu
Carry flag = clear
AH = 00H
If function unsuccessful
Carry flag = set
AH = status (see INT 13H Function 01H)
Comments:
This function initialize disk sector and track address fields on a drive attached to the ESDI Fixed Disk Drive Adapter.
The operation of this function is called a low level format and prepares the disk for physical read/write operations at the sector level. The drive must be subsequently partitioned with the FDISK command and then given a high level format with the FORMAT command to install a file system.
Page Modified on: 12/01/2022