📄 floppy.c
字号:
param.sides = 2; /* the default (initialize value!) */
}
if (param.four==TRUE)
{
/* (also need special SETUP for 360k disk in 1200k drive) */
param.sectors = 9;
param.cylinders = 40;
param.t = TRUE; /* trigger media type search */
}
if (param.eight==TRUE)
{
/* (this is only for 120k and 320k DOS 1.0 formats) */
param.sectors = 8;
param.cylinders = 40;
param.t = TRUE; /* trigger media type search */
}
if ( (param.t==TRUE) /* user wanted a certain number of cylinders (tracks) */
|| (param.f==TRUE) /* user wanted a certain size */
)
{
int index = 0; /* find matching media type from list */
do
{
if ( ( (param.f==TRUE)
&& (param.size == (drive_specs[index].total_sectors >> 1))
) ||
( (param.t==TRUE)
&& (param.cylinders == drive_specs[index].cylinders)
&& (param.sectors == drive_specs[index].sectors_per_cylinder)
&& (param.sides == drive_specs[index].number_of_heads)
)
)
{
param.media_type = index;
/* size is always found in the drive_specs, even if already given */
param.size = drive_specs[index].total_sectors >> 1;
if (/* *** param.f== *** */ TRUE) /* size given, geometry wanted */
{
param.cylinders = drive_specs[index].cylinders;
param.sectors = drive_specs[index].sectors_per_cylinder;
param.sides = drive_specs[index].number_of_heads;
}
printf("Formatting to %ldk (Cyl=%ld Head=%ld Sec=%2ld)\n",
param.size, param.cylinders, param.sides, param.sectors);
index = -10; /* break out of the loop */
} /* end "if match" */
else
{
index++;
} /* search on if no match */
} while ( (index>=0) && (drive_specs[index].bytes_per_sector==512) );
if (index>0)
{
if (param.f==TRUE) /* only size given */
{
printf("No media type found for %ldk format\n", param.size);
}
else /* geometry given */
{
param.size = (param.cylinders * param.sides * param.sectors) >> 1;
printf("No media type found for %ldk format (Cyl=%ld Head=%ld Sec=%2ld)\n",
param.size, param.cylinders, param.sides, param.sectors);
}
exit(50); /* cannot continue anyway, media type needed later! */
}
}
drive_number = param.drive_number;
/* IF the user gave ANY size indication, we already know which */
/* media_type the user wants, so we check drive capabilities now! */
if (TRUE) /* just limiting variable scope */
{
int drive_number = param.drive_number;
int preferredsize = 0;
regs.h.ah = 0x08;
regs.h.dl = drive_number;
int86(0x13, ®s, ®s);
drive_type = regs.h.bl;
preferredsize = 0; /* drive not installed */
switch (drive_type)
{
case 1: preferredsize = 360;
break;
case 2: preferredsize = 1200;
break;
case 3: preferredsize = 720;
break;
case 4: preferredsize = 1440;
break;
case 5:
case 6: preferredsize = 2880;
break;
/* Type 5 is originally for floppy tape drives */
}
if (param.media_type==UNKNOWN) /* do auto-detection of size! */
{
int index = 0; /* find matching media type from list */
param.size = preferredsize;
do
{
if (param.size == (drive_specs[index].total_sectors >> 1))
{
param.media_type = index;
param.cylinders = drive_specs[index].cylinders;
param.sectors = drive_specs[index].sectors_per_cylinder;
param.sides = drive_specs[index].number_of_heads;
printf("Using drive default: %ldk (Cyl=%ld Head=%ld Sec=%2ld)\n",
param.size, param.cylinders, param.sides, param.sectors);
index = -10;
}
else
{
index++;
}
} while ( (index>=0) && (drive_specs[index].bytes_per_sector==512) );
if (index >= 0)
{
printf("Internal error: default geometry for size %ldk unknown!\n",
param.size);
exit(51);
}
}
else
{
if (param.size > preferredsize)
{
if (param.size > (preferredsize + (preferredsize >> 2)))
{
printf("You are trying to go format to more than 125 percent of the\n");
printf("standard disk size for this drive. You must be kidding.\n");
printf("Your size: %ldk Standard for this drive: %dk\n",
param.size, preferredsize);
exit(43);
}
printf("Formatting to more than 100 percent of the standard size\n");
printf("for this drive: %ldk instead of only %dk. Good luck!\n",
param.size, preferredsize);
}
}
} /* variable scope end */
number_of_cylinders = drive_specs[param.media_type].cylinders;
sectors_per_cylinder = drive_specs[param.media_type].sectors_per_cylinder;
/* cannot configure drive for "number of heads" - only used in formatting */
/* useful cases: 360k in 1200k, 1200k in 1200k, ... */
/* formats >= 1440k are only set up by int 13.17, not here. */
/* we already aborted if the format is ABOVE possible range */
switch (drive_type)
{
case 1: /* 360k */
regs.h.al = 1; /* mode 1: 160, 180, 320, 360, 400k */
break;
case 2: /* 1200k */
regs.h.al = (param.size > 400) ? 3 : 2;
/* mode 2: like 1, but in 1200k drive. mode 3: 1200k */
/* mode 3 is probably only for 1220k, but we allow smaller */
break;
case 3: /* 720k */
regs.h.al = 4; /* mode 3: 720, 800k */
if (param.four || param.one || param.eight)
{
printf("This is a 720k drive which does not support /1, /4 or /8\n");
exit(44);
}
if (param.size < 720)
{
printf("Minimum size for this drive type is 720k\n");
exit(44);
}
break;
case 4: /* 1440k */
regs.h.al = 4; /* standard mode!? (int 13.18 sets details) */
if (param.four || param.one || param.eight)
{
printf("This is an 1440k drive which does not support /1, /4 or /8\n");
exit(45);
}
if ((param.size < 720) || (param.size == 1200))
{
printf("Minimum size for this drive type is 720k. 1200k not allowed.\n");
exit(45);
}
break;
case 5: /* 2880k */
case 6: /* 2880k */
default:
regs.h.al = 0xff; /* no mode setting needed (?) */
if (param.four || param.one || param.eight)
{
printf("This is a 2880k drive which does not support /1, /4 or /8\n");
exit(46);
}
if ((param.size < 720) || (param.size == 1200))
{
printf("Minimum size for this drive type is 720k. 1200k not allowed.\n");
exit(46);
}
break;
}
if (regs.h.al != 0xff)
{
int sizeclass = regs.h.al;
do
{
regs.h.ah = 0x17; /* set disk mode, e.g "360k disk in 1200k drive */
/* regs.x.cx = 0xffff; */ /* unused */
regs.h.dl = drive_number;
regs.x.cflag = 0;
int86(0x13, ®s, ®s);
} while ((regs.x.cflag != 0) && (regs.h.ah == 6));
/* retry if error is only "disk changed" */
if (regs.x.cflag != 0)
{
printf("Drive mode (size class %d) setting failed, error %2.2x (hex)\n",
sizeclass, regs.h.ah);
if (regs.h.ah == 0x80)
{
printf("No disk in drive!\n");
exit(42);
}
else
{
printf("Continuing anyway.\n");
}
}
}
#if 0
/* why should we not set this now already???: */
ddpt->sectors_per_cylinder = sectors_per_cylinder;
#endif
/* only more modern drives / BIOSes support this at all, probably. */
/* we may not give non-standard geometries NOW - no BIOS support. */
regs.h.ah = 0x18; /* set geometry, apart from head count of course */
regs.h.ch = (number_of_cylinders > 43) ? 79 : 39;
regs.h.cl = sectors_per_cylinder;
if (regs.h.cl >= 36)
{
regs.h.cl = 36; /* 2.88M or oversized -> 2.88M */
}
else
{
if (regs.h.cl >= 18)
{
regs.h.cl = 18; /* 1.44M or oversized -> 1.44M */
}
else
{
if (regs.h.cl >= 15)
{
regs.h.cl = 15; /* 1.2M or oversized -> 1.2M */
}
else
{
regs.h.cl = (regs.h.cl > 9) ? 9 : (regs.h.cl);
/* 720k or 360k or oversized -> 720k or 360k */
}
}
}
regs.h.dl = drive_number;
if ((regs.h.cl > 15) || (regs.h.cl < 9) ||
(ddpt->sectors_per_cylinder != regs.h.cl)
)
{
int86x(0x13, ®s, ®s, &sregs);
/* 40x[1,2]x8 (?), 80x2x[18,36]: 120, 320, 1440, 2880k */
if (regs.x.cflag==0)
{
regs.h.ah = 0; /* ensure "ok" */
}
else
{
if (regs.h.ah == 0)
regs.h.ah = 0x0c; /* ensure "invalid geometry" */
}
}
else
{
if (debug_prog==TRUE)
{
printf("[DEBUG] Not setting geometry - disk mode should say it all already\n");
/* 40x[1,2]x9, 80x2x[9,15]: 180, 360, 720, 1200k */
}
regs.h.ah = 1; /* "not supported by BIOS" (ignore errors) */
}
if (regs.h.ah != 0)
{
#if 0
/* try setting sectors per cylinder via DDPT !?!?: */
ddpt->sectors_per_cylinder = sectors_per_cylinder;
#endif
if (regs.h.ah==0x80)
{
printf("No disk in drive!\n");
exit(42);
}
if (regs.h.ah==1)
{
/* BIOS simply does not support 13.18, bad luck */
}
else
{
printf("Media type %ldk (%d x %ld x %2d) not supported by this drive!\n",
param.size, number_of_cylinders, param.sides, sectors_per_cylinder);
printf("Geometry set (int 13.18) error (%2.2x). Giving up.\n",
regs.h.ah);
exit(24);
}
}
else /* if geometry setting did work */
{
/* ES:DI points to an array to which the int 1E vectors should point! */
/* (added this! -ea) */
ddpt = MK_FP(sregs.es, regs.x.di); /* WE should know the update, too */
regs.h.ah = 0x25;
regs.h.al = 0x1e;
regs.x.dx = regs.x.di;
sregs.ds = sregs.es;
intdosx(®s,®s,&sregs);
/* if we had COPIED the DDPT, we could actually EDIT (tune) it now */
/* *** NON-standard formats only work by editing the DDPT *** */
/* if we COPY the DDPT, we must make sure to RESET it at EXIT */
if (debug_prog==TRUE)
{
printf("[DEBUG] New INT 1E (DDPT) vector: %4.4x:%4.4x.\n",
sregs.es, regs.x.di);
}
}
#if 0
printf("Media type: %d\n",param.media_type);
#endif
if (drive_specs[param.media_type].interleave_factor != 1)
/* could use OTHER marking for "non-standard format" here! */
/* e.g.: cylinders not 40 or 80, sectors not 8, 9, 15, 18 or 36 */
{
/* Adjust for non-standard formats. */ /* *** TODO *** */
/* if we had COPIED the DDPT, we could actually EDIT (tune) it now */
/* *** NON-standard formats only work by editing the DDPT *** */
/* if we COPY the DDPT, we must make sure to RESET it at EXIT */
/* The DDPT is what the INT 1E vector points to... */
if (debug_prog==TRUE)
{
printf("Using non-standard (oversized) format. Good luck...\n");
}
printf("*** DDPT tweaking for oversized formats not yet possible ***\n");
exit(88);
}
drive_statistics.bytes_total_disk_space =
((unsigned long)drive_specs[param.media_type].bytes_per_sector *
(unsigned long)drive_specs[param.media_type].total_sectors) -
((1+(2*(unsigned long)drive_specs[param.media_type].sectors_per_fat) +
((unsigned long)drive_specs[param.media_type].root_directory_entries/16)) *
(unsigned long)drive_specs[param.media_type].bytes_per_sector);
drive_statistics.bytes_available_on_disk =
drive_statistics.bytes_total_disk_space;
drive_statistics.bytes_in_each_allocation_unit =
(unsigned long)drive_specs[param.media_type].sectors_per_cluster *
(unsigned long)drive_specs[param.media_type].bytes_per_sector;
/* Copy BPB into bpb_standard structure. */
memcpy(&bpb_standard, &drive_specs[param.media_type].bytes_per_sector, 37);
Compute_Interleave_Factor();
if (debug_prog==TRUE)
{
printf("\n[DEBUG] Configured Disk Drive Parameter Table Values:\n");
ddptPrinter();
}
if (debug_prog==TRUE)
{
char ch;
printf("-- press ENTER to start formatting or ESCAPE to abort --\n");
do
{
regs.h.ah = 7;
intdos(®s, ®s);
ch = regs.h.al;
}
while ((ch != 13) && (ch != 27));
/* (avoids important information scrolling away) */
if (ch != 13)
exit(1);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -