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

📄 fl_drver.c

📁 移植Nuclues_RTC到coldfire5307在diab下编译通过
💻 C
📖 第 1 页 / 共 5 页
字号:
* 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 + -