📄 driveio.c
字号:
/*
// Program: Format
// Version: 0.90d
// (0.90b/c/d - warnings fixed, buffers far, boot sector IO - EA 2003)
// 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"
#include "userint.h" /* Critical_* */
unsigned int FloppyBootReadWrite(char, int, ULONG, void far *, unsigned);
/* Clear Huge Sector Buffer */
void Clear_Huge_Sector_Buffer(void)
{
memset(huge_sector_buffer_0, 0, sizeof(huge_sector_buffer_0));
}
/* Clear Sector Buffer */
void Clear_Sector_Buffer(void)
{
memset(sector_buffer_0, 0, sizeof(sector_buffer_0));
}
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);
/* return code: lo is int 24 / DI code, hi is bitmask: */
/* 1 bad command 2 bad address mark 3 (int 26 only) write protection */
/* 4 sector not found 8 dma failure 10 crc error 20 controller fail */
/* 40 seek fail 80 timeout, no response */
}
if ( (return_code==0x0207 /* 0x0408 */) &&
((param.drive_number & 0x80)==0) /* avoid fishy retry */
) /* changed -ea */
{
/* As per RBIL, if 0x0408 is returned, retry with high bit of AL set. */
/* MY copy of RBIL mentions 0x0207 for that case!? -ea */
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");
/* printf("+"); */
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);
printf("*"); /* give some problem indicator -ea */
goto retry;
}
if (return_code!=0)
{
if ( ((param.drive_number & 0x7f)>=2) ||
(command==WRITE) || (sector_number!=0L) )
{
/* Added more details -ea */
printf("Drive_IO( command=%s sector=%ld count=%d ) [%s] [drive %c%c]\n",
(command==WRITE) ? "WRITE" : "READ", sector_number, number_of_sectors,
(param.fat_type==FAT32) ? "FAT32" : "FAT12/16",
'A' + (param.drive_number & 0x7f),
(param.drive_number & 0x80) ? '*' : ':' );
Critical_Error_Handler(DOS, return_code);
}
else
{
/* Only HARDDISK and WRITE and READ-beyond-BOOTSECTOR errors */
/* are CRITICAL, others are handled by the CALLER instead! -ea */
printf("#");
}
}
param.drive_number = param.drive_number & 0x7f; /* unset high bit. */
return (return_code);
}
void Enable_Disk_Access(void)
{
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 far * buffer, unsigned ReadOrWrite)
{
unsigned diskReadPacket_seg;
unsigned diskReadPacket_off;
#ifndef __TURBOC__
unsigned int return_code; /* was char -ea */
#endif
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++;
#ifdef __TURBOC__
/* no inline asm for Turbo C 2.01! -ea */
/* Turbo C also complains about packed bitfield structures -ea */
{
struct SREGS s;
regs.x.ax = 0x7305;
regs.x.bx = diskReadPacket_off;
s.ds = diskReadPacket_seg;
regs.x.cx = 0xffff;
regs.h.dl = DosDrive;
regs.x.si = mode_flags.direction | (mode_flags.write_type << 13);
intdosx(®s, ®s, &s);
return regs.x.cflag ? regs.x.ax : 0;
}
#else
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 WORD PTR return_code,al
jc carry_set
} /* Changed return code on error from AH to AX -ea */
/* return regs.x.cflag ? regs.x.ax : 0; */
return 0;
carry_set:
return return_code;
#endif
}
/* TE_AbsReadWrite() is written by Tom Ehlert. */
unsigned int TE_AbsReadWrite(char DosDrive, int count, ULONG sector,
void far * buffer, unsigned ReadOrWrite)
{
struct {
unsigned long sectorNumber;
unsigned short count;
void far *address;
} diskReadPacket;
void far * dRP_p;
union REGS regs;
struct SREGS sregs;
if ( (count==1) && (sector==0) && ((DosDrive & 0x7f) < 2) )
{
/* ONLY use lowlevel function if only a floppy boot sector is */
/* affected: maybe DOS simply does not know filesystem params yet */
/* the lowlevel function also tells DOS about the new fs. params! */
if (debug_prog==TRUE)
printf("[DEBUG] Using lowlevel boot sector access...\n");
regs.x.ax = FloppyBootReadWrite(DosDrive & 0x7f, 1, 0,
buffer, ReadOrWrite); /* (F.B.R.W. by -ea) */
return (regs.x.ax == 0) ? 0 : 0x0808;
/* could translate BIOS to DOS error codes in more detail here */
}
diskReadPacket.sectorNumber = sector;
diskReadPacket.count = count;
diskReadPacket.address = buffer;
dRP_p = &diskReadPacket;
regs.h.al = DosDrive; /* 0 is A:, 1 is B:, ... */
/* in "int" 25/26, the high bit of AL is an extra flag */
regs.x.bx = FP_OFF(dRP_p);
sregs.ds = FP_SEG(dRP_p);
regs.x.cx = 0xffff;
switch(ReadOrWrite)
{
case READ: int86x(0x25,®s,®s,&sregs); break;
case WRITE: int86x(0x26,®s,®s,&sregs); break;
default:
printf("TE_AbsReadWrite wrong called %02x\n", ReadOrWrite);
exit(1);
}
return regs.x.cflag ? regs.x.ax : 0;
}
/* TE_* not usable while boot sector invalid, so... */
unsigned int FloppyBootReadWrite(char DosDrive, int count, ULONG sector,
void far * buffer, unsigned ReadOrWrite)
{
union REGS regs;
struct SREGS sregs;
int i = 0;
if ((DosDrive > 1) || ((DosDrive & 0x80) != 0))
return 0x0808; /* sector not found (DOS) */
if ((sector != 0) || (count != 1))
return 0x0808; /* sector not found (DOS) */
do
{
if (ReadOrWrite == WRITE)
{
regs.x.ax = 0x0301; /* read 1 sector */
}
else
{
regs.x.ax = 0x0201; /* write 1 sector */
}
regs.x.bx = FP_OFF(buffer);
regs.x.cx = 1; /* 1st sector, 1th (0th) track */
regs.h.dl = DosDrive; /* drive ... */
regs.h.dh = 0; /* 1st (0th) side */
sregs.es = FP_SEG(buffer);
int86x(0x13,®s,®s,&sregs);
if (regs.h.ah != 0)
i++; /* error count */
else
{
regs.h.ah = 0x0d;
intdos(®s,®s); /* flush buffers, reset disk system */
regs.h.ah = 0x32;
regs.h.dl = DosDrive + 1; /* 0 default 1 A: 2 B: ... */
intdosx(®s,®s,&sregs); /* re-read DPB for that drive */
#if 0
if (regs.h.al == 0)
{
/* existing DPB found - pointer to it is DS:BX */
}
else
{
/* no DPB reachable for DOS - no real error, as */
/* FloppyBootReadWrite is not only for DOS floppies */
/* (you want to be able to re-format OTHER floppies) */
}
#endif
return 0; /* WORKED */
}
}
while (i < 5); /* do ... while */
return regs.x.ax; /* return ERROR code */
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -