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

📄 ftape-rw.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
	int expected = 0;	int count = 1;	int short_seek;	int target = segment_id - margin;	TRACE_FUN(ft_t_flow);	if (ft_location.known && !validate(segment_id)) {		ftape_sleep(1 * FT_SECOND);		ft_failure = 1;		TRACE_ABORT(-EIO, ft_t_err,			    "fatal: head off track (bad hardware?)");	}	do {		if (!ft_location.known) {			TRACE(ft_t_warn, "warning: location not known");		}		TRACE(ft_t_noise, "from %d/%d to %d/0 - %d",		      ft_location.segment, ft_location.sector,		      segment_id, margin);		/*  min_rewind == 1 + overshoot_when_doing_minimum_rewind		 *  overshoot  == overshoot_when_doing_larger_rewind		 *  Initially min_rewind == 1 + overshoot, optimization		 *  of both values will be done separately.		 *  overshoot and min_rewind can be negative as both are		 *  sums of three components:		 *  any_overshoot == rewind_overshoot - 		 *                   stop_overshoot   -		 *                   start_overshoot		 */		if (ft_location.segment - target - (min_rewind - 1) < 1) {			short_seek = 1;		} else {			count = ft_location.segment - target - overshoot;			short_seek = (count < 1);		}		if (short_seek) {			count = 1;	/* do shortest rewind */			expected = ft_location.segment - min_rewind;			if (expected/ft_segments_per_track != ft_location.track) {				expected = (ft_location.track * 					    ft_segments_per_track);			}		} else {			expected = target;		}		fast_seek(count, 1);		logical_forward();		if (ftape_read_id() < 0 || !ft_location.known ||		    (sigtestsetmask(&current->pending.signal, _DONT_BLOCK))) {			if ((!ftape_tape_running && !ft_location.known) ||			    ++failures > FT_SECTORS_PER_SEGMENT) {				TRACE_ABORT(-EIO, ft_t_err,					    "read_id failed completely");			}			FT_SIGNAL_EXIT(_DONT_BLOCK);			TRACE_CATCH(ftape_report_drive_status(pstatus),);			TRACE(ft_t_noise, "ftape_read_id failed, retry (%d)",			      failures);			continue;		}		TRACE(ft_t_noise, "ended at %d/%d (%d,%d,%d)", 		      ft_location.segment, ft_location.sector,		      min_rewind, overshoot, inhibit_correction);		if (!inhibit_correction &&		    (ft_location.segment < expected ||		     ft_location.segment > expected + margin)) {			int error = expected - ft_location.segment;			if (short_seek) {				TRACE(ft_t_noise,				      "adjusting min_rewind from %d to %d",				      min_rewind, min_rewind + error);				min_rewind += error;				if (min_rewind < -5) {					/* is this right ? FIXME ! */					/* keep sane value */					min_rewind = -5;					TRACE(ft_t_noise, 					      "clipped min_rewind to %d",					      min_rewind);				}			} else {				TRACE(ft_t_noise,				      "adjusting overshoot from %d to %d",				      overshoot, overshoot + error);				overshoot += error;				if (overshoot < -5 ||				    overshoot > OVERSHOOT_LIMIT) {					if (overshoot < 0) {						/* keep sane value */						overshoot = -5;					} else {						/* keep sane value */						overshoot = OVERSHOOT_LIMIT;					}					TRACE(ft_t_noise,					      "clipped overshoot to %d",					      overshoot);				}			}		}	} while (ft_location.segment > segment_id);	if (ft_location.known) {		TRACE(ft_t_noise, "current location: %d/%d",		      ft_location.segment, ft_location.sector);	}	TRACE_EXIT 0;}static int determine_position(void){	int retry = 0;	int status;	int result;	TRACE_FUN(ft_t_flow);	if (!ftape_tape_running) {		/*  This should only happen if tape is stopped by isr.		 */		TRACE(ft_t_flow, "waiting for tape stop");		if (ftape_ready_wait(ftape_timeout.pause, &status) < 0) {			TRACE(ft_t_flow, "drive still running (fatal)");			ftape_tape_running = 1;	/* ? */		}	} else {		ftape_report_drive_status(&status);	}	if (status & QIC_STATUS_READY) {		/*  Drive must be ready to check error state !		 */		TRACE(ft_t_flow, "drive is ready");		if (status & QIC_STATUS_ERROR) {			unsigned int error;			qic117_cmd_t command;			/*  Report and clear error state, try to continue.			 */			TRACE(ft_t_flow, "error status set");			ftape_report_error(&error, &command, 1);			ftape_ready_wait(ftape_timeout.reset, &status);			ftape_tape_running = 0;	/* ? */		}		if (check_bot_eot(status)) {			if (ft_location.bot) {				if ((status & QIC_STATUS_READY) == 0) {					/* tape moving away from					 * bot/eot, let's see if we					 * can catch up with the first					 * segment on this track.					 */				} else {					TRACE(ft_t_flow,					      "start tape from logical bot");					logical_forward();	/* start moving */				}			} else {				if ((status & QIC_STATUS_READY) == 0) {					TRACE(ft_t_noise, "waiting for logical end of track");					result = ftape_ready_wait(ftape_timeout.reset, &status);					/* error handling needed ? */				} else {					TRACE(ft_t_noise,					      "tape at logical end of track");				}			}		} else {			TRACE(ft_t_flow, "start tape");			logical_forward();	/* start moving */			ft_location.known = 0;	/* not cleared by logical forward ! */		}	}	/* tape should be moving now, start reading id's	 */	while (!ft_location.known &&	       retry++ < FT_SECTORS_PER_SEGMENT &&	       (result = ftape_read_id()) < 0) {		TRACE(ft_t_flow, "location unknown");		/* exit on signal		 */		FT_SIGNAL_EXIT(_DONT_BLOCK);		/*  read-id somehow failed, tape may		 *  have reached end or some other		 *  error happened.		 */		TRACE(ft_t_flow, "read-id failed");		TRACE_CATCH(ftape_report_drive_status(&status),);		TRACE(ft_t_err, "ftape_report_drive_status: 0x%02x", status);		if (status & QIC_STATUS_READY) {			ftape_tape_running = 0;			TRACE(ft_t_noise, "tape stopped for unknown reason! "			      "status = 0x%02x", status);			if (status & QIC_STATUS_ERROR ||			    !check_bot_eot(status)) {				/* oops, tape stopped but not at end!				 */				TRACE_EXIT -EIO;			}		}	}	TRACE(ft_t_flow,	      "tape is positioned at segment %d", ft_location.segment);	TRACE_EXIT ft_location.known ? 0 : -EIO;}/*      Get the tape running and position it just before the *      requested segment. *      Seek tape-track and reposition as needed. */int ftape_start_tape(int segment_id, int sector_offset){	int track = segment_id / ft_segments_per_track;	int result = -EIO;	int status;	static int last_segment = -1;	static int bad_bus_timing = 0;	/* number of segments passing the head between starting the tape	 * and being able to access the first sector.	 */	static int start_offset = 1;	int retry;	TRACE_FUN(ft_t_flow);	/* If sector_offset > 0, seek into wanted segment instead of	 * into previous.	 * This allows error recovery if a part of the segment is bad	 * (erased) causing the tape drive to generate an index pulse	 * thus causing a no-data error before the requested sector	 * is reached.	 */	ftape_tape_running = 0;	TRACE(ft_t_noise, "target segment: %d/%d%s", segment_id, sector_offset,		ft_buffer[ft_head]->retry > 0 ? " retry" : "");	if (ft_buffer[ft_head]->retry > 0) {	/* this is a retry */		int dist = segment_id - last_segment;		if ((int)ft_history.overrun_errors < overrun_count_offset) {			overrun_count_offset = ft_history.overrun_errors;		} else if (dist < 0 || dist > 50) {			overrun_count_offset = ft_history.overrun_errors;		} else if ((ft_history.overrun_errors -			    overrun_count_offset) >= 8) {			if (ftape_increase_threshold() >= 0) {				--ft_buffer[ft_head]->retry;				overrun_count_offset =					ft_history.overrun_errors;				TRACE(ft_t_warn, "increased threshold because "				      "of excessive overrun errors");			} else if (!bad_bus_timing && ft_data_rate >= 1000) {				ftape_half_data_rate();				--ft_buffer[ft_head]->retry;				bad_bus_timing = 1;				overrun_count_offset =					ft_history.overrun_errors;				TRACE(ft_t_warn, "reduced datarate because "				      "of excessive overrun errors");			}		}	}	last_segment = segment_id;	if (ft_location.track != track ||	    (ftape_might_be_off_track && ft_buffer[ft_head]->retry== 0)) {		/* current track unknown or not equal to destination		 */		ftape_ready_wait(ftape_timeout.seek, &status);		ftape_seek_head_to_track(track);		/* overrun_count_offset = ft_history.overrun_errors; */	}	result = -EIO;	retry = 0;	while (result < 0     &&	       retry++ <= 5   &&	       !ft_failure &&	       !(sigtestsetmask(&current->pending.signal, _DONT_BLOCK))) {				if (retry && start_offset < 5) {			start_offset ++;		}		/*  Check if we are able to catch the requested		 *  segment in time.		 */		if ((ft_location.known || (determine_position() == 0)) &&		    ft_location.segment >=		    (segment_id -		     ((ftape_tape_running || ft_location.bot)		      ? 0 : start_offset))) {			/*  Too far ahead (in or past target segment).			 */			if (ftape_tape_running) {				if ((result = ftape_stop_tape(&status)) < 0) {					TRACE(ft_t_err,					      "stop tape failed with code %d",					      result);					break;				}				TRACE(ft_t_noise, "tape stopped");				ftape_tape_running = 0;			}			TRACE(ft_t_noise, "repositioning");			++ft_history.rewinds;			if (segment_id % ft_segments_per_track < start_offset){				TRACE(ft_t_noise, "end of track condition\n"				      KERN_INFO "segment_id        : %d\n"				      KERN_INFO "ft_segments_per_track: %d\n"				      KERN_INFO "start_offset      : %d",				      segment_id, ft_segments_per_track, 				      start_offset);				      				/*  If seeking to first segments on				 *  track better do a complete rewind				 *  to logical begin of track to get a				 *  more steady tape motion.  				 */				result = ftape_command_wait(					(ft_location.track & 1)					? QIC_PHYSICAL_FORWARD					: QIC_PHYSICAL_REVERSE,					ftape_timeout.rewind, &status);				check_bot_eot(status);	/* update location */			} else {				result= skip_reverse(segment_id - start_offset,						     &status);			}		}		if (!ft_location.known) {			TRACE(ft_t_bug, "panic: location not known");			result = -EIO;			continue; /* while() will check for failure */		}		TRACE(ft_t_noise, "current segment: %d/%d",		      ft_location.segment, ft_location.sector);		/*  We're on the right track somewhere before the		 *  wanted segment.  Start tape movement if needed and		 *  skip to just before or inside the requested		 *  segment. Keep tape running.  		 */		result = 0;		if (ft_location.segment < 		    (segment_id - ((ftape_tape_running || ft_location.bot)				   ? 0 : start_offset))) {			if (sector_offset > 0) {				result = seek_forward(segment_id,						      retry <= 3);			} else {				result = seek_forward(segment_id - 1,						      retry <= 3);			}		}		if (result == 0 &&		    ft_location.segment !=		    (segment_id - (sector_offset > 0 ? 0 : 1))) {			result = -EIO;		}	}	if (result < 0) {		TRACE(ft_t_err, "failed to reposition");	} else {		ft_runner_status = running;	}	TRACE_EXIT result;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -