📄 fl_drver.c
字号:
/* fl_recalibrate - Seek to cylinder 0, clear 765's internal PCN register
*
* Summary:
* BOOLEAN fl_reclaibrate(int driveno)
*
*
* Inputs:
* int driveno - 0 or 1 = a: b:
*
* Returns:
* TRUE on success else FALSE.
*
* This routine issues a recal, waits for an interupt and then checks
* the status by issueing a sense interupt command. If all went
* well it returns TRUE.
*
*/
static BOOLEAN fl_recalibrate(int driveno) /*__fn__*/
{
COMMAND_BLOCK b;
int i;
byte status_0;
floppy[driveno].last_cyl = 0; //AM: clear saved sector.
floppy[driveno].last_head = 0;
for (i = 0; i < 2; i++)
{
b.n_to_send = 2;
b.n_to_get = 0;
b.commands[0] = FL_RECALIBRATE;
b.commands[1] = (byte) driveno;
/* Clear any outstanding interrupt complete messages */
OS_FLOPPY_SIGNAL_BIND(0);
OS_FLOPPY_SIGNAL_CLEAR(0);
if (fl_command_phase(&b))
{
if (fl_waitint((int)FLTMO_RECAL))
{
if (fl_sense_interrupt(&b))
{
status_0 = b.results[0];
if (status_0 & BIT4) /* Missed track 0 on recal */
{
continue;
}
if (!(status_0 & BIT5))
continue;
if (status_0 & (BIT6|BIT7)) /* Not normal termination */
continue;
if (b.results[1]) /* PCN Should be 0 */
continue;
return(TRUE);
}
}
}
}
return(FALSE);
}
/* fl_specify - Issue a specify command to the drive
*
* Summary:
* BOOLEAN fl_specify(int driveno)
*
*
* Inputs:
* int driveno - 0 or 1 = a: b:
*
* Returns:
* TRUE on success else FALSE.
*
* This routine issues a specify command for the drive to the controller
* this process sets the head load/unload delays. The delay values come
* from the _floppy[] structure which was copied from the devtable.
*
*/
static BOOLEAN fl_specify(int driveno) /*__fn__*/
{
COMMAND_BLOCK b;
b.n_to_send = 3;
b.n_to_get = 0;
b.commands[0] = FL_SPECIFY;
b.commands[1] = floppy[driveno].specify_1;
b.commands[2] = floppy[driveno].specify_2;
if (fl_command_phase(&b))
return(TRUE);
else
return(FALSE);
}
/* This is a callback that allows the floppy to shut the motor off */
void fl_motor_off(void) /*__fn__*/
{
if (shut_mo_off_in && !(--shut_mo_off_in))
{
shadow_dig_out &= ~(DORB_DSEL|DORB_MOEN2|DORB_MOEN1);
fl_write_dor(shadow_dig_out);
}
}
static void fl_motor_on(int driveno) /*__fn__*/
{
BOOLEAN must_sleep;
#if (defined(ERTFS_SA))
shut_bios_timer_off();
#else
#if (defined(__BORLANDC__) || defined(_MSC_VER) || __WATCOMC__)
#if (!IS_MS_PM && !IS_BCC_PM && !IS_WC_PM )
/* This is for PC hosted environments... */
static PFBYTE bios_motor_timer = 0;
if (!bios_motor_timer)
{
bios_motor_timer = (PFBYTE) (MK_FP(0x40, 0x40));
}
*bios_motor_timer = 0xff;
#endif
#endif
#endif
/* rearm the motor timeout daemon for 3 seconds. Do this first so we are
sure that the daemon won't shut off the motors while we are in here */
shut_mo_off_in = MOTOR_TIMEOUT;
must_sleep = FALSE;
if (driveno==1)
{
/* Turn on motor 2 and off motor 1 */
if (!(shadow_dig_out & DORB_MOEN2))
{
shadow_dig_out |= DORB_DSEL|DORB_MOEN2;
shadow_dig_out &= ~DORB_MOEN1;
must_sleep = TRUE;
}
}
else
{
/* Turn on motor 1 and off motor 2 */
if (!(shadow_dig_out & DORB_MOEN1))
{
shadow_dig_out |= DORB_MOEN1;
shadow_dig_out &= ~(DORB_DSEL|DORB_MOEN2);
must_sleep = TRUE;
}
}
fl_write_dor(shadow_dig_out);
if (must_sleep)
{
/* Wait for the motor to come up to speed */
ks_sleep((word)(FL_SPINUP));
/* Set the daemon again (3 seconds) */
shut_mo_off_in = MOTOR_TIMEOUT;
}
}
/* Send command phase info to the floppy chip */
static BOOLEAN fl_command_phase(COMMAND_BLOCK *p) /*__fn__*/
{
int i;
int ready;
/* If the floppy is in the results phase clear it */
for (i = 0; i < 10; i++)
{
ready = fl_ready();
if (ready == FL_TOHOST)
fl_read_data();
else
break;
}
for (i = 0; i < p->n_to_send; i++)
{
if (ready != FL_FRHOST)
return(FALSE);
fl_write_data(p->commands[i]);
ready = fl_ready();
}
return(TRUE);
}
/* Get results phase info from the floppy chip Return TRUE if results match expected */
static BOOLEAN fl_results_phase(COMMAND_BLOCK *p) /*__fn__*/
{
int i;
p->n_gotten = 0;
for (i = 0; i < p->n_to_get; i++)
{
if (fl_ready() != FL_TOHOST)
return(FALSE);
p->results[i] = fl_read_data();
}
p->n_gotten = p->n_to_get;
return(TRUE);
}
/* Check the master status register. Return FL_TOHOST if the chip has data for
the CPU, FL_FRHOST if it expects data, 0 IF The chip doesn't assert RQM */
static int fl_ready() /*__fn__*/
{
byte main_status_register; /* Master status register */
int timeout;
int i;
timeout = 32000;
/* Check the master status register for RQM. */
main_status_register = 0;
while (!(main_status_register & BIT7))
{
if (!timeout--)
{
return(0);
}
main_status_register = fl_read_msr();
if (!(main_status_register & BIT7))
{
/* Sleep at least 25 uSeconds after reading MSR */
for (i = 0; i < 25; i++) io_delay();
}
}
/* If bit 6 is high the chip will send data to the CPU. */
if (main_status_register & BIT6)
return(FL_TOHOST);
else
return(FL_FRHOST);
}
/* Check the floppy disk change line. Return TRUE if the line has changed */
/* Note: We use change_checked[] to test if we just came up. Need to do
this because change is false at first but we still need to repower */
static BOOLEAN fl_change_line(int driveno) /*__fn__*/
{
fl_motor_on(driveno);
if (fl_read_drr() & BIT7)
{
change_checked[driveno] = TRUE;
return(TRUE);
}
else
{
if (!change_checked[driveno])
{
change_checked[driveno] = TRUE;
return(TRUE);
}
else
{
change_checked[driveno] = TRUE;
return(FALSE);
}
}
}
/* copy values from the parameter table to the floppy structure */
static void fl_cp_parms(int driveno, int parmindex) /*__fn__*/
{
floppy[driveno].drive_type = fl_devparms[parmindex].drive_type;
floppy[driveno].media_type = fl_devparms[parmindex].media_type;
floppy[driveno].specify_1 = fl_devparms[parmindex].specify_1;
floppy[driveno].specify_2 = fl_devparms[parmindex].specify_2;
floppy[driveno].data_rate = fl_devparms[parmindex].data_rate;
floppy[driveno].sectors_per_track = fl_devparms[parmindex].sectors_per_track;
floppy[driveno].sectors_per_cyl = (byte) (2 * fl_devparms[parmindex].sectors_per_track);
floppy[driveno].cylinders_per_disk = fl_devparms[parmindex].cylinders_per_disk;
floppy[driveno].gpl_read = fl_devparms[parmindex].gpl_read;
if ((fl_devparms[parmindex].drive_type == DT_12)&&( fl_devparms[parmindex].media_type == DT_360))
floppy[driveno].double_step = TRUE;
else
floppy[driveno].double_step = FALSE;
}
/*
* Name:
* fl_waitint() - Wait for a floppy interrupt. If one doesn't come. Fail.
*
* Summary:
* fl_waitint(int ticks)
*
* Inputs:
* ticks - Number of ticks to wait for the interrupt to occur.
*
*
* Returns:
* TRUE if the interrupt occured, FALSE if it timed out
*
* Description:
* This function is called when the driver is waiting for an interrupt from the
* controller. On entry the controller interrupt is masked off. This routine must
* turn the interrupt on and then wait for the the interrupt service routine to
* occur.
*
* Porting considerations:
*
* In the reference port we enter a loop and wait for either the floppy interrupt
* to occur or for the tick count to occur. In a real time kernel you would
* probably wait on a event channel with a timeout that will be signaled by
* the floppy interrupt service routine or time out
*
*/
static BOOLEAN fl_waitint(int ticks) /*__fn__*/
{
/* Wait for an interrupt or timeout */
#if (defined(ERTFS_SA))
return (ks_test_floppy_signal((word)ticks));
#else
return(OS_FLOPPY_SIGNAL_TEST(0, ticks));
#endif
}
/*
* Name:
* fl_report_error() Report and clear an error
*
* Summary:
* BOOLEAN fl_report_error(int error, BOOLEAN return_me)
*
* Inputs:
* error - Error number
* return_me - This is returned
* Returns:
* return_me
*
* Description:
* This routine reports and clears errors. The table of error strings and
* the printing of the errors is optional. Clearing the error consists of
* reseting the controller and clearing the known media type. When IO is
* is resumed the media type will be re-established.
*
* Porting considerations:
*
*/
char * fl_errors[] = {
/* 0 */ "",
/* FLERR_ABN_TERM */ "Abnormal Termination Error",
/* FLERR_CHIP_HUNG */ "Floppy controller not responding",
/* FLERR_DMA */ "Dma Error",
/* FLERR_FORMAT */ "Error during format",
/* FLERR_INVALID_INTERLEAVE */ "Invalid Interleave For Media Type",
/* FLERR_IO_SECTOR */ "Sector Not Found",
/* FLERR_IO_TMO */ "Time out",
/* FLERR_MEDIA */ "Can't determine Media",
/* FLERR_RECAL */ "Error During Recal",
/* FLERR_RESET */ "Error resetting drive",
/* FLERR_SEEK */ "Error during seek",
/* FLERR_SPECIFY */ "Error during specify",
/* FLERR_UNK_DRIVE */ "Unknown Drive type"
};
static BOOLEAN fl_report_error(int error, BOOLEAN return_me) /*__fn__*/
{
switch(error)
{
case FLERR_ABN_TERM:
case FLERR_CHIP_HUNG:
case FLERR_DMA:
case FLERR_FORMAT:
case FLERR_IO_SECTOR:
case FLERR_IO_TMO:
case FLERR_MEDIA:
case FLERR_RECAL:
case FLERR_SEEK:
case FLERR_SPECIFY:
floppy[0].media_type = (byte) DT_NONE;
#if (N_FLOPPY_UNITS == 2)
floppy[1].media_type = (byte) DT_NONE;
#endif
fl_reset_controller();
// break;
case FLERR_RESET:
case FLERR_INVALID_INTERLEAVE:
case FLERR_UNK_DRIVE:
case FLERR_EXEC_EST:
#if (!defined(ERTFS_SA))
DEBUG_ERROR(fl_errors[error], NOVAR, 0 , 0);
#else
tm_printf_2("%s\n", fl_errors[error]);
#endif
break;
default:
#if (!defined(ERTFS_SA))
DEBUG_ERROR("Unspecified floppy error", NOVAR, 0 , 0);
#else
tm_printf("Unspecified floppy error");
#endif
break;
}
return(return_me);
}
#if (USE_DMA)
/*
* Name:
* fl_waitdma() - Wait for a dma transfer to complete
*
* Summary:
* fl_waitdma(int ticks)
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -