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

📄 floppy.c

📁 可以格式化超过200G硬盘的格式化工具
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
// Program:  Format
// Version:  0.90f
// (0.90b/c/d - DMA in track_address_fields fix - Eric Auer May 2003)
// (0.90e/f - more formats, better media type setting - Eric Auer)
// Written By:  Brian E. Reifsnyder
// Copyright:  2002 under the terms of the GNU GPL, Version 2
// Module:  floppy.c
// Description:  Floppy disk specific functions.
*/

#define FLOP

#include <stdlib.h>

#include "floppy.h"
#include "format.h"
#include "btstrct.h"
#include "userint.h" /* Critical_* */
#include "driveio.h" /* huge_sector_buffer* */

void Compute_Interleave_Factor(void);

void Compute_Interleave_Factor()
{
  int index;
  int starting_sector;


  low_level.interleave_factor = drive_specs[param.media_type].interleave_factor;

  index = 1;
  starting_sector = 0;
  low_level.interleave_index = 0;
  do
    {
    low_level.interleave_map[low_level.interleave_index]=index;
    low_level.interleave_index
     =low_level.interleave_index+low_level.interleave_factor;
    if(low_level.interleave_index >= drive_specs[param.media_type].sectors_per_cylinder)
      {
      starting_sector = starting_sector + 1;
      low_level.interleave_index = starting_sector;
      }

    index++;
    } while (index <= drive_specs[param.media_type].sectors_per_cylinder);

  if ((debug_prog==TRUE)
#if 0
 && (low_level.interleave_factor != 1)
#endif
     )
    {
    printf("\n[DEBUG]  Initial Interleave Map:  \n          ");

    index = 0;
    do
      {
      printf("%2d ",low_level.interleave_map[index]);
      index++;
      } while (index <= (drive_specs[param.media_type].sectors_per_cylinder-1));
    printf("\n");
    }
}

void Compute_Sector_Skew()
{
  int carry;
  int index;
  int skew_counter;

  if (drive_specs[param.media_type].sector_skew==0)
    return;

  skew_counter = 0;

  do
    {
    carry =
      low_level.interleave_map[(drive_specs[param.media_type].sectors_per_cylinder-1)];

    index = (drive_specs[param.media_type].sectors_per_cylinder - 1);

    do
      {
      low_level.interleave_map[index] = low_level.interleave_map[(index-1)];

      index--;
      } while (index>0);

    low_level.interleave_map[0] = carry;

    skew_counter++;
    } while (skew_counter < drive_specs[param.media_type].sector_skew);

  if (debug_prog==TRUE)
    {
    printf("\n[DEBUG]  Interleave Map After Sector Skew:  \n          ");

    index = 0;
    do
      {
      printf("%d ",low_level.interleave_map[index]);
      index++;
      } while (index <= (drive_specs[param.media_type].sectors_per_cylinder-1));
    printf("\n");
    }
}



#define TAFinSEC 1 /* use 1 sector buffer to hold 36*4 bytes of TAF */

/* this saves stack space and avoids other hassles, but you may not */
/* use DriveIO of single sectors unless you accept buffer overwrite */


/* now returns the bad-sector-count -ea */
int Format_Floppy_Cylinder(int cylinder,int head) 
{
  int drive_number;
  int sector_index;
  int retry_count;
  int index;
  int secPerTrack=0;
  int badSecCount=0;

  unsigned int result;
  unsigned int result2;

  /* Set Up Track Address Fields */
#ifdef TAFinSEC
  TAF far *track_address_fields_p = (TAF far *) sector_buffer;
  /* use this buffer to save stack -ea */

#else
>  TAF track_address_fields[72]; /* 2 * 36 used, allow moving -ea */
>  int taf_which = 0;
>  TAF far *track_address_fields_p = &track_address_fields[taf_which];
>  unsigned long int where;
>
>  where = FP_SEG(track_address_fields_p);
>  where <<= 4;
>  where += FP_OFF(track_address_fields_p);
>
>  /* start DMA boundary avoidance -ea */
>  while ((where & 0xffff) > (0xffff - (4*36))) {
>    taf_which++;
>    track_address_fields_p = &track_address_fields[taf_which];
>    where = FP_SEG(track_address_fields_p);
>    where <<= 4;
>    where += FP_OFF(track_address_fields_p);
>    if(debug_prog==TRUE) {
>      printf(">f>");
>    }
>  }
>  if(debug_prog==TRUE) {
>    printf("[DEBUG]  track_address_fields_p = %4.4x:%4.4x\n",
>      FP_SEG(track_address_fields_p),FP_OFF(track_address_fields_p));
>  }
#endif

  /* DMA boundary avoided -ea */

  secPerTrack = drive_specs[param.media_type].sectors_per_cylinder;
  index = 0;
  do
    {
    (track_address_fields_p+index)->cylinder = cylinder;
    (track_address_fields_p+index)->head = head;
    (track_address_fields_p+index)->sector = low_level.interleave_map[index];
    (track_address_fields_p+index)->size_code = 0x02; /* 128<<2: 512by */

    index++;
    } while (index<secPerTrack);

  drive_number = param.drive_number;

  if (debug_prog==TRUE)
    {
    printf("[DEBUG]  Formatting: Cylinder: %2d  Head: %2d  Sectors: %2d\n",
      cylinder, head, secPerTrack);
    }

  /* Format the Track */
  result = 0;
  regs.h.ah = 0x05;
  regs.h.al = secPerTrack; /* feels better -ea */
  regs.h.ch = cylinder;
  regs.h.dh = head;
  regs.h.dl = drive_number;
  sregs.es  = FP_SEG(track_address_fields_p);
  regs.x.bx = FP_OFF(track_address_fields_p);
  int86x(0x13, &regs, &regs, &sregs);
  result = regs.h.ah;

  if (result!=0) {
    printf("Format_Floppy_Cylinder( head=%d cylinder=%d ) sectors=%d [int 13.5]\n",
      head, cylinder, secPerTrack );
    Critical_Error_Handler(BIOS,result);
  }


  result2 = result;

  if (param.verify==TRUE)
    {
    /* Verify the Track */
    /* According to RBIL, this uses cached CRC values, but it  */
    /* might use the ES:BX data buffer on 1985/before BIOSes!? */
    /* -> SHOULD we use READ to huge_sector_buffer instead???  */
    /* Warning: huge_sector_buffer is only 18 sectors for now. */
    result=0;
    regs.h.ah = 0x02; /* changed from VERIFY to READ */
    regs.h.al = secPerTrack;
    if ( regs.h.al > (sizeof(huge_sector_buffer_0)>>9) )
      {
        regs.h.al = sizeof(huge_sector_buffer_0) >> 9;
        printf("Only checking first %d sectors per track\n", regs.h.al);
        /* could read 2 half-tracks or use pinpointing below here     */
        /* instead... however, only 2.88MB disks have > 18 sect/track */
      }
    regs.h.ch = cylinder;
    regs.h.cl = 1;                     /* Start with the first sector. */
    regs.h.dh = head;
    regs.h.dl = drive_number;
    regs.x.bx = FP_OFF(huge_sector_buffer); /* if using READ */
    sregs.es  = FP_SEG(huge_sector_buffer); /* if using READ */
    int86x(0x13, &regs, &regs, &sregs);
    result = regs.h.ah;

    if ( (debug_prog==TRUE) && ((result!=0) || (result2!=0)) )
      {
      printf("[DEBUG]  Intr 0x13 results: FORMAT -> %X, VERIFY -> %X\n",
        result2, result);
      }

    if (result!=0)
      {
      if (debug_prog==TRUE)
	{
	printf("[DEBUG]  Errors found, pinpointing bad sectors now...\n");
	}

      retry_count  = 0;
      sector_index = 1;

      do
	{
retry:
	if (debug_prog==TRUE)
	  {
	  printf("[DEBUG]  Scanning sector number->  %d\n",sector_index);
	  }

	/* Verify the Track...sector by sector. */
	/* According to RBIL, this uses cached CRC values, but it  */
	/* might use the ES:BX data buffer on 1985/before BIOSes!? */
	/* -> SHOULD we use READ to sector_buffer instead???       */
	result = 0;
	regs.h.ah = 0x02; /* changed from 4 VERIFY to 2 READ */
	regs.h.al = 1;
	regs.h.ch = cylinder;
	regs.h.cl = sector_index;
	regs.h.dh = head;
	regs.h.dl = drive_number;
        regs.x.bx = FP_OFF(huge_sector_buffer); /* if using READ */
        sregs.es  = FP_SEG(huge_sector_buffer); /* if using READ */
	int86x(0x13, &regs, &regs, &sregs);
	result = regs.h.ah;

	if (result!=0)
	  {
	  if (debug_prog==TRUE)
	    {
	    printf("[DEBUG]  Possible bad sector found... testing.  retry_count->  %d\n",retry_count);
	    }

	  retry_count++;

	  if (retry_count>=3)
	    {
	    /* Record this sector as bad. */
	    bad_sector_map[bad_sector_map_pointer] =
	      ( (cylinder * (drive_specs[param.media_type].number_of_heads) )
	      * drive_specs[param.media_type].sectors_per_cylinder)
	      + (head * drive_specs[param.media_type].sectors_per_cylinder)
	      + sector_index;

	    bad_sector_map_pointer++;
	    drive_statistics.bytes_in_bad_sectors =
	      drive_statistics.bytes_in_bad_sectors +
	      drive_specs[param.media_type].bytes_per_sector;

	    if (debug_prog==TRUE)
	      {
	      printf("[DEBUG]  Bad Sector %4ld CHS=[%2d:%d:%2d] on drive %X\n",
	        bad_sector_map[(bad_sector_map_pointer-1)],
	        cylinder, head, sector_index, drive_number);
	      }
	    else
	      {
	      printf("Sector %4ld CHS=[%2d:%d:%2d] bad\n",
	        bad_sector_map[(bad_sector_map_pointer-1)],
	        cylinder, head, sector_index);
	      }

	    retry_count = 0;
            badSecCount++;
	    }
	  else
            {

            regs.x.ax = 0;
            regs.h.dl = drive_number;
            int86(0x13, &regs, &regs); /* reset drive */

            goto retry;   /* Yes, it's a goto.  :-)  Even goto has uses. */

            }
	  }

	sector_index++;
	} while (sector_index<=drive_specs[param.media_type].sectors_per_cylinder);

      }
    }

  return badSecCount;

}


/* void ddptPrinter(void); */


void ddptPrinter(void)
{
    /* note that the default step rate 15*16ms is pretty long */
    printf("[DEBUG]      Step Rate:                 %d msec\n",
      ddpt->step_rate * 16);               /* 1st byte, LO4 */

    /* this defaults to pretty long as well */
    printf("[DEBUG]      Head Unload Time:          %d msec\n",
      (16 - ddpt->head_unload_time) << 4); /* 1st byte, HI4 */

    /* default is 0 - always 0? */
    printf("[DEBUG]      DMA Flag:                  %d\n",
      ddpt->dma_flag);                     /* 2nd byte, LO1 */

    /* default unknown */
    printf("[DEBUG]      Head Load Time:            %d msec\n",
      ddpt->head_load_time << 1);          /* 2nd byte, HI7 */

    /* default is 2.035 sec */
    printf("[DEBUG]      Motor Post Rotating Time:  %d msec\n",
      ddpt->post_rt_of_disk_motor * 55); /* unit is timer ticks */

    /* default is 512 */
    printf("[DEBUG]      Sector Size:               %d bytes\n",
      128 << ddpt->sector_size);

    /* default depends on drive type */
    printf("[DEBUG]  *** Sectors Per Cylinder: ***  %d\n",
      ddpt->sectors_per_cylinder);

    /* better NOT MESS with this */
    printf("[DEBUG]   () Intersector Gap Length:    %d\n",
      ddpt->gap3_length_rw);

    /* better NOT MESS with this */
    printf("[DEBUG]   () Data Length:               %d\n",
      ddpt->dtl);

    /* better NOT MESS with this */
    printf("[DEBUG]   () Int.sect. Gap Len. Format: %d\n",
      ddpt->gap3_length_xmat);

    /* default 246 */
    printf("[DEBUG]      Fill Character:            0x0%x (%c)\n",
      ddpt->fill_char_xmat, ddpt->fill_char_xmat);

    /* default 25ms */
    printf("[DEBUG]      Head Settle Time:          %d msec\n",
      ddpt->head_settle_time);

    /* default BIOS 0.5 sec, DOS 0.25 sec */
    printf("[DEBUG]      Motor start-up time:       %d msec\n",
      ddpt->run_up_time * 125);
}


void Set_Floppy_Media_Type()
{
  int drive_number = param.drive_number;
  int number_of_cylinders;
  int sectors_per_cylinder;
  int drive_type = 0;


  param.media_type = UNKNOWN;

  if ((drive_number & 0x80) != 0)
    {
    printf("Drive number > 127: This is no floppy! Aborting.\n");
    exit(1);
    }

  regs.x.ax = 0;
  regs.h.dl = drive_number;
  int86(0x13, &regs, &regs); /* reset drive */

  if(debug_prog==TRUE)
    {
    printf("[DEBUG]  Current Disk Drive Parameter Table Values:\n");
    ddptPrinter();
    }

  param.fat_type = FAT12;

  if (param.one==TRUE)
    {
    /* *** (this is only for 160k and 180k formats) *** */
    param.cylinders = 40;
    if ((param.sectors!=9) && (param.sectors!=8))
      {
      param.sectors = 9;
      }

    param.sides = 1;
    param.t = TRUE; /* trigger media type search */
    }
  else
    {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -