📄 fl_drver.c
字号:
fl_controller_init();
return ReportError(ERR_IO_SECTOR);
}
if (!count)
break;
/* Add n transfered to the sector.
If we wrapped the track reset the sector pointer.
This wrap will occur almost every time. When we have a dma
wrap condition we truncated the sector count and will not
wrap
*/
sec += n_todo;
if (sec >= floppy[driveno].sectors_per_track)
{
sec = 0;
if (head)
{
head = 0;
cyl += 1;
}
else
head = 1;
}
count -= n_todo;
buffer += (n_todo<<9);
/* Read the rest of the blocks or to the end of track. Whichever is less */
/* Note: sec will usually be 0. unless a dma segment wrap occured. */
utemp = (UCOUNT) (floppy[driveno].sectors_per_track - sec);
if (count < utemp)
n_todo = count;
else
n_todo = utemp;
}
return (YES);
}
/* floppy_format - Format a floppy disk.
*
* Summary:
*
* BOOL floppy_format(driveno, drivesize, interleave, callback())
*
*
* Inputs:
* UCOUNT driveno - 0 or 1 = a: b:
* COUNT drivesize - 360,1200,1440,720
* COUNT interleave - interleave factor. (1 ==s no interleave gap)
* void (*callback)() - If non null this routine is called at each
* cylinder is formatted. The arguments are
* cylinder number and highest cylinder. This
* may be used to print a progress summary.
* (see pcmkfs for a sample)
*
* Returns:
* YES on success else NO.
*
* This routine formats every track on the drive. Before doing so it
* validates the interleave and returns if it is wrong. The interleave
* must be either 1 or it must follow these two rules.
* It may not divide evenly into sectors/track and if sectors/track is an
* even number interleave must be odd. If sectors/track is an odd number
* interleave must be even.
*
* This routine is portable
*
*/
BOOL floppy_format(UCOUNT driveno, COUNT drivesize, COUNT interleave, void (*callback)(COUNT, COUNT)) /*__fn__*/
{
COMMAND_BLOCK b;
COUNT parmindex;
UTINY cylinder;
UTINY sector;
UTINY head;
COUNT index;
UTINY *sec_info;
UCOUNT utemp;
if (!interleave)
return(NO);
for (parmindex = 0; fl_devparms[parmindex].drive_size; parmindex++)
{
if ( (fl_devparms[parmindex].drive_size == drivesize) &&
(floppy[driveno].drive_type == fl_devparms[parmindex].drive_type) )
break;
}
if (!fl_devparms[parmindex].drive_size)
{
Stop_gTimer();
fl_controller_init();
return ReportError(ERR_INIT_DRNO);
// return(fl_report_error(FLERR_UNK_DRIVE, NO));
}
if ((interleave > 1))
{
/* Interleave can not be an even multiple of sec/per track */
if ( (((COUNT)(fl_devparms[parmindex].sectors_per_track)%interleave) == 0) ||
/* Must be odd/even or even/odd */
((fl_devparms[parmindex].sectors_per_track & 0x01) == (interleave & 0x01) ) )
return(fl_report_error(FLERR_INVALID_INTERLEAVE, NO));
}
/* load the floppy table from the device desc table. */
fl_cp_parms(driveno, parmindex);
fl_write_drr(floppy[driveno].data_rate);
if (!fl_specify(driveno))
return(fl_report_error(FLERR_SPECIFY, NO));
fl_motor_on(driveno);
if (!fl_recalibrate(driveno))
{
Stop_gTimer();
fl_controller_init();
return ReportError(ERR_RECAL);
// return(fl_report_error(FLERR_RECAL, NO));
}
for (cylinder = 0; cylinder < fl_devparms[parmindex].cylinders_per_disk; cylinder++)
{
/* If a callback is provided print running status */
if (callback)
callback((COUNT)cylinder, (COUNT)(fl_devparms[parmindex].cylinders_per_disk-1));
fl_motor_on(driveno);
for (head = 0; head < 2; head++)
{
utemp = cylinder;
if (floppy[driveno].double_step)
utemp <<= 1;
if (!fl_seek(driveno, utemp, head))
{
Stop_gTimer();
fl_controller_init();
return ReportError(ERR_SEEK);
// return(fl_report_error(FLERR_SEEK, NO));
}
index = 0;
/* build of the sector IDs. Include interleave calculation */
for (sector = 1; sector <= fl_devparms[parmindex].sectors_per_track; sector++)
{
#ifdef POLLED
sec_info = format_buffer+(index*4);
#else /* POLLED */
sec_info = dma_buffer+(index*4);
#endif /* POLLED */
*sec_info++ = cylinder;
*sec_info++ = head;
*sec_info++ = sector;
*sec_info = 0x02; /* N = 2 for 512 byte sectors */
/* These three line do the interleave calulation */
index += interleave;
if (index >= (COUNT) fl_devparms[parmindex].sectors_per_track)
index -= fl_devparms[parmindex].sectors_per_track;
}
b.n_to_send = 6;
b.n_to_get = 7;
b.commands[0] = (UTINY) (MFMBIT|FL_FORMAT);
b.commands[1] = (UTINY) ((head << 2)|driveno);
b.commands[2] = (UTINY) 0x02; /* bytes/sector */
b.commands[3] = (UTINY) fl_devparms[parmindex].sectors_per_track;
b.commands[4] = (UTINY) fl_devparms[parmindex].gpl_format;
b.commands[5] = (UTINY) FORMAT_FILLER;
/* Set up to write sec_per_track * 4 bytes */
#ifdef POLLED
if (!fl_dma_init((UTINY *) format_buffer,(UCOUNT)((fl_devparms[parmindex].sectors_per_track)<<2), NO))
return(fl_report_error(FLERR_DMA, NO));
#else /* POLLED */
if (!fl_dma_init((UTINY *) dma_buffer,(UCOUNT)((fl_devparms[parmindex].sectors_per_track)<<2), NO))
return(fl_report_error(FLERR_DMA, NO));
#endif /* POLLED */
fl_motor_on(driveno);
fl_int_enable(NO);
if (!fl_command_phase(&b))
{
fl_int_enable(YES);
goto fmterr;
}
/* Wait for the io to complete */
if (!fl_waitdma(FLTMO_FMTTRACK))
goto fmterr;
if (!fl_results_phase(&b))
goto fmterr;
/* Check status register 0 for abnormal termination */
if (b.results[0] & (BIT7|BIT6))
goto fmterr;
}
}
return(YES);
fmterr:
return(fl_report_error(FLERR_FORMAT, NO));
}
/* fl_controller_init - Initialize the floppy controller
*
* summary
* BOOL fl_controller_init()
*
*
* Inputs:
*
* Returns:
* YES on success else NO.
*
* This routine zeroes out our data structures (floppy[0,1]). Then calls
* the host specific initialization code fl_establish() (sets up vectors/
* watchdogs). Then it attempts to reset the controller. If all is succesful
* it returns YES.
*
* Called by floppy_open()
*
*/
static BOOL fl_controller_init() /* __fn__ */
{
selected_floppy = 0;
pc_memfill(&floppy[0], sizeof(_FLOPPY), 0);
pc_memfill(&floppy[1], sizeof(_FLOPPY), 0);
/* Make sure the system timer is running */
/* mex_establish_timer(); */
/* Event for signalling IO complete */
/* if (!mex_floppy_event) */
/* mex_floppy_event = NUF_FLOPPY_EVENT; */
/* mex_floppy_event = mex_signal_alloc(); */
/* make sure interrupt vector is installed */
mex_establish_floppy_vector();
floppy[0].drive_type = mex_floppy_type(0);
floppy[1].drive_type = mex_floppy_type(1);
floppy[0].media_type = (UTINY) DT_NONE;
floppy[1].media_type = (UTINY) DT_NONE;
Start_gTimer(); //Liuxuedong on 2002-3-28
return (fl_reset_controller());
}
/* Issue a reset through the digital output register and wait for
an interrupt. */
static BOOL fl_reset_controller() /*__fn__*/
{
COMMAND_BLOCK b;
fl_int_enable(NO);
/* reset the floppy by toggling the reset line (BIT 3) */
shadow_dig_out = 0;
fl_write_dor(shadow_dig_out);
/* Clear reset. Enable DMA and interrupts */
#ifdef POLLED
shadow_dig_out |= (DORB_SRSTBAR); /* Don't enable DMA or interrupts */
#else /* POLLED */
shadow_dig_out |= (DORB_SRSTBAR|DORB_DMAEN);
#endif /* POLLED */
fl_write_dor(shadow_dig_out);
/* Wait up to 5 seconds for the interrupt to occur.*/
if (!fl_waitint(FLTMO_RESET))
return(fl_report_error(FLERR_RESET, NO));
if (!fl_sense_interrupt(&b))
return(fl_report_error(FLERR_RESET, NO));
/*Enable the FIFO and set the FIFO threshold*/
if(!fl_configure()) //by zhaowei
return(NO);
return(YES);
}
/* fl_claim - Claim the controller for IO to a drive
*
* Summary:
*
* BOOL fl_claim(driveno)
*
*
* Inputs:
* UCOUNT driveno - 0 or 1 = a: b:
*
* Returns:
* YES on success else NO.
*
* This routine is called by floppy_io each time it will do io to a drive.
* if the drive is the current active drive it writes the data rate reg and
* returns. Otherwise the other drive will be accessed. If the medai type
* has not been established this is done. The controller timing parameters
* are specified and the data rate is set.
*
*/
static BOOL fl_claim(UCOUNT driveno) /*__fn__*/
{
if (selected_floppy != (driveno+1))
{
selected_floppy = (UCOUNT) (driveno+1);
if (floppy[driveno].media_type == DT_NONE)
{
if (!fl_establish_media(driveno))
return(NO);
}
else if (!fl_specify(driveno))
return(fl_report_error(FLERR_SPECIFY, NO));
selected_floppy = (UCOUNT) (driveno+1);
}
fl_write_drr(floppy[driveno].data_rate);
return(YES);
}
/* fl_establish_media - Vary the data rate and read until succesful
*
* Summary:
*
* BOOL fl_establish_media(driveno)
*
*
* Inputs:
* UCOUNT driveno - 0 or 1 = a: b:
*
* Returns:
* YES on success else NO.
*
* For each possible media type for this drive type in the devparms table.
* Set the data rate, recal ,seek and read sector ID information from the
* drive. If the read ID works return YES. If all possible media are exhausted
* return NO.
*
* NOTE: The floppy change line is cleared by the seek operations.
*/
static BOOL fl_establish_media(UCOUNT driveno) /*__fn__*/
{
COUNT i;
COMMAND_BLOCK b;
/* Find the first drive description entry for the drive type */
for (i = 0; fl_devparms[i].drive_type; i++)
{
if (fl_devparms[i].drive_type == floppy[driveno].drive_type)
break;
}
/* Now scan through all drive descriptions for this drive type until
we get get one we can read */
while (fl_devparms[i].drive_type == floppy[driveno].drive_type)
{
/* Copy params from the drive table to the device */
fl_cp_parms(driveno, i);
/* Set the data rate */
fl_write_drr(floppy[driveno].data_rate);
if (fl_specify(driveno))
{
fl_motor_on(driveno);
if (fl_recalibrate(driveno))
{
Recalibrate_Ok = YES ;//重校准OK,置YES Liao Yibai 2002-11-26
/* read sector markers. if we get a normal terminaton we're ok */
fl_motor_on(driveno);
/* See if we can read the sector ID field */
if (fl_read_id(driveno, &b))
{
if ((b.results[0] & (BIT6|BIT7)) == 0)
{
/* Now we seek to cyl 2 and back to zero. This will
clear the change line if needed */
fl_motor_on(driveno);
if (!(fl_seek(driveno, 2, 0) && fl_seek(driveno, 0, 0)))
break;
else
return(YES);
}
}
}
//重校准不OK,以此判断软盘驱动器接线是否正确 Liao Yibai 2002-11-26
else
{
Recalibrate_Ok = NO ;
}
}
i++;
}
floppy[driveno].media_type = DT_NONE;
return (fl_report_error(FLERR_MEDIA, NO));
}
/* fl_sense_interrupt - Issue a sense interrupt command
* 寻道命令和重校正命令都没有结果阶段.所以在使用这两条命令后,
* 必须用检测中断状态命令来结束操作并核查磁头的位置。
* Summary:
*
* BOOL fl_sense_interrupt(COMMAND_BLOCK *p)
*
*
* Inputs:
* COMMAND_BLOCK *p - storage area. On return the results[0,1,2] will contain
* status registers 0,1,2
*
* Returns:
* YES on success else NO.
*
* This routine issues a sense interrupt command. It is called after
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -