📄 driveio.c
字号:
/*
// Program: Format
// Version: 0.90
// Written By: Brian E. Reifsnyder
// Copyright: 2002 under the terms of the GNU GPL, Version 2
// Module Name: driveio.c
// Module Description: Functions specific to accessing a disk.
*/
#define DIO
#include "driveio.h"
#include "format.h"
/* Clear Huge Sector Buffer */
void Clear_Huge_Sector_Buffer()
{
memset(huge_sector_buffer, 0, sizeof(huge_sector_buffer));
}
/* Clear Sector Buffer */
void Clear_Sector_Buffer()
{
memset(sector_buffer, 0, 512);
}
int Drive_IO(int command,unsigned long sector_number,int number_of_sectors)
{
unsigned int return_code;
int error_counter = 0;
retry:
if(param.fat_type != FAT32)
{
return_code =
TE_AbsReadWrite(param.drive_number,number_of_sectors,sector_number,
number_of_sectors==1 ?sector_buffer : huge_sector_buffer,
command);
}
else
{
return_code =
FAT32_AbsReadWrite(param.drive_number,number_of_sectors,sector_number,
number_of_sectors==1 ?sector_buffer : huge_sector_buffer,
command);
}
if(return_code==0x0408)
{
/* As per RBIL, if 0x0408 is returned, retry with high bit of AL set. */
param.drive_number = param.drive_number + 0x80; /* set high bit. */
error_counter++;
if(debug_prog==TRUE) printf("[DEBUG] Retrying drive access. High bit of AL is set.\n");
goto retry;
}
if( (return_code!=0) && (error_counter<3) )
{
error_counter++;
if(debug_prog==TRUE) printf("[DEBUG] Retrying drive access. Retry number-> %2d\n",error_counter);
goto retry;
}
if(return_code!=0) Critical_Error_Handler(DOS,return_code);
param.drive_number = param.drive_number & 0x7f; /* unset high bit. */
return (return_code);
}
void Enable_Disk_Access()
{
unsigned char category_code;
unsigned long error_code=0;
if(param.fat_type!=FAT32) category_code = 0x08;
else category_code = 0x48;
if(debug_prog==TRUE)
{
printf("[DEBUG] Enable_Disk_Access() function\n");
}
/* Get the device parameters for the logical drive */
regs.h.ah=0x44; /* IOCTL Block Device Request */
regs.h.al=0x0d;
regs.h.bl=param.drive_number + 1;
regs.h.ch=category_code; /* 0x08 if !FAT32, 0x48 if FAT32 */
regs.h.cl=0x67; /* Get Access Flags */
regs.x.dx=FP_OFF(&access_flags);
sregs.ds =FP_SEG(&access_flags);
intdosx(®s, ®s, &sregs);
error_code = regs.h.al;
if (regs.x.cflag)
{
/* BO: if invalid function: try to format anyway maybe access
flags do not work this way in this DOS (e.g. DRDOS 7.03) */
if (error_code == 0x1 || error_code == 0x16)
return;
/* Add error trapping here */
printf("\nFatal error obtaining disk access flags...format terminated.\n", error_code);
printf("Error Code: %02x\n",error_code);
exit(1);
}
if(access_flags.disk_access==0)
{
access_flags.disk_access++;
regs.h.ah = 0x44; /* IOCTL Block Device Request */
regs.h.al = 0x0d;
regs.h.bl = param.drive_number + 1;
regs.h.ch = category_code; /* 0x08 if !FAT32, 0x48 if FAT32 */
regs.h.cl = 0x47; /* Set device parameters */
regs.x.dx = FP_OFF(&access_flags);
sregs.ds = FP_SEG(&access_flags);
intdosx( ®s, ®s, &sregs);
error_code = regs.h.al;
if (regs.x.cflag)
{
/* Add error trapping here */
printf("\nFatal error writing setting disk access flags...format terminated.\n", error_code);
printf("Error Code: %02x\n",error_code);
exit(1);
}
}
if(debug_prog==TRUE)
{
printf("[DEBUG] Exit Exit_Enable_Disk_Access() function\n");
}
}
/* FAT32_AbsReadWrite() is modified from TE_AbsReadWrite(). */
unsigned int FAT32_AbsReadWrite(char DosDrive, int count, ULONG sector, void *buffer, unsigned ReadOrWrite)
{
unsigned diskReadPacket_seg;
unsigned diskReadPacket_off;
unsigned char return_code;
void far * diskReadPacket_p;
struct {
unsigned long sectorNumber;
unsigned short count;
void far *address;
} diskReadPacket;
union REGS regs;
struct {
unsigned direction : 1 ;
unsigned reserved_1 : 12;
unsigned write_type : 2 ;
unsigned reserved_2 : 1 ;
} mode_flags;
diskReadPacket.sectorNumber = sector;
diskReadPacket.count = count;
diskReadPacket.address = buffer;
diskReadPacket_p =& diskReadPacket;
diskReadPacket_seg = FP_SEG(diskReadPacket_p);
diskReadPacket_off = FP_OFF(diskReadPacket_p);
mode_flags.reserved_1 = 0;
mode_flags.write_type = 0;
mode_flags.direction = ReadOrWrite == READ ?0 : 1;
mode_flags.reserved_2 = 0;
DosDrive++;
asm{
mov ax,0x7305
mov bx,WORD PTR diskReadPacket_off
mov cx,0xffff
mov dl,BYTE PTR DosDrive
mov ds,WORD PTR diskReadPacket_seg
mov si,WORD PTR mode_flags
int 0x21
mov BYTE PTR return_code,ah
jc carry_set
}
// return regs.x.cflag ? regs.x.ax : 0;
return 0;
carry_set:
return return_code;
}
/* TE_AbsReadWrite() is written by Tom Ehlert. */
unsigned int TE_AbsReadWrite(char DosDrive, int count, ULONG sector, void *buffer, unsigned ReadOrWrite)
{
struct {
unsigned long sectorNumber;
unsigned short count;
void far *address;
} diskReadPacket;
union REGS regs;
diskReadPacket.sectorNumber = sector;
diskReadPacket.count = count;
diskReadPacket.address = buffer;
regs.h.al = DosDrive;
regs.x.bx = (short)&diskReadPacket;
regs.x.cx = 0xffff;
switch(ReadOrWrite)
{
case READ: int86(0x25,®s,®s); break;
case WRITE: int86(0x26,®s,®s); break;
default:
printf("TE_AbsReadWrite wrong called %02x\n", ReadOrWrite);
exit(1);
}
return regs.x.cflag ? regs.x.ax : 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -