📄 fl_drver.c
字号:
* seeks/recals and resets. The status registers are interpreted by
* the calling routine
*
*/
static BOOL fl_sense_interrupt(COMMAND_BLOCK *p) /*__fn__*/
{
p->n_to_send = 1;
p->n_to_get = 2;
p->commands[0] = FL_SENSE_INTERRUPT;
/* commands to the chip (always) */
if (fl_command_phase(p))
return(fl_results_phase(p));
return(NO);
}
/* fl_read_id - Read sector ID
*
* Summary:
*
* BOOL fl_read_id(UCOUNT driveno, COMMAND_BLOCK *p)
*
*
* Inputs:
* UCOUNT driveno - 0 or 1 = a: b:
* COMMAND_BLOCK *p - storage area. On return the results[0,1,N] will
* be valid.
*
* Returns:
* YES on success else NO.
*
* This routine is called by fl_establish_media. If the data rate is set
* right this routine should work. If it does work we know what the
* installed media is. fl_establish_media checks the return codes in the
* status registers.
*
*/
static BOOL fl_read_id(UCOUNT driveno, COMMAND_BLOCK *p) /*__fn__*/
{
p->n_to_send = 2;
p->n_to_get = 7;
p->commands[0] = MFMBIT|FL_READID;
p->commands[1] = (UTINY) driveno;
/* commands to the chip (always) */
fl_int_enable(NO);
if (fl_command_phase(p))
{
if (fl_waitint(FLTMO_READID))
return(fl_results_phase(p));
}
else
fl_int_enable(YES);
return(NO);
}
/* fl_seek - Seek to cylinder/head
*
* Summary:
* BOOL fl_seek(UCOUNT driveno, UCOUNT cyl, UCOUNT head)
*
*
* Inputs:
* UCOUNT driveno - 0 or 1 = a: b:
* UCOUNT cyl
* UCOUNT head
*
* Returns:
* YES on success else NO.
*
* This routine issues a seek waits for an interupt and then checks
* the status by issueing a sense interupt command. If all went
* well it returns YES.
*
*/
static BOOL fl_seek(UCOUNT driveno, UCOUNT cyl, UCOUNT head) /*__fn__*/
{
COMMAND_BLOCK b;
//char int_ascii[2];
UTINY cyl_offset; //Daniel
UTINY out_data;
b.n_to_send = 3;
b.n_to_get = 0;
b.commands[0] = FL_SEEK;
b.commands[1] = (UTINY) ((head<<2)| ((UTINY) driveno));
b.commands[2] = (UTINY) cyl;
fl_int_enable(NO);
if (fl_command_phase(&b))
{
//Daniel Start here
if(g_current_cyl > cyl)
cyl_offset = (g_current_cyl - cyl) * 3 + 2;
else
cyl_offset = (cyl - g_current_cyl) * 3 + 2;
g_current_cyl = (UTINY) cyl;
if (fl_waitint(cyl_offset)) //FLTMO_SEEK))
{
if (fl_sense_interrupt(&b))
{
/* Should have BIT5 (seek end == 1) and bits 6 & 7 == 0
the cylinder should be the same as passed in */
if ( ((b.results[0] & (BIT5|BIT6|BIT7)) == BIT5) &&
(b.results[1] == (UTINY) cyl) )
return(YES);
else
out_data = 4;
}
else
out_data = 3;
}
else
out_data = 2;
}
else
{
/* Command phase failed. We never called wait int so ints were
never enabled. */
fl_int_enable(YES);
out_data = 1;
}
/* printf("Seek Failed CYL HEAD %d %d", cyl, head); */
puts("Seek Failed CYL HEAD ");
// itoa(cyl, int_ascii);
// puts(int_ascii);
// puts(" ");
// itoa(head, int_ascii);
// puts(int_ascii);
puts("\n");
return(NO);
}
/* fl_recalibrate - Seek to cylinder 0, clear 765's internal PCN register
*
* Summary:
* BOOL fl_reclaibrate(UCOUNT driveno)
*
*
* Inputs:
* UCOUNT driveno - 0 or 1 = a: b:
*
* Returns:
* YES on success else NO.
*
* 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 YES.
*
*/
static BOOL fl_recalibrate(UCOUNT driveno) /*__fn__*/
{
COMMAND_BLOCK b;
COUNT i;
UTINY status_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] = (UTINY) driveno;
fl_int_enable(NO);
if (fl_command_phase(&b))
{
if (fl_waitint(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;
g_current_cyl = 0; //Daniel
return(YES);
}
}
}
else
fl_int_enable(YES);
}
return(NO);
}
/* fl_specify - Issue a specify command to the drive
*
* Summary:
* BOOL fl_specify(UCOUNT driveno)
*驱动器参数命令
*
* Inputs:
* UCOUNT driveno - 0 or 1 = a: b:
*
* Returns:
* YES on success else NO.
*
* 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 BOOL fl_specify(UCOUNT 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(YES);
else
return(NO);
}
/* This is a callback that shuts off the floppy motor when the timer expires */
VOID fl_motor_off(UCOUNT arg) /*__fn__*/
{
arg = arg;
shadow_dig_out &= ~(DORB_DSEL|DORB_MOEN2|DORB_MOEN1);
fl_write_dor(shadow_dig_out);
}
static VOID fl_motor_on(UCOUNT driveno) /*__fn__*/
{
BOOL must_sleep;
/* 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 */
mex_rearm_alarm(MOTOR_TIMEOUT);
must_sleep = NO;
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 = YES;
}
}
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 = YES;
}
}
fl_write_dor(shadow_dig_out);
if (must_sleep)
{
/* Wait for the motor to come up to speed */
/* mex_sleep(FL_SPINUP); */
NU_Sleep(FL_SPINUP);
/* Set the daemon again (3 seconds) */
mex_rearm_alarm(MOTOR_TIMEOUT);
}
}
/* Send command phase info to the floppy chip */
static BOOL fl_command_phase(COMMAND_BLOCK *p) /*__fn__*/
{
COUNT i;
COUNT ready;
ready = 0; /* Initializing "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();
delay_1us(); //wait the msr.bit7 to be ready, Lxd on 2002-2-8
}
else
break;
}
for (i = 0; i < p->n_to_send; i++)
{
if (ready != FL_FRHOST)
{
return(NO);
}
fl_write_data(p->commands[i]);
delay_1us(); //wait the msr.bit7 to be ready, Lxd on 2002-2-8
ready = fl_ready();
}
return(YES);
}
/*Get results phase info from the floppy chip Return YES if results match expected */
//读出命令执行的结果
static BOOL fl_results_phase(COMMAND_BLOCK *p) /*__fn__*/
{
COUNT i;
p->n_gotten = 0;
for (i = 0; i < p->n_to_get; i++)
{
if (fl_ready() != FL_TOHOST)
{
return(NO);
}
p->results[i] = fl_read_data();
delay_1us(); //wait the msr.bit7 to be ready, Lxd on 2002-2-8
}
p->n_gotten = p->n_to_get;
#ifdef POLLED
/* When in polled mode, there is no hardware line to tell the floppy
controller that we have read/written the number of sectors we expect.
Therefore, the result reported will always be "Abnormal Termination".
To get around this, we mask off the IC0 and IC1 bits at this point to
allow the driver to continue as normal. All other bits are passed back,
so that they are available for inspection if necessary. */
p->results[0] = p->results[0] & 0x3F; /* Ignore IC0,IC1 bits in polled mode */
#endif /* POLLED */
return(YES);
}
/* 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 COUNT fl_ready() /*__fn__*/
{
UTINY main_status_register; /* Master status register */
int timeout = 0xFFFE;//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 */
// mex_delay_25();
delay_25us();
}
}
/* 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 yes if the line has changed */
/*static*/ BOOL fl_change_line(UCOUNT driveno) /*__fn__*/
{
fl_motor_on(driveno);
if (fl_read_drr() & BIT7)
return(YES);
else
return(NO);
}
/* copy values from the parameter table to the floppy structure */
static VOID fl_cp_parms(UCOUNT driveno, COUNT 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 = (UTINY) (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 = YES;
else
floppy[driveno].double_step = NO;
}
/*
* Name:
* fl_int_enable() - Mask floppy iterrupts on and off
*
* Summary:
* fl_int_enable(BOOL on)
*
* Inputs:
* on - If YES enable the floppy interrupt, If NO disable it
*
*
* Returns:
* Nothing
*
* Description:
* The driver calls this function to mask off interrupts from the
* controller before it issues a command to the floppy controller.
* It then enables them when it is ready to service interrupts
* (inside fl_waitin()).
*
*/
static VOID fl_int_enable(BOOL on) /*__fn__*/
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -