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

📄 zftape-ctl.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
	TRACE_EXIT result;} /*  Sets the new blocksize in BYTES * */static int mt_setblk(int *new_size){	TRACE_FUN(ft_t_flow);		if((unsigned int)(*new_size) > ZFT_MAX_BLK_SZ) {		TRACE_ABORT(-EINVAL, ft_t_info,			    "desired blk_sz (%d) should be <= %d bytes",			    *new_size, ZFT_MAX_BLK_SZ);	}	if ((*new_size & (FT_SECTOR_SIZE-1)) != 0) {		TRACE_ABORT(-EINVAL, ft_t_info,			"desired blk_sz (%d) must be a multiple of %d bytes",			    *new_size, FT_SECTOR_SIZE);	}	if (*new_size == 0) {		if (zft_use_compression) {			TRACE_ABORT(-EINVAL, ft_t_info,				    "Variable block size not yet "				    "supported with compression");		}		*new_size = 1;	}	zft_blk_sz = *new_size;	TRACE_EXIT 0;} static int mt_setdensity(int *arg){	TRACE_FUN(ft_t_flow);		SET_TRACE_LEVEL(*arg);	TRACE(TRACE_LEVEL, "tracing set to %d", TRACE_LEVEL);	if ((int)TRACE_LEVEL != *arg) {		TRACE_EXIT -EINVAL;	}	TRACE_EXIT 0;}          static int mt_seek(int *new_block_pos){ 	int result= 0;        	TRACE_FUN(ft_t_any);		result = seek_block(0, (__s64)*new_block_pos, &zft_pos);	TRACE_EXIT result;}/*  OK, this is totally different from SCSI, but the worst thing that can  *  happen is that there is not enough defragmentated memory that can be  *  allocated. Also, there is a hardwired limit of 16 dma buffers in the  *  stock ftape module. This shouldn't bring the system down. * * NOTE: the argument specifies the total number of dma buffers to use. *       The driver needs at least 3 buffers to function at all. *  */static int mt_setdrvbuffer(int *cnt){	TRACE_FUN(ft_t_flow);	if (*cnt < 3) {		TRACE_EXIT -EINVAL;	}	TRACE_CATCH(ftape_set_nr_buffers(*cnt),);	TRACE_EXIT 0;}/* return the block position from start of volume  */static int mt_tell(int *arg){	TRACE_FUN(ft_t_flow);		*arg   = zft_div_blksz(zft_pos.volume_pos,			       zft_find_volume(zft_pos.seg_pos)->blk_sz);	TRACE_EXIT 0;}static int mt_compression(int *arg){	TRACE_FUN(ft_t_flow);		/*  Ok. We could also check whether compression is available at	 *  all by trying to load the compression module.  We could	 *  also check for a block size of 1 byte which is illegal	 *  with compression.  Instead of doing it here we rely on	 *  zftape_write() to do the proper checks.	 */	if ((unsigned int)*arg > 1) {		TRACE_EXIT -EINVAL;	}	if (*arg != 0 && zft_blk_sz == 1) { /* variable block size */		TRACE_ABORT(-EINVAL, ft_t_info,			    "Compression not yet supported "			    "with variable block size");	}	zft_mt_compression  = *arg;	if ((zft_unit & ZFT_ZIP_MODE) == 0) {		zft_use_compression = zft_mt_compression;	}	TRACE_EXIT 0;}/*  check whether write access is allowed. Write access is denied when *  + zft_write_protected == 1 -- this accounts for either hard write  *                                protection of the cartridge or for  *                                O_RDONLY access mode of the tape device *  + zft_offline == 1         -- this meany that there is either no tape  *                                or that the MTOFFLINE ioctl has been  *                                previously issued (`soft eject') *  + ft_formatted == 0        -- this means that the cartridge is not *                                formatted *  Then we distinuguish two cases. When zft_qic_mode is TRUE, then we try *  to emulate a `traditional' (aka SCSI like) UN*X tape device. Therefore we *  deny writes when *  + zft_qic_mode ==1 &&  *       (!zft_tape_at_lbot() &&   -- tape no at logical BOT *        !(zft_tape_at_eom() ||   -- tape not at logical EOM (or EOD) *          (zft_tape_at_eom() && *           zft_old_ftape())))    -- we can't add new volume to tapes  *                                    written by old ftape because ftape *                                    don't use the volume table * *  when the drive is in true raw mode (aka /dev/rawft0) then we don't  *  care about LBOT and EOM conditions. This device is intended for a  *  user level program that wants to truly implement the QIC-80 compliance *  at the logical data layout level of the cartridge, i.e. implement all *  that volume table and volume directory stuff etc.< */int zft_check_write_access(zft_position *pos){	TRACE_FUN(ft_t_flow);	if (zft_offline) { /* offline includes no_tape */		TRACE_ABORT(-ENXIO,			    ft_t_info, "tape is offline or no cartridge");	}	if (!ft_formatted) {		TRACE_ABORT(-EACCES, ft_t_info, "tape is not formatted");	} 	if (zft_write_protected) {		TRACE_ABORT(-EACCES, ft_t_info, "cartridge write protected");	} 	if (zft_qic_mode) {		/*  check BOT condition */		if (!zft_tape_at_lbot(pos)) {			/*  protect cartridges written by old ftape if			 *  not at BOT because they use the vtbl			 *  segment for storing data			 */			if (zft_old_ftape) {				TRACE_ABORT(-EACCES, ft_t_warn,       "Cannot write to cartridges written by old ftape when not at BOT");			}			/*  not at BOT, but allow writes at EOD, of course			 */			if (!zft_tape_at_eod(pos)) {				TRACE_ABORT(-EACCES, ft_t_info,					    "tape not at BOT and not at EOD");			}		}		/*  fine. Now the tape is either at BOT or at EOD. */	}	/* or in raw mode in which case we don't care about BOT and EOD */	TRACE_EXIT 0;}/*      OPEN routine called by kernel-interface code * *      NOTE: this is also called by mt_reset() with dev_minor == -1 *            to fake a reopen after a reset. */int _zft_open(unsigned int dev_minor, unsigned int access_mode){	static unsigned int tape_unit;	static unsigned int file_access_mode;	int result;	TRACE_FUN(ft_t_flow);	if ((int)dev_minor == -1) {		/* fake reopen */		zft_unit    = tape_unit;		access_mode = file_access_mode;		zft_init_driver(); /* reset all static data to defaults */	} else {		tape_unit        = dev_minor;		file_access_mode = access_mode;		if ((result = ftape_enable(FTAPE_SEL(dev_minor))) < 0) {			TRACE_ABORT(-ENXIO, ft_t_err,				    "ftape_enable failed: %d", result);		}		if (ft_new_tape || ft_no_tape || !ft_formatted ||		    (FTAPE_SEL(zft_unit) != FTAPE_SEL(dev_minor)) ||		    (zft_unit & ZFT_RAW_MODE) != (dev_minor & ZFT_RAW_MODE)) {			/* reset all static data to defaults,			 */			zft_init_driver(); 		}		zft_unit = dev_minor;	}	zft_set_flags(zft_unit); /* decode the minor bits */	if (zft_blk_sz == 1 && zft_use_compression) {		ftape_disable(); /* resets ft_no_tape */		TRACE_ABORT(-ENODEV, ft_t_warn, "Variable block size not yet "			    "supported with compression");	}	/*  no need for most of the buffers when no tape or not	 *  formatted.  for the read/write operations, it is the	 *  regardless whether there is no tape, a not-formatted tape	 *  or the whether the driver is soft offline.  	 *  Nevertheless we allow some ioctls with non-formatted tapes, 	 *  like rewind and reset.	 */	if (ft_no_tape || !ft_formatted) {		zft_uninit_mem();	}	if (ft_no_tape) {		zft_offline = 1; /* so we need not test two variables */	}	if ((access_mode == O_WRONLY || access_mode == O_RDWR) &&	    (ft_write_protected || ft_no_tape)) {		ftape_disable(); /* resets ft_no_tape */		TRACE_ABORT(ft_no_tape ? -ENXIO : -EROFS,			    ft_t_warn, "wrong access mode %s cartridge",			    ft_no_tape ? "without a" : "with write protected");	}	zft_write_protected = (access_mode == O_RDONLY || 			       ft_write_protected != 0);	if (zft_write_protected) {		TRACE(ft_t_noise,		      "read only access mode: %d, "		      "drive write protected: %d", 		      access_mode == O_RDONLY,		      ft_write_protected != 0);	}	if (!zft_offline) {		TRACE_CATCH(zft_vmalloc_once(&zft_deblock_buf,FT_SEGMENT_SIZE),			    ftape_disable());	}	/* zft_seg_pos should be greater than the vtbl segpos but not	 * if in compatibility mode and only after we read in the	 * header segments	 *	 * might also be a problem if the user makes a backup with a	 * *qft* device and rewinds it with a raw device.	 */	if (zft_qic_mode         &&	    !zft_old_ftape       &&	    zft_pos.seg_pos >= 0 &&	    zft_header_read      && 	    zft_pos.seg_pos <= ft_first_data_segment) {		TRACE(ft_t_noise, "you probably mixed up the zftape devices!");		zft_reset_position(&zft_pos); 	}	TRACE_EXIT 0;}/*      RELEASE routine called by kernel-interface code */int _zft_close(void){	int result = 0;	TRACE_FUN(ft_t_flow);		if (zft_offline) {		/* call the hardware release routine. Puts the drive offline */		ftape_disable();		TRACE_EXIT 0;	}	if (!(ft_write_protected || zft_old_ftape)) {		result = zft_flush_buffers();		TRACE(ft_t_noise, "writing file mark at current position");		if (zft_qic_mode && zft_close_volume(&zft_pos) == 0) {			zft_move_past_eof(&zft_pos);		}		if ((zft_tape_at_lbot(&zft_pos) ||		     !(zft_unit & FTAPE_NO_REWIND))) {			if (result >= 0) {				result = zft_update_header_segments();			} else {				TRACE(ft_t_err,				"Error: unable to update header segments");			}		}	}	ftape_abort_operation();	if (!(zft_unit & FTAPE_NO_REWIND)) {		TRACE(ft_t_noise, "rewinding tape");		if (ftape_seek_to_bot() < 0 && result >= 0) {			result = -EIO; /* keep old value */		}		zft_reset_position(&zft_pos);	} 	zft_zap_read_buffers();	/*  now free up memory as much as possible. We don't destroy	 *  the deblock buffer if it containes a valid segment.	 */	if (zft_deblock_segment == -1) {		zft_vfree(&zft_deblock_buf, FT_SEGMENT_SIZE); 	}	/* high level driver status, forces creation of a new volume	 * when calling ftape_write again and not zft_just_before_eof	 */	zft_io_state = zft_idle;  	if (going_offline) {		zft_init_driver();		zft_uninit_mem();		going_offline = 0;		zft_offline   = 1;	} else if (zft_cmpr_lock(0 /* don't load */) == 0) {		(*zft_cmpr_ops->reset)(); /* unlock it again */	}	zft_memory_stats();	/* call the hardware release routine. Puts the drive offline */	ftape_disable();	TRACE_EXIT result;}/* *  the wrapper function around the wrapper MTIOCTOP ioctl */static int mtioctop(struct mtop *mtop, int arg_size){	int result = 0;	fun_entry *mt_fun_entry;	TRACE_FUN(ft_t_flow);		if (arg_size != sizeof(struct mtop) || mtop->mt_op >= NR_MT_CMDS) {		TRACE_EXIT -EINVAL;	}	TRACE(ft_t_noise, "calling MTIOCTOP command: %s",	      mt_funs[mtop->mt_op].name);	mt_fun_entry= &mt_funs[mtop->mt_op];	zft_resid = mtop->mt_count;	if (!mt_fun_entry->offline && zft_offline) {		if (ft_no_tape) {			TRACE_ABORT(-ENXIO, ft_t_info, "no tape present");		} else {			TRACE_ABORT(-ENXIO, ft_t_info, "drive is offline");		}	}	if (!mt_fun_entry->not_formatted && !ft_formatted) {		TRACE_ABORT(-EACCES, ft_t_info, "tape is not formatted");	}	if (!mt_fun_entry->write_protected) {		TRACE_CATCH(zft_check_write_access(&zft_pos),);	}	if (mt_fun_entry->need_idle_state && !(zft_offline || !ft_formatted)) {		TRACE_CATCH(zft_def_idle_state(),);	}	if (!zft_qic_mode && !mt_fun_entry->raw_mode) {		TRACE_ABORT(-EACCES, ft_t_info, "Drive needs to be in QIC-80 compatibility mode for this command");	}	result = (mt_fun_entry->function)(&mtop->mt_count);	if (zft_tape_at_lbot(&zft_pos)) {		TRACE_CATCH(zft_update_header_segments(),);	}	if (result >= 0) {		zft_resid = 0;	}	TRACE_EXIT result;}/* *  standard MTIOCGET ioctl */static int mtiocget(struct mtget *mtget, int arg_size){	const zft_volinfo *volume;	__s64 max_tape_pos;	TRACE_FUN(ft_t_flow);		if (arg_size != sizeof(struct mtget)) {		TRACE_ABORT(-EINVAL, ft_t_info, "bad argument size: %d",			    arg_size);	}	mtget->mt_type  = ft_drive_type.vendor_id + 0x800000;	mtget->mt_dsreg = ft_last_status.space;	mtget->mt_erreg = ft_last_error.space; /* error register */	mtget->mt_resid = zft_resid; /* residuum of writes, reads and				      * MTIOCTOP commands 				      */	if (!zft_offline) { /* neither no_tape nor soft offline */		mtget->mt_gstat = GMT_ONLINE(~0UL);		/* should rather return the status of the cartridge		 * than the access mode of the file, therefor use		 * ft_write_protected, not zft_write_protected 		 */		if (ft_write_protected) {			mtget->mt_gstat |= GMT_WR_PROT(~0UL);		}		if(zft_header_read) { /* this catches non-formatted */			volume = zft_find_volume(zft_pos.seg_pos);			mtget->mt_fileno = volume->count;			max_tape_pos = zft_capacity - zft_blk_sz;			if (zft_use_compression) {				max_tape_pos -= ZFT_CMPR_OVERHEAD;			}			if (zft_tape_at_eod(&zft_pos)) {				mtget->mt_gstat |= GMT_EOD(~0UL);			}			if (zft_pos.tape_pos > max_tape_pos) {				mtget->mt_gstat |= GMT_EOT(~0UL);			}			mtget->mt_blkno = zft_div_blksz(zft_pos.volume_pos,							volume->blk_sz);			if (zft_just_before_eof) {				mtget->mt_gstat |= GMT_EOF(~0UL);			}			if (zft_tape_at_lbot(&zft_pos)) {				mtget->mt_gstat |= GMT_BOT(~0UL);			}		} else {			mtget->mt_fileno = mtget->mt_blkno = -1;			if (mtget->mt_dsreg & QIC_STATUS_AT_BOT) {				mtget->mt_gstat |= GMT_BOT(~0UL);			}		}	} else {		if (ft_no_tape) {			mtget->mt_gstat = GMT_DR_OPEN(~0UL);		} else {			mtget->mt_gstat = 0UL;		} 		mtget->mt_fileno = mtget->mt_blkno = -1;	}	TRACE_EXIT 0;}#ifdef MTIOCRDFTSEG/* *  Read a floppy tape segment. This is useful for manipulating the *  volume table, and read the old header segment before re-formatting *  the cartridge. */static int mtiocrdftseg(struct mtftseg * mtftseg, int arg_size){	TRACE_FUN(ft_t_flow);		TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCRDFTSEG");	if (zft_qic_mode) {		TRACE_ABORT(-EACCES, ft_t_info,			    "driver needs to be in raw mode for this ioctl");	} 	if (arg_size != sizeof(struct mtftseg)) {		TRACE_ABORT(-EINVAL, ft_t_info, "bad argument size: %d",			    arg_size);	}	if (zft_offline) {		TRACE_EXIT -ENXIO;	}	if (mtftseg->mt_mode != FT_RD_SINGLE &&	    mtftseg->mt_mode != FT_RD_AHEAD) {		TRACE_ABORT(-EINVAL, ft_t_info, "invalid read mode");	}	if (!ft_formatted) {		TRACE_EXIT -EACCES; /* -ENXIO ? */	}	if (!zft_header_read) {		TRACE_CATCH(zft_def_idle_state(),);	}	if (mtftseg->mt_segno > ft_last_data_segment) {		TRACE_ABORT(-EINVAL, ft_t_info, "segment number is too large");	}	mtftseg->mt_result = ftape_read_segment(mtftseg->mt_segno,						zft_deblock_buf,

⌨️ 快捷键说明

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