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

📄 zftape-ctl.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
/*  *      Copyright (C) 1996, 1997 Claus-Justus Heine 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: /homes/cvs/ftape-stacked/ftape/zftape/zftape-ctl.c,v $ * $Revision: 1.2.6.2 $ * $Date: 1997/11/14 18:07:33 $ * *      This file contains the non-read/write zftape functions *      for the QIC-40/80/3010/3020 floppy-tape driver for Linux. */#include <linux/config.h>#include <linux/errno.h>#include <linux/mm.h>#include <linux/module.h>#include <linux/fcntl.h>#include <linux/zftape.h>#include <asm/uaccess.h>#include "../zftape/zftape-init.h"#include "../zftape/zftape-eof.h"#include "../zftape/zftape-ctl.h"#include "../zftape/zftape-write.h"#include "../zftape/zftape-read.h"#include "../zftape/zftape-rw.h"#include "../zftape/zftape-vtbl.h"/*      Global vars. */int zft_write_protected; /* this is when cartridge rdonly or O_RDONLY */int zft_header_read;int zft_offline;unsigned int zft_unit;int zft_resid;int zft_mt_compression;/*      Local vars. */static int going_offline;typedef int (mt_fun)(int *argptr);typedef int (*mt_funp)(int *argptr);typedef struct{	mt_funp function;	unsigned offline         : 1; /* op permitted if offline or no_tape */	unsigned write_protected : 1; /* op permitted if write-protected    */	unsigned not_formatted   : 1; /* op permitted if tape not formatted */	unsigned raw_mode        : 1; /* op permitted if zft_mode == 0    */	unsigned need_idle_state : 1; /* need to call def_idle_state        */	char     *name;} fun_entry;static mt_fun mt_dummy, mt_reset, mt_fsr, mt_bsr, mt_rew, mt_offl, mt_nop,	mt_weof, mt_erase, mt_ras2, mt_setblk, mt_setdensity,	mt_seek, mt_tell, mt_reten, mt_eom, mt_fsf, mt_bsf,	mt_fsfm, mt_bsfm, mt_setdrvbuffer, mt_compression;static fun_entry mt_funs[]={ 	{mt_reset       , 1, 1, 1, 1, 0, "MT_RESET" }, /*  0 */	{mt_fsf         , 0, 1, 0, 0, 1, "MT_FSF"   },	{mt_bsf         , 0, 1, 0, 0, 1, "MT_BSF"   },	{mt_fsr         , 0, 1, 0, 1, 1, "MT_FSR"   },	{mt_bsr         , 0, 1, 0, 1, 1, "MT_BSR"   },	{mt_weof        , 0, 0, 0, 0, 0, "MT_WEOF"  }, /*  5 */	{mt_rew         , 0, 1, 1, 1, 0, "MT_REW"   },	{mt_offl        , 0, 1, 1, 1, 0, "MT_OFFL"  },	{mt_nop         , 1, 1, 1, 1, 0, "MT_NOP"   },	{mt_reten       , 0, 1, 1, 1, 0, "MT_RETEN" },	{mt_bsfm        , 0, 1, 0, 0, 1, "MT_BSFM"  }, /* 10 */	{mt_fsfm        , 0, 1, 0, 0, 1, "MT_FSFM"  },	{mt_eom         , 0, 1, 0, 0, 1, "MT_EOM"   },	{mt_erase       , 0, 0, 0, 1, 0, "MT_ERASE" },	{mt_dummy       , 1, 1, 1, 1, 0, "MT_RAS1"  },	{mt_ras2        , 0, 0, 0, 1, 0, "MT_RAS2"  },	{mt_dummy       , 1, 1, 1, 1, 0, "MT_RAS3"  },	{mt_dummy       , 1, 1, 1, 1, 0, "UNKNOWN"  },	{mt_dummy       , 1, 1, 1, 1, 0, "UNKNOWN"  },	{mt_dummy       , 1, 1, 1, 1, 0, "UNKNOWN"  },	{mt_setblk      , 1, 1, 1, 1, 1, "MT_SETBLK"}, /* 20 */	{mt_setdensity  , 1, 1, 1, 1, 0, "MT_SETDENSITY"},	{mt_seek        , 0, 1, 0, 1, 1, "MT_SEEK"  },	{mt_dummy       , 0, 1, 0, 1, 1, "MT_TELL"  }, /* wr-only ?! */	{mt_setdrvbuffer, 1, 1, 1, 1, 0, "MT_SETDRVBUFFER" },	{mt_dummy       , 1, 1, 1, 1, 0, "MT_FSS"   }, /* 25 */	{mt_dummy       , 1, 1, 1, 1, 0, "MT_BSS"   },	{mt_dummy       , 1, 1, 1, 1, 0, "MT_WSM"   },	{mt_dummy       , 1, 1, 1, 1, 0, "MT_LOCK"  },	{mt_dummy       , 1, 1, 1, 1, 0, "MT_UNLOCK"},	{mt_dummy       , 1, 1, 1, 1, 0, "MT_LOAD"  }, /* 30 */	{mt_dummy       , 1, 1, 1, 1, 0, "MT_UNLOAD"},	{mt_compression , 1, 1, 1, 0, 1, "MT_COMPRESSION"},	{mt_dummy       , 1, 1, 1, 1, 0, "MT_SETPART"},	{mt_dummy       , 1, 1, 1, 1, 0, "MT_MKPART"}};  #define NR_MT_CMDS NR_ITEMS(mt_funs)void zft_reset_position(zft_position *pos){	TRACE_FUN(ft_t_flow);	pos->seg_byte_pos =		pos->volume_pos = 0;	if (zft_header_read) {		/* need to keep track of the volume table and		 * compression map. We therefor simply		 * position at the beginning of the first		 * volume. This covers old ftape archives as		 * well has various flavours of the		 * compression map segments. The worst case is		 * that the compression map shows up as a		 * additional volume in front of all others.		 */		pos->seg_pos  = zft_find_volume(0)->start_seg;		pos->tape_pos = zft_calc_tape_pos(pos->seg_pos);	} else {		pos->tape_pos =  0;		pos->seg_pos  = -1;	}	zft_just_before_eof =  0;	zft_deblock_segment = -1;	zft_io_state        = zft_idle;	zft_zap_read_buffers();	zft_prevent_flush();	/*  unlock the compresison module if it is loaded.	 *  The zero arg means not to try to load the module.	 */	if (zft_cmpr_lock(0) == 0) {		(*zft_cmpr_ops->reset)(); /* unlock */	}	TRACE_EXIT;}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;}int zft_def_idle_state(void){ 	int result = 0;	TRACE_FUN(ft_t_flow);		if (!zft_header_read) {		result = zft_read_header_segments();	} else if ((result = zft_flush_buffers()) >= 0 && zft_qic_mode) {		/*  don't move past eof		 */		(void)zft_close_volume(&zft_pos);	}	if (ftape_abort_operation() < 0) {		TRACE(ft_t_warn, "ftape_abort_operation() failed");		result = -EIO;	}	/* clear remaining read buffers */	zft_zap_read_buffers();	zft_io_state = zft_idle;	TRACE_EXIT result;}/***************************************************************************** *                                                                           * *  functions for the MTIOCTOP commands                                      * *                                                                           * *****************************************************************************/static int mt_dummy(int *dummy){	TRACE_FUN(ft_t_flow);		TRACE_EXIT -ENOSYS;}static int mt_reset(int *dummy){        	TRACE_FUN(ft_t_flow);		(void)ftape_seek_to_bot();	TRACE_CATCH(ftape_reset_drive(),		    zft_init_driver(); zft_uninit_mem(); zft_offline = 1);	/*  fake a re-open of the device. This will set all flage and 	 *  allocate buffers as appropriate. The new tape condition will	 *  force the open routine to do anything we need.	 */	TRACE_CATCH(_zft_open(-1 /* fake reopen */, 0 /* dummy */),);	TRACE_EXIT 0;}static int mt_fsf(int *arg){	int result;	TRACE_FUN(ft_t_flow);	result = zft_skip_volumes(*arg, &zft_pos);	zft_just_before_eof = 0;	TRACE_EXIT result;}static int mt_bsf(int *arg){	int result = 0;	TRACE_FUN(ft_t_flow);		if (*arg != 0) {		result = zft_skip_volumes(-*arg + 1, &zft_pos);	}	TRACE_EXIT result;}static int seek_block(__s64 data_offset,		      __s64 block_increment,		      zft_position *pos){ 	int result      = 0;	__s64 new_block_pos;	__s64 vol_block_count;	const zft_volinfo *volume;	int exceed;	TRACE_FUN(ft_t_flow);		volume = zft_find_volume(pos->seg_pos);	if (volume->start_seg == 0 || volume->end_seg == 0) {		TRACE_EXIT -EIO;	}	new_block_pos   = (zft_div_blksz(data_offset, volume->blk_sz)			   + block_increment);	vol_block_count = zft_div_blksz(volume->size, volume->blk_sz);	if (new_block_pos < 0) {		TRACE(ft_t_noise,		      "new_block_pos " LL_X " < 0", LL(new_block_pos));		zft_resid     = (int)new_block_pos;		new_block_pos = 0;		exceed = 1;	} else if (new_block_pos > vol_block_count) {		TRACE(ft_t_noise,		      "new_block_pos " LL_X " exceeds size of volume " LL_X,		      LL(new_block_pos), LL(vol_block_count));		zft_resid     = (int)(vol_block_count - new_block_pos);		new_block_pos = vol_block_count;		exceed = 1;	} else {		exceed = 0;	}	if (zft_use_compression && volume->use_compression) {		TRACE_CATCH(zft_cmpr_lock(1 /* try to load */),);		result = (*zft_cmpr_ops->seek)(new_block_pos, pos, volume,					       zft_deblock_buf);		pos->tape_pos  = zft_calc_tape_pos(pos->seg_pos);		pos->tape_pos += pos->seg_byte_pos;	} else {		pos->volume_pos = zft_mul_blksz(new_block_pos, volume->blk_sz);		pos->tape_pos   = zft_calc_tape_pos(volume->start_seg);		pos->tape_pos  += pos->volume_pos;		pos->seg_pos    = zft_calc_seg_byte_coord(&pos->seg_byte_pos,							  pos->tape_pos);	}	zft_just_before_eof = volume->size == pos->volume_pos;	if (zft_just_before_eof) {		/* why this? because zft_file_no checks agains start		 * and end segment of a volume. We do not want to		 * advance to the next volume with this function.		 */		TRACE(ft_t_noise, "set zft_just_before_eof");		zft_position_before_eof(pos, volume);	}	TRACE(ft_t_noise, "\n"	      KERN_INFO "new_seg_pos : %d\n"	      KERN_INFO "new_tape_pos: " LL_X "\n"	      KERN_INFO "vol_size    : " LL_X "\n"	      KERN_INFO "seg_byte_pos: %d\n"	      KERN_INFO "blk_sz  : %d", 	      pos->seg_pos, LL(pos->tape_pos),	      LL(volume->size), pos->seg_byte_pos,	      volume->blk_sz);	if (!exceed) {		zft_resid = new_block_pos - zft_div_blksz(pos->volume_pos,							  volume->blk_sz);	}	if (zft_resid < 0) {		zft_resid = -zft_resid;	}	TRACE_EXIT ((exceed || zft_resid != 0) && result >= 0) ? -EINVAL : result;}     static int mt_fsr(int *arg){ 	int result;	TRACE_FUN(ft_t_flow);		result = seek_block(zft_pos.volume_pos,  *arg, &zft_pos);	TRACE_EXIT result;}static int mt_bsr(int *arg){   	int result;	TRACE_FUN(ft_t_flow);		result = seek_block(zft_pos.volume_pos, -*arg, &zft_pos);	TRACE_EXIT result;}static int mt_weof(int *arg){	int result;	TRACE_FUN(ft_t_flow);		TRACE_CATCH(zft_flush_buffers(),);	result = zft_weof(*arg, &zft_pos);	TRACE_EXIT result;}static int mt_rew(int *dummy){          	int result;	TRACE_FUN(ft_t_flow);		if(zft_header_read) {		(void)zft_def_idle_state();	}	result = ftape_seek_to_bot();	zft_reset_position(&zft_pos);	TRACE_EXIT result;}static int mt_offl(int *dummy){	int result;	TRACE_FUN(ft_t_flow);		going_offline= 1;	result = mt_rew(NULL);	TRACE_EXIT result;}static int mt_nop(int *dummy){	TRACE_FUN(ft_t_flow);	/*  should we set tape status?	 */	if (!zft_offline) { /* offline includes no_tape */		(void)zft_def_idle_state();	}	TRACE_EXIT 0; }static int mt_reten(int *dummy){  	int result;	TRACE_FUN(ft_t_flow);		if(zft_header_read) {		(void)zft_def_idle_state();	}	result = ftape_seek_to_eot();	if (result >= 0) {		result = ftape_seek_to_bot();	}	TRACE_EXIT(result);}static int fsfbsfm(int arg, zft_position *pos){ 	const zft_volinfo *vtbl;	__s64 block_pos;	TRACE_FUN(ft_t_flow);		/* What to do? This should seek to the next file-mark and	 * position BEFORE. That is, a next write would just extend	 * the current file.  Well. Let's just seek to the end of the	 * current file, if count == 1.  If count > 1, then do a	 * "mt_fsf(count - 1)", and then seek to the end of that file.	 * If count == 0, do nothing	 */	if (arg == 0) {		TRACE_EXIT 0;	}	zft_just_before_eof = 0;	TRACE_CATCH(zft_skip_volumes(arg < 0 ? arg : arg-1, pos),		    if (arg > 0) {			    zft_resid ++; 		    });	vtbl      = zft_find_volume(pos->seg_pos);	block_pos = zft_div_blksz(vtbl->size, vtbl->blk_sz);	(void)seek_block(0, block_pos, pos);	if (pos->volume_pos != vtbl->size) {		zft_just_before_eof = 0;		zft_resid = 1;		/* we didn't managed to go there */		TRACE_ABORT(-EIO, ft_t_err, 			    "wanted file position " LL_X ", arrived at " LL_X, 			    LL(vtbl->size), LL(pos->volume_pos));	}	zft_just_before_eof = 1;	TRACE_EXIT 0; }static int mt_bsfm(int *arg){	int result;	TRACE_FUN(ft_t_flow);		result = fsfbsfm(-*arg, &zft_pos);	TRACE_EXIT result;}static int mt_fsfm(int *arg){	int result;	TRACE_FUN(ft_t_flow);		result = fsfbsfm(*arg, &zft_pos);	TRACE_EXIT result;}static int mt_eom(int *dummy){              	TRACE_FUN(ft_t_flow);		zft_skip_to_eom(&zft_pos);	TRACE_EXIT 0;}static int mt_erase(int *dummy){	int result;	TRACE_FUN(ft_t_flow);		result = zft_erase();	TRACE_EXIT result;}static int mt_ras2(int *dummy){	int result;	TRACE_FUN(ft_t_flow);		result = -ENOSYS;

⌨️ 快捷键说明

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