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