OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [char/] [ftape/] [zftape/] [zftape-ctl.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
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: /home/marcus/revision_ctrl_test/oc_cvs/cvs/or1k/linux/linux-2.4/drivers/char/ftape/zftape/zftape-ctl.c,v $
20
 * $Revision: 1.1.1.1 $
21
 * $Date: 2004-04-15 02:02:29 $
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
 
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
 
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
 
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
 
207
static int mt_dummy(int *dummy)
208
{
209
        TRACE_FUN(ft_t_flow);
210
 
211
        TRACE_EXIT -ENOSYS;
212
}
213
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 
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
 */
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
 
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
 
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
 */
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
 */
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
 
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
 */
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
 */
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
 */
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
 */
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
 */
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
 */
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
 */
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
 */
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
 */
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  
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
 */
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
 
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
 */
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
 */
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
 
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
 */
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
 */
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
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.