Example #1
0
/* --- Main FDC dispatcher --- */
static void fdc_execute(FDC_765 *self)
{
/* This code to dump out FDC commands as they are received is very useful
 * in debugging
 *
 * */
	int NC;
	fdc_dprintf(5, "FDC: ");
	for (NC = 0; NC < bytes_in_cmd[self->fdc_cmd_buf[0] & 0x1F]; NC++)
		fdc_dprintf(5, "%02x ", self->fdc_cmd_buf[NC]);
	fdc_dprintf(5, "\n");
 /* */
	/* Check if the DOR (ugh!) is being used to force us to a 
	   different drive. */
	fdc_dorcheck(self);

	/* Reset "seek finished" flag */
	self->fdc_st0 &= 0xBF;	 
	switch(self->fdc_cmd_buf[0] & 0x1F)
	{
		case 2: fdc_read_track(self);	break;	/* 2: READ TRACK */
		case 3: fdc_specify(self);	break;	/* 3: SPECIFY */
		case 4:	fdc_sense_drive(self);	break;	/* 4: SENSE DRV STATUS*/
		case 5:	fdc_write(self, 0);	break;	/* 5: WRITE */
		case 6: fdc_read(self, 0);	break;	/* 6: READ */
		case 7:	fdc_recalibrate(self);	break;	/* 7: RECALIBRATE */
		case 8: fdc_sense_int(self);	break;	/* 8: SENSE INT STATUS*/
		case 9: fdc_write(self, 1);	break;	/* 9: WRITE DELETED */
		case 10:fdc_read_id(self);	break;	/*10: READ ID */
		case 12:fdc_read(self, 1);	break;	/*12: READ DELETED */
		case 13:fdc_format(self);	break;	/*13: FORMAT TRACK */
		case 15:fdc_seek(self);		break;	/*15: SEEK */
		case 17:				/*17: SCAN EQUAL */
		case 25:				/*25: SCAN LOW/EQUAL */
		case 30:fdc_scan(self);		break;	/*30: SCAN HIGH/EQUAL*/
		default:
			fdc_dprintf(2, "Unknown FDC command %d\n", 
					self->fdc_cmd_buf[0] & 0x1F);
			fdc_error(self);	break;
	}

}
Example #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;
}