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

📄 ftape-write.c

📁 arm平台上的uclinux系统全部源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *      Copyright (C) 1993-1995 Bas Laarhoven. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING.  If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. $Source: /usr/local/cvsroot/AplioTRIO/linux/drivers/char/ftape/ftape-write.c,v $ $Author: vadim $ * $Revision: 1.1.1.1 $ $Date: 1999/11/15 13:41:58 $ $State: Exp $ * *      This file contains the writing code *      for the QIC-117 floppy-tape driver for Linux. */#include <linux/string.h>#include <linux/errno.h>#include <linux/mm.h>#include <linux/ftape.h>#include <asm/segment.h>#include "tracing.h"#include "ftape-write.h"#include "ftape-read.h"#include "qic117.h"#include "ftape-io.h"#include "ftape-ctl.h"#include "ftape-rw.h"#include "ftape-eof.h"#include "ecc.h"#include "ftape-bsm.h"/*      Global vars. *//*      Local vars. */static int buf_pos_wr = 0;static int last_write_failed = 0;static int need_flush = 0;#define WRITE_MULTI  0#define WRITE_SINGLE 1void ftape_zap_write_buffers(void){	int i;	for (i = 0; i < NR_BUFFERS; ++i) {		buffer[i].status = done;	}	need_flush = 0;}int copy_and_gen_ecc(char *destination, byte * source,		     unsigned int bad_sector_map){	TRACE_FUN(8, "copy_and_gen_ecc");	int result;	struct memory_segment mseg;	int bads = count_ones(bad_sector_map);	if (bads > 0) {		TRACEi(4, "bad sectors in map:", bads);	}	if (bads + 3 >= SECTORS_PER_SEGMENT) {		TRACE(4, "empty segment");		mseg.blocks = 0;	/* skip entire segment */		result = 0;	/* nothing written */	} else {		mseg.blocks = SECTORS_PER_SEGMENT - bads;		mseg.data = destination;		memcpy(mseg.data, source, (mseg.blocks - 3) * SECTOR_SIZE);		result = ecc_set_segment_parity(&mseg);		if (result < 0) {			TRACE(1, "ecc_set_segment_parity failed");		} else {			result = (mseg.blocks - 3) * SECTOR_SIZE;		}	}	TRACE_EXIT;	return result;}void prevent_flush(void){	need_flush = 0;	ftape_state = idle;}int start_writing(int mode){	TRACE_FUN(5, "start_writing");	int result = 0;	buffer_struct *buff = &buffer[head];	int segment_id = buff->segment_id;	if (ftape_state == writing && buff->status == waiting) {		setup_new_segment(buff, segment_id, 1);		if (mode == WRITE_SINGLE) {			buffer[head].next_segment = 0;	/* stop tape instead of pause */		}		calc_next_cluster(buff);	/* prepare */		buff->status = writing;		if (runner_status == idle) {			TRACEi(5, "starting runner for segment", segment_id);			result = ftape_start_tape(segment_id, buff->sector_offset);			if (result >= 0) {				runner_status = running;			}		}		if (result >= 0) {			result = setup_fdc_and_dma(buff, FDC_WRITE);	/* go */		}		ftape_state = writing;	}	TRACE_EXIT;	return result;}int loop_until_writes_done(void){	TRACE_FUN(5, "loop_until_writes_done");	int i;	int result = 0;	/*	 *  Wait until all data is actually written to tape.	 */	while (ftape_state == writing && buffer[head].status != done) {		TRACEx2(7, "tail: %d, head: %d", tail, head);		for (i = 0; i < NR_BUFFERS; ++i) {			TRACEx3(8, "buffer[ %d] segment_id: %d, status: %d",			      i, buffer[i].segment_id, buffer[i].status);		}		result = fdc_interrupt_wait(5 * SECOND);		if (result < 0) {			TRACE(1, "fdc_interrupt_wait failed");			last_write_failed = 1;			break;		}		if (buffer[head].status == error) {			/* Allow escape from loop when signaled !			 */			if (current->signal & _DONT_BLOCK) {				TRACE(2, "interrupted by signal");				TRACE_EXIT;				result = -EINTR;	/* is this the right return value ? */				break;			}			if (buffer[head].hard_error_map != 0) {				/*  Implement hard write error recovery here				 */			}			buffer[head].status = waiting;	/* retry this one */			if (runner_status == aborting) {				ftape_dumb_stop();				runner_status = idle;			}			if (runner_status != idle) {				TRACE(1, "unexpected state: runner_status != idle");				result = -EIO;				break;			}			start_writing(WRITE_MULTI);		}		TRACE(5, "looping until writes done");		result = 0;	/* normal exit status */	}	TRACE_EXIT;	return result;}/*      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;}/*  Write as much as fits from buffer to the given segment on tape *  and handle retries. *  Return the number of bytes written (>= 0), or: *      -EIO          write failed *      -EINTR        interrupted by signal *      -ENOSPC       device full */int _write_segment(unsigned int segment_id, byte * buffer, int flush){	TRACE_FUN(5, "_write_segment");	int retry = 0;	int result;	history.used |= 2;	for (;;) {		if (segment_id > ftape_last_segment.id && !flush) {			result = -ENOSPC;	/* tape full */			break;		}		result = write_segment(segment_id, buffer, flush);		if (result < 0) {			if (result == -EAGAIN) {				if (++retry > 100) {					TRACE(1, "write failed, >100 retries in segment");					result = -EIO;	/* give up */					break;				} else {					TRACEx1(2, "write error, retry %d", retry);				}			} else {				TRACEi(1, "write_segment failed, error:", -result);				break;			}		} else {	/* success */			if (result == 0) {	/* empty segment */				TRACE(4, "empty segment, nothing written");			}			break;		}		/* Allow escape from loop when signaled !		 */		if (current->signal & _DONT_BLOCK) {			TRACE(2, "interrupted by signal");			TRACE_EXIT;			result = -EINTR;	/* is this the right return value ? */			break;		}	}	TRACE_EXIT;	return result;}int update_header_segment(unsigned segment, byte * buffer){	TRACE_FUN(5, "update_header_segment");	int result = 0;	int status;	if (buffer == NULL) {		TRACE(5, "no input buffer specified");		buffer = deblock_buffer;		result = read_segment(used_header_segment, buffer, &status, 0);		if (bad_sector_map_changed) {			store_bad_sector_map(buffer);		}		if (failed_sector_log_changed) {			update_failed_sector_log(buffer);		}	}	if (result >= 0 && GET4(buffer, 0) != 0xaa55aa55) {

⌨️ 快捷键说明

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