📄 pdiskio.c
字号:
/*
// Module: PDISKIO.C
// Module Description: Disk Input/Output Code Module
// All functions that access the hard disk via
// interrupt 0x13 are here, including LBA support.
// Written By: Brian E. Reifsnyder
// Module Version: 3.0
// Copyright: 2001 under the terms of the GNU GPL, Version 2
*/
/*
/////////////////////////////////////////////////////////////////////////////
// SPECIAL
/////////////////////////////////////////////////////////////////////////////
*/
#define PDISKIO
#include "main.h"
/*
/////////////////////////////////////////////////////////////////////////////
// INCLUDES
/////////////////////////////////////////////////////////////////////////////
*/
#include <conio.h>
#include <bios.h>
#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "pdiskio.h"
extern void Pause(void);
/*
/////////////////////////////////////////////////////////////////////////////
// PROTOTYPES
/////////////////////////////////////////////////////////////////////////////
*/
/* Module Prototype Declarations */
/* ***************************** */
int Get_Hard_Drive_Parameters(int physical_drive);
int Read_Physical_Sectors_CHS(int drive,long cylinder, long head, long sector, int number_of_sectors);
int Read_Physical_Sectors_LBA(int drive,long cylinder, long head, long sector, int number_of_sectors);
int Write_Physical_Sectors_CHS(int drive, long cylinder, long head, long sector, int number_of_sectors);
int Write_Physical_Sectors_LBA(int drive, long cylinder, long head, long sector, int number_of_sectors);
long Translate_CHS_To_LBA(unsigned long cylinder,unsigned long head
,unsigned long sector,unsigned long total_heads,unsigned long total_sectors);
void Clear_Partition_Table_Area_Of_Sector_Buffer(void);
void Check_For_INT13_Extensions();
void Convert_Logical_To_Physical(unsigned long sector
,unsigned long total_heads,unsigned long total_sectors);
void Get_Partition_Information(void);
int Determine_Drive_Letters();
int Read_Partition_Tables();
int Read_Physical_Sectors(int drive, long cylinder, long head, long sector, int number_of_sectors);
int Write_Logical_Sectors(unsigned char drive_letter[2]
, unsigned long logical_sector_number, int number_of_sectors);
int Write_Partition_Tables();
int Write_Physical_Sectors(int drive, long cylinder, long head, long sector, int number_of_sectors);
unsigned long Decimal_Number(unsigned long hex1, unsigned long hex2, unsigned long hex3, unsigned long hex4);
void StorePartitionInSectorBuffer( char *sector_buffer,struct Partition *pPart);
void Check_For_INT13_Extensions();
void Clear_Sector_Buffer();
void Initialize_LBA_Structures();
void Load_Brief_Partition_Table();
/* External Prototype Declarations */
/* ******************************* */
extern void Clear_Extended_Partition_Table(int drive);
extern void Clear_Screen(int type);
/* extern void Convert_Long_To_Integer(long number);*/
extern void Pause();
extern void Print_Centered(int y,char *text,int style);
extern void Position_Cursor(int row,int column);
/*
/////////////////////////////////////////////////////////////////////////////
// FUNCTIONS
/////////////////////////////////////////////////////////////////////////////
*/
/* Check for interrupt 0x13 extensions */
void Check_For_INT13_Extensions()
{
int carry;
int drive_number=0x80;
unsigned int ah_register;
unsigned int bx_register;
unsigned int cx_register;
#ifdef DEBUG
if(debug.lba==TRUE)
{
Clear_Screen(NULL);
Print_Centered(0,"void Check_For_INT13_Extensions() debugging screen",BOLD);
printf("\n\n drive int 0x13 ext? access w/packet\n\n");
}
#endif
do
{
carry=99;
asm{
mov ah,0x41
mov bx,0x55aa
mov dl,BYTE PTR drive_number
int 0x13
mov BYTE PTR ah_register,ah
mov WORD PTR bx_register,bx
mov WORD PTR cx_register,cx
jnc carry_flag_not_set /* Jump if the carry flag is clear */
} /* If the carry flag is clear, then */
/* the extensions exist. */
carry=1;
part_table[(drive_number-128)].ext_int_13=FALSE;
carry_flag_not_set:
if( (carry==99) && (bx_register==0xaa55) )
{
flags.use_extended_int_13=TRUE;
part_table[(drive_number-128)].ext_int_13=TRUE;
if((cx_register&0x0001)==1) part_table[(drive_number-128)].device_access_using_packet_structure=TRUE;
else part_table[(drive_number-128)].device_access_using_packet_structure=FALSE;
part_table[(drive_number-128)].ext_int_13_version=ah_register;
#ifdef DEBUG
if(debug.lba==TRUE)
{
printf(" 0x%2x yes",drive_number);
if((cx_register&0x0001)==1) printf(" yes");
else printf(" no");
printf("\n");
}
#endif
}
#ifdef DEBUG
else if(debug.lba==TRUE) printf(" 0x%2x no\n",drive_number);
#endif
drive_number++;
}while(drive_number<0x88);
#ifdef DEBUG
if(debug.lba==TRUE)
{
printf("\n\n\n");
Pause();
}
#endif
}
/* Clear the Boot Sector of a partition */
void Clear_Boot_Sector(int drive,long cylinder,long head,long sector)
{
unsigned char stored_sector_buffer[512];
long index;
/* Save sector_buffer[512] into stored_sector_buffer[512] */
memcpy(stored_sector_buffer,sector_buffer,512);
/* Write all 0xf6 values to sector_buffer[index] */
memset(sector_buffer,0xf6,512);
for (index=0; index < 16; index++)
{
Write_Physical_Sectors(drive,cylinder,head,(sector+index),1);
}
/* Restore sector_buffer[512] to its original contents */
memcpy(sector_buffer,stored_sector_buffer,512);
}
/* Clear The Partition Table Area Of sector_buffer only. */
void Clear_Partition_Table_Area_Of_Sector_Buffer()
{
memset(sector_buffer+0x1be,0,4*16);
}
/* Clear Sector Buffer */
void Clear_Sector_Buffer()
{
memset(sector_buffer,0,512);
}
/* Combine Cylinder and Sector Values */
unsigned long Combine_Cylinder_and_Sector(unsigned long cylinder, unsigned long sector)
{
long value = 0;
asm{
mov ax,WORD PTR cylinder
mov bx,WORD PTR sector
mov dl,ah
shl dl,1
shl dl,1
shl dl,1
shl dl,1
shl dl,1
shl dl,1
mov dh,al
add dx,bx
mov WORD PTR value,dx
}
return(value);
}
/* Determine drive letters */
int Determine_Drive_Letters()
/* Returns last used drive letter as ASCII number. */
{
// int active_found=FALSE;
int current_letter='C';
// int drive_found=FALSE;
int index=0;
int non_dos_partition;
int non_dos_partition_counter;
int sub_index=0;
int active_part_found[8];
Load_Brief_Partition_Table();
/* Clear drive_lettering_buffer[8] [27] */
index=0;
do
{
sub_index=0;
do
{
drive_lettering_buffer[index] [sub_index]=0;
sub_index++;
}while(sub_index<27);
index++;
}while(index<8);
/* Set all active_part_found[] values to 0. */
index=0;
do
{
active_part_found[index]=0;
index++;
}while(index<8);
/* Begin placement of drive letters */
/* First, look for and assign drive letters to all active */
/* primary partitions. */
index=0;
do
{
Partition_Table *pDrive = &part_table[index];
sub_index=0;
do
{
if( (IsRecognizedFatPartition(brief_partition_table[index] [sub_index]))
&& (pDrive->pri_part[sub_index].active_status==0x80) )
{
drive_lettering_buffer[index] [sub_index]=current_letter;
active_part_found[index]=1;
sub_index=5; /* get out of loop */
current_letter++;
}
sub_index++;
}while(sub_index<4);
index++;
}while(index<8);
/* Next, assign one drive letter for one existing primary partition */
/* if an active partition does not exist on that hard disk. */
index=0;
do
{
if(active_part_found[index]==0)
{
sub_index=0;
do
{
if(IsRecognizedFatPartition(brief_partition_table[index] [sub_index]))
{
drive_lettering_buffer[index] [sub_index]=current_letter;
current_letter++;
sub_index=5; /* Set sub_index = 5 to break out of loop early. */
}
sub_index++;
}while(sub_index<4);
}
index++;
}while(index<8);
/* Next assign drive letters to applicable extended partitions... */
index=0;
do
{
sub_index=4;
do
{
if(IsRecognizedFatPartition (brief_partition_table[index] [sub_index]))
{
drive_lettering_buffer[index] [sub_index]=current_letter;
current_letter++;
}
sub_index++;
}while(sub_index<27);
index++;
}while(index<8);
/* Return to the primary partitions... */
index=0;
do
{
sub_index=0;
do
{
if( drive_lettering_buffer[index] [sub_index]==0)
{
if (IsRecognizedFatPartition(brief_partition_table[index] [sub_index]))
{
drive_lettering_buffer[index] [sub_index]=current_letter;
current_letter++;
}
}
sub_index++;
}while(sub_index<4);
index++;
}while(index<8);
/* Find the Non-DOS Logical Drives in the Extended Partition Table */
non_dos_partition_counter='1';
index=0;
do
{
Partition_Table *pDrive = &part_table[index];
pDrive->num_of_non_dos_log_drives=0;
sub_index=4;
do
{
if(brief_partition_table[index] [sub_index]>0)
{
non_dos_partition=TRUE;
if( IsRecognizedFatPartition(brief_partition_table[index] [sub_index]))
{
non_dos_partition=FALSE;
}
if( (non_dos_partition==TRUE) && (non_dos_partition_counter<='9') )
{
drive_lettering_buffer[index] [sub_index]=non_dos_partition_counter;
pDrive->num_of_non_dos_log_drives++;
non_dos_partition_counter++;
}
}
sub_index++;
}while(sub_index<27);
non_dos_partition_counter='1';
index++;
}while(index<8);
return(current_letter-1);
}
/* Extract Cylinder */
unsigned long Extract_Cylinder(unsigned long hex1, unsigned long hex2)
{
unsigned long cylinder_and_sector = ( (256*hex2) + hex1 );
unsigned long extracted_cylinder = ( ( (cylinder_and_sector*4) & 768) + (cylinder_and_sector /256) );
return(extracted_cylinder);
}
/* Extract the Cylinder from an LBA Value */
unsigned long Extract_Cylinder_From_LBA_Value(long lba_value
,long head,long sector,long total_heads
,long total_sectors)
{
return( ( ( ( (lba_value-(sector-1))/total_sectors)-head)/(total_heads+1) ) );
}
/* Extract Sector */
unsigned long Extract_Sector(unsigned long hex1, unsigned long hex2)
{
unsigned long cylinder_and_sector = ( (256*hex2) + hex1 );
unsigned long extracted_sector = cylinder_and_sector % 64;
return(extracted_sector);
}
/* Get the parameters of the hard disk */
int Get_Hard_Drive_Parameters(int physical_drive)
{
int error_code=0;
unsigned int total_number_hard_disks=0;
unsigned long total_cylinders=0;
unsigned long total_heads=0;
unsigned long total_sectors=0;
Partition_Table *pDrive = &part_table[physical_drive-0x80];
if( (physical_drive-0x80)>=flags.total_number_hard_disks) return(255);
if(user_defined_chs_settings[(physical_drive-128)].defined==TRUE)
{
pDrive->total_cyl
=user_defined_chs_settings[(physical_drive-0x80)].total_cylinders;
pDrive->total_head
=user_defined_chs_settings[(physical_drive-0x80)].total_heads;
pDrive->total_sect
=user_defined_chs_settings[(physical_drive-0x80)].total_sectors;
pDrive->num_of_log_drives=0;
return(0);
}
/* Get the hard drive parameters with normal int 0x13 calls. */
asm{
mov ah, 0x08
mov dl, BYTE PTR physical_drive
int 0x13
mov bl,cl
and bl,00111111B
mov BYTE PTR error_code, ah
mov BYTE PTR total_sectors, bl
mov BYTE PTR total_number_hard_disks,dl
mov bl,cl
mov cl,ch
shr bl,1
shr bl,1
shr bl,1
shr bl,1
shr bl,1
shr bl,1
mov ch,bl
mov WORD PTR total_cylinders, cx
mov BYTE PTR total_heads, dh
}
if(flags.total_number_hard_disks==255)
flags.total_number_hard_disks = total_number_hard_disks;
if(total_number_hard_disks==0) return(255);
if(error_code>0) return(error_code);
pDrive->total_head=total_heads;
pDrive->total_sect=total_sectors;
pDrive->num_of_log_drives=0;
if(pDrive->ext_int_13==TRUE)
{
/* Get the hard drive parameters with extended int 0x13 calls. */
/* Note: Supported interrupt 0x13 extensions have already been */
/* checked for in the function Check_For_INT13_Extensions(). */
unsigned int result_buffer_segment=FP_SEG(result_buffer);
unsigned int result_buffer_offset=FP_OFF(result_buffer);
unsigned long legacy_total_cylinders=total_cylinders;
unsigned long number_of_physical_sectors;
asm {
mov ah,0x48
mov dl,BYTE PTR physical_drive
mov ds,result_buffer_segment
mov si,result_buffer_offset
int 0x13
mov BYTE PTR error_code,ah
}
if(error_code>0) return(error_code);
/* Compute the total number of logical cylinders based upon the number */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -