コード例 #1
0
int ftape_report_operation(int *status,
			   qic117_cmd_t command,
			   int result_length)
{
	int i, st3;
	unsigned int t0;
	unsigned int dt;
	TRACE_FUN(ft_t_any);

	TRACE_CATCH(ftape_command(command),);
	t0 = ftape_timestamp();
	i = 0;
	do {
		++i;
		ftape_sleep(3 * FT_MILLISECOND);	/* see remark below */
		TRACE_CATCH(fdc_sense_drive_status(&st3),);
		dt = ftape_timediff(t0, ftape_timestamp());
		/*  Ack should be asserted within Ttimout + Tack = 6 msec.
		 *  Looks like some drives fail to do this so extend this
		 *  period to 300 msec.
		 */
	} while (!(st3 & ST3_TRACK_0) && dt < 300000);
	if (!(st3 & ST3_TRACK_0)) {
		TRACE(ft_t_err,
		      "No acknowledge after %u msec. (%i iter)", dt / 1000, i);
		TRACE_ABORT(-EIO, ft_t_err, "timeout on Acknowledge");
	}
	/*  dt may be larger than expected because of other tasks
	 *  scheduled while we were sleeping.
	 */
	if (i > 1 && dt > 6000) {
		TRACE(ft_t_err, "Acknowledge after %u msec. (%i iter)",
		      dt / 1000, i);
	}
	*status = 0;
	for (i = 0; i < result_length + 1; i++) {
		TRACE_CATCH(ftape_command(QIC_REPORT_NEXT_BIT),);
		TRACE_CATCH(fdc_sense_drive_status(&st3),);
		if (i < result_length) {
			*status |= ((st3 & ST3_TRACK_0) ? 1 : 0) << i;
		} else if ((st3 & ST3_TRACK_0) == 0) {
			TRACE_ABORT(-EIO, ft_t_err, "missing status stop bit");
		}
	}
	/* this command will put track zero and index back into normal state */
	(void)ftape_command(QIC_REPORT_NEXT_BIT);
	TRACE_EXIT 0;
}
コード例 #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;
}