📄 fl_drver.c
字号:
WriteRealMem(dma_buffer, parms_buffer, 512);
if (!fl_dma_init((DMAPTYPE) dma_buffer,(word)((fl_devparms[parmindex].sectors_per_track)<<2), FALSE))
#endif
{
pc_free_buf(buf,TRUE);
return(fl_report_error(FLERR_DMA, FALSE));
}
/* Clear any outstanding interrupt complete messages */
OS_FLOPPY_SIGNAL_BIND(0);
OS_FLOPPY_SIGNAL_CLEAR(0);
fl_motor_on(driveno);
if (!fl_command_phase(&b))
{
goto fmterr;
}
/* Wait for the io to complete */
if (!fl_waitdma((int)FLTMO_FMTTRACK))
goto fmterr;
#else
shadow_dig_out &= ~DORB_DMAEN;
fl_write_dor(shadow_dig_out);
fl_motor_on(driveno);
for (i = 0; i < 10; i++)
if ((ready = fl_ready())== FL_TOHOST)
fl_read_data();
else
break;
for (i = 0; i < b.n_to_send; i++)
{
if ((ready = fl_ready()) != FL_FRHOST)
{
shadow_dig_out |= DORB_DMAEN;
fl_write_dor(shadow_dig_out);
pc_free_buf(buf,TRUE);
return(fl_report_error(FLERR_CHIP_HUNG, FALSE));
}
/* Write command bytes. On the last byte call the read routine
so it can set up the last command byte and be ready to
read the data without overruns */
if (i < (b.n_to_send-1))
fl_write_data(b.commands[i]);
else
residual = polled_write(
(byte KS_FAR *) parms_buffer,
(word)((fl_devparms[parmindex].sectors_per_track)<<2)
, b.commands[i]);
if (residual)
{
#if (!defined(ERTFS_SA))
DEBUG_ERROR("Format failed resid", NOVAR, 0, 0);
#else
tm_printf("Format failed resid\n");
#endif
goto fmterr;
}
}
/* Out of dma mode */
shadow_dig_out |= DORB_DMAEN;
fl_write_dor(shadow_dig_out);
#endif
if (!fl_results_phase(&b))
goto fmterr;
/* Check status register 0 for abnormal termination */
if (b.results[0] & (BIT7|BIT6))
goto fmterr;
}
}
pc_free_buf(buf,TRUE);
return(TRUE);
fmterr:
pc_free_buf(buf,TRUE);
return(fl_report_error(FLERR_FORMAT, FALSE));
}
/* fl_controller_init - Initialize the floppy controller
*
* summary
* BOOLEAN fl_controller_init()
*
*
* Inputs:
*
* Returns:
* TRUE on success else FALSE.
*
* 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 TRUE.
*
* Called by floppy_open()
*
*/
static BOOLEAN fl_controller_init() /* __fn__ */
{
selected_floppy = 0;
pc_memfill(&floppy[0], sizeof(_FLOPPY), 0);
#if (N_FLOPPY_UNITS == 2)
pc_memfill(&floppy[1], sizeof(_FLOPPY), 0);
#endif
/* Initialize interrupt vectors, timer, motor timer etc */
#if (defined(ERTFS_SA))
hook_floppy_interrupt(6);
#else
ks_hook_interrupt(6, (PFVOID) 0, floppy_isr, (RTIPINTFN_POINTER) 0, 0);
#endif
/* Clear any pending signals */
OS_FLOPPY_SIGNAL_CLEAR(0);
floppy[0].drive_type = os_floppy_type(0);
floppy[0].media_type = (byte) DT_NONE;
#if (N_FLOPPY_UNITS == 2)
floppy[1].drive_type = os_floppy_type(1);
floppy[1].media_type = (byte) DT_NONE;
#endif
return(fl_reset_controller());
}
/* Issue a reset through the digital output register and wait for
an interrupt. */
static BOOLEAN fl_reset_controller() /*__fn__*/
{
COMMAND_BLOCK b;
/* Clear any outstanding interrupt complete messages */
OS_FLOPPY_SIGNAL_BIND(0);
OS_FLOPPY_SIGNAL_CLEAR(0);
/* 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 */
shadow_dig_out |= (DORB_SRSTBAR|DORB_DMAEN);
fl_write_dor(shadow_dig_out);
/* Wait up to 5 seconds for the interrupt to occur.*/
if (!fl_waitint((int)FLTMO_RESET))
{
return(fl_report_error(FLERR_RESET, FALSE));
}
/* Delay a little otherwise sense interrupt fails */
ks_sleep((word)(FL_SPINUP));
if (!fl_sense_interrupt(&b))
return(fl_report_error(FLERR_RESET, FALSE));
return(TRUE);
}
/* fl_claim - Claim the controller for IO to a drive
*
* Summary:
*
* BOOLEAN fl_claim(driveno)
*
*
* Inputs:
* int driveno - 0 or 1 = a: b:
*
* Returns:
* TRUE on success else FALSE.
*
* 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 BOOLEAN fl_claim(int driveno) /*__fn__*/
{
if (selected_floppy != (driveno+1))
{
selected_floppy = (int ) (driveno+1);
if (floppy[driveno].media_type == DT_NONE)
{
if (!fl_establish_media(driveno))
return(FALSE);
}
else if (!fl_specify(driveno))
return(fl_report_error(FLERR_SPECIFY, FALSE));
selected_floppy = (int ) (driveno+1);
}
fl_write_drr(floppy[driveno].data_rate);
return(TRUE);
}
/* fl_establish_media - Vary the data rate and read until succesful
*
* Summary:
*
* BOOLEAN fl_establish_media(driveno)
*
*
* Inputs:
* int driveno - 0 or 1 = a: b:
*
* Returns:
* TRUE on success else FALSE.
*
* 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 TRUE. If all possible media are exhausted
* return FALSE.
*
* NOTE: The floppy change line is cleared by the seek operations.
*/
BOOLEAN fl_establish_media(int driveno) /*__fn__*/
{
int 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))
{
/* 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(TRUE);
}
}
}
}
i++;
}
floppy[driveno].media_type = DT_NONE;
return(fl_report_error(FLERR_MEDIA, FALSE));
}
/* fl_sense_interrupt - Issue a sense interrupt command
*
* Summary:
*
* BOOLEAN 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:
* TRUE on success else FALSE.
*
* This routine issues a sense interrupt command. It is called after
* seeks/recals and resets. The status registers are interpreted by
* the calling routine
*
*/
static BOOLEAN 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(FALSE);
}
/* fl_read_id - Read sector ID
*
* Summary:
*
* BOOLEAN fl_read_id(int driveno, COMMAND_BLOCK *p)
*
*
* Inputs:
* int driveno - 0 or 1 = a: b:
* COMMAND_BLOCK *p - storage area. On return the results[0,1,N] will
* be valid.
*
* Returns:
* TRUE on success else FALSE.
*
* 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 BOOLEAN fl_read_id(int driveno, COMMAND_BLOCK *p) /*__fn__*/
{
p->n_to_send = 2;
p->n_to_get = 7;
p->commands[0] = MFMBIT|FL_READID;
p->commands[1] = (byte) driveno;
/* Clear any outstanding interrupt complete messages */
OS_FLOPPY_SIGNAL_BIND(0);
OS_FLOPPY_SIGNAL_CLEAR(0);
/* commands to the chip (always) */
if (fl_command_phase(p))
{
if (fl_waitint((int)FLTMO_READID))
return(fl_results_phase(p));
}
return(FALSE);
}
/* fl_seek - Seek to cylinder/head
*
* Summary:
* BOOLEAN fl_seek(int driveno, word cyl, word head)
*
*
* Inputs:
* int driveno - 0 or 1 = a: b:
* word cyl
* word head
*
* Returns:
* TRUE on success else FALSE.
*
* 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 TRUE.
*
*/
static BOOLEAN fl_seek(int driveno, word cyl, word head) /*__fn__*/
{
COMMAND_BLOCK b;
//AM: Only seek if moving to different track. In that case, recalibrate.
//AM: You may speed up floppy by removing the recalibrate call which was inserted
//AM: to remedy problems with certain floppy controllers.
#if (0)
// Removed because it was causing problems
if ((cyl == floppy[driveno].last_cyl) && (head == floppy[driveno].last_head))
return(TRUE);
fl_recalibrate(driveno);
#endif
b.n_to_send = 3;
b.n_to_get = 0;
b.commands[0] = FL_SEEK;
b.commands[1] = (byte) ((head<<2)| ((byte) driveno));
b.commands[2] = (byte) cyl;
/* 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_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] == (byte) cyl) )
{
//AM: save information for last successful seek so will know
//AM: to recalibrate if seeking new cylinder/head.
floppy[driveno].last_cyl = (byte)cyl;
floppy[driveno].last_head = (byte)head;
return(TRUE);
}
}
}
}
return(FALSE);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -