Exemple #1
0
/*      Wait for the drive to get ready.
 *      timeout time in milli-seconds
 *      Returned status is valid if result != -EIO
 *
 *      Should we allow to be killed by SIGINT?  (^C)
 *      Would be nice at least for large timeouts.
 */
int ftape_ready_wait(unsigned int timeout, int *status)
{
	unsigned long t0;
	unsigned int poll_delay;
	int signal_retries;
	TRACE_FUN(ft_t_any);

	/*  the following ** REALLY ** reduces the system load when
	 *  e.g. one simply rewinds or retensions. The tape is slow 
	 *  anyway. It is really not necessary to detect error 
	 *  conditions with 1/10 seconds granularity
	 *
	 *  On my AMD 133MHZ 486: 100 ms: 23% system load
	 *                        1  sec:  5%
	 *                        5  sec:  0.6%, yeah
	 */
	if (timeout <= FT_SECOND) {
		poll_delay = 100 * FT_MILLISECOND;
		signal_retries = 20; /* two seconds */
	} else if (timeout < 20 * FT_SECOND) {
		TRACE(ft_t_flow, "setting poll delay to 1 second");
		poll_delay = FT_SECOND;
		signal_retries = 2; /* two seconds */
	} else {
		TRACE(ft_t_flow, "setting poll delay to 5 seconds");
		poll_delay = 5 * FT_SECOND;
		signal_retries = 1; /* five seconds */
	}
	for (;;) {
		t0 = jiffies;
		TRACE_CATCH(ftape_report_raw_drive_status(status),);
		if (*status & QIC_STATUS_READY) {
			TRACE_EXIT 0;
		}
		if (!signal_retries--) {
			FT_SIGNAL_EXIT(_NEVER_BLOCK);
		}
		if ((int)timeout >= 0) {
			/* this will fail when jiffies wraps around about
			 * once every year :-)
			 */
			timeout -= ((jiffies - t0) * FT_SECOND) / HZ;
			if (timeout <= 0) {
				TRACE_ABORT(-ETIME, ft_t_err, "timeout");
			}
			ftape_sleep(poll_delay);
			timeout -= poll_delay;
		} else {
			ftape_sleep(poll_delay);
		}
	}
	TRACE_EXIT -ETIME;
}
Exemple #2
0
int ftape_get_drive_status(void)
{
	int result;
	int status;
	TRACE_FUN(ft_t_flow);

	ft_no_tape = ft_write_protected = 0;
	/*    Tape drive is activated now.
	 *    First clear error status if present.
	 */
	do {
		result = ftape_ready_wait(ftape_timeout.reset, &status);
		if (result < 0) {
			if (result == -ETIME) {
				TRACE(ft_t_err, "ftape_ready_wait timeout");
			} else if (result == -EINTR) {
				TRACE(ft_t_err, "ftape_ready_wait aborted");
			} else {
				TRACE(ft_t_err, "ftape_ready_wait failed");
			}
			TRACE_EXIT -EIO;
		}
		/*  Clear error condition (drive is ready !)
		 */
		if (status & QIC_STATUS_ERROR) {
			unsigned int error;
			qic117_cmd_t command;

			TRACE(ft_t_err, "error status set");
			result = ftape_report_error(&error, &command, 1);
			if (result < 0) {
				TRACE(ft_t_err,
				      "report_error_code failed: %d", result);
				/* hope it's working next time */
				ftape_reset_drive();
				TRACE_EXIT -EIO;
			} else if (error != 0) {
				TRACE(ft_t_noise, "error code   : %d", error);
				TRACE(ft_t_noise, "error command: %d", command);
			}
		}
		if (status & QIC_STATUS_NEW_CARTRIDGE) {
			unsigned int error;
			qic117_cmd_t command;
			const ft_trace_t old_tracing = TRACE_LEVEL;
			SET_TRACE_LEVEL(ft_t_bug);

			/*  Undocumented feature: Must clear (not present!)
			 *  error here or we'll fail later.
			 */
			ftape_report_error(&error, &command, 1);

			SET_TRACE_LEVEL(old_tracing);
			TRACE(ft_t_info, "status: new cartridge");
			ft_new_tape = 1;
		} else {
			ft_new_tape = 0;
		}
		FT_SIGNAL_EXIT(_DONT_BLOCK);
	} while (status & QIC_STATUS_ERROR);
	
	ft_no_tape = !(status & QIC_STATUS_CARTRIDGE_PRESENT);
	ft_write_protected = (status & QIC_STATUS_WRITE_PROTECT) != 0;
	if (ft_no_tape) {
		TRACE(ft_t_warn, "no cartridge present");
	} else {
		if (ft_write_protected) {
			TRACE(ft_t_noise, "Write protected cartridge");
		}
	}
	TRACE_EXIT 0;
}
Exemple #3
0
static int ft_check_cmd_restrictions(qic117_cmd_t command)
{
	int status = -1;
	TRACE_FUN(ft_t_any);
	
	TRACE(ft_t_flow, "%s", qic117_cmds[command].name);
	/* A new motion command during an uninterruptible (motion)
	 *  command requires a ready status before the new command can
	 *  be issued. Otherwise a new motion command needs to be
	 *  checked against required status.
	 */
	if (qic117_cmds[command].cmd_type == motion &&
	    qic117_cmds[ftape_current_command].non_intr) {
		ftape_report_raw_drive_status(&status);
		if ((status & QIC_STATUS_READY) == 0) {
			TRACE(ft_t_noise,
			      "motion cmd (%d) during non-intr cmd (%d)",
			      command, ftape_current_command);
			TRACE(ft_t_noise, "waiting until drive gets ready");
			ftape_ready_wait(ftape_timeout.seek,
					 &status);
		}
	}
	if (qic117_cmds[command].mask != 0) {
		__u8 difference;
		/*  Some commands do require a certain status:
		 */
		if (status == -1) {	/* not yet set */
			ftape_report_raw_drive_status(&status);
		}
		difference = ((status ^ qic117_cmds[command].state) &
			      qic117_cmds[command].mask);
		/*  Wait until the drive gets
		 *  ready. This may last forever if
		 *  the drive never gets ready... 
		 */
		while ((difference & QIC_STATUS_READY) != 0) {
			TRACE(ft_t_noise, "command %d issued while not ready",
			      command);
			TRACE(ft_t_noise, "waiting until drive gets ready");
			if (ftape_ready_wait(ftape_timeout.seek,
					     &status) == -EINTR) {
				/*  Bail out on signal !
				 */
				TRACE_ABORT(-EINTR, ft_t_warn,
				      "interrupted by non-blockable signal");
			}
			difference = ((status ^ qic117_cmds[command].state) &
				      qic117_cmds[command].mask);
		}
		while ((difference & QIC_STATUS_ERROR) != 0) {
			int err;
			qic117_cmd_t cmd;

			TRACE(ft_t_noise,
			      "command %d issued while error pending",
			      command);
			TRACE(ft_t_noise, "clearing error status");
			ftape_report_error(&err, &cmd, 1);
			ftape_report_raw_drive_status(&status);
			difference = ((status ^ qic117_cmds[command].state) &
				      qic117_cmds[command].mask);
			if ((difference & QIC_STATUS_ERROR) != 0) {
				/*  Bail out on fatal signal !
				 */
				FT_SIGNAL_EXIT(_NEVER_BLOCK);
			}
		}
		if (difference) {
			/*  Any remaining difference can't be solved
			 *  here.  
			 */
			if (difference & (QIC_STATUS_CARTRIDGE_PRESENT |
					  QIC_STATUS_NEW_CARTRIDGE |
					  QIC_STATUS_REFERENCED)) {
				TRACE(ft_t_warn,
				      "Fatal: tape removed or reinserted !");
				ft_failure = 1;
			} else {
				TRACE(ft_t_err, "wrong state: 0x%02x should be: 0x%02x",
				      status & qic117_cmds[command].mask,
				      qic117_cmds[command].state);
			}
			TRACE_EXIT -EIO;
		}
		if (~status & QIC_STATUS_READY & qic117_cmds[command].mask) {
			TRACE_ABORT(-EBUSY, ft_t_err, "Bad: still busy!");
		}
	}
	TRACE_EXIT 0;
}