⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fl_drver.c

📁 ertfs文件系统里面既有完整ucos程序
💻 C
📖 第 1 页 / 共 5 页
字号:
/*  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 + -