📄 fl_drver.c
字号:
UTINY c;
int old_level; /* old interrupt level */
#ifdef PLUS
old_level = NU_Control_Interrupts(NU_DISABLE_INTERRUPTS);
#else
old_level = NU_Control_Interrupts(NU_DISABLE_INTERRUPTS);
#endif
/* Toggle bit six in the PIC */
c = (UTINY) fl_inp(0x21);
if (on)
c &= ~BIT6;
else
c |= BIT6;
fl_outp(0x21, c);
#ifdef PLUS
NU_Control_Interrupts(old_level);
#else
old_level = NU_Control_Interrupts(NU_DISABLE_INTERRUPTS);
enable();
#endif
}
#ifndef POLLED
#ifdef PLUS
/* real_lisr_fl_isr - this function is invoked by the LISR in file FL_ASM.ASM
* and is responsible for scheduling an HISR.
* Inputs
* None
* Outputs
* HISR Activated
*
* This function, when called, simply schedules an HISR which is responsible
* for calling real_fl_isr which in-turn sets an event.
*
*/
/* void far real_lisr_fl_isr() */
void real_lisr_fl_isr()
{
/* Activate the HISR to handle IDE interrupts. */
NU_Activate_HISR(&FL_HISR_Control);
}
/* fl_init_HISR - Provides Nucleus PLUS initialization for interrupt service
* routines used by the Floppy driver.
* Inputs
* global definitions of FL_HISR_Control and FL_HISR_Stack
* Outputs
* HISR created to handle Floppy interrupts
* Returns
* Nothing
*
* This routine is called to create the HISR (fl_real_isr) used by
* the Floppy driver for processing floppy interrupts.
*/
VOID fl_init_HISR()
{
/* Create the HISR for the ide_interrupt. The parameters are the
control structure (defined globally above, the ASCII string that
represent the HISR's name, the function that will be activated from
the HISR, a priority of 2 (the lowest), a pointer to the memory to
be used for the HISR's stack, and the size of the stack (see definition
of FL_HISR_Stack above). */
NU_Create_HISR(&FL_HISR_Control, "FL_HISR", real_fl_isr,
2, FL_HISR_Stack, 500);
}
#endif
/* NUCLEUS fl_isr() is the pc specific vectored interupt routine
that calls this routine */
void real_fl_isr() /*__fn__*/
{
/* mex_signal_send(NUF_FLOPPY_EVENT); */
/* Signal interupt complete */
#ifdef PLUS
// NU_Set_Events(&NUFP_RTX_To_PLUS_Events[NUF_FLOPPY_EVENT],
NU_Set_Events(&NUFP_Events[NUF_FLOPPY_EVENT],
(UNSIGNED) ~0, NU_OR);
#else
/* PC SPECIFIC Send and end of interrupt to the PIC */
NU_Set_Events(NUF_FLOPPY_EVENT, NU_EVENT_OR, (unsigned int) ~0);
#endif /* PLUS */
}
#endif /* NOT POLLED */
/*
* Name:
* fl_waitint() - Wait for a floppy interrupt. If one doesn't come. Fail.
*
* Summary:
* fl_waitint(COUNT millis)
*
* Inputs:
* millis - Number of miliseconds to wait for the interrupt to occur.
*
*
* Returns:
* YES if the interrupt occured, NO 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 BOOL fl_waitint(COUNT millis) /*__fn__*/
{
BOOL ret_val;
#ifndef POLLED
#ifdef PLUS
unsigned long current_events;
#else
unsigned int current_events;
#endif
#endif /* NOT POLLED */
/* Enable ints at the controller */
fl_int_enable(YES);
/* Wait for an interrupt or timeout */
#if (LOCK_METHOD == 2)
/* Release the file system */
fs_release();
#endif
/* ret_val = mex_signal_test(NUF_FLOPPY_EVENT,millis); */
#ifdef PLUS
#ifdef POLLED
NU_Sleep(millis); /*MAT Wait for command to finish */
#else /* POLLED */
// if (NU_Retrieve_Events(&NUFP_RTX_To_PLUS_Events[NUF_FLOPPY_EVENT],
if (NU_Retrieve_Events(&NUFP_Events[NUF_FLOPPY_EVENT],
(UNSIGNED) ~0, NU_OR_CONSUME, ¤t_events,
millis) != NU_SUCCESS)
#endif /* POLLED */
#else /* PLUS */
#ifdef POLLED
NU_Sleep(millis); /*MAT Wait for command to finish */
#else /* POLLED */
if (NU_Wait_For_Events(NUF_FLOPPY_EVENT, NU_EVENT_OR_CONSUME,
(unsigned int) ~0, ¤t_events, millis)
!= NU_SUCCESS)
#endif /* POLLED */
#endif /* PLUS */
#ifndef POLLED
ret_val = NO;
else
#endif /* NOT POLLED */
ret_val = YES; /* For Polled mode, always return YES */
#if (LOCK_METHOD == 2)
/* reclaim */
fs_reclaim();
#endif
return( (BOOL) ret_val);
}
/*
* Name:
* fl_report_error() Report and clear an error
*
* Summary:
* BOOL fl_report_error(COUNT error, BOOL 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:
*
*/
TEXT * 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 BOOL fl_report_error(COUNT error, BOOL 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 = (UTINY) DT_NONE;
// floppy[1].media_type = (UTINY) DT_NONE;
// fl_reset_controller();
Stop_gTimer();
fl_controller_init();
/* printf("%s\n",fl_errors[error]); */
#ifdef DEBUG //Daniel
puts((const char *)fl_errors[error]);
#endif //Daniel
break;
case FLERR_RESET:
case FLERR_INVALID_INTERLEAVE:
case FLERR_UNK_DRIVE:
case FLERR_EXEC_EST:
/* printf("%s\n",fl_errors[error]); */
#ifdef DEBUG //Daniel
puts((const char *)fl_errors[error]);
#endif //Daniel
break;
default:
/* printf("Unknown Floppy Error\n"); */
#ifdef DEBUG //Daniel
puts("Unknown Floppy Error\n");
#endif //Daniel
break;
}
return(return_me);
}
/*
* Name:
* fl_waitdma() - Wait for a dma transfer to complete
*
* Summary:
* fl_waitdma(COUNT millis)
*
* Inputs:
* millis - Fail if more than milli milliseconds elapses
*
*
* Returns:
* YES if the dma transfer was sucessful.
*
* Description:
* This function is called when the driver is waiting for a dma transfer to
* complete. The transfer was set up by fl_dma_setup().
*
* This routine calls pc_wait_int(millis) for the floppy to interrupt
* and then verifies that the dma channel has reach terminal count.
* need to do is wait for the floppy interrupt. We seperated the two
*
* Note: In a system using programmed transfer the transfer loop
* would go inside here. The addresses and could would come from
* fl_dma_init().
*
*/
/* DMA registers */
#define STATUS_REGISTER 0x08
#define MASK_REGISTER 0x0a
#define MODE_REGISTER 0x0b
#define FLIPFLOP_REGISTER 0x0c
#define BANK_REGISTER 0x81
/* Channel 2 register bank */
#define ADDRESS_REGISTER 0x04
#define COUNT_REGISTER 0x05
static BOOL fl_waitdma(COUNT millis) /*__fn__*/
{
#ifdef POLLED
UTINY main_status_register;
COUNT i ;
COUNT ready;
int timeout = 0xFFFE;//32000;
#else /* POLLED */
UTINY status;
#endif /* POLLED */
#ifdef POLLED
ready = 0; /* Initializing "ready" */
ready = fl_ready();
if (polled_reading)
{
for (i = 0; i < polled_length; i++)
{
if (ready != FL_TOHOST)
{
return(NO);
}
polled_buffer[i] = fl_read_data();
delay_1us(); //wait the msr.bit7 to be ready, Lxd on 2002-2-8
ready = fl_ready();
/* while (YES)
{
if (!timeout--)
{
ready = 0;
return NO;//break; 如果不返回,写磁盘时将磁盘抽走会死机!
}
main_status_register = fl_read_msr();
if (main_status_register & BIT7)
break;
delay_25us();
}
if (main_status_register & BIT6)
ready = FL_TOHOST;
else
ready = FL_FRHOST;
*/
}
}
else
{
for (i = 0; i < polled_length; i++)
{
if (ready != FL_FRHOST)
{
return(NO);
}
fl_write_data(polled_buffer[i]);
delay_1us(); //wait the msr.bit7 to be ready, Lxd on 2002-2-8
ready = fl_ready();
/* while (YES)
{
if (!timeout--)
{
ready = 0;
return NO;//break; 如果不返回,写磁盘时将磁盘抽走会死机!
}
main_status_register = fl_read_msr();
if (main_status_register & BIT7)
break;
delay_25us();
}
if (main_status_register & BIT6)
ready = FL_TOHOST;
else
ready = FL_FRHOST;
*/
}
}
fl_waitint(millis);
return(YES);
#else /* POLLED */
if (fl_waitint(millis))
{
/* Check terminal count flag */
status = (UTINY) fl_inp(STATUS_REGISTER);
if (status & BIT2)
return(YES);
else
return(NO);
}
return(NO);
#endif /* POLLED */
}
/*
* Name:
* fl_dma_init() - Initialize a dma transfer
*
* Summary:
* BOOL fl_dma_init(UTINY *in_address, UCOUNT length, BOOL reading)
*
* Inputs:
* in_address - Address to transfer data to/from
* length - Length in bytes to transfer
* reading - If yes, floppy to memory, else mem to floppy
* Returns:
* YES if the setup was successful. NO on a boundary wrap.
*
* Description:
* This function is called to set up a dma transfer.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -