⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 driveio.c

📁 可以格式化超过200G硬盘的格式化工具
💻 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(&regs, &regs, &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( &regs, &regs, &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(&regs, &regs, &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,&regs,&regs,&sregs); break;
	    case WRITE: int86x(0x26,&regs,&regs,&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,&regs,&regs,&sregs);
      
      if (regs.h.ah != 0)
        i++; /* error count */
      else
        {
        regs.h.ah = 0x0d;
        intdos(&regs,&regs); /* flush buffers, reset disk system */

        regs.h.ah = 0x32;
        regs.h.dl = DosDrive + 1; /* 0 default 1 A: 2 B: ... */
        intdosx(&regs,&regs,&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 + -