Exemplo n.º 1
0
/*  Input a res_len long result string from the FDC.
 *  The FDC should be ready to send the result or an error
 *  (EBUSY or ETIME) will occur.
 */
int fdc_result(__u8 * res_data, int res_len)
{
	int result = 0;
	unsigned long flags;
	int count = res_len;
	int retry = 0;
	TRACE_FUN(ft_t_any);

	save_flags(flags);
	cli();
	fdc_status = inb(fdc.msr);
	if ((fdc_status & FDC_DATA_READY_MASK) != FDC_DATA_OUT_READY) {
		TRACE(ft_t_err, "fdc not ready");
		result = -EBUSY;
	} else while (count) {
		if (!(fdc_status & FDC_BUSY)) {
			restore_flags(flags);
			TRACE_ABORT(-EIO, ft_t_err, "premature end of result phase");
		}
		result = fdc_read(res_data);
		if (result < 0) {
			TRACE(ft_t_fdc_dma,
			      "fdc_mode = %02x, status = %02x at index %d",
			      (int) fdc_mode,
			      (int) fdc_status,
			      res_len - count);
			if (++retry <= 3) {
				TRACE(ft_t_warn, "fdc_read timeout, retry");
			} else {
				TRACE(ft_t_err, "fdc_read timeout, fatal");
				/* recover ??? */
				break;
				++retry;
			}
		} else {
			--count;
			++res_data;
		}
	}
	restore_flags(flags);
	fdc_usec_wait(FT_RQM_DELAY);	/* allow FDC to negate BSY */
	TRACE_EXIT result;
}
Exemplo n.º 2
0
/*  Output a cmd_len long command string to the FDC.
 *  The FDC should be ready to receive a new command or
 *  an error (EBUSY or ETIME) will occur.
 */
int fdc_command(const __u8 * cmd_data, int cmd_len)
{
	int result = 0;
	unsigned long flags;
	int count = cmd_len;
	int retry = 0;
#ifdef TESTING
	static unsigned int last_time;
	unsigned int time;
#endif
	TRACE_FUN(ft_t_any);

	fdc_usec_wait(FT_RQM_DELAY);	/* wait for valid RQM status */
	spin_lock_irqsave(&fdc_io_lock, flags);
	if (!in_interrupt())
		/* Yes, I know, too much comments inside this function
		 * ...
		 * 
		 * Yet another bug in the original driver. All that
		 * havoc is caused by the fact that the isr() sends
		 * itself a command to the floppy tape driver (pause,
		 * micro step pause).  Now, the problem is that
		 * commands are transmitted via the fdc_seek
		 * command. But: the fdc performs seeks in the
		 * background i.e. it doesn't signal busy while
		 * sending the step pulses to the drive. Therefore the
		 * non-interrupt level driver has no chance to tell
		 * whether the isr() just has issued a seek. Therefore
		 * we HAVE TO have a look at the ft_hide_interrupt
		 * flag: it signals the non-interrupt level part of
		 * the driver that it has to wait for the fdc until it
		 * has completet seeking.
		 *
		 * THIS WAS PRESUMABLY THE REASON FOR ALL THAT
		 * "fdc_read timeout" errors, I HOPE :-)
		 */
		if (ft_hide_interrupt) {
			restore_flags(flags);
			TRACE(ft_t_info,
			      "Waiting for the isr() completing fdc_seek()");
			if (fdc_interrupt_wait(2 * FT_SECOND) < 0) {
				TRACE(ft_t_warn,
		      "Warning: timeout waiting for isr() seek to complete");
			}
			if (ft_hide_interrupt || !ft_seek_completed) {
				/* There cannot be another
				 * interrupt. The isr() only stops
				 * the tape and the next interrupt
				 * won't come until we have send our
				 * command to the drive.
				 */
				TRACE_ABORT(-EIO, ft_t_bug,
					    "BUG? isr() is still seeking?\n"
					    KERN_INFO "hide: %d\n"
					    KERN_INFO "seek: %d",
					    ft_hide_interrupt,
					    ft_seek_completed);

			}
			fdc_usec_wait(FT_RQM_DELAY);	/* wait for valid RQM status */
			spin_lock_irqsave(&fdc_io_lock, flags);
		}
	fdc_status = inb(fdc.msr);
	if ((fdc_status & FDC_DATA_READY_MASK) != FDC_DATA_IN_READY) {
		spin_unlock_irqrestore(&fdc_io_lock, flags);
		TRACE_ABORT(-EBUSY, ft_t_err, "fdc not ready");
	} 
	fdc_mode = *cmd_data;	/* used by isr */
#ifdef TESTING
	if (fdc_mode == FDC_SEEK) {
		time = ftape_timediff(last_time, ftape_timestamp());
		if (time < 6000) {
	TRACE(ft_t_bug,"Warning: short timeout between seek commands: %d",
	      time);
		}
	}
#endif
	if (!in_interrupt()) {
		/* shouldn't be cleared if called from isr
		 */
		ft_interrupt_seen = 0;
	}
	while (count) {
		result = fdc_write(*cmd_data);
		if (result < 0) {
			TRACE(ft_t_fdc_dma,
			      "fdc_mode = %02x, status = %02x at index %d",
			      (int) fdc_mode, (int) fdc_status,
			      cmd_len - count);
			if (++retry <= 3) {
				TRACE(ft_t_warn, "fdc_write timeout, retry");
			} else {
				TRACE(ft_t_err, "fdc_write timeout, fatal");
				/* recover ??? */
				break;
			}
		} else {
			--count;
			++cmd_data;
		}
        }
#ifdef TESTING
	if (fdc_mode == FDC_SEEK) {
		last_time = ftape_timestamp();
	}
#endif
	spin_unlock_irqrestore(&fdc_io_lock, flags);
	TRACE_EXIT result;
}
Exemplo n.º 3
0
static int fdc_ready_out_wait(unsigned int usecs)
{
	fdc_usec_wait(FT_RQM_DELAY);	/* wait for valid RQM status */
	return fdc_wait(usecs, FDC_DATA_OUT_READY, FDC_DATA_OUT_READY);
}