Пример #1
0
int ftape_abort_operation(void)
{
	int result = 0;
	int status;
	TRACE_FUN(ft_t_flow);

	if (ft_runner_status == running) {
		TRACE(ft_t_noise, "aborting runner, waiting");
		
		ft_runner_status = do_abort;
		/* set timeout so that the tape will run to logical EOT
		 * if we missed the last sector and there are no queue pulses.
		 */
		result = ftape_dumb_stop();
	}
	if (ft_runner_status != idle) {
		if (ft_runner_status == do_abort) {
			TRACE(ft_t_noise, "forcing runner abort");
		}
		TRACE(ft_t_noise, "stopping tape");
		result = ftape_stop_tape(&status);
		ft_location.known = 0;
		ft_runner_status  = idle;
	}
	ftape_reset_buffer();
	ftape_zap_read_buffers();
	ftape_set_state(idle);
	TRACE_EXIT result;
}
Пример #2
0
static int ftape_new_cartridge(void)
{
	ft_location.track = -1; /* force seek on first access */
	ftape_zap_read_buffers();
	ftape_zap_write_buffers();
	return 0;
}
Пример #3
0
int ftape_new_cartridge(void)
{
	location.track = -1;	/* force seek on first access */
	first_data_segment = -1;	/* unknown */
	ftape_zap_read_buffers();
	ftape_zap_write_buffers();
	ftape_reset_position();
	return 0;
}
int ftape_set_nr_buffers(int cnt)
{
    int delta = cnt - ft_nr_buffers;
    TRACE_FUN(ft_t_flow);

    if (delta > 0) {
        while (delta--) {
            if (add_one_buffer() < 0) {
                TRACE_EXIT -ENOMEM;
            }
        }
    } else if (delta < 0) {
        while (delta++) {
            del_one_buffer();
        }
    }
    ftape_zap_read_buffers();
    TRACE_EXIT 0;
}
Пример #5
0
static void zft_init_driver(void)
{
	TRACE_FUN(ft_t_flow);

	zft_resid =
		zft_header_read          =
		zft_old_ftape            =
		zft_offline              =
		zft_write_protected      =
		going_offline            =
		zft_mt_compression       =
		zft_header_changed       =
		zft_volume_table_changed =
		zft_written_segments     = 0;
	zft_blk_sz = CONFIG_ZFT_DFLT_BLK_SZ;
	zft_reset_position(&zft_pos); /* does most of the stuff */
	ftape_zap_read_buffers();
	ftape_set_state(idle);
	TRACE_EXIT;
}
Пример #6
0
/*      RELEASE routine called by kernel-interface code
 */
int _ftape_close(void)
{
	TRACE_FUN(8, "_ftape_close");
	int result = 0;
	int last_segment = 0;

	if (!ftape_offline) {
		result = ftape_flush_buffers();
		last_segment = ftape_seg_pos - 1;
		if (!(ftape_unit & FTAPE_NO_REWIND)) {
			if (result >= 0) {
				result = ftape_update_header_segments(NULL, 1);
				if (result < 0) {
					TRACE(1, "error: update of header segments failed");
				}
			} else {
				TRACE(1, "error: unable to update header segments");
			}
		}
		ftape_abort_operation();
		if (!(ftape_unit & FTAPE_NO_REWIND)) {
			if (!no_tape) {
				TRACE(5, "rewinding tape");
				result = ftape_seek_to_bot();
			}
			ftape_reset_position();
			ftape_zap_read_buffers();
			ftape_zap_write_buffers();
		}
	}
	ftape_detach_drive();
	fdc_uninit();
	if (history.used) {
		TRACE(3, "== Non-fatal errors this run: ==");
		TRACE(3, "fdc isr statistics:");
		TRACEi(3, " id_am_errors     :", history.id_am_errors);
		TRACEi(3, " id_crc_errors    :", history.id_crc_errors);
		TRACEi(3, " data_am_errors   :", history.data_am_errors);
		TRACEi(3, " data_crc_errors  :", history.data_crc_errors);
		TRACEi(3, " overrun_errors   :", history.overrun_errors);
		TRACEi(3, " no_data_errors   :", history.no_data_errors);
		TRACEi(3, " retries          :", history.retries);
		if (history.used & 1) {
			TRACE(3, "ecc statistics:");
			TRACEi(3, " crc_errors       :", history.crc_errors);
			TRACEi(3, " crc_failures     :", history.crc_failures);
			TRACEi(3, " ecc_failures     :", history.ecc_failures);
			TRACEi(3, " sectors corrected:", history.corrected);
		}
		TRACEx2(3, "media defects     : %d%s", history.defects,
			history.defects ? " !!!" : "");
		TRACEi(3, "repositions       :", history.rewinds);
		TRACEi(3, "last segment      :", last_segment);
	}
	if (going_offline) {
		going_offline = 0;
		ftape_offline = 1;
	}
	TRACE_EXIT;
	return result;
}
Пример #7
0
/*      Write given segment from buffer at address onto tape.
 */
int write_segment(unsigned segment_id, byte * address, int flushing)
{
    TRACE_FUN(5, "write_segment");
    int result = 0;
    int bytes_written = 0;

    TRACEi(5, "segment_id =", segment_id);
    if (ftape_state != writing) {
        if (ftape_state == reading) {
            TRACE(5, "calling ftape_abort_operation");
            result = ftape_abort_operation();
            if (result < 0) {
                TRACE(1, "ftape_abort_operation failed");
            }
        }
        ftape_zap_read_buffers();
        ftape_zap_write_buffers();
        ftape_state = writing;
    }
    /*    if all buffers full we'll have to wait...
     */
    wait_segment(writing);
    if (buffer[tail].status == error) {
        /*  setup for a retry
         */
        buffer[tail].status = waiting;
        bytes_written = -EAGAIN;	/* force retry */
        if (buffer[tail].hard_error_map != 0) {
            TRACEx1(1, "warning: %d hard error(s) in written segment",
                    count_ones(buffer[tail].hard_error_map));
            TRACEx1(4, "hard_error_map = 0x%08lx", buffer[tail].hard_error_map);
            /*  Implement hard write error recovery here
             */
        }
    } else if (buffer[tail].status == done) {
        history.defects += count_ones(buffer[tail].hard_error_map);
    } else {
        TRACE(1, "wait for empty segment failed");
        result = -EIO;
    }
    /*    If just passed last segment on tape: wait for BOT or EOT mark.
     */
    if (result >= 0 && runner_status == logical_eot) {
        int status;

        result = ftape_ready_wait(timeout.seek, &status);
        if (result < 0 || (status & (QIC_STATUS_AT_BOT | QIC_STATUS_AT_EOT)) == 0) {
            TRACE(1, "eot/bot not reached");
        } else {
            runner_status = end_of_tape;
        }
    }
    /*    should runner stop ?
     */
    if (result >= 0 &&
            (runner_status == aborting || runner_status == buffer_underrun ||
             runner_status == end_of_tape)) {
        if (runner_status != end_of_tape) {
            result = ftape_dumb_stop();
        }
        if (result >= 0) {
            if (runner_status == aborting) {
                if (buffer[head].status == writing) {
                    buffer[head].status = done;	/* ????? */
                }
            }
            runner_status = idle;	/* aborted ? */
        }
    }
    /*  Don't start tape if runner idle and segment empty.
     */
    if (result >= 0 && !(runner_status == idle &&
                         get_bad_sector_entry(segment_id) == EMPTY_SEGMENT)) {
        if (buffer[tail].status == done) {
            /*    now at least one buffer is empty, fill it with our data.
             *    skip bad sectors and generate ecc.
             *    copy_and_gen_ecc return nr of bytes written,
             *    range 0..29 Kb inclusive !
             */
            result = copy_and_gen_ecc(buffer[tail].address, address,
                                      get_bad_sector_entry(segment_id));
            if (result >= 0) {
                bytes_written = result;
                buffer[tail].segment_id = segment_id;
                buffer[tail].status = waiting;
                next_buffer(&tail);
            }
        }
        /*    Start tape only if all buffers full or flush mode.
         *    This will give higher probability of streaming.
         */
        if (result >= 0 && runner_status != running &&
                ((head == tail && buffer[tail].status == waiting) || flushing)) {
            result = start_writing(WRITE_MULTI);
        }
    }
    TRACE_EXIT;
    return (result < 0) ? result : bytes_written;
}