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