1 /*
2  *      Copyright (C) 1996, 1997 Claus-Justus Heine
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2, or (at your option)
7  any later version.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; see the file COPYING.  If not, write to
16  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
17 
18  *
19  * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-ctl.c,v $
20  * $Revision: 1.2.6.2 $
21  * $Date: 1997/11/14 18:07:33 $
22  *
23  *      This file contains the non-read/write zftape functions
24  *      for the QIC-40/80/3010/3020 floppy-tape driver for Linux.
25  */
26 
27 #include <linux/config.h>
28 #include <linux/errno.h>
29 #include <linux/mm.h>
30 #define __NO_VERSION__
31 #include <linux/module.h>
32 #include <linux/fcntl.h>
33 
34 #include <linux/zftape.h>
35 
36 #if LINUX_VERSION_CODE >= KERNEL_VER(2,1,6)
37 #include <asm/uaccess.h>
38 #else
39 #include <asm/segment.h>
40 #endif
41 
42 #include "../zftape/zftape-init.h"
43 #include "../zftape/zftape-eof.h"
44 #include "../zftape/zftape-ctl.h"
45 #include "../zftape/zftape-write.h"
46 #include "../zftape/zftape-read.h"
47 #include "../zftape/zftape-rw.h"
48 #include "../zftape/zftape-vtbl.h"
49 
50 /*      Global vars.
51  */
52 int zft_write_protected; /* this is when cartridge rdonly or O_RDONLY */
53 int zft_header_read;
54 int zft_offline;
55 unsigned int zft_unit;
56 int zft_resid;
57 int zft_mt_compression;
58 
59 /*      Local vars.
60  */
61 static int going_offline;
62 
63 typedef int (mt_fun)(int *argptr);
64 typedef int (*mt_funp)(int *argptr);
65 typedef struct
66 {
67 	mt_funp function;
68 	unsigned offline         : 1; /* op permitted if offline or no_tape */
69 	unsigned write_protected : 1; /* op permitted if write-protected    */
70 	unsigned not_formatted   : 1; /* op permitted if tape not formatted */
71 	unsigned raw_mode        : 1; /* op permitted if zft_mode == 0    */
72 	unsigned need_idle_state : 1; /* need to call def_idle_state        */
73 	char     *name;
74 } fun_entry;
75 
76 static mt_fun mt_dummy, mt_reset, mt_fsr, mt_bsr, mt_rew, mt_offl, mt_nop,
77 	mt_weof, mt_erase, mt_ras2, mt_setblk, mt_setdensity,
78 	mt_seek, mt_tell, mt_reten, mt_eom, mt_fsf, mt_bsf,
79 	mt_fsfm, mt_bsfm, mt_setdrvbuffer, mt_compression;
80 
81 static fun_entry mt_funs[]=
82 {
83 	{mt_reset       , 1, 1, 1, 1, 0, "MT_RESET" }, /*  0 */
84 	{mt_fsf         , 0, 1, 0, 0, 1, "MT_FSF"   },
85 	{mt_bsf         , 0, 1, 0, 0, 1, "MT_BSF"   },
86 	{mt_fsr         , 0, 1, 0, 1, 1, "MT_FSR"   },
87 	{mt_bsr         , 0, 1, 0, 1, 1, "MT_BSR"   },
88 	{mt_weof        , 0, 0, 0, 0, 0, "MT_WEOF"  }, /*  5 */
89 	{mt_rew         , 0, 1, 1, 1, 0, "MT_REW"   },
90 	{mt_offl        , 0, 1, 1, 1, 0, "MT_OFFL"  },
91 	{mt_nop         , 1, 1, 1, 1, 0, "MT_NOP"   },
92 	{mt_reten       , 0, 1, 1, 1, 0, "MT_RETEN" },
93 	{mt_bsfm        , 0, 1, 0, 0, 1, "MT_BSFM"  }, /* 10 */
94 	{mt_fsfm        , 0, 1, 0, 0, 1, "MT_FSFM"  },
95 	{mt_eom         , 0, 1, 0, 0, 1, "MT_EOM"   },
96 	{mt_erase       , 0, 0, 0, 1, 0, "MT_ERASE" },
97 	{mt_dummy       , 1, 1, 1, 1, 0, "MT_RAS1"  },
98 	{mt_ras2        , 0, 0, 0, 1, 0, "MT_RAS2"  },
99 	{mt_dummy       , 1, 1, 1, 1, 0, "MT_RAS3"  },
100 	{mt_dummy       , 1, 1, 1, 1, 0, "UNKNOWN"  },
101 	{mt_dummy       , 1, 1, 1, 1, 0, "UNKNOWN"  },
102 	{mt_dummy       , 1, 1, 1, 1, 0, "UNKNOWN"  },
103 	{mt_setblk      , 1, 1, 1, 1, 1, "MT_SETBLK"}, /* 20 */
104 	{mt_setdensity  , 1, 1, 1, 1, 0, "MT_SETDENSITY"},
105 	{mt_seek        , 0, 1, 0, 1, 1, "MT_SEEK"  },
106 	{mt_dummy       , 0, 1, 0, 1, 1, "MT_TELL"  }, /* wr-only ?! */
107 	{mt_setdrvbuffer, 1, 1, 1, 1, 0, "MT_SETDRVBUFFER" },
108 	{mt_dummy       , 1, 1, 1, 1, 0, "MT_FSS"   }, /* 25 */
109 	{mt_dummy       , 1, 1, 1, 1, 0, "MT_BSS"   },
110 	{mt_dummy       , 1, 1, 1, 1, 0, "MT_WSM"   },
111 	{mt_dummy       , 1, 1, 1, 1, 0, "MT_LOCK"  },
112 	{mt_dummy       , 1, 1, 1, 1, 0, "MT_UNLOCK"},
113 	{mt_dummy       , 1, 1, 1, 1, 0, "MT_LOAD"  }, /* 30 */
114 	{mt_dummy       , 1, 1, 1, 1, 0, "MT_UNLOAD"},
115 	{mt_compression , 1, 1, 1, 0, 1, "MT_COMPRESSION"},
116 	{mt_dummy       , 1, 1, 1, 1, 0, "MT_SETPART"},
117 	{mt_dummy       , 1, 1, 1, 1, 0, "MT_MKPART"}
118 };
119 
120 #define NR_MT_CMDS NR_ITEMS(mt_funs)
121 
zft_reset_position(zft_position * pos)122 void zft_reset_position(zft_position *pos)
123 {
124 	TRACE_FUN(ft_t_flow);
125 
126 	pos->seg_byte_pos =
127 		pos->volume_pos = 0;
128 	if (zft_header_read) {
129 		/* need to keep track of the volume table and
130 		 * compression map. We therefor simply
131 		 * position at the beginning of the first
132 		 * volume. This covers old ftape archives as
133 		 * well has various flavours of the
134 		 * compression map segments. The worst case is
135 		 * that the compression map shows up as a
136 		 * additional volume in front of all others.
137 		 */
138 		pos->seg_pos  = zft_find_volume(0)->start_seg;
139 		pos->tape_pos = zft_calc_tape_pos(pos->seg_pos);
140 	} else {
141 		pos->tape_pos =  0;
142 		pos->seg_pos  = -1;
143 	}
144 	zft_just_before_eof =  0;
145 	zft_deblock_segment = -1;
146 	zft_io_state        = zft_idle;
147 	zft_zap_read_buffers();
148 	zft_prevent_flush();
149 	/*  unlock the compresison module if it is loaded.
150 	 *  The zero arg means not to try to load the module.
151 	 */
152 	if (zft_cmpr_lock(0) == 0) {
153 		(*zft_cmpr_ops->reset)(); /* unlock */
154 	}
155 	TRACE_EXIT;
156 }
157 
zft_init_driver(void)158 static void zft_init_driver(void)
159 {
160 	TRACE_FUN(ft_t_flow);
161 
162 	zft_resid =
163 		zft_header_read          =
164 		zft_old_ftape            =
165 		zft_offline              =
166 		zft_write_protected      =
167 		going_offline            =
168 		zft_mt_compression       =
169 		zft_header_changed       =
170 		zft_volume_table_changed =
171 		zft_written_segments     = 0;
172 	zft_blk_sz = CONFIG_ZFT_DFLT_BLK_SZ;
173 	zft_reset_position(&zft_pos); /* does most of the stuff */
174 	ftape_zap_read_buffers();
175 	ftape_set_state(idle);
176 	TRACE_EXIT;
177 }
178 
zft_def_idle_state(void)179 int zft_def_idle_state(void)
180 {
181 	int result = 0;
182 	TRACE_FUN(ft_t_flow);
183 
184 	if (!zft_header_read) {
185 		result = zft_read_header_segments();
186 	} else if ((result = zft_flush_buffers()) >= 0 && zft_qic_mode) {
187 		/*  don't move past eof
188 		 */
189 		(void)zft_close_volume(&zft_pos);
190 	}
191 	if (ftape_abort_operation() < 0) {
192 		TRACE(ft_t_warn, "ftape_abort_operation() failed");
193 		result = -EIO;
194 	}
195 	/* clear remaining read buffers */
196 	zft_zap_read_buffers();
197 	zft_io_state = zft_idle;
198 	TRACE_EXIT result;
199 }
200 
201 /*****************************************************************************
202  *                                                                           *
203  *  functions for the MTIOCTOP commands                                      *
204  *                                                                           *
205  *****************************************************************************/
206 
mt_dummy(int * dummy)207 static int mt_dummy(int *dummy)
208 {
209 	TRACE_FUN(ft_t_flow);
210 
211 	TRACE_EXIT -ENOSYS;
212 }
213 
mt_reset(int * dummy)214 static int mt_reset(int *dummy)
215 {
216 	TRACE_FUN(ft_t_flow);
217 
218 	(void)ftape_seek_to_bot();
219 	TRACE_CATCH(ftape_reset_drive(),
220 		    zft_init_driver(); zft_uninit_mem(); zft_offline = 1);
221 	/*  fake a re-open of the device. This will set all flage and
222 	 *  allocate buffers as appropriate. The new tape condition will
223 	 *  force the open routine to do anything we need.
224 	 */
225 	TRACE_CATCH(_zft_open(-1 /* fake reopen */, 0 /* dummy */),);
226 	TRACE_EXIT 0;
227 }
228 
mt_fsf(int * arg)229 static int mt_fsf(int *arg)
230 {
231 	int result;
232 	TRACE_FUN(ft_t_flow);
233 
234 	result = zft_skip_volumes(*arg, &zft_pos);
235 	zft_just_before_eof = 0;
236 	TRACE_EXIT result;
237 }
238 
mt_bsf(int * arg)239 static int mt_bsf(int *arg)
240 {
241 	int result = 0;
242 	TRACE_FUN(ft_t_flow);
243 
244 	if (*arg != 0) {
245 		result = zft_skip_volumes(-*arg + 1, &zft_pos);
246 	}
247 	TRACE_EXIT result;
248 }
249 
seek_block(__s64 data_offset,__s64 block_increment,zft_position * pos)250 static int seek_block(__s64 data_offset,
251 		      __s64 block_increment,
252 		      zft_position *pos)
253 {
254 	int result      = 0;
255 	__s64 new_block_pos;
256 	__s64 vol_block_count;
257 	const zft_volinfo *volume;
258 	int exceed;
259 	TRACE_FUN(ft_t_flow);
260 
261 	volume = zft_find_volume(pos->seg_pos);
262 	if (volume->start_seg == 0 || volume->end_seg == 0) {
263 		TRACE_EXIT -EIO;
264 	}
265 	new_block_pos   = (zft_div_blksz(data_offset, volume->blk_sz)
266 			   + block_increment);
267 	vol_block_count = zft_div_blksz(volume->size, volume->blk_sz);
268 	if (new_block_pos < 0) {
269 		TRACE(ft_t_noise,
270 		      "new_block_pos " LL_X " < 0", LL(new_block_pos));
271 		zft_resid     = (int)new_block_pos;
272 		new_block_pos = 0;
273 		exceed = 1;
274 	} else if (new_block_pos > vol_block_count) {
275 		TRACE(ft_t_noise,
276 		      "new_block_pos " LL_X " exceeds size of volume " LL_X,
277 		      LL(new_block_pos), LL(vol_block_count));
278 		zft_resid     = (int)(vol_block_count - new_block_pos);
279 		new_block_pos = vol_block_count;
280 		exceed = 1;
281 	} else {
282 		exceed = 0;
283 	}
284 	if (zft_use_compression && volume->use_compression) {
285 		TRACE_CATCH(zft_cmpr_lock(1 /* try to load */),);
286 		result = (*zft_cmpr_ops->seek)(new_block_pos, pos, volume,
287 					       zft_deblock_buf);
288 		pos->tape_pos  = zft_calc_tape_pos(pos->seg_pos);
289 		pos->tape_pos += pos->seg_byte_pos;
290 	} else {
291 		pos->volume_pos = zft_mul_blksz(new_block_pos, volume->blk_sz);
292 		pos->tape_pos   = zft_calc_tape_pos(volume->start_seg);
293 		pos->tape_pos  += pos->volume_pos;
294 		pos->seg_pos    = zft_calc_seg_byte_coord(&pos->seg_byte_pos,
295 							  pos->tape_pos);
296 	}
297 	zft_just_before_eof = volume->size == pos->volume_pos;
298 	if (zft_just_before_eof) {
299 		/* why this? because zft_file_no checks agains start
300 		 * and end segment of a volume. We do not want to
301 		 * advance to the next volume with this function.
302 		 */
303 		TRACE(ft_t_noise, "set zft_just_before_eof");
304 		zft_position_before_eof(pos, volume);
305 	}
306 	TRACE(ft_t_noise, "\n"
307 	      KERN_INFO "new_seg_pos : %d\n"
308 	      KERN_INFO "new_tape_pos: " LL_X "\n"
309 	      KERN_INFO "vol_size    : " LL_X "\n"
310 	      KERN_INFO "seg_byte_pos: %d\n"
311 	      KERN_INFO "blk_sz  : %d",
312 	      pos->seg_pos, LL(pos->tape_pos),
313 	      LL(volume->size), pos->seg_byte_pos,
314 	      volume->blk_sz);
315 	if (!exceed) {
316 		zft_resid = new_block_pos - zft_div_blksz(pos->volume_pos,
317 							  volume->blk_sz);
318 	}
319 	if (zft_resid < 0) {
320 		zft_resid = -zft_resid;
321 	}
322 	TRACE_EXIT ((exceed || zft_resid != 0) && result >= 0) ? -EINVAL : result;
323 }
324 
mt_fsr(int * arg)325 static int mt_fsr(int *arg)
326 {
327 	int result;
328 	TRACE_FUN(ft_t_flow);
329 
330 	result = seek_block(zft_pos.volume_pos,  *arg, &zft_pos);
331 	TRACE_EXIT result;
332 }
333 
mt_bsr(int * arg)334 static int mt_bsr(int *arg)
335 {
336 	int result;
337 	TRACE_FUN(ft_t_flow);
338 
339 	result = seek_block(zft_pos.volume_pos, -*arg, &zft_pos);
340 	TRACE_EXIT result;
341 }
342 
mt_weof(int * arg)343 static int mt_weof(int *arg)
344 {
345 	int result;
346 	TRACE_FUN(ft_t_flow);
347 
348 	TRACE_CATCH(zft_flush_buffers(),);
349 	result = zft_weof(*arg, &zft_pos);
350 	TRACE_EXIT result;
351 }
352 
mt_rew(int * dummy)353 static int mt_rew(int *dummy)
354 {
355 	int result;
356 	TRACE_FUN(ft_t_flow);
357 
358 	if(zft_header_read) {
359 		(void)zft_def_idle_state();
360 	}
361 	result = ftape_seek_to_bot();
362 	zft_reset_position(&zft_pos);
363 	TRACE_EXIT result;
364 }
365 
mt_offl(int * dummy)366 static int mt_offl(int *dummy)
367 {
368 	int result;
369 	TRACE_FUN(ft_t_flow);
370 
371 	going_offline= 1;
372 	result = mt_rew(NULL);
373 	TRACE_EXIT result;
374 }
375 
mt_nop(int * dummy)376 static int mt_nop(int *dummy)
377 {
378 	TRACE_FUN(ft_t_flow);
379 	/*  should we set tape status?
380 	 */
381 	if (!zft_offline) { /* offline includes no_tape */
382 		(void)zft_def_idle_state();
383 	}
384 	TRACE_EXIT 0;
385 }
386 
mt_reten(int * dummy)387 static int mt_reten(int *dummy)
388 {
389 	int result;
390 	TRACE_FUN(ft_t_flow);
391 
392 	if(zft_header_read) {
393 		(void)zft_def_idle_state();
394 	}
395 	result = ftape_seek_to_eot();
396 	if (result >= 0) {
397 		result = ftape_seek_to_bot();
398 	}
399 	TRACE_EXIT(result);
400 }
401 
fsfbsfm(int arg,zft_position * pos)402 static int fsfbsfm(int arg, zft_position *pos)
403 {
404 	const zft_volinfo *vtbl;
405 	__s64 block_pos;
406 	TRACE_FUN(ft_t_flow);
407 
408 	/* What to do? This should seek to the next file-mark and
409 	 * position BEFORE. That is, a next write would just extend
410 	 * the current file.  Well. Let's just seek to the end of the
411 	 * current file, if count == 1.  If count > 1, then do a
412 	 * "mt_fsf(count - 1)", and then seek to the end of that file.
413 	 * If count == 0, do nothing
414 	 */
415 	if (arg == 0) {
416 		TRACE_EXIT 0;
417 	}
418 	zft_just_before_eof = 0;
419 	TRACE_CATCH(zft_skip_volumes(arg < 0 ? arg : arg-1, pos),
420 		    if (arg > 0) {
421 			    zft_resid ++;
422 		    });
423 	vtbl      = zft_find_volume(pos->seg_pos);
424 	block_pos = zft_div_blksz(vtbl->size, vtbl->blk_sz);
425 	(void)seek_block(0, block_pos, pos);
426 	if (pos->volume_pos != vtbl->size) {
427 		zft_just_before_eof = 0;
428 		zft_resid = 1;
429 		/* we didn't managed to go there */
430 		TRACE_ABORT(-EIO, ft_t_err,
431 			    "wanted file position " LL_X ", arrived at " LL_X,
432 			    LL(vtbl->size), LL(pos->volume_pos));
433 	}
434 	zft_just_before_eof = 1;
435 	TRACE_EXIT 0;
436 }
437 
mt_bsfm(int * arg)438 static int mt_bsfm(int *arg)
439 {
440 	int result;
441 	TRACE_FUN(ft_t_flow);
442 
443 	result = fsfbsfm(-*arg, &zft_pos);
444 	TRACE_EXIT result;
445 }
446 
mt_fsfm(int * arg)447 static int mt_fsfm(int *arg)
448 {
449 	int result;
450 	TRACE_FUN(ft_t_flow);
451 
452 	result = fsfbsfm(*arg, &zft_pos);
453 	TRACE_EXIT result;
454 }
455 
mt_eom(int * dummy)456 static int mt_eom(int *dummy)
457 {
458 	TRACE_FUN(ft_t_flow);
459 
460 	zft_skip_to_eom(&zft_pos);
461 	TRACE_EXIT 0;
462 }
463 
mt_erase(int * dummy)464 static int mt_erase(int *dummy)
465 {
466 	int result;
467 	TRACE_FUN(ft_t_flow);
468 
469 	result = zft_erase();
470 	TRACE_EXIT result;
471 }
472 
mt_ras2(int * dummy)473 static int mt_ras2(int *dummy)
474 {
475 	int result;
476 	TRACE_FUN(ft_t_flow);
477 
478 	result = -ENOSYS;
479 	TRACE_EXIT result;
480 }
481 
482 /*  Sets the new blocksize in BYTES
483  *
484  */
mt_setblk(int * new_size)485 static int mt_setblk(int *new_size)
486 {
487 	TRACE_FUN(ft_t_flow);
488 
489 	if((unsigned int)(*new_size) > ZFT_MAX_BLK_SZ) {
490 		TRACE_ABORT(-EINVAL, ft_t_info,
491 			    "desired blk_sz (%d) should be <= %d bytes",
492 			    *new_size, ZFT_MAX_BLK_SZ);
493 	}
494 	if ((*new_size & (FT_SECTOR_SIZE-1)) != 0) {
495 		TRACE_ABORT(-EINVAL, ft_t_info,
496 			"desired blk_sz (%d) must be a multiple of %d bytes",
497 			    *new_size, FT_SECTOR_SIZE);
498 	}
499 	if (*new_size == 0) {
500 		if (zft_use_compression) {
501 			TRACE_ABORT(-EINVAL, ft_t_info,
502 				    "Variable block size not yet "
503 				    "supported with compression");
504 		}
505 		*new_size = 1;
506 	}
507 	zft_blk_sz = *new_size;
508 	TRACE_EXIT 0;
509 }
510 
mt_setdensity(int * arg)511 static int mt_setdensity(int *arg)
512 {
513 	TRACE_FUN(ft_t_flow);
514 
515 	SET_TRACE_LEVEL(*arg);
516 	TRACE(TRACE_LEVEL, "tracing set to %d", TRACE_LEVEL);
517 	if ((int)TRACE_LEVEL != *arg) {
518 		TRACE_EXIT -EINVAL;
519 	}
520 	TRACE_EXIT 0;
521 }
522 
mt_seek(int * new_block_pos)523 static int mt_seek(int *new_block_pos)
524 {
525 	int result= 0;
526 	TRACE_FUN(ft_t_any);
527 
528 	result = seek_block(0, (__s64)*new_block_pos, &zft_pos);
529 	TRACE_EXIT result;
530 }
531 
532 /*  OK, this is totally different from SCSI, but the worst thing that can
533  *  happen is that there is not enough defragmentated memory that can be
534  *  allocated. Also, there is a hardwired limit of 16 dma buffers in the
535  *  stock ftape module. This shouldn't bring the system down.
536  *
537  * NOTE: the argument specifies the total number of dma buffers to use.
538  *       The driver needs at least 3 buffers to function at all.
539  *
540  */
mt_setdrvbuffer(int * cnt)541 static int mt_setdrvbuffer(int *cnt)
542 {
543 	TRACE_FUN(ft_t_flow);
544 
545 	if (*cnt < 3) {
546 		TRACE_EXIT -EINVAL;
547 	}
548 	TRACE_CATCH(ftape_set_nr_buffers(*cnt),);
549 	TRACE_EXIT 0;
550 }
551 /* return the block position from start of volume
552  */
mt_tell(int * arg)553 static int mt_tell(int *arg)
554 {
555 	TRACE_FUN(ft_t_flow);
556 
557 	*arg   = zft_div_blksz(zft_pos.volume_pos,
558 			       zft_find_volume(zft_pos.seg_pos)->blk_sz);
559 	TRACE_EXIT 0;
560 }
561 
mt_compression(int * arg)562 static int mt_compression(int *arg)
563 {
564 	TRACE_FUN(ft_t_flow);
565 
566 	/*  Ok. We could also check whether compression is available at
567 	 *  all by trying to load the compression module.  We could
568 	 *  also check for a block size of 1 byte which is illegal
569 	 *  with compression.  Instead of doing it here we rely on
570 	 *  zftape_write() to do the proper checks.
571 	 */
572 	if ((unsigned int)*arg > 1) {
573 		TRACE_EXIT -EINVAL;
574 	}
575 	if (*arg != 0 && zft_blk_sz == 1) { /* variable block size */
576 		TRACE_ABORT(-EINVAL, ft_t_info,
577 			    "Compression not yet supported "
578 			    "with variable block size");
579 	}
580 	zft_mt_compression  = *arg;
581 	if ((zft_unit & ZFT_ZIP_MODE) == 0) {
582 		zft_use_compression = zft_mt_compression;
583 	}
584 	TRACE_EXIT 0;
585 }
586 
587 /*  check whether write access is allowed. Write access is denied when
588  *  + zft_write_protected == 1 -- this accounts for either hard write
589  *                                protection of the cartridge or for
590  *                                O_RDONLY access mode of the tape device
591  *  + zft_offline == 1         -- this meany that there is either no tape
592  *                                or that the MTOFFLINE ioctl has been
593  *                                previously issued (`soft eject')
594  *  + ft_formatted == 0        -- this means that the cartridge is not
595  *                                formatted
596  *  Then we distinuguish two cases. When zft_qic_mode is TRUE, then we try
597  *  to emulate a `traditional' (aka SCSI like) UN*X tape device. Therefore we
598  *  deny writes when
599  *  + zft_qic_mode ==1 &&
600  *       (!zft_tape_at_lbot() &&   -- tape no at logical BOT
601  *        !(zft_tape_at_eom() ||   -- tape not at logical EOM (or EOD)
602  *          (zft_tape_at_eom() &&
603  *           zft_old_ftape())))    -- we can't add new volume to tapes
604  *                                    written by old ftape because ftape
605  *                                    don't use the volume table
606  *
607  *  when the drive is in true raw mode (aka /dev/rawft0) then we don't
608  *  care about LBOT and EOM conditions. This device is intended for a
609  *  user level program that wants to truly implement the QIC-80 compliance
610  *  at the logical data layout level of the cartridge, i.e. implement all
611  *  that volume table and volume directory stuff etc.<
612  */
zft_check_write_access(zft_position * pos)613 int zft_check_write_access(zft_position *pos)
614 {
615 	TRACE_FUN(ft_t_flow);
616 
617 	if (zft_offline) { /* offline includes no_tape */
618 		TRACE_ABORT(-ENXIO,
619 			    ft_t_info, "tape is offline or no cartridge");
620 	}
621 	if (!ft_formatted) {
622 		TRACE_ABORT(-EACCES, ft_t_info, "tape is not formatted");
623 	}
624 	if (zft_write_protected) {
625 		TRACE_ABORT(-EACCES, ft_t_info, "cartridge write protected");
626 	}
627 	if (zft_qic_mode) {
628 		/*  check BOT condition */
629 		if (!zft_tape_at_lbot(pos)) {
630 			/*  protect cartridges written by old ftape if
631 			 *  not at BOT because they use the vtbl
632 			 *  segment for storing data
633 			 */
634 			if (zft_old_ftape) {
635 				TRACE_ABORT(-EACCES, ft_t_warn,
636       "Cannot write to cartridges written by old ftape when not at BOT");
637 			}
638 			/*  not at BOT, but allow writes at EOD, of course
639 			 */
640 			if (!zft_tape_at_eod(pos)) {
641 				TRACE_ABORT(-EACCES, ft_t_info,
642 					    "tape not at BOT and not at EOD");
643 			}
644 		}
645 		/*  fine. Now the tape is either at BOT or at EOD. */
646 	}
647 	/* or in raw mode in which case we don't care about BOT and EOD */
648 	TRACE_EXIT 0;
649 }
650 
651 /*  decide when we should lock the module in memory, even when calling
652  *  the release routine. This really is necessary for use with
653  *  kerneld.
654  *
655  *  NOTE: we MUST NOT use zft_write_protected, because this includes
656  *  the file access mode as well which has no meaning with our
657  *  asynchronous update scheme.
658  *
659  *  Ugly, ugly. We need to look the module if we changed the block size.
660  *  How sad! Need persistent modules storage!
661  *
662  *  NOTE: I don't want to lock the module if the number of dma buffers
663  *  has been changed. It's enough! Stop the story! Give me persisitent
664  *  module storage! Do it!
665  */
zft_dirty(void)666 int zft_dirty(void)
667 {
668 	if (!ft_formatted || zft_offline) {
669 		/* cannot be dirty if not formatted or offline */
670 		return 0;
671 	}
672 	if (zft_blk_sz != CONFIG_ZFT_DFLT_BLK_SZ) {
673 		/* blocksize changed, must lock */
674 		return 1;
675 	}
676 	if (zft_mt_compression != 0) {
677 		/* compression mode with /dev/qft, must lock */
678 		return 1;
679 	}
680 	if (!zft_header_read) {
681 		/* tape is logical at BOT, no lock */
682 		return 0;
683 	}
684 	if (!zft_tape_at_lbot(&zft_pos)) {
685 		/* somewhere inside a volume, lock tape */
686 		return 1;
687 	}
688 	if (zft_volume_table_changed || zft_header_changed) {
689 		/* header segments dirty if tape not write protected */
690 		return !(ft_write_protected || zft_old_ftape);
691 	}
692 	return 0;
693 }
694 
695 /*      OPEN routine called by kernel-interface code
696  *
697  *      NOTE: this is also called by mt_reset() with dev_minor == -1
698  *            to fake a reopen after a reset.
699  */
_zft_open(unsigned int dev_minor,unsigned int access_mode)700 int _zft_open(unsigned int dev_minor, unsigned int access_mode)
701 {
702 	static unsigned int tape_unit;
703 	static unsigned int file_access_mode;
704 	int result;
705 	TRACE_FUN(ft_t_flow);
706 
707 	if ((int)dev_minor == -1) {
708 		/* fake reopen */
709 		zft_unit    = tape_unit;
710 		access_mode = file_access_mode;
711 		zft_init_driver(); /* reset all static data to defaults */
712 	} else {
713 		tape_unit        = dev_minor;
714 		file_access_mode = access_mode;
715 		if ((result = ftape_enable(FTAPE_SEL(dev_minor))) < 0) {
716 			TRACE_ABORT(-ENXIO, ft_t_err,
717 				    "ftape_enable failed: %d", result);
718 		}
719 		if (ft_new_tape || ft_no_tape || !ft_formatted ||
720 		    (FTAPE_SEL(zft_unit) != FTAPE_SEL(dev_minor)) ||
721 		    (zft_unit & ZFT_RAW_MODE) != (dev_minor & ZFT_RAW_MODE)) {
722 			/* reset all static data to defaults,
723 			 */
724 			zft_init_driver();
725 		}
726 		zft_unit = dev_minor;
727 	}
728 	zft_set_flags(zft_unit); /* decode the minor bits */
729 	if (zft_blk_sz == 1 && zft_use_compression) {
730 		ftape_disable(); /* resets ft_no_tape */
731 		TRACE_ABORT(-ENODEV, ft_t_warn, "Variable block size not yet "
732 			    "supported with compression");
733 	}
734 	/*  no need for most of the buffers when no tape or not
735 	 *  formatted.  for the read/write operations, it is the
736 	 *  regardless whether there is no tape, a not-formatted tape
737 	 *  or the whether the driver is soft offline.
738 	 *  Nevertheless we allow some ioctls with non-formatted tapes,
739 	 *  like rewind and reset.
740 	 */
741 	if (ft_no_tape || !ft_formatted) {
742 		zft_uninit_mem();
743 	}
744 	if (ft_no_tape) {
745 		zft_offline = 1; /* so we need not test two variables */
746 	}
747 	if ((access_mode == O_WRONLY || access_mode == O_RDWR) &&
748 	    (ft_write_protected || ft_no_tape)) {
749 		ftape_disable(); /* resets ft_no_tape */
750 		TRACE_ABORT(ft_no_tape ? -ENXIO : -EROFS,
751 			    ft_t_warn, "wrong access mode %s cartridge",
752 			    ft_no_tape ? "without a" : "with write protected");
753 	}
754 	zft_write_protected = (access_mode == O_RDONLY ||
755 			       ft_write_protected != 0);
756 	if (zft_write_protected) {
757 		TRACE(ft_t_noise,
758 		      "read only access mode: %d, "
759 		      "drive write protected: %d",
760 		      access_mode == O_RDONLY,
761 		      ft_write_protected != 0);
762 	}
763 	if (!zft_offline) {
764 		TRACE_CATCH(zft_vmalloc_once(&zft_deblock_buf,FT_SEGMENT_SIZE),
765 			    ftape_disable());
766 	}
767 	/* zft_seg_pos should be greater than the vtbl segpos but not
768 	 * if in compatability mode and only after we read in the
769 	 * header segments
770 	 *
771 	 * might also be a problem if the user makes a backup with a
772 	 * *qft* device and rewinds it with a raw device.
773 	 */
774 	if (zft_qic_mode         &&
775 	    !zft_old_ftape       &&
776 	    zft_pos.seg_pos >= 0 &&
777 	    zft_header_read      &&
778 	    zft_pos.seg_pos <= ft_first_data_segment) {
779 		TRACE(ft_t_noise, "you probably mixed up the zftape devices!");
780 		zft_reset_position(&zft_pos);
781 	}
782 	TRACE_EXIT 0;
783 }
784 
785 /*      RELEASE routine called by kernel-interface code
786  */
_zft_close(void)787 int _zft_close(void)
788 {
789 	int result = 0;
790 	TRACE_FUN(ft_t_flow);
791 
792 	if (zft_offline) {
793 		/* call the hardware release routine. Puts the drive offline */
794 		ftape_disable();
795 		TRACE_EXIT 0;
796 	}
797 	if (!(ft_write_protected || zft_old_ftape)) {
798 		result = zft_flush_buffers();
799 		TRACE(ft_t_noise, "writing file mark at current position");
800 		if (zft_qic_mode && zft_close_volume(&zft_pos) == 0) {
801 			zft_move_past_eof(&zft_pos);
802 		}
803 		if ((zft_tape_at_lbot(&zft_pos) ||
804 		     !(zft_unit & FTAPE_NO_REWIND))) {
805 			if (result >= 0) {
806 				result = zft_update_header_segments();
807 			} else {
808 				TRACE(ft_t_err,
809 				"Error: unable to update header segments");
810 			}
811 		}
812 	}
813 	ftape_abort_operation();
814 	if (!(zft_unit & FTAPE_NO_REWIND)) {
815 		TRACE(ft_t_noise, "rewinding tape");
816 		if (ftape_seek_to_bot() < 0 && result >= 0) {
817 			result = -EIO; /* keep old value */
818 		}
819 		zft_reset_position(&zft_pos);
820 	}
821 	zft_zap_read_buffers();
822 	/*  now free up memory as much as possible. We don't destroy
823 	 *  the deblock buffer if it containes a valid segment.
824 	 */
825 	if (zft_deblock_segment == -1) {
826 		zft_vfree(&zft_deblock_buf, FT_SEGMENT_SIZE);
827 	}
828 	/* high level driver status, forces creation of a new volume
829 	 * when calling ftape_write again and not zft_just_before_eof
830 	 */
831 	zft_io_state = zft_idle;
832 	if (going_offline) {
833 		zft_init_driver();
834 		zft_uninit_mem();
835 		going_offline = 0;
836 		zft_offline   = 1;
837 	} else if (zft_dirty()) {
838 		TRACE(ft_t_noise, "Keeping module locked in memory because:\n"
839 		      KERN_INFO "header segments need updating: %s\n"
840 		      KERN_INFO "tape not at BOT              : %s",
841 		      (zft_volume_table_changed || zft_header_changed)
842 		      ? "yes" : "no",
843 		      zft_tape_at_lbot(&zft_pos) ? "no" : "yes");
844 	} else if (zft_cmpr_lock(0 /* don't load */) == 0) {
845 		(*zft_cmpr_ops->reset)(); /* unlock it again */
846 	}
847 	zft_memory_stats();
848 	/* call the hardware release routine. Puts the drive offline */
849 	ftape_disable();
850 	TRACE_EXIT result;
851 }
852 
853 /*
854  *  the wrapper function around the wrapper MTIOCTOP ioctl
855  */
mtioctop(struct mtop * mtop,int arg_size)856 static int mtioctop(struct mtop *mtop, int arg_size)
857 {
858 	int result = 0;
859 	fun_entry *mt_fun_entry;
860 	TRACE_FUN(ft_t_flow);
861 
862 	if (arg_size != sizeof(struct mtop) || mtop->mt_op >= NR_MT_CMDS) {
863 		TRACE_EXIT -EINVAL;
864 	}
865 	TRACE(ft_t_noise, "calling MTIOCTOP command: %s",
866 	      mt_funs[mtop->mt_op].name);
867 	mt_fun_entry= &mt_funs[mtop->mt_op];
868 	zft_resid = mtop->mt_count;
869 	if (!mt_fun_entry->offline && zft_offline) {
870 		if (ft_no_tape) {
871 			TRACE_ABORT(-ENXIO, ft_t_info, "no tape present");
872 		} else {
873 			TRACE_ABORT(-ENXIO, ft_t_info, "drive is offline");
874 		}
875 	}
876 	if (!mt_fun_entry->not_formatted && !ft_formatted) {
877 		TRACE_ABORT(-EACCES, ft_t_info, "tape is not formatted");
878 	}
879 	if (!mt_fun_entry->write_protected) {
880 		TRACE_CATCH(zft_check_write_access(&zft_pos),);
881 	}
882 	if (mt_fun_entry->need_idle_state && !(zft_offline || !ft_formatted)) {
883 		TRACE_CATCH(zft_def_idle_state(),);
884 	}
885 	if (!zft_qic_mode && !mt_fun_entry->raw_mode) {
886 		TRACE_ABORT(-EACCES, ft_t_info,
887 "Drive needs to be in QIC-80 compatibility mode for this command");
888 	}
889 	result = (mt_fun_entry->function)(&mtop->mt_count);
890 	if (zft_tape_at_lbot(&zft_pos)) {
891 		TRACE_CATCH(zft_update_header_segments(),);
892 	}
893 	if (result >= 0) {
894 		zft_resid = 0;
895 	}
896 	TRACE_EXIT result;
897 }
898 
899 /*
900  *  standard MTIOCGET ioctl
901  */
mtiocget(struct mtget * mtget,int arg_size)902 static int mtiocget(struct mtget *mtget, int arg_size)
903 {
904 	const zft_volinfo *volume;
905 	__s64 max_tape_pos;
906 	TRACE_FUN(ft_t_flow);
907 
908 	if (arg_size != sizeof(struct mtget)) {
909 		TRACE_ABORT(-EINVAL, ft_t_info, "bad argument size: %d",
910 			    arg_size);
911 	}
912 	mtget->mt_type  = ft_drive_type.vendor_id + 0x800000;
913 	mtget->mt_dsreg = ft_last_status.space;
914 	mtget->mt_erreg = ft_last_error.space; /* error register */
915 	mtget->mt_resid = zft_resid; /* residuum of writes, reads and
916 				      * MTIOCTOP commands
917 				      */
918 	if (!zft_offline) { /* neither no_tape nor soft offline */
919 		mtget->mt_gstat = GMT_ONLINE(~0UL);
920 		/* should rather return the status of the cartridge
921 		 * than the access mode of the file, therefor use
922 		 * ft_write_protected, not zft_write_protected
923 		 */
924 		if (ft_write_protected) {
925 			mtget->mt_gstat |= GMT_WR_PROT(~0UL);
926 		}
927 		if(zft_header_read) { /* this catches non-formatted */
928 			volume = zft_find_volume(zft_pos.seg_pos);
929 			mtget->mt_fileno = volume->count;
930 			max_tape_pos = zft_capacity - zft_blk_sz;
931 			if (zft_use_compression) {
932 				max_tape_pos -= ZFT_CMPR_OVERHEAD;
933 			}
934 			if (zft_tape_at_eod(&zft_pos)) {
935 				mtget->mt_gstat |= GMT_EOD(~0UL);
936 			}
937 			if (zft_pos.tape_pos > max_tape_pos) {
938 				mtget->mt_gstat |= GMT_EOT(~0UL);
939 			}
940 			mtget->mt_blkno = zft_div_blksz(zft_pos.volume_pos,
941 							volume->blk_sz);
942 			if (zft_just_before_eof) {
943 				mtget->mt_gstat |= GMT_EOF(~0UL);
944 			}
945 			if (zft_tape_at_lbot(&zft_pos)) {
946 				mtget->mt_gstat |= GMT_BOT(~0UL);
947 			}
948 		} else {
949 			mtget->mt_fileno = mtget->mt_blkno = -1;
950 			if (mtget->mt_dsreg & QIC_STATUS_AT_BOT) {
951 				mtget->mt_gstat |= GMT_BOT(~0UL);
952 			}
953 		}
954 	} else {
955 		if (ft_no_tape) {
956 			mtget->mt_gstat = GMT_DR_OPEN(~0UL);
957 		} else {
958 			mtget->mt_gstat = 0UL;
959 		}
960  		mtget->mt_fileno = mtget->mt_blkno = -1;
961 	}
962 	TRACE_EXIT 0;
963 }
964 
965 #ifdef MTIOCRDFTSEG
966 /*
967  *  Read a floppy tape segment. This is useful for manipulating the
968  *  volume table, and read the old header segment before re-formatting
969  *  the cartridge.
970  */
mtiocrdftseg(struct mtftseg * mtftseg,int arg_size)971 static int mtiocrdftseg(struct mtftseg * mtftseg, int arg_size)
972 {
973 	TRACE_FUN(ft_t_flow);
974 
975 	TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCRDFTSEG");
976 	if (zft_qic_mode) {
977 		TRACE_ABORT(-EACCES, ft_t_info,
978 			    "driver needs to be in raw mode for this ioctl");
979 	}
980 	if (arg_size != sizeof(struct mtftseg)) {
981 		TRACE_ABORT(-EINVAL, ft_t_info, "bad argument size: %d",
982 			    arg_size);
983 	}
984 	if (zft_offline) {
985 		TRACE_EXIT -ENXIO;
986 	}
987 	if (mtftseg->mt_mode != FT_RD_SINGLE &&
988 	    mtftseg->mt_mode != FT_RD_AHEAD) {
989 		TRACE_ABORT(-EINVAL, ft_t_info, "invalid read mode");
990 	}
991 	if (!ft_formatted) {
992 		TRACE_EXIT -EACCES; /* -ENXIO ? */
993 
994 	}
995 	if (!zft_header_read) {
996 		TRACE_CATCH(zft_def_idle_state(),);
997 	}
998 	if (mtftseg->mt_segno > ft_last_data_segment) {
999 		TRACE_ABORT(-EINVAL, ft_t_info, "segment number is too large");
1000 	}
1001 	mtftseg->mt_result = ftape_read_segment(mtftseg->mt_segno,
1002 						zft_deblock_buf,
1003 						mtftseg->mt_mode);
1004 	if (mtftseg->mt_result < 0) {
1005 		/*  a negativ result is not an ioctl error. if
1006 		 *  the user wants to read damaged tapes,
1007 		 *  it's up to her/him
1008 		 */
1009 		TRACE_EXIT 0;
1010 	}
1011 #if LINUX_VERSION_CODE > KERNEL_VER(2,1,3)
1012 	if (copy_to_user(mtftseg->mt_data,
1013 			 zft_deblock_buf,
1014 			 mtftseg->mt_result) != 0) {
1015 		TRACE_EXIT -EFAULT;
1016 	}
1017 #else
1018 	TRACE_CATCH(verify_area(VERIFY_WRITE, mtftseg->mt_data,
1019 				mtftseg->mt_result),);
1020 	memcpy_tofs(mtftseg->mt_data, zft_deblock_buf,
1021 		    mtftseg->mt_result);
1022 #endif
1023 	TRACE_EXIT 0;
1024 }
1025 #endif
1026 
1027 #ifdef MTIOCWRFTSEG
1028 /*
1029  *  write a floppy tape segment. This version features writing of
1030  *  deleted address marks, and gracefully ignores the (software)
1031  *  ft_formatted flag to support writing of header segments after
1032  *  formatting.
1033  */
mtiocwrftseg(struct mtftseg * mtftseg,int arg_size)1034 static int mtiocwrftseg(struct mtftseg * mtftseg, int arg_size)
1035 {
1036 	int result;
1037 	TRACE_FUN(ft_t_flow);
1038 
1039 	TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCWRFTSEG");
1040 	if (zft_write_protected || zft_qic_mode) {
1041 		TRACE_EXIT -EACCES;
1042 	}
1043 	if (arg_size != sizeof(struct mtftseg)) {
1044 		TRACE_ABORT(-EINVAL, ft_t_info, "bad argument size: %d",
1045 			    arg_size);
1046 	}
1047 	if (zft_offline) {
1048 		TRACE_EXIT -ENXIO;
1049 	}
1050 	if (mtftseg->mt_mode != FT_WR_ASYNC   &&
1051 	    mtftseg->mt_mode != FT_WR_MULTI   &&
1052 	    mtftseg->mt_mode != FT_WR_SINGLE  &&
1053 	    mtftseg->mt_mode != FT_WR_DELETE) {
1054 		TRACE_ABORT(-EINVAL, ft_t_info, "invalid write mode");
1055 	}
1056 	/*
1057 	 *  We don't check for ft_formatted, because this gives
1058 	 *  only the software status of the driver.
1059 	 *
1060 	 *  We assume that the user knows what it is
1061 	 *  doing. And rely on the low level stuff to fail
1062 	 *  when the tape isn't formatted. We only make sure
1063 	 *  that The header segment buffer is allocated,
1064 	 *  because it holds the bad sector map.
1065 	 */
1066 	if (zft_hseg_buf == NULL) {
1067 		TRACE_EXIT -ENXIO;
1068 	}
1069 	if (mtftseg->mt_mode != FT_WR_DELETE) {
1070 #if LINUX_VERSION_CODE > KERNEL_VER(2,1,3)
1071 		if (copy_from_user(zft_deblock_buf,
1072 				   mtftseg->mt_data,
1073 				   FT_SEGMENT_SIZE) != 0) {
1074 			TRACE_EXIT -EFAULT;
1075 		}
1076 #else
1077 		TRACE_CATCH(verify_area(VERIFY_READ,
1078 					mtftseg->mt_data,
1079 					FT_SEGMENT_SIZE),);
1080 		memcpy_fromfs(zft_deblock_buf, mtftseg->mt_data,
1081 			      FT_SEGMENT_SIZE);
1082 #endif
1083 	}
1084 	mtftseg->mt_result = ftape_write_segment(mtftseg->mt_segno,
1085 						 zft_deblock_buf,
1086 						 mtftseg->mt_mode);
1087 	if (mtftseg->mt_result >= 0 && mtftseg->mt_mode == FT_WR_SINGLE) {
1088 		/*
1089 		 *  a negativ result is not an ioctl error. if
1090 		 *  the user wants to write damaged tapes,
1091 		 *  it's up to her/him
1092 		 */
1093 		if ((result = ftape_loop_until_writes_done()) < 0) {
1094 			mtftseg->mt_result = result;
1095 		}
1096 	}
1097 	TRACE_EXIT 0;
1098 }
1099 #endif
1100 
1101 #ifdef MTIOCVOLINFO
1102 /*
1103  *  get information about volume positioned at.
1104  */
mtiocvolinfo(struct mtvolinfo * volinfo,int arg_size)1105 static int mtiocvolinfo(struct mtvolinfo *volinfo, int arg_size)
1106 {
1107 	const zft_volinfo *volume;
1108 	TRACE_FUN(ft_t_flow);
1109 
1110 	TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCVOLINFO");
1111 	if (arg_size != sizeof(struct mtvolinfo)) {
1112 		TRACE_ABORT(-EINVAL,
1113 			    ft_t_info, "bad argument size: %d", arg_size);
1114 	}
1115 	if (zft_offline) {
1116 		TRACE_EXIT -ENXIO;
1117 	}
1118 	if (!ft_formatted) {
1119 		TRACE_EXIT -EACCES;
1120 	}
1121 	TRACE_CATCH(zft_def_idle_state(),);
1122 	volume = zft_find_volume(zft_pos.seg_pos);
1123 	volinfo->mt_volno   = volume->count;
1124 	volinfo->mt_blksz   = volume->blk_sz == 1 ? 0 : volume->blk_sz;
1125 	volinfo->mt_size    = volume->size >> 10;
1126 	volinfo->mt_rawsize = ((zft_calc_tape_pos(volume->end_seg + 1) >> 10) -
1127 			       (zft_calc_tape_pos(volume->start_seg) >> 10));
1128 	volinfo->mt_cmpr    = volume->use_compression;
1129 	TRACE_EXIT 0;
1130 }
1131 #endif
1132 
1133 #ifdef ZFT_OBSOLETE
mtioc_zftape_getblksz(struct mtblksz * blksz,int arg_size)1134 static int mtioc_zftape_getblksz(struct mtblksz *blksz, int arg_size)
1135 {
1136 	TRACE_FUN(ft_t_flow);
1137 
1138 	TRACE(ft_t_noise, "\n"
1139 	      KERN_INFO "Mag tape ioctl command: MTIOC_ZTAPE_GETBLKSZ\n"
1140 	      KERN_INFO "This ioctl is here merely for compatibility.\n"
1141 	      KERN_INFO "Please use MTIOCVOLINFO instead");
1142 	if (arg_size != sizeof(struct mtblksz)) {
1143 		TRACE_ABORT(-EINVAL,
1144 			    ft_t_info, "bad argument size: %d", arg_size);
1145 	}
1146 	if (zft_offline) {
1147 		TRACE_EXIT -ENXIO;
1148 	}
1149 	if (!ft_formatted) {
1150 		TRACE_EXIT -EACCES;
1151 	}
1152 	TRACE_CATCH(zft_def_idle_state(),);
1153 	blksz->mt_blksz = zft_find_volume(zft_pos.seg_pos)->blk_sz;
1154 	TRACE_EXIT 0;
1155 }
1156 #endif
1157 
1158 #ifdef MTIOCGETSIZE
1159 /*
1160  *  get the capacity of the tape cartridge.
1161  */
mtiocgetsize(struct mttapesize * size,int arg_size)1162 static int mtiocgetsize(struct mttapesize *size, int arg_size)
1163 {
1164 	TRACE_FUN(ft_t_flow);
1165 
1166 	TRACE(ft_t_noise, "Mag tape ioctl command: MTIOC_ZFTAPE_GETSIZE");
1167 	if (arg_size != sizeof(struct mttapesize)) {
1168 		TRACE_ABORT(-EINVAL,
1169 			    ft_t_info, "bad argument size: %d", arg_size);
1170 	}
1171 	if (zft_offline) {
1172 		TRACE_EXIT -ENXIO;
1173 	}
1174 	if (!ft_formatted) {
1175 		TRACE_EXIT -EACCES;
1176 	}
1177 	TRACE_CATCH(zft_def_idle_state(),);
1178 	size->mt_capacity = (unsigned int)(zft_capacity>>10);
1179 	size->mt_used     = (unsigned int)(zft_get_eom_pos()>>10);
1180 	TRACE_EXIT 0;
1181 }
1182 #endif
1183 
mtiocpos(struct mtpos * mtpos,int arg_size)1184 static int mtiocpos(struct mtpos *mtpos, int arg_size)
1185 {
1186 	int result;
1187 	TRACE_FUN(ft_t_flow);
1188 
1189 	TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCPOS");
1190 	if (arg_size != sizeof(struct mtpos)) {
1191 		TRACE_ABORT(-EINVAL,
1192 			    ft_t_info, "bad argument size: %d", arg_size);
1193 	}
1194 	result = mt_tell((int *)&mtpos->mt_blkno);
1195 	TRACE_EXIT result;
1196 }
1197 
1198 #ifdef MTIOCFTFORMAT
1199 /*
1200  * formatting of floppy tape cartridges. This is intended to be used
1201  * together with the MTIOCFTCMD ioctl and the new mmap feature
1202  */
1203 
1204 /*
1205  *  This function uses ftape_decode_header_segment() to inform the low
1206  *  level ftape module about the new parameters.
1207  *
1208  *  It erases the hseg_buf. The calling process must specify all
1209  *  parameters to assure proper operation.
1210  *
1211  *  return values: -EINVAL - wrong argument size
1212  *                 -EINVAL - if ftape_decode_header_segment() failed.
1213  */
set_format_parms(struct ftfmtparms * p,__u8 * hseg_buf)1214 static int set_format_parms(struct ftfmtparms *p, __u8 *hseg_buf)
1215 {
1216 	ft_trace_t old_level = TRACE_LEVEL;
1217 	TRACE_FUN(ft_t_flow);
1218 
1219 	TRACE(ft_t_noise, "MTIOCFTFORMAT operation FTFMT_SETPARMS");
1220 	memset(hseg_buf, 0, FT_SEGMENT_SIZE);
1221 	PUT4(hseg_buf, FT_SIGNATURE, FT_HSEG_MAGIC);
1222 
1223 	/*  fill in user specified parameters
1224 	 */
1225 	hseg_buf[FT_FMT_CODE] = (__u8)p->ft_fmtcode;
1226 	PUT2(hseg_buf, FT_SPT, p->ft_spt);
1227 	hseg_buf[FT_TPC]      = (__u8)p->ft_tpc;
1228 	hseg_buf[FT_FHM]      = (__u8)p->ft_fhm;
1229 	hseg_buf[FT_FTM]      = (__u8)p->ft_ftm;
1230 
1231 	/*  fill in sane defaults to make ftape happy.
1232 	 */
1233 	hseg_buf[FT_FSM] = (__u8)128; /* 128 is hard wired all over ftape */
1234 	if (p->ft_fmtcode == fmt_big) {
1235 		PUT4(hseg_buf, FT_6_HSEG_1,   0);
1236 		PUT4(hseg_buf, FT_6_HSEG_2,   1);
1237 		PUT4(hseg_buf, FT_6_FRST_SEG, 2);
1238 		PUT4(hseg_buf, FT_6_LAST_SEG, p->ft_spt * p->ft_tpc - 1);
1239 	} else {
1240 		PUT2(hseg_buf, FT_HSEG_1,    0);
1241 		PUT2(hseg_buf, FT_HSEG_2,    1);
1242 		PUT2(hseg_buf, FT_FRST_SEG,  2);
1243 		PUT2(hseg_buf, FT_LAST_SEG, p->ft_spt * p->ft_tpc - 1);
1244 	}
1245 
1246 	/*  Synchronize with the low level module. This is particularly
1247 	 *  needed for unformatted cartridges as the QIC std was previously
1248 	 *  unknown BUT is needed to set data rate and to calculate timeouts.
1249 	 */
1250 	TRACE_CATCH(ftape_calibrate_data_rate(p->ft_qicstd&QIC_TAPE_STD_MASK),
1251 		    _res = -EINVAL);
1252 
1253 	/*  The following will also recalcualte the timeouts for the tape
1254 	 *  length and QIC std we want to format to.
1255 	 *  abort with -EINVAL rather than -EIO
1256 	 */
1257 	SET_TRACE_LEVEL(ft_t_warn);
1258 	TRACE_CATCH(ftape_decode_header_segment(hseg_buf),
1259 		    SET_TRACE_LEVEL(old_level); _res = -EINVAL);
1260 	SET_TRACE_LEVEL(old_level);
1261 	TRACE_EXIT 0;
1262 }
1263 
1264 /*
1265  *  Return the internal SOFTWARE status of the kernel driver. This does
1266  *  NOT query the tape drive about its status.
1267  */
get_format_parms(struct ftfmtparms * p,__u8 * hseg_buffer)1268 static int get_format_parms(struct ftfmtparms *p, __u8 *hseg_buffer)
1269 {
1270 	TRACE_FUN(ft_t_flow);
1271 
1272 	TRACE(ft_t_noise, "MTIOCFTFORMAT operation FTFMT_GETPARMS");
1273 	p->ft_qicstd  = ft_qic_std;
1274 	p->ft_fmtcode = ft_format_code;
1275 	p->ft_fhm     = hseg_buffer[FT_FHM];
1276 	p->ft_ftm     = hseg_buffer[FT_FTM];
1277 	p->ft_spt     = ft_segments_per_track;
1278 	p->ft_tpc     = ft_tracks_per_tape;
1279 	TRACE_EXIT 0;
1280 }
1281 
mtiocftformat(struct mtftformat * mtftformat,int arg_size)1282 static int mtiocftformat(struct mtftformat *mtftformat, int arg_size)
1283 {
1284 	int result;
1285 	union fmt_arg *arg = &mtftformat->fmt_arg;
1286 	TRACE_FUN(ft_t_flow);
1287 
1288 	TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCFTFORMAT");
1289 	if (zft_offline) {
1290 		if (ft_no_tape) {
1291 			TRACE_ABORT(-ENXIO, ft_t_info, "no tape present");
1292 		} else {
1293 			TRACE_ABORT(-ENXIO, ft_t_info, "drive is offline");
1294 		}
1295 	}
1296 	if (zft_qic_mode) {
1297 		TRACE_ABORT(-EACCES, ft_t_info,
1298 			    "driver needs to be in raw mode for this ioctl");
1299 	}
1300 	if (zft_hseg_buf == NULL) {
1301 		TRACE_CATCH(zft_vcalloc_once(&zft_hseg_buf, FT_SEGMENT_SIZE),);
1302 	}
1303 	zft_header_read = 0;
1304 	switch(mtftformat->fmt_op) {
1305 	case FTFMT_SET_PARMS:
1306 		TRACE_CATCH(set_format_parms(&arg->fmt_parms, zft_hseg_buf),);
1307 		TRACE_EXIT 0;
1308 	case FTFMT_GET_PARMS:
1309 		TRACE_CATCH(get_format_parms(&arg->fmt_parms, zft_hseg_buf),);
1310 		TRACE_EXIT 0;
1311 	case FTFMT_FORMAT_TRACK:
1312 		if ((ft_formatted && zft_check_write_access(&zft_pos) < 0) ||
1313 		    (!ft_formatted && zft_write_protected)) {
1314 			TRACE_ABORT(-EACCES, ft_t_info, "Write access denied");
1315 		}
1316 		TRACE_CATCH(ftape_format_track(arg->fmt_track.ft_track,
1317 					       arg->fmt_track.ft_gap3),);
1318 		TRACE_EXIT 0;
1319 	case FTFMT_STATUS:
1320 		TRACE_CATCH(ftape_format_status(&arg->fmt_status.ft_segment),);
1321 		TRACE_EXIT 0;
1322 	case FTFMT_VERIFY:
1323 		TRACE_CATCH(ftape_verify_segment(arg->fmt_verify.ft_segment,
1324 				(SectorMap *)&arg->fmt_verify.ft_bsm),);
1325 		TRACE_EXIT 0;
1326 	default:
1327 		TRACE_ABORT(-EINVAL, ft_t_err, "Invalid format operation");
1328 	}
1329 	TRACE_EXIT result;
1330 }
1331 #endif
1332 
1333 #ifdef MTIOCFTCMD
1334 /*
1335  *  send a QIC-117 command to the drive, with optional timeouts,
1336  *  parameter and result bits. This is intended to be used together
1337  *  with the formatting ioctl.
1338  */
mtiocftcmd(struct mtftcmd * ftcmd,int arg_size)1339 static int mtiocftcmd(struct mtftcmd *ftcmd, int arg_size)
1340 {
1341 	int i;
1342 	TRACE_FUN(ft_t_flow);
1343 
1344 	TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCFTCMD");
1345 	if (!capable(CAP_SYS_ADMIN)) {
1346 		TRACE_ABORT(-EPERM, ft_t_info,
1347 			    "need CAP_SYS_ADMIN capability to send raw qic-117 commands");
1348 	}
1349 	if (zft_qic_mode) {
1350 		TRACE_ABORT(-EACCES, ft_t_info,
1351 			    "driver needs to be in raw mode for this ioctl");
1352 	}
1353 	if (arg_size != sizeof(struct mtftcmd)) {
1354 		TRACE_ABORT(-EINVAL,
1355 			    ft_t_info, "bad argument size: %d", arg_size);
1356 	}
1357 	if (ftcmd->ft_wait_before) {
1358 		TRACE_CATCH(ftape_ready_wait(ftcmd->ft_wait_before,
1359 					     &ftcmd->ft_status),);
1360 	}
1361 	if (ftcmd->ft_status & QIC_STATUS_ERROR)
1362 		goto ftmtcmd_error;
1363 	if (ftcmd->ft_result_bits != 0) {
1364 		TRACE_CATCH(ftape_report_operation(&ftcmd->ft_result,
1365 						   ftcmd->ft_cmd,
1366 						   ftcmd->ft_result_bits),);
1367 	} else {
1368 		TRACE_CATCH(ftape_command(ftcmd->ft_cmd),);
1369 		if (ftcmd->ft_status & QIC_STATUS_ERROR)
1370 			goto ftmtcmd_error;
1371 		for (i = 0; i < ftcmd->ft_parm_cnt; i++) {
1372 			TRACE_CATCH(ftape_parameter(ftcmd->ft_parms[i]&0x0f),);
1373 			if (ftcmd->ft_status & QIC_STATUS_ERROR)
1374 				goto ftmtcmd_error;
1375 		}
1376 	}
1377 	if (ftcmd->ft_wait_after != 0) {
1378 		TRACE_CATCH(ftape_ready_wait(ftcmd->ft_wait_after,
1379 					     &ftcmd->ft_status),);
1380 	}
1381 ftmtcmd_error:
1382 	if (ftcmd->ft_status & QIC_STATUS_ERROR) {
1383 		TRACE(ft_t_noise, "error status set");
1384 		TRACE_CATCH(ftape_report_error(&ftcmd->ft_error,
1385 					       &ftcmd->ft_cmd, 1),);
1386 	}
1387 	TRACE_EXIT 0; /* this is not an i/o error */
1388 }
1389 #endif
1390 
1391 /*  IOCTL routine called by kernel-interface code
1392  */
_zft_ioctl(unsigned int command,void * arg)1393 int _zft_ioctl(unsigned int command, void * arg)
1394 {
1395 	int result;
1396 	union { struct mtop       mtop;
1397 		struct mtget      mtget;
1398 		struct mtpos      mtpos;
1399 #ifdef MTIOCRDFTSEG
1400 		struct mtftseg    mtftseg;
1401 #endif
1402 #ifdef MTIOCVOLINFO
1403 		struct mtvolinfo  mtvolinfo;
1404 #endif
1405 #ifdef MTIOCGETSIZE
1406 		struct mttapesize mttapesize;
1407 #endif
1408 #ifdef MTIOCFTFORMAT
1409 		struct mtftformat mtftformat;
1410 #endif
1411 #ifdef ZFT_OBSOLETE
1412 		struct mtblksz mtblksz;
1413 #endif
1414 #ifdef MTIOCFTCMD
1415 		struct mtftcmd mtftcmd;
1416 #endif
1417 	} krnl_arg;
1418 	int arg_size = _IOC_SIZE(command);
1419 	int dir = _IOC_DIR(command);
1420 	TRACE_FUN(ft_t_flow);
1421 
1422 	/* This check will only catch arguments that are too large !
1423 	 */
1424 	if (dir & (_IOC_READ | _IOC_WRITE) && arg_size > sizeof(krnl_arg)) {
1425 		TRACE_ABORT(-EINVAL,
1426 			    ft_t_info, "bad argument size: %d", arg_size);
1427 	}
1428 	if (dir & _IOC_WRITE) {
1429 #if LINUX_VERSION_CODE > KERNEL_VER(2,1,3)
1430 		if (copy_from_user(&krnl_arg, arg, arg_size) != 0) {
1431 			TRACE_EXIT -EFAULT;
1432 		}
1433 #else
1434 		TRACE_CATCH(verify_area(VERIFY_READ, arg, arg_size),);
1435 		memcpy_fromfs(&krnl_arg, arg, arg_size);
1436 #endif
1437 	}
1438 	TRACE(ft_t_flow, "called with ioctl command: 0x%08x", command);
1439 	switch (command) {
1440 	case MTIOCTOP:
1441 		result = mtioctop(&krnl_arg.mtop, arg_size);
1442 		break;
1443 	case MTIOCGET:
1444 		result = mtiocget(&krnl_arg.mtget, arg_size);
1445 		break;
1446 	case MTIOCPOS:
1447 		result = mtiocpos(&krnl_arg.mtpos, arg_size);
1448 		break;
1449 #ifdef MTIOCVOLINFO
1450 	case MTIOCVOLINFO:
1451 		result = mtiocvolinfo(&krnl_arg.mtvolinfo, arg_size);
1452 		break;
1453 #endif
1454 #ifdef ZFT_OBSOLETE
1455 	case MTIOC_ZFTAPE_GETBLKSZ:
1456 		result = mtioc_zftape_getblksz(&krnl_arg.mtblksz, arg_size);
1457 		break;
1458 #endif
1459 #ifdef MTIOCRDFTSEG
1460 	case MTIOCRDFTSEG: /* read a segment via ioctl */
1461 		result = mtiocrdftseg(&krnl_arg.mtftseg, arg_size);
1462 		break;
1463 #endif
1464 #ifdef MTIOCWRFTSEG
1465 	case MTIOCWRFTSEG: /* write a segment via ioctl */
1466 		result = mtiocwrftseg(&krnl_arg.mtftseg, arg_size);
1467 		break;
1468 #endif
1469 #ifdef MTIOCGETSIZE
1470 	case MTIOCGETSIZE:
1471 		result = mtiocgetsize(&krnl_arg.mttapesize, arg_size);
1472 		break;
1473 #endif
1474 #ifdef MTIOCFTFORMAT
1475 	case MTIOCFTFORMAT:
1476 		result = mtiocftformat(&krnl_arg.mtftformat, arg_size);
1477 		break;
1478 #endif
1479 #ifdef MTIOCFTCMD
1480 	case MTIOCFTCMD:
1481 		result = mtiocftcmd(&krnl_arg.mtftcmd, arg_size);
1482 		break;
1483 #endif
1484 	default:
1485 		result = -EINVAL;
1486 		break;
1487 	}
1488 	if ((result >= 0) && (dir & _IOC_READ)) {
1489 #if LINUX_VERSION_CODE > KERNEL_VER(2,1,3)
1490 		if (copy_to_user(arg, &krnl_arg, arg_size) != 0) {
1491 			TRACE_EXIT -EFAULT;
1492 		}
1493 #else
1494 		TRACE_CATCH(verify_area(VERIFY_WRITE, arg, arg_size),);
1495 		memcpy_tofs(arg, &krnl_arg, arg_size);
1496 #endif
1497 	}
1498 	TRACE_EXIT result;
1499 }
1500