📄 floppy.c
字号:
/*
// 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, ®s, ®s, &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, ®s, ®s, &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, ®s, ®s, &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, ®s, ®s); /* 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, ®s, ®s); /* 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 + -