aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/ftape/zftape
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/ftape/zftape')
-rw-r--r--drivers/char/ftape/zftape/Makefile36
-rw-r--r--drivers/char/ftape/zftape/zftape-buffers.c149
-rw-r--r--drivers/char/ftape/zftape/zftape-buffers.h55
-rw-r--r--drivers/char/ftape/zftape/zftape-ctl.c1417
-rw-r--r--drivers/char/ftape/zftape/zftape-ctl.h58
-rw-r--r--drivers/char/ftape/zftape/zftape-eof.c199
-rw-r--r--drivers/char/ftape/zftape/zftape-eof.h52
-rw-r--r--drivers/char/ftape/zftape/zftape-init.c377
-rw-r--r--drivers/char/ftape/zftape/zftape-init.h77
-rw-r--r--drivers/char/ftape/zftape/zftape-read.c377
-rw-r--r--drivers/char/ftape/zftape/zftape-read.h53
-rw-r--r--drivers/char/ftape/zftape/zftape-rw.c375
-rw-r--r--drivers/char/ftape/zftape/zftape-rw.h101
-rw-r--r--drivers/char/ftape/zftape/zftape-vtbl.c757
-rw-r--r--drivers/char/ftape/zftape/zftape-vtbl.h227
-rw-r--r--drivers/char/ftape/zftape/zftape-write.c483
-rw-r--r--drivers/char/ftape/zftape/zftape-write.h38
-rw-r--r--drivers/char/ftape/zftape/zftape_syms.c43
18 files changed, 0 insertions, 4874 deletions
diff --git a/drivers/char/ftape/zftape/Makefile b/drivers/char/ftape/zftape/Makefile
deleted file mode 100644
index 6d91c1f77c05..000000000000
--- a/drivers/char/ftape/zftape/Makefile
+++ /dev/null
@@ -1,36 +0,0 @@
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# $Source: /homes/cvs/ftape-stacked/ftape/zftape/Makefile,v $
19# $Revision: 1.4 $
20# $Date: 1997/10/05 19:18:58 $
21#
22# Makefile for the QIC-40/80/3010/3020 zftape interface VFS to
23# ftape
24#
25
26
27# ZFT_OBSOLETE - enable the MTIOC_ZFTAPE_GETBLKSZ ioctl. You should
28# leave this enabled for compatibility with taper.
29
30obj-$(CONFIG_ZFTAPE) += zftape.o
31
32zftape-objs := zftape-rw.o zftape-ctl.o zftape-read.o \
33 zftape-write.o zftape-vtbl.o zftape-eof.o \
34 zftape-init.o zftape-buffers.o zftape_syms.o
35
36EXTRA_CFLAGS := -DZFT_OBSOLETE
diff --git a/drivers/char/ftape/zftape/zftape-buffers.c b/drivers/char/ftape/zftape/zftape-buffers.c
deleted file mode 100644
index 7ebce2ec7897..000000000000
--- a/drivers/char/ftape/zftape/zftape-buffers.c
+++ /dev/null
@@ -1,149 +0,0 @@
1/*
2 * Copyright (C) 1995-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-buffers.c,v $
20 * $Revision: 1.2 $
21 * $Date: 1997/10/05 19:18:59 $
22 *
23 * This file contains the dynamic buffer allocation routines
24 * of zftape
25 */
26
27#include <linux/errno.h>
28#include <linux/mm.h>
29#include <linux/slab.h>
30#include <linux/delay.h>
31
32#include <linux/zftape.h>
33
34#include <linux/vmalloc.h>
35
36#include "../zftape/zftape-init.h"
37#include "../zftape/zftape-eof.h"
38#include "../zftape/zftape-ctl.h"
39#include "../zftape/zftape-write.h"
40#include "../zftape/zftape-read.h"
41#include "../zftape/zftape-rw.h"
42#include "../zftape/zftape-vtbl.h"
43
44/* global variables
45 */
46
47/* local varibales
48 */
49static unsigned int used_memory;
50static unsigned int peak_memory;
51
52void zft_memory_stats(void)
53{
54 TRACE_FUN(ft_t_flow);
55
56 TRACE(ft_t_noise, "Memory usage (vmalloc allocations):\n"
57 KERN_INFO "total allocated: %d\n"
58 KERN_INFO "peak allocation: %d",
59 used_memory, peak_memory);
60 peak_memory = used_memory;
61 TRACE_EXIT;
62}
63
64int zft_vcalloc_once(void *new, size_t size)
65{
66 TRACE_FUN(ft_t_flow);
67 if (zft_vmalloc_once(new, size) < 0) {
68 TRACE_EXIT -ENOMEM;
69 }
70 memset(*(void **)new, '\0', size);
71 TRACE_EXIT 0;
72}
73int zft_vmalloc_once(void *new, size_t size)
74{
75 TRACE_FUN(ft_t_flow);
76
77 if (*(void **)new != NULL || size == 0) {
78 TRACE_EXIT 0;
79 }
80 if ((*(void **)new = vmalloc(size)) == NULL) {
81 TRACE_EXIT -ENOMEM;
82 }
83 used_memory += size;
84 if (peak_memory < used_memory) {
85 peak_memory = used_memory;
86 }
87 TRACE_ABORT(0, ft_t_noise,
88 "allocated buffer @ %p, %zd bytes", *(void **)new, size);
89}
90int zft_vmalloc_always(void *new, size_t size)
91{
92 TRACE_FUN(ft_t_flow);
93
94 zft_vfree(new, size);
95 TRACE_EXIT zft_vmalloc_once(new, size);
96}
97void zft_vfree(void *old, size_t size)
98{
99 TRACE_FUN(ft_t_flow);
100
101 if (*(void **)old) {
102 vfree(*(void **)old);
103 used_memory -= size;
104 TRACE(ft_t_noise, "released buffer @ %p, %zd bytes",
105 *(void **)old, size);
106 *(void **)old = NULL;
107 }
108 TRACE_EXIT;
109}
110
111void *zft_kmalloc(size_t size)
112{
113 void *new;
114
115 while ((new = kmalloc(size, GFP_KERNEL)) == NULL) {
116 msleep_interruptible(100);
117 }
118 memset(new, 0, size);
119 used_memory += size;
120 if (peak_memory < used_memory) {
121 peak_memory = used_memory;
122 }
123 return new;
124}
125
126void zft_kfree(void *old, size_t size)
127{
128 kfree(old);
129 used_memory -= size;
130}
131
132/* there are some more buffers that are allocated on demand.
133 * cleanup_module() calles this function to be sure to have released
134 * them
135 */
136void zft_uninit_mem(void)
137{
138 TRACE_FUN(ft_t_flow);
139
140 zft_vfree(&zft_hseg_buf, FT_SEGMENT_SIZE);
141 zft_vfree(&zft_deblock_buf, FT_SEGMENT_SIZE); zft_deblock_segment = -1;
142 zft_free_vtbl();
143 if (zft_cmpr_lock(0 /* don't load */) == 0) {
144 (*zft_cmpr_ops->cleanup)();
145 (*zft_cmpr_ops->reset)(); /* unlock it again */
146 }
147 zft_memory_stats();
148 TRACE_EXIT;
149}
diff --git a/drivers/char/ftape/zftape/zftape-buffers.h b/drivers/char/ftape/zftape/zftape-buffers.h
deleted file mode 100644
index 798e3128c682..000000000000
--- a/drivers/char/ftape/zftape/zftape-buffers.h
+++ /dev/null
@@ -1,55 +0,0 @@
1#ifndef _FTAPE_DYNMEM_H
2#define _FTAPE_DYNMEM_H
3
4/*
5 * Copyright (C) 1995-1997 Claus-Justus Heine.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; see the file COPYING. If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
20
21 *
22 * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-buffers.h,v $
23 * $Revision: 1.2 $
24 * $Date: 1997/10/05 19:18:59 $
25 *
26 * memory allocation routines.
27 *
28 */
29
30/* we do not allocate all of the really large buffer memory before
31 * someone tries to open the drive. ftape_open() may fail with
32 * -ENOMEM, but that's better having 200k of vmalloced memory which
33 * cannot be swapped out.
34 */
35
36extern void zft_memory_stats(void);
37extern int zft_vmalloc_once(void *new, size_t size);
38extern int zft_vcalloc_once(void *new, size_t size);
39extern int zft_vmalloc_always(void *new, size_t size);
40extern void zft_vfree(void *old, size_t size);
41extern void *zft_kmalloc(size_t size);
42extern void zft_kfree(void *old, size_t size);
43
44/* called by cleanup_module()
45 */
46extern void zft_uninit_mem(void);
47
48#endif
49
50
51
52
53
54
55
diff --git a/drivers/char/ftape/zftape/zftape-ctl.c b/drivers/char/ftape/zftape/zftape-ctl.c
deleted file mode 100644
index 22ba0f5d00cf..000000000000
--- a/drivers/char/ftape/zftape/zftape-ctl.c
+++ /dev/null
@@ -1,1417 +0,0 @@
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/errno.h>
28#include <linux/mm.h>
29#include <linux/module.h>
30#include <linux/fcntl.h>
31
32#include <linux/zftape.h>
33
34#include <asm/uaccess.h>
35
36#include "../zftape/zftape-init.h"
37#include "../zftape/zftape-eof.h"
38#include "../zftape/zftape-ctl.h"
39#include "../zftape/zftape-write.h"
40#include "../zftape/zftape-read.h"
41#include "../zftape/zftape-rw.h"
42#include "../zftape/zftape-vtbl.h"
43
44/* Global vars.
45 */
46int zft_write_protected; /* this is when cartridge rdonly or O_RDONLY */
47int zft_header_read;
48int zft_offline;
49unsigned int zft_unit;
50int zft_resid;
51int zft_mt_compression;
52
53/* Local vars.
54 */
55static int going_offline;
56
57typedef int (mt_fun)(int *argptr);
58typedef int (*mt_funp)(int *argptr);
59typedef struct
60{
61 mt_funp function;
62 unsigned offline : 1; /* op permitted if offline or no_tape */
63 unsigned write_protected : 1; /* op permitted if write-protected */
64 unsigned not_formatted : 1; /* op permitted if tape not formatted */
65 unsigned raw_mode : 1; /* op permitted if zft_mode == 0 */
66 unsigned need_idle_state : 1; /* need to call def_idle_state */
67 char *name;
68} fun_entry;
69
70static mt_fun mt_dummy, mt_reset, mt_fsr, mt_bsr, mt_rew, mt_offl, mt_nop,
71 mt_weof, mt_erase, mt_ras2, mt_setblk, mt_setdensity,
72 mt_seek, mt_tell, mt_reten, mt_eom, mt_fsf, mt_bsf,
73 mt_fsfm, mt_bsfm, mt_setdrvbuffer, mt_compression;
74
75static fun_entry mt_funs[]=
76{
77 {mt_reset , 1, 1, 1, 1, 0, "MT_RESET" }, /* 0 */
78 {mt_fsf , 0, 1, 0, 0, 1, "MT_FSF" },
79 {mt_bsf , 0, 1, 0, 0, 1, "MT_BSF" },
80 {mt_fsr , 0, 1, 0, 1, 1, "MT_FSR" },
81 {mt_bsr , 0, 1, 0, 1, 1, "MT_BSR" },
82 {mt_weof , 0, 0, 0, 0, 0, "MT_WEOF" }, /* 5 */
83 {mt_rew , 0, 1, 1, 1, 0, "MT_REW" },
84 {mt_offl , 0, 1, 1, 1, 0, "MT_OFFL" },
85 {mt_nop , 1, 1, 1, 1, 0, "MT_NOP" },
86 {mt_reten , 0, 1, 1, 1, 0, "MT_RETEN" },
87 {mt_bsfm , 0, 1, 0, 0, 1, "MT_BSFM" }, /* 10 */
88 {mt_fsfm , 0, 1, 0, 0, 1, "MT_FSFM" },
89 {mt_eom , 0, 1, 0, 0, 1, "MT_EOM" },
90 {mt_erase , 0, 0, 0, 1, 0, "MT_ERASE" },
91 {mt_dummy , 1, 1, 1, 1, 0, "MT_RAS1" },
92 {mt_ras2 , 0, 0, 0, 1, 0, "MT_RAS2" },
93 {mt_dummy , 1, 1, 1, 1, 0, "MT_RAS3" },
94 {mt_dummy , 1, 1, 1, 1, 0, "UNKNOWN" },
95 {mt_dummy , 1, 1, 1, 1, 0, "UNKNOWN" },
96 {mt_dummy , 1, 1, 1, 1, 0, "UNKNOWN" },
97 {mt_setblk , 1, 1, 1, 1, 1, "MT_SETBLK"}, /* 20 */
98 {mt_setdensity , 1, 1, 1, 1, 0, "MT_SETDENSITY"},
99 {mt_seek , 0, 1, 0, 1, 1, "MT_SEEK" },
100 {mt_dummy , 0, 1, 0, 1, 1, "MT_TELL" }, /* wr-only ?! */
101 {mt_setdrvbuffer, 1, 1, 1, 1, 0, "MT_SETDRVBUFFER" },
102 {mt_dummy , 1, 1, 1, 1, 0, "MT_FSS" }, /* 25 */
103 {mt_dummy , 1, 1, 1, 1, 0, "MT_BSS" },
104 {mt_dummy , 1, 1, 1, 1, 0, "MT_WSM" },
105 {mt_dummy , 1, 1, 1, 1, 0, "MT_LOCK" },
106 {mt_dummy , 1, 1, 1, 1, 0, "MT_UNLOCK"},
107 {mt_dummy , 1, 1, 1, 1, 0, "MT_LOAD" }, /* 30 */
108 {mt_dummy , 1, 1, 1, 1, 0, "MT_UNLOAD"},
109 {mt_compression , 1, 1, 1, 0, 1, "MT_COMPRESSION"},
110 {mt_dummy , 1, 1, 1, 1, 0, "MT_SETPART"},
111 {mt_dummy , 1, 1, 1, 1, 0, "MT_MKPART"}
112};
113
114#define NR_MT_CMDS NR_ITEMS(mt_funs)
115
116void zft_reset_position(zft_position *pos)
117{
118 TRACE_FUN(ft_t_flow);
119
120 pos->seg_byte_pos =
121 pos->volume_pos = 0;
122 if (zft_header_read) {
123 /* need to keep track of the volume table and
124 * compression map. We therefor simply
125 * position at the beginning of the first
126 * volume. This covers old ftape archives as
127 * well has various flavours of the
128 * compression map segments. The worst case is
129 * that the compression map shows up as a
130 * additional volume in front of all others.
131 */
132 pos->seg_pos = zft_find_volume(0)->start_seg;
133 pos->tape_pos = zft_calc_tape_pos(pos->seg_pos);
134 } else {
135 pos->tape_pos = 0;
136 pos->seg_pos = -1;
137 }
138 zft_just_before_eof = 0;
139 zft_deblock_segment = -1;
140 zft_io_state = zft_idle;
141 zft_zap_read_buffers();
142 zft_prevent_flush();
143 /* unlock the compresison module if it is loaded.
144 * The zero arg means not to try to load the module.
145 */
146 if (zft_cmpr_lock(0) == 0) {
147 (*zft_cmpr_ops->reset)(); /* unlock */
148 }
149 TRACE_EXIT;
150}
151
152static void zft_init_driver(void)
153{
154 TRACE_FUN(ft_t_flow);
155
156 zft_resid =
157 zft_header_read =
158 zft_old_ftape =
159 zft_offline =
160 zft_write_protected =
161 going_offline =
162 zft_mt_compression =
163 zft_header_changed =
164 zft_volume_table_changed =
165 zft_written_segments = 0;
166 zft_blk_sz = CONFIG_ZFT_DFLT_BLK_SZ;
167 zft_reset_position(&zft_pos); /* does most of the stuff */
168 ftape_zap_read_buffers();
169 ftape_set_state(idle);
170 TRACE_EXIT;
171}
172
173int zft_def_idle_state(void)
174{
175 int result = 0;
176 TRACE_FUN(ft_t_flow);
177
178 if (!zft_header_read) {
179 result = zft_read_header_segments();
180 } else if ((result = zft_flush_buffers()) >= 0 && zft_qic_mode) {
181 /* don't move past eof
182 */
183 (void)zft_close_volume(&zft_pos);
184 }
185 if (ftape_abort_operation() < 0) {
186 TRACE(ft_t_warn, "ftape_abort_operation() failed");
187 result = -EIO;
188 }
189 /* clear remaining read buffers */
190 zft_zap_read_buffers();
191 zft_io_state = zft_idle;
192 TRACE_EXIT result;
193}
194
195/*****************************************************************************
196 * *
197 * functions for the MTIOCTOP commands *
198 * *
199 *****************************************************************************/
200
201static int mt_dummy(int *dummy)
202{
203 TRACE_FUN(ft_t_flow);
204
205 TRACE_EXIT -ENOSYS;
206}
207
208static int mt_reset(int *dummy)
209{
210 TRACE_FUN(ft_t_flow);
211
212 (void)ftape_seek_to_bot();
213 TRACE_CATCH(ftape_reset_drive(),
214 zft_init_driver(); zft_uninit_mem(); zft_offline = 1);
215 /* fake a re-open of the device. This will set all flage and
216 * allocate buffers as appropriate. The new tape condition will
217 * force the open routine to do anything we need.
218 */
219 TRACE_CATCH(_zft_open(-1 /* fake reopen */, 0 /* dummy */),);
220 TRACE_EXIT 0;
221}
222
223static int mt_fsf(int *arg)
224{
225 int result;
226 TRACE_FUN(ft_t_flow);
227
228 result = zft_skip_volumes(*arg, &zft_pos);
229 zft_just_before_eof = 0;
230 TRACE_EXIT result;
231}
232
233static int mt_bsf(int *arg)
234{
235 int result = 0;
236 TRACE_FUN(ft_t_flow);
237
238 if (*arg != 0) {
239 result = zft_skip_volumes(-*arg + 1, &zft_pos);
240 }
241 TRACE_EXIT result;
242}
243
244static int seek_block(__s64 data_offset,
245 __s64 block_increment,
246 zft_position *pos)
247{
248 int result = 0;
249 __s64 new_block_pos;
250 __s64 vol_block_count;
251 const zft_volinfo *volume;
252 int exceed;
253 TRACE_FUN(ft_t_flow);
254
255 volume = zft_find_volume(pos->seg_pos);
256 if (volume->start_seg == 0 || volume->end_seg == 0) {
257 TRACE_EXIT -EIO;
258 }
259 new_block_pos = (zft_div_blksz(data_offset, volume->blk_sz)
260 + block_increment);
261 vol_block_count = zft_div_blksz(volume->size, volume->blk_sz);
262 if (new_block_pos < 0) {
263 TRACE(ft_t_noise,
264 "new_block_pos " LL_X " < 0", LL(new_block_pos));
265 zft_resid = (int)new_block_pos;
266 new_block_pos = 0;
267 exceed = 1;
268 } else if (new_block_pos > vol_block_count) {
269 TRACE(ft_t_noise,
270 "new_block_pos " LL_X " exceeds size of volume " LL_X,
271 LL(new_block_pos), LL(vol_block_count));
272 zft_resid = (int)(vol_block_count - new_block_pos);
273 new_block_pos = vol_block_count;
274 exceed = 1;
275 } else {
276 exceed = 0;
277 }
278 if (zft_use_compression && volume->use_compression) {
279 TRACE_CATCH(zft_cmpr_lock(1 /* try to load */),);
280 result = (*zft_cmpr_ops->seek)(new_block_pos, pos, volume,
281 zft_deblock_buf);
282 pos->tape_pos = zft_calc_tape_pos(pos->seg_pos);
283 pos->tape_pos += pos->seg_byte_pos;
284 } else {
285 pos->volume_pos = zft_mul_blksz(new_block_pos, volume->blk_sz);
286 pos->tape_pos = zft_calc_tape_pos(volume->start_seg);
287 pos->tape_pos += pos->volume_pos;
288 pos->seg_pos = zft_calc_seg_byte_coord(&pos->seg_byte_pos,
289 pos->tape_pos);
290 }
291 zft_just_before_eof = volume->size == pos->volume_pos;
292 if (zft_just_before_eof) {
293 /* why this? because zft_file_no checks agains start
294 * and end segment of a volume. We do not want to
295 * advance to the next volume with this function.
296 */
297 TRACE(ft_t_noise, "set zft_just_before_eof");
298 zft_position_before_eof(pos, volume);
299 }
300 TRACE(ft_t_noise, "\n"
301 KERN_INFO "new_seg_pos : %d\n"
302 KERN_INFO "new_tape_pos: " LL_X "\n"
303 KERN_INFO "vol_size : " LL_X "\n"
304 KERN_INFO "seg_byte_pos: %d\n"
305 KERN_INFO "blk_sz : %d",
306 pos->seg_pos, LL(pos->tape_pos),
307 LL(volume->size), pos->seg_byte_pos,
308 volume->blk_sz);
309 if (!exceed) {
310 zft_resid = new_block_pos - zft_div_blksz(pos->volume_pos,
311 volume->blk_sz);
312 }
313 if (zft_resid < 0) {
314 zft_resid = -zft_resid;
315 }
316 TRACE_EXIT ((exceed || zft_resid != 0) && result >= 0) ? -EINVAL : result;
317}
318
319static int mt_fsr(int *arg)
320{
321 int result;
322 TRACE_FUN(ft_t_flow);
323
324 result = seek_block(zft_pos.volume_pos, *arg, &zft_pos);
325 TRACE_EXIT result;
326}
327
328static int mt_bsr(int *arg)
329{
330 int result;
331 TRACE_FUN(ft_t_flow);
332
333 result = seek_block(zft_pos.volume_pos, -*arg, &zft_pos);
334 TRACE_EXIT result;
335}
336
337static int mt_weof(int *arg)
338{
339 int result;
340 TRACE_FUN(ft_t_flow);
341
342 TRACE_CATCH(zft_flush_buffers(),);
343 result = zft_weof(*arg, &zft_pos);
344 TRACE_EXIT result;
345}
346
347static int mt_rew(int *dummy)
348{
349 int result;
350 TRACE_FUN(ft_t_flow);
351
352 if(zft_header_read) {
353 (void)zft_def_idle_state();
354 }
355 result = ftape_seek_to_bot();
356 zft_reset_position(&zft_pos);
357 TRACE_EXIT result;
358}
359
360static int mt_offl(int *dummy)
361{
362 int result;
363 TRACE_FUN(ft_t_flow);
364
365 going_offline= 1;
366 result = mt_rew(NULL);
367 TRACE_EXIT result;
368}
369
370static int mt_nop(int *dummy)
371{
372 TRACE_FUN(ft_t_flow);
373 /* should we set tape status?
374 */
375 if (!zft_offline) { /* offline includes no_tape */
376 (void)zft_def_idle_state();
377 }
378 TRACE_EXIT 0;
379}
380
381static int mt_reten(int *dummy)
382{
383 int result;
384 TRACE_FUN(ft_t_flow);
385
386 if(zft_header_read) {
387 (void)zft_def_idle_state();
388 }
389 result = ftape_seek_to_eot();
390 if (result >= 0) {
391 result = ftape_seek_to_bot();
392 }
393 TRACE_EXIT(result);
394}
395
396static int fsfbsfm(int arg, zft_position *pos)
397{
398 const zft_volinfo *vtbl;
399 __s64 block_pos;
400 TRACE_FUN(ft_t_flow);
401
402 /* What to do? This should seek to the next file-mark and
403 * position BEFORE. That is, a next write would just extend
404 * the current file. Well. Let's just seek to the end of the
405 * current file, if count == 1. If count > 1, then do a
406 * "mt_fsf(count - 1)", and then seek to the end of that file.
407 * If count == 0, do nothing
408 */
409 if (arg == 0) {
410 TRACE_EXIT 0;
411 }
412 zft_just_before_eof = 0;
413 TRACE_CATCH(zft_skip_volumes(arg < 0 ? arg : arg-1, pos),
414 if (arg > 0) {
415 zft_resid ++;
416 });
417 vtbl = zft_find_volume(pos->seg_pos);
418 block_pos = zft_div_blksz(vtbl->size, vtbl->blk_sz);
419 (void)seek_block(0, block_pos, pos);
420 if (pos->volume_pos != vtbl->size) {
421 zft_just_before_eof = 0;
422 zft_resid = 1;
423 /* we didn't managed to go there */
424 TRACE_ABORT(-EIO, ft_t_err,
425 "wanted file position " LL_X ", arrived at " LL_X,
426 LL(vtbl->size), LL(pos->volume_pos));
427 }
428 zft_just_before_eof = 1;
429 TRACE_EXIT 0;
430}
431
432static int mt_bsfm(int *arg)
433{
434 int result;
435 TRACE_FUN(ft_t_flow);
436
437 result = fsfbsfm(-*arg, &zft_pos);
438 TRACE_EXIT result;
439}
440
441static int mt_fsfm(int *arg)
442{
443 int result;
444 TRACE_FUN(ft_t_flow);
445
446 result = fsfbsfm(*arg, &zft_pos);
447 TRACE_EXIT result;
448}
449
450static int mt_eom(int *dummy)
451{
452 TRACE_FUN(ft_t_flow);
453
454 zft_skip_to_eom(&zft_pos);
455 TRACE_EXIT 0;
456}
457
458static int mt_erase(int *dummy)
459{
460 int result;
461 TRACE_FUN(ft_t_flow);
462
463 result = zft_erase();
464 TRACE_EXIT result;
465}
466
467static int mt_ras2(int *dummy)
468{
469 int result;
470 TRACE_FUN(ft_t_flow);
471
472 result = -ENOSYS;
473 TRACE_EXIT result;
474}
475
476/* Sets the new blocksize in BYTES
477 *
478 */
479static int mt_setblk(int *new_size)
480{
481 TRACE_FUN(ft_t_flow);
482
483 if((unsigned int)(*new_size) > ZFT_MAX_BLK_SZ) {
484 TRACE_ABORT(-EINVAL, ft_t_info,
485 "desired blk_sz (%d) should be <= %d bytes",
486 *new_size, ZFT_MAX_BLK_SZ);
487 }
488 if ((*new_size & (FT_SECTOR_SIZE-1)) != 0) {
489 TRACE_ABORT(-EINVAL, ft_t_info,
490 "desired blk_sz (%d) must be a multiple of %d bytes",
491 *new_size, FT_SECTOR_SIZE);
492 }
493 if (*new_size == 0) {
494 if (zft_use_compression) {
495 TRACE_ABORT(-EINVAL, ft_t_info,
496 "Variable block size not yet "
497 "supported with compression");
498 }
499 *new_size = 1;
500 }
501 zft_blk_sz = *new_size;
502 TRACE_EXIT 0;
503}
504
505static int mt_setdensity(int *arg)
506{
507 TRACE_FUN(ft_t_flow);
508
509 SET_TRACE_LEVEL(*arg);
510 TRACE(TRACE_LEVEL, "tracing set to %d", TRACE_LEVEL);
511 if ((int)TRACE_LEVEL != *arg) {
512 TRACE_EXIT -EINVAL;
513 }
514 TRACE_EXIT 0;
515}
516
517static int mt_seek(int *new_block_pos)
518{
519 int result= 0;
520 TRACE_FUN(ft_t_any);
521
522 result = seek_block(0, (__s64)*new_block_pos, &zft_pos);
523 TRACE_EXIT result;
524}
525
526/* OK, this is totally different from SCSI, but the worst thing that can
527 * happen is that there is not enough defragmentated memory that can be
528 * allocated. Also, there is a hardwired limit of 16 dma buffers in the
529 * stock ftape module. This shouldn't bring the system down.
530 *
531 * NOTE: the argument specifies the total number of dma buffers to use.
532 * The driver needs at least 3 buffers to function at all.
533 *
534 */
535static int mt_setdrvbuffer(int *cnt)
536{
537 TRACE_FUN(ft_t_flow);
538
539 if (*cnt < 3) {
540 TRACE_EXIT -EINVAL;
541 }
542 TRACE_CATCH(ftape_set_nr_buffers(*cnt),);
543 TRACE_EXIT 0;
544}
545/* return the block position from start of volume
546 */
547static int mt_tell(int *arg)
548{
549 TRACE_FUN(ft_t_flow);
550
551 *arg = zft_div_blksz(zft_pos.volume_pos,
552 zft_find_volume(zft_pos.seg_pos)->blk_sz);
553 TRACE_EXIT 0;
554}
555
556static int mt_compression(int *arg)
557{
558 TRACE_FUN(ft_t_flow);
559
560 /* Ok. We could also check whether compression is available at
561 * all by trying to load the compression module. We could
562 * also check for a block size of 1 byte which is illegal
563 * with compression. Instead of doing it here we rely on
564 * zftape_write() to do the proper checks.
565 */
566 if ((unsigned int)*arg > 1) {
567 TRACE_EXIT -EINVAL;
568 }
569 if (*arg != 0 && zft_blk_sz == 1) { /* variable block size */
570 TRACE_ABORT(-EINVAL, ft_t_info,
571 "Compression not yet supported "
572 "with variable block size");
573 }
574 zft_mt_compression = *arg;
575 if ((zft_unit & ZFT_ZIP_MODE) == 0) {
576 zft_use_compression = zft_mt_compression;
577 }
578 TRACE_EXIT 0;
579}
580
581/* check whether write access is allowed. Write access is denied when
582 * + zft_write_protected == 1 -- this accounts for either hard write
583 * protection of the cartridge or for
584 * O_RDONLY access mode of the tape device
585 * + zft_offline == 1 -- this meany that there is either no tape
586 * or that the MTOFFLINE ioctl has been
587 * previously issued (`soft eject')
588 * + ft_formatted == 0 -- this means that the cartridge is not
589 * formatted
590 * Then we distinuguish two cases. When zft_qic_mode is TRUE, then we try
591 * to emulate a `traditional' (aka SCSI like) UN*X tape device. Therefore we
592 * deny writes when
593 * + zft_qic_mode ==1 &&
594 * (!zft_tape_at_lbot() && -- tape no at logical BOT
595 * !(zft_tape_at_eom() || -- tape not at logical EOM (or EOD)
596 * (zft_tape_at_eom() &&
597 * zft_old_ftape()))) -- we can't add new volume to tapes
598 * written by old ftape because ftape
599 * don't use the volume table
600 *
601 * when the drive is in true raw mode (aka /dev/rawft0) then we don't
602 * care about LBOT and EOM conditions. This device is intended for a
603 * user level program that wants to truly implement the QIC-80 compliance
604 * at the logical data layout level of the cartridge, i.e. implement all
605 * that volume table and volume directory stuff etc.<
606 */
607int zft_check_write_access(zft_position *pos)
608{
609 TRACE_FUN(ft_t_flow);
610
611 if (zft_offline) { /* offline includes no_tape */
612 TRACE_ABORT(-ENXIO,
613 ft_t_info, "tape is offline or no cartridge");
614 }
615 if (!ft_formatted) {
616 TRACE_ABORT(-EACCES, ft_t_info, "tape is not formatted");
617 }
618 if (zft_write_protected) {
619 TRACE_ABORT(-EACCES, ft_t_info, "cartridge write protected");
620 }
621 if (zft_qic_mode) {
622 /* check BOT condition */
623 if (!zft_tape_at_lbot(pos)) {
624 /* protect cartridges written by old ftape if
625 * not at BOT because they use the vtbl
626 * segment for storing data
627 */
628 if (zft_old_ftape) {
629 TRACE_ABORT(-EACCES, ft_t_warn,
630 "Cannot write to cartridges written by old ftape when not at BOT");
631 }
632 /* not at BOT, but allow writes at EOD, of course
633 */
634 if (!zft_tape_at_eod(pos)) {
635 TRACE_ABORT(-EACCES, ft_t_info,
636 "tape not at BOT and not at EOD");
637 }
638 }
639 /* fine. Now the tape is either at BOT or at EOD. */
640 }
641 /* or in raw mode in which case we don't care about BOT and EOD */
642 TRACE_EXIT 0;
643}
644
645/* OPEN routine called by kernel-interface code
646 *
647 * NOTE: this is also called by mt_reset() with dev_minor == -1
648 * to fake a reopen after a reset.
649 */
650int _zft_open(unsigned int dev_minor, unsigned int access_mode)
651{
652 static unsigned int tape_unit;
653 static unsigned int file_access_mode;
654 int result;
655 TRACE_FUN(ft_t_flow);
656
657 if ((int)dev_minor == -1) {
658 /* fake reopen */
659 zft_unit = tape_unit;
660 access_mode = file_access_mode;
661 zft_init_driver(); /* reset all static data to defaults */
662 } else {
663 tape_unit = dev_minor;
664 file_access_mode = access_mode;
665 if ((result = ftape_enable(FTAPE_SEL(dev_minor))) < 0) {
666 TRACE_ABORT(-ENXIO, ft_t_err,
667 "ftape_enable failed: %d", result);
668 }
669 if (ft_new_tape || ft_no_tape || !ft_formatted ||
670 (FTAPE_SEL(zft_unit) != FTAPE_SEL(dev_minor)) ||
671 (zft_unit & ZFT_RAW_MODE) != (dev_minor & ZFT_RAW_MODE)) {
672 /* reset all static data to defaults,
673 */
674 zft_init_driver();
675 }
676 zft_unit = dev_minor;
677 }
678 zft_set_flags(zft_unit); /* decode the minor bits */
679 if (zft_blk_sz == 1 && zft_use_compression) {
680 ftape_disable(); /* resets ft_no_tape */
681 TRACE_ABORT(-ENODEV, ft_t_warn, "Variable block size not yet "
682 "supported with compression");
683 }
684 /* no need for most of the buffers when no tape or not
685 * formatted. for the read/write operations, it is the
686 * regardless whether there is no tape, a not-formatted tape
687 * or the whether the driver is soft offline.
688 * Nevertheless we allow some ioctls with non-formatted tapes,
689 * like rewind and reset.
690 */
691 if (ft_no_tape || !ft_formatted) {
692 zft_uninit_mem();
693 }
694 if (ft_no_tape) {
695 zft_offline = 1; /* so we need not test two variables */
696 }
697 if ((access_mode == O_WRONLY || access_mode == O_RDWR) &&
698 (ft_write_protected || ft_no_tape)) {
699 ftape_disable(); /* resets ft_no_tape */
700 TRACE_ABORT(ft_no_tape ? -ENXIO : -EROFS,
701 ft_t_warn, "wrong access mode %s cartridge",
702 ft_no_tape ? "without a" : "with write protected");
703 }
704 zft_write_protected = (access_mode == O_RDONLY ||
705 ft_write_protected != 0);
706 if (zft_write_protected) {
707 TRACE(ft_t_noise,
708 "read only access mode: %d, "
709 "drive write protected: %d",
710 access_mode == O_RDONLY,
711 ft_write_protected != 0);
712 }
713 if (!zft_offline) {
714 TRACE_CATCH(zft_vmalloc_once(&zft_deblock_buf,FT_SEGMENT_SIZE),
715 ftape_disable());
716 }
717 /* zft_seg_pos should be greater than the vtbl segpos but not
718 * if in compatibility mode and only after we read in the
719 * header segments
720 *
721 * might also be a problem if the user makes a backup with a
722 * *qft* device and rewinds it with a raw device.
723 */
724 if (zft_qic_mode &&
725 !zft_old_ftape &&
726 zft_pos.seg_pos >= 0 &&
727 zft_header_read &&
728 zft_pos.seg_pos <= ft_first_data_segment) {
729 TRACE(ft_t_noise, "you probably mixed up the zftape devices!");
730 zft_reset_position(&zft_pos);
731 }
732 TRACE_EXIT 0;
733}
734
735/* RELEASE routine called by kernel-interface code
736 */
737int _zft_close(void)
738{
739 int result = 0;
740 TRACE_FUN(ft_t_flow);
741
742 if (zft_offline) {
743 /* call the hardware release routine. Puts the drive offline */
744 ftape_disable();
745 TRACE_EXIT 0;
746 }
747 if (!(ft_write_protected || zft_old_ftape)) {
748 result = zft_flush_buffers();
749 TRACE(ft_t_noise, "writing file mark at current position");
750 if (zft_qic_mode && zft_close_volume(&zft_pos) == 0) {
751 zft_move_past_eof(&zft_pos);
752 }
753 if ((zft_tape_at_lbot(&zft_pos) ||
754 !(zft_unit & FTAPE_NO_REWIND))) {
755 if (result >= 0) {
756 result = zft_update_header_segments();
757 } else {
758 TRACE(ft_t_err,
759 "Error: unable to update header segments");
760 }
761 }
762 }
763 ftape_abort_operation();
764 if (!(zft_unit & FTAPE_NO_REWIND)) {
765 TRACE(ft_t_noise, "rewinding tape");
766 if (ftape_seek_to_bot() < 0 && result >= 0) {
767 result = -EIO; /* keep old value */
768 }
769 zft_reset_position(&zft_pos);
770 }
771 zft_zap_read_buffers();
772 /* now free up memory as much as possible. We don't destroy
773 * the deblock buffer if it containes a valid segment.
774 */
775 if (zft_deblock_segment == -1) {
776 zft_vfree(&zft_deblock_buf, FT_SEGMENT_SIZE);
777 }
778 /* high level driver status, forces creation of a new volume
779 * when calling ftape_write again and not zft_just_before_eof
780 */
781 zft_io_state = zft_idle;
782 if (going_offline) {
783 zft_init_driver();
784 zft_uninit_mem();
785 going_offline = 0;
786 zft_offline = 1;
787 } else if (zft_cmpr_lock(0 /* don't load */) == 0) {
788 (*zft_cmpr_ops->reset)(); /* unlock it again */
789 }
790 zft_memory_stats();
791 /* call the hardware release routine. Puts the drive offline */
792 ftape_disable();
793 TRACE_EXIT result;
794}
795
796/*
797 * the wrapper function around the wrapper MTIOCTOP ioctl
798 */
799static int mtioctop(struct mtop *mtop, int arg_size)
800{
801 int result = 0;
802 fun_entry *mt_fun_entry;
803 TRACE_FUN(ft_t_flow);
804
805 if (arg_size != sizeof(struct mtop) || mtop->mt_op >= NR_MT_CMDS) {
806 TRACE_EXIT -EINVAL;
807 }
808 TRACE(ft_t_noise, "calling MTIOCTOP command: %s",
809 mt_funs[mtop->mt_op].name);
810 mt_fun_entry= &mt_funs[mtop->mt_op];
811 zft_resid = mtop->mt_count;
812 if (!mt_fun_entry->offline && zft_offline) {
813 if (ft_no_tape) {
814 TRACE_ABORT(-ENXIO, ft_t_info, "no tape present");
815 } else {
816 TRACE_ABORT(-ENXIO, ft_t_info, "drive is offline");
817 }
818 }
819 if (!mt_fun_entry->not_formatted && !ft_formatted) {
820 TRACE_ABORT(-EACCES, ft_t_info, "tape is not formatted");
821 }
822 if (!mt_fun_entry->write_protected) {
823 TRACE_CATCH(zft_check_write_access(&zft_pos),);
824 }
825 if (mt_fun_entry->need_idle_state && !(zft_offline || !ft_formatted)) {
826 TRACE_CATCH(zft_def_idle_state(),);
827 }
828 if (!zft_qic_mode && !mt_fun_entry->raw_mode) {
829 TRACE_ABORT(-EACCES, ft_t_info,
830"Drive needs to be in QIC-80 compatibility mode for this command");
831 }
832 result = (mt_fun_entry->function)(&mtop->mt_count);
833 if (zft_tape_at_lbot(&zft_pos)) {
834 TRACE_CATCH(zft_update_header_segments(),);
835 }
836 if (result >= 0) {
837 zft_resid = 0;
838 }
839 TRACE_EXIT result;
840}
841
842/*
843 * standard MTIOCGET ioctl
844 */
845static int mtiocget(struct mtget *mtget, int arg_size)
846{
847 const zft_volinfo *volume;
848 __s64 max_tape_pos;
849 TRACE_FUN(ft_t_flow);
850
851 if (arg_size != sizeof(struct mtget)) {
852 TRACE_ABORT(-EINVAL, ft_t_info, "bad argument size: %d",
853 arg_size);
854 }
855 mtget->mt_type = ft_drive_type.vendor_id + 0x800000;
856 mtget->mt_dsreg = ft_last_status.space;
857 mtget->mt_erreg = ft_last_error.space; /* error register */
858 mtget->mt_resid = zft_resid; /* residuum of writes, reads and
859 * MTIOCTOP commands
860 */
861 if (!zft_offline) { /* neither no_tape nor soft offline */
862 mtget->mt_gstat = GMT_ONLINE(~0UL);
863 /* should rather return the status of the cartridge
864 * than the access mode of the file, therefor use
865 * ft_write_protected, not zft_write_protected
866 */
867 if (ft_write_protected) {
868 mtget->mt_gstat |= GMT_WR_PROT(~0UL);
869 }
870 if(zft_header_read) { /* this catches non-formatted */
871 volume = zft_find_volume(zft_pos.seg_pos);
872 mtget->mt_fileno = volume->count;
873 max_tape_pos = zft_capacity - zft_blk_sz;
874 if (zft_use_compression) {
875 max_tape_pos -= ZFT_CMPR_OVERHEAD;
876 }
877 if (zft_tape_at_eod(&zft_pos)) {
878 mtget->mt_gstat |= GMT_EOD(~0UL);
879 }
880 if (zft_pos.tape_pos > max_tape_pos) {
881 mtget->mt_gstat |= GMT_EOT(~0UL);
882 }
883 mtget->mt_blkno = zft_div_blksz(zft_pos.volume_pos,
884 volume->blk_sz);
885 if (zft_just_before_eof) {
886 mtget->mt_gstat |= GMT_EOF(~0UL);
887 }
888 if (zft_tape_at_lbot(&zft_pos)) {
889 mtget->mt_gstat |= GMT_BOT(~0UL);
890 }
891 } else {
892 mtget->mt_fileno = mtget->mt_blkno = -1;
893 if (mtget->mt_dsreg & QIC_STATUS_AT_BOT) {
894 mtget->mt_gstat |= GMT_BOT(~0UL);
895 }
896 }
897 } else {
898 if (ft_no_tape) {
899 mtget->mt_gstat = GMT_DR_OPEN(~0UL);
900 } else {
901 mtget->mt_gstat = 0UL;
902 }
903 mtget->mt_fileno = mtget->mt_blkno = -1;
904 }
905 TRACE_EXIT 0;
906}
907
908#ifdef MTIOCRDFTSEG
909/*
910 * Read a floppy tape segment. This is useful for manipulating the
911 * volume table, and read the old header segment before re-formatting
912 * the cartridge.
913 */
914static int mtiocrdftseg(struct mtftseg * mtftseg, int arg_size)
915{
916 TRACE_FUN(ft_t_flow);
917
918 TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCRDFTSEG");
919 if (zft_qic_mode) {
920 TRACE_ABORT(-EACCES, ft_t_info,
921 "driver needs to be in raw mode for this ioctl");
922 }
923 if (arg_size != sizeof(struct mtftseg)) {
924 TRACE_ABORT(-EINVAL, ft_t_info, "bad argument size: %d",
925 arg_size);
926 }
927 if (zft_offline) {
928 TRACE_EXIT -ENXIO;
929 }
930 if (mtftseg->mt_mode != FT_RD_SINGLE &&
931 mtftseg->mt_mode != FT_RD_AHEAD) {
932 TRACE_ABORT(-EINVAL, ft_t_info, "invalid read mode");
933 }
934 if (!ft_formatted) {
935 TRACE_EXIT -EACCES; /* -ENXIO ? */
936
937 }
938 if (!zft_header_read) {
939 TRACE_CATCH(zft_def_idle_state(),);
940 }
941 if (mtftseg->mt_segno > ft_last_data_segment) {
942 TRACE_ABORT(-EINVAL, ft_t_info, "segment number is too large");
943 }
944 mtftseg->mt_result = ftape_read_segment(mtftseg->mt_segno,
945 zft_deblock_buf,
946 mtftseg->mt_mode);
947 if (mtftseg->mt_result < 0) {
948 /* a negativ result is not an ioctl error. if
949 * the user wants to read damaged tapes,
950 * it's up to her/him
951 */
952 TRACE_EXIT 0;
953 }
954 if (copy_to_user(mtftseg->mt_data,
955 zft_deblock_buf,
956 mtftseg->mt_result) != 0) {
957 TRACE_EXIT -EFAULT;
958 }
959 TRACE_EXIT 0;
960}
961#endif
962
963#ifdef MTIOCWRFTSEG
964/*
965 * write a floppy tape segment. This version features writing of
966 * deleted address marks, and gracefully ignores the (software)
967 * ft_formatted flag to support writing of header segments after
968 * formatting.
969 */
970static int mtiocwrftseg(struct mtftseg * mtftseg, int arg_size)
971{
972 int result;
973 TRACE_FUN(ft_t_flow);
974
975 TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCWRFTSEG");
976 if (zft_write_protected || zft_qic_mode) {
977 TRACE_EXIT -EACCES;
978 }
979 if (arg_size != sizeof(struct mtftseg)) {
980 TRACE_ABORT(-EINVAL, ft_t_info, "bad argument size: %d",
981 arg_size);
982 }
983 if (zft_offline) {
984 TRACE_EXIT -ENXIO;
985 }
986 if (mtftseg->mt_mode != FT_WR_ASYNC &&
987 mtftseg->mt_mode != FT_WR_MULTI &&
988 mtftseg->mt_mode != FT_WR_SINGLE &&
989 mtftseg->mt_mode != FT_WR_DELETE) {
990 TRACE_ABORT(-EINVAL, ft_t_info, "invalid write mode");
991 }
992 /*
993 * We don't check for ft_formatted, because this gives
994 * only the software status of the driver.
995 *
996 * We assume that the user knows what it is
997 * doing. And rely on the low level stuff to fail
998 * when the tape isn't formatted. We only make sure
999 * that The header segment buffer is allocated,
1000 * because it holds the bad sector map.
1001 */
1002 if (zft_hseg_buf == NULL) {
1003 TRACE_EXIT -ENXIO;
1004 }
1005 if (mtftseg->mt_mode != FT_WR_DELETE) {
1006 if (copy_from_user(zft_deblock_buf,
1007 mtftseg->mt_data,
1008 FT_SEGMENT_SIZE) != 0) {
1009 TRACE_EXIT -EFAULT;
1010 }
1011 }
1012 mtftseg->mt_result = ftape_write_segment(mtftseg->mt_segno,
1013 zft_deblock_buf,
1014 mtftseg->mt_mode);
1015 if (mtftseg->mt_result >= 0 && mtftseg->mt_mode == FT_WR_SINGLE) {
1016 /*
1017 * a negativ result is not an ioctl error. if
1018 * the user wants to write damaged tapes,
1019 * it's up to her/him
1020 */
1021 if ((result = ftape_loop_until_writes_done()) < 0) {
1022 mtftseg->mt_result = result;
1023 }
1024 }
1025 TRACE_EXIT 0;
1026}
1027#endif
1028
1029#ifdef MTIOCVOLINFO
1030/*
1031 * get information about volume positioned at.
1032 */
1033static int mtiocvolinfo(struct mtvolinfo *volinfo, int arg_size)
1034{
1035 const zft_volinfo *volume;
1036 TRACE_FUN(ft_t_flow);
1037
1038 TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCVOLINFO");
1039 if (arg_size != sizeof(struct mtvolinfo)) {
1040 TRACE_ABORT(-EINVAL,
1041 ft_t_info, "bad argument size: %d", arg_size);
1042 }
1043 if (zft_offline) {
1044 TRACE_EXIT -ENXIO;
1045 }
1046 if (!ft_formatted) {
1047 TRACE_EXIT -EACCES;
1048 }
1049 TRACE_CATCH(zft_def_idle_state(),);
1050 volume = zft_find_volume(zft_pos.seg_pos);
1051 volinfo->mt_volno = volume->count;
1052 volinfo->mt_blksz = volume->blk_sz == 1 ? 0 : volume->blk_sz;
1053 volinfo->mt_size = volume->size >> 10;
1054 volinfo->mt_rawsize = ((zft_calc_tape_pos(volume->end_seg + 1) >> 10) -
1055 (zft_calc_tape_pos(volume->start_seg) >> 10));
1056 volinfo->mt_cmpr = volume->use_compression;
1057 TRACE_EXIT 0;
1058}
1059#endif
1060
1061#ifdef ZFT_OBSOLETE
1062static int mtioc_zftape_getblksz(struct mtblksz *blksz, int arg_size)
1063{
1064 TRACE_FUN(ft_t_flow);
1065
1066 TRACE(ft_t_noise, "\n"
1067 KERN_INFO "Mag tape ioctl command: MTIOC_ZTAPE_GETBLKSZ\n"
1068 KERN_INFO "This ioctl is here merely for compatibility.\n"
1069 KERN_INFO "Please use MTIOCVOLINFO instead");
1070 if (arg_size != sizeof(struct mtblksz)) {
1071 TRACE_ABORT(-EINVAL,
1072 ft_t_info, "bad argument size: %d", arg_size);
1073 }
1074 if (zft_offline) {
1075 TRACE_EXIT -ENXIO;
1076 }
1077 if (!ft_formatted) {
1078 TRACE_EXIT -EACCES;
1079 }
1080 TRACE_CATCH(zft_def_idle_state(),);
1081 blksz->mt_blksz = zft_find_volume(zft_pos.seg_pos)->blk_sz;
1082 TRACE_EXIT 0;
1083}
1084#endif
1085
1086#ifdef MTIOCGETSIZE
1087/*
1088 * get the capacity of the tape cartridge.
1089 */
1090static int mtiocgetsize(struct mttapesize *size, int arg_size)
1091{
1092 TRACE_FUN(ft_t_flow);
1093
1094 TRACE(ft_t_noise, "Mag tape ioctl command: MTIOC_ZFTAPE_GETSIZE");
1095 if (arg_size != sizeof(struct mttapesize)) {
1096 TRACE_ABORT(-EINVAL,
1097 ft_t_info, "bad argument size: %d", arg_size);
1098 }
1099 if (zft_offline) {
1100 TRACE_EXIT -ENXIO;
1101 }
1102 if (!ft_formatted) {
1103 TRACE_EXIT -EACCES;
1104 }
1105 TRACE_CATCH(zft_def_idle_state(),);
1106 size->mt_capacity = (unsigned int)(zft_capacity>>10);
1107 size->mt_used = (unsigned int)(zft_get_eom_pos()>>10);
1108 TRACE_EXIT 0;
1109}
1110#endif
1111
1112static int mtiocpos(struct mtpos *mtpos, int arg_size)
1113{
1114 int result;
1115 TRACE_FUN(ft_t_flow);
1116
1117 TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCPOS");
1118 if (arg_size != sizeof(struct mtpos)) {
1119 TRACE_ABORT(-EINVAL,
1120 ft_t_info, "bad argument size: %d", arg_size);
1121 }
1122 result = mt_tell((int *)&mtpos->mt_blkno);
1123 TRACE_EXIT result;
1124}
1125
1126#ifdef MTIOCFTFORMAT
1127/*
1128 * formatting of floppy tape cartridges. This is intended to be used
1129 * together with the MTIOCFTCMD ioctl and the new mmap feature
1130 */
1131
1132/*
1133 * This function uses ftape_decode_header_segment() to inform the low
1134 * level ftape module about the new parameters.
1135 *
1136 * It erases the hseg_buf. The calling process must specify all
1137 * parameters to assure proper operation.
1138 *
1139 * return values: -EINVAL - wrong argument size
1140 * -EINVAL - if ftape_decode_header_segment() failed.
1141 */
1142static int set_format_parms(struct ftfmtparms *p, __u8 *hseg_buf)
1143{
1144 ft_trace_t old_level = TRACE_LEVEL;
1145 TRACE_FUN(ft_t_flow);
1146
1147 TRACE(ft_t_noise, "MTIOCFTFORMAT operation FTFMT_SETPARMS");
1148 memset(hseg_buf, 0, FT_SEGMENT_SIZE);
1149 PUT4(hseg_buf, FT_SIGNATURE, FT_HSEG_MAGIC);
1150
1151 /* fill in user specified parameters
1152 */
1153 hseg_buf[FT_FMT_CODE] = (__u8)p->ft_fmtcode;
1154 PUT2(hseg_buf, FT_SPT, p->ft_spt);
1155 hseg_buf[FT_TPC] = (__u8)p->ft_tpc;
1156 hseg_buf[FT_FHM] = (__u8)p->ft_fhm;
1157 hseg_buf[FT_FTM] = (__u8)p->ft_ftm;
1158
1159 /* fill in sane defaults to make ftape happy.
1160 */
1161 hseg_buf[FT_FSM] = (__u8)128; /* 128 is hard wired all over ftape */
1162 if (p->ft_fmtcode == fmt_big) {
1163 PUT4(hseg_buf, FT_6_HSEG_1, 0);
1164 PUT4(hseg_buf, FT_6_HSEG_2, 1);
1165 PUT4(hseg_buf, FT_6_FRST_SEG, 2);
1166 PUT4(hseg_buf, FT_6_LAST_SEG, p->ft_spt * p->ft_tpc - 1);
1167 } else {
1168 PUT2(hseg_buf, FT_HSEG_1, 0);
1169 PUT2(hseg_buf, FT_HSEG_2, 1);
1170 PUT2(hseg_buf, FT_FRST_SEG, 2);
1171 PUT2(hseg_buf, FT_LAST_SEG, p->ft_spt * p->ft_tpc - 1);
1172 }
1173
1174 /* Synchronize with the low level module. This is particularly
1175 * needed for unformatted cartridges as the QIC std was previously
1176 * unknown BUT is needed to set data rate and to calculate timeouts.
1177 */
1178 TRACE_CATCH(ftape_calibrate_data_rate(p->ft_qicstd&QIC_TAPE_STD_MASK),
1179 _res = -EINVAL);
1180
1181 /* The following will also recalcualte the timeouts for the tape
1182 * length and QIC std we want to format to.
1183 * abort with -EINVAL rather than -EIO
1184 */
1185 SET_TRACE_LEVEL(ft_t_warn);
1186 TRACE_CATCH(ftape_decode_header_segment(hseg_buf),
1187 SET_TRACE_LEVEL(old_level); _res = -EINVAL);
1188 SET_TRACE_LEVEL(old_level);
1189 TRACE_EXIT 0;
1190}
1191
1192/*
1193 * Return the internal SOFTWARE status of the kernel driver. This does
1194 * NOT query the tape drive about its status.
1195 */
1196static int get_format_parms(struct ftfmtparms *p, __u8 *hseg_buffer)
1197{
1198 TRACE_FUN(ft_t_flow);
1199
1200 TRACE(ft_t_noise, "MTIOCFTFORMAT operation FTFMT_GETPARMS");
1201 p->ft_qicstd = ft_qic_std;
1202 p->ft_fmtcode = ft_format_code;
1203 p->ft_fhm = hseg_buffer[FT_FHM];
1204 p->ft_ftm = hseg_buffer[FT_FTM];
1205 p->ft_spt = ft_segments_per_track;
1206 p->ft_tpc = ft_tracks_per_tape;
1207 TRACE_EXIT 0;
1208}
1209
1210static int mtiocftformat(struct mtftformat *mtftformat, int arg_size)
1211{
1212 int result;
1213 union fmt_arg *arg = &mtftformat->fmt_arg;
1214 TRACE_FUN(ft_t_flow);
1215
1216 TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCFTFORMAT");
1217 if (zft_offline) {
1218 if (ft_no_tape) {
1219 TRACE_ABORT(-ENXIO, ft_t_info, "no tape present");
1220 } else {
1221 TRACE_ABORT(-ENXIO, ft_t_info, "drive is offline");
1222 }
1223 }
1224 if (zft_qic_mode) {
1225 TRACE_ABORT(-EACCES, ft_t_info,
1226 "driver needs to be in raw mode for this ioctl");
1227 }
1228 if (zft_hseg_buf == NULL) {
1229 TRACE_CATCH(zft_vcalloc_once(&zft_hseg_buf, FT_SEGMENT_SIZE),);
1230 }
1231 zft_header_read = 0;
1232 switch(mtftformat->fmt_op) {
1233 case FTFMT_SET_PARMS:
1234 TRACE_CATCH(set_format_parms(&arg->fmt_parms, zft_hseg_buf),);
1235 TRACE_EXIT 0;
1236 case FTFMT_GET_PARMS:
1237 TRACE_CATCH(get_format_parms(&arg->fmt_parms, zft_hseg_buf),);
1238 TRACE_EXIT 0;
1239 case FTFMT_FORMAT_TRACK:
1240 if ((ft_formatted && zft_check_write_access(&zft_pos) < 0) ||
1241 (!ft_formatted && zft_write_protected)) {
1242 TRACE_ABORT(-EACCES, ft_t_info, "Write access denied");
1243 }
1244 TRACE_CATCH(ftape_format_track(arg->fmt_track.ft_track,
1245 arg->fmt_track.ft_gap3),);
1246 TRACE_EXIT 0;
1247 case FTFMT_STATUS:
1248 TRACE_CATCH(ftape_format_status(&arg->fmt_status.ft_segment),);
1249 TRACE_EXIT 0;
1250 case FTFMT_VERIFY:
1251 TRACE_CATCH(ftape_verify_segment(arg->fmt_verify.ft_segment,
1252 (SectorMap *)&arg->fmt_verify.ft_bsm),);
1253 TRACE_EXIT 0;
1254 default:
1255 TRACE_ABORT(-EINVAL, ft_t_err, "Invalid format operation");
1256 }
1257 TRACE_EXIT result;
1258}
1259#endif
1260
1261#ifdef MTIOCFTCMD
1262/*
1263 * send a QIC-117 command to the drive, with optional timeouts,
1264 * parameter and result bits. This is intended to be used together
1265 * with the formatting ioctl.
1266 */
1267static int mtiocftcmd(struct mtftcmd *ftcmd, int arg_size)
1268{
1269 int i;
1270 TRACE_FUN(ft_t_flow);
1271
1272 TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCFTCMD");
1273 if (!capable(CAP_SYS_ADMIN)) {
1274 TRACE_ABORT(-EPERM, ft_t_info,
1275 "need CAP_SYS_ADMIN capability to send raw qic-117 commands");
1276 }
1277 if (zft_qic_mode) {
1278 TRACE_ABORT(-EACCES, ft_t_info,
1279 "driver needs to be in raw mode for this ioctl");
1280 }
1281 if (arg_size != sizeof(struct mtftcmd)) {
1282 TRACE_ABORT(-EINVAL,
1283 ft_t_info, "bad argument size: %d", arg_size);
1284 }
1285 if (ftcmd->ft_wait_before) {
1286 TRACE_CATCH(ftape_ready_wait(ftcmd->ft_wait_before,
1287 &ftcmd->ft_status),);
1288 }
1289 if (ftcmd->ft_status & QIC_STATUS_ERROR)
1290 goto ftmtcmd_error;
1291 if (ftcmd->ft_result_bits != 0) {
1292 TRACE_CATCH(ftape_report_operation(&ftcmd->ft_result,
1293 ftcmd->ft_cmd,
1294 ftcmd->ft_result_bits),);
1295 } else {
1296 TRACE_CATCH(ftape_command(ftcmd->ft_cmd),);
1297 if (ftcmd->ft_status & QIC_STATUS_ERROR)
1298 goto ftmtcmd_error;
1299 for (i = 0; i < ftcmd->ft_parm_cnt; i++) {
1300 TRACE_CATCH(ftape_parameter(ftcmd->ft_parms[i]&0x0f),);
1301 if (ftcmd->ft_status & QIC_STATUS_ERROR)
1302 goto ftmtcmd_error;
1303 }
1304 }
1305 if (ftcmd->ft_wait_after != 0) {
1306 TRACE_CATCH(ftape_ready_wait(ftcmd->ft_wait_after,
1307 &ftcmd->ft_status),);
1308 }
1309ftmtcmd_error:
1310 if (ftcmd->ft_status & QIC_STATUS_ERROR) {
1311 TRACE(ft_t_noise, "error status set");
1312 TRACE_CATCH(ftape_report_error(&ftcmd->ft_error,
1313 &ftcmd->ft_cmd, 1),);
1314 }
1315 TRACE_EXIT 0; /* this is not an i/o error */
1316}
1317#endif
1318
1319/* IOCTL routine called by kernel-interface code
1320 */
1321int _zft_ioctl(unsigned int command, void __user * arg)
1322{
1323 int result;
1324 union { struct mtop mtop;
1325 struct mtget mtget;
1326 struct mtpos mtpos;
1327#ifdef MTIOCRDFTSEG
1328 struct mtftseg mtftseg;
1329#endif
1330#ifdef MTIOCVOLINFO
1331 struct mtvolinfo mtvolinfo;
1332#endif
1333#ifdef MTIOCGETSIZE
1334 struct mttapesize mttapesize;
1335#endif
1336#ifdef MTIOCFTFORMAT
1337 struct mtftformat mtftformat;
1338#endif
1339#ifdef ZFT_OBSOLETE
1340 struct mtblksz mtblksz;
1341#endif
1342#ifdef MTIOCFTCMD
1343 struct mtftcmd mtftcmd;
1344#endif
1345 } krnl_arg;
1346 int arg_size = _IOC_SIZE(command);
1347 int dir = _IOC_DIR(command);
1348 TRACE_FUN(ft_t_flow);
1349
1350 /* This check will only catch arguments that are too large !
1351 */
1352 if (dir & (_IOC_READ | _IOC_WRITE) && arg_size > sizeof(krnl_arg)) {
1353 TRACE_ABORT(-EINVAL,
1354 ft_t_info, "bad argument size: %d", arg_size);
1355 }
1356 if (dir & _IOC_WRITE) {
1357 if (copy_from_user(&krnl_arg, arg, arg_size) != 0) {
1358 TRACE_EXIT -EFAULT;
1359 }
1360 }
1361 TRACE(ft_t_flow, "called with ioctl command: 0x%08x", command);
1362 switch (command) {
1363 case MTIOCTOP:
1364 result = mtioctop(&krnl_arg.mtop, arg_size);
1365 break;
1366 case MTIOCGET:
1367 result = mtiocget(&krnl_arg.mtget, arg_size);
1368 break;
1369 case MTIOCPOS:
1370 result = mtiocpos(&krnl_arg.mtpos, arg_size);
1371 break;
1372#ifdef MTIOCVOLINFO
1373 case MTIOCVOLINFO:
1374 result = mtiocvolinfo(&krnl_arg.mtvolinfo, arg_size);
1375 break;
1376#endif
1377#ifdef ZFT_OBSOLETE
1378 case MTIOC_ZFTAPE_GETBLKSZ:
1379 result = mtioc_zftape_getblksz(&krnl_arg.mtblksz, arg_size);
1380 break;
1381#endif
1382#ifdef MTIOCRDFTSEG
1383 case MTIOCRDFTSEG: /* read a segment via ioctl */
1384 result = mtiocrdftseg(&krnl_arg.mtftseg, arg_size);
1385 break;
1386#endif
1387#ifdef MTIOCWRFTSEG
1388 case MTIOCWRFTSEG: /* write a segment via ioctl */
1389 result = mtiocwrftseg(&krnl_arg.mtftseg, arg_size);
1390 break;
1391#endif
1392#ifdef MTIOCGETSIZE
1393 case MTIOCGETSIZE:
1394 result = mtiocgetsize(&krnl_arg.mttapesize, arg_size);
1395 break;
1396#endif
1397#ifdef MTIOCFTFORMAT
1398 case MTIOCFTFORMAT:
1399 result = mtiocftformat(&krnl_arg.mtftformat, arg_size);
1400 break;
1401#endif
1402#ifdef MTIOCFTCMD
1403 case MTIOCFTCMD:
1404 result = mtiocftcmd(&krnl_arg.mtftcmd, arg_size);
1405 break;
1406#endif
1407 default:
1408 result = -EINVAL;
1409 break;
1410 }
1411 if ((result >= 0) && (dir & _IOC_READ)) {
1412 if (copy_to_user(arg, &krnl_arg, arg_size) != 0) {
1413 TRACE_EXIT -EFAULT;
1414 }
1415 }
1416 TRACE_EXIT result;
1417}
diff --git a/drivers/char/ftape/zftape/zftape-ctl.h b/drivers/char/ftape/zftape/zftape-ctl.h
deleted file mode 100644
index 8e6f2d7ac74e..000000000000
--- a/drivers/char/ftape/zftape/zftape-ctl.h
+++ /dev/null
@@ -1,58 +0,0 @@
1#ifndef _ZFTAPE_CTL_H
2#define _ZFTAPE_CTL_H
3
4/*
5 * Copyright (C) 1996, 1997 Claus-Justus Heine.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; see the file COPYING. If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
20
21 *
22 * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-ctl.h,v $
23 * $Revision: 1.2 $
24 * $Date: 1997/10/05 19:19:02 $
25 *
26 * This file contains the non-standard IOCTL related definitions
27 * for the QIC-40/80 floppy-tape driver for Linux.
28 */
29
30#include <linux/ioctl.h>
31#include <linux/mtio.h>
32
33#include "../zftape/zftape-rw.h"
34
35#ifdef CONFIG_ZFTAPE_MODULE
36#define ftape_status (*zft_status)
37#endif
38
39extern int zft_offline;
40extern int zft_mt_compression;
41extern int zft_write_protected;
42extern int zft_header_read;
43extern unsigned int zft_unit;
44extern int zft_resid;
45
46extern void zft_reset_position(zft_position *pos);
47extern int zft_check_write_access(zft_position *pos);
48extern int zft_def_idle_state(void);
49
50/* hooks for the VFS interface
51 */
52extern int _zft_open(unsigned int dev_minor, unsigned int access_mode);
53extern int _zft_close(void);
54extern int _zft_ioctl(unsigned int command, void __user *arg);
55#endif
56
57
58
diff --git a/drivers/char/ftape/zftape/zftape-eof.c b/drivers/char/ftape/zftape/zftape-eof.c
deleted file mode 100644
index dcadcaee9ac1..000000000000
--- a/drivers/char/ftape/zftape/zftape-eof.c
+++ /dev/null
@@ -1,199 +0,0 @@
1/*
2 * I use these routines just to decide when I have to fake a
3 * volume-table to preserve compatibility to original ftape.
4 */
5/*
6 * Copyright (C) 1994-1995 Bas Laarhoven.
7 *
8 * Modified for zftape 1996, 1997 Claus Heine.
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
13 any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; see the file COPYING. If not, write to
22 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23
24 * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-eof.c,v $
25 * $Revision: 1.2 $
26 * $Date: 1997/10/05 19:19:02 $
27 *
28 * This file contains the eof mark handling code
29 * for the QIC-40/80 floppy-tape driver for Linux.
30 */
31
32#include <linux/string.h>
33#include <linux/errno.h>
34
35#include <linux/zftape.h>
36
37#include "../zftape/zftape-init.h"
38#include "../zftape/zftape-rw.h"
39#include "../zftape/zftape-eof.h"
40
41/* Global vars.
42 */
43
44/* a copy of the failed sector log from the header segment.
45 */
46eof_mark_union *zft_eof_map;
47
48/* number of eof marks (entries in bad sector log) on tape.
49 */
50int zft_nr_eof_marks = -1;
51
52
53/* Local vars.
54 */
55
56static char linux_tape_label[] = "Linux raw format V";
57enum {
58 min_fmt_version = 1, max_fmt_version = 2
59};
60static unsigned ftape_fmt_version = 0;
61
62
63/* Ftape (mis)uses the bad sector log to record end-of-file marks.
64 * Initially (when the tape is erased) all entries in the bad sector
65 * log are added to the tape's bad sector map. The bad sector log then
66 * is cleared.
67 *
68 * The bad sector log normally contains entries of the form:
69 * even 16-bit word: segment number of bad sector
70 * odd 16-bit word: encoded date
71 * There can be a total of 448 entries (1792 bytes).
72 *
73 * My guess is that no program is using this bad sector log (the *
74 * format seems useless as there is no indication of the bad sector
75 * itself, only the segment) However, if any program does use the bad
76 * sector log, the format used by ftape will let the program think
77 * there are some bad sectors and no harm is done.
78 *
79 * The eof mark entries that ftape stores in the bad sector log: even
80 * 16-bit word: segment number of eof mark odd 16-bit word: sector
81 * number of eof mark [1..32]
82 *
83 * The zft_eof_map as maintained is a sorted list of eof mark entries.
84 *
85 *
86 * The tape name field in the header segments is used to store a linux
87 * tape identification string and a version number. This way the tape
88 * can be recognized as a Linux raw format tape when using tools under
89 * other OS's.
90 *
91 * 'Wide' QIC tapes (format code 4) don't have a failed sector list
92 * anymore. That space is used for the (longer) bad sector map that
93 * now is a variable length list too. We now store our end-of-file
94 * marker list after the bad-sector-map on tape. The list is delimited
95 * by a (__u32) 0 entry.
96 */
97
98int zft_ftape_validate_label(char *label)
99{
100 static char tmp_label[45];
101 int result = 0;
102 TRACE_FUN(ft_t_any);
103
104 memcpy(tmp_label, label, FT_LABEL_SZ);
105 tmp_label[FT_LABEL_SZ] = '\0';
106 TRACE(ft_t_noise, "tape label = `%s'", tmp_label);
107 ftape_fmt_version = 0;
108 if (memcmp(label, linux_tape_label, strlen(linux_tape_label)) == 0) {
109 int pos = strlen(linux_tape_label);
110 while (label[pos] >= '0' && label[pos] <= '9') {
111 ftape_fmt_version *= 10;
112 ftape_fmt_version = label[ pos++] - '0';
113 }
114 result = (ftape_fmt_version >= min_fmt_version &&
115 ftape_fmt_version <= max_fmt_version);
116 }
117 TRACE(ft_t_noise, "format version = %d", ftape_fmt_version);
118 TRACE_EXIT result;
119}
120
121static __u8 * find_end_of_eof_list(__u8 * ptr, __u8 * limit)
122{
123 while (ptr + 3 < limit) {
124
125 if (get_unaligned((__u32*)ptr)) {
126 ptr += sizeof(__u32);
127 } else {
128 return ptr;
129 }
130 }
131 return NULL;
132}
133
134void zft_ftape_extract_file_marks(__u8* address)
135{
136 int i;
137 TRACE_FUN(ft_t_any);
138
139 zft_eof_map = NULL;
140 if (ft_format_code == fmt_var || ft_format_code == fmt_big) {
141 __u8* end;
142 __u8* start = ftape_find_end_of_bsm_list(address);
143
144 zft_nr_eof_marks = 0;
145 if (start) {
146 start += 3; /* skip end of list mark */
147 end = find_end_of_eof_list(start,
148 address + FT_SEGMENT_SIZE);
149 if (end && end - start <= FT_FSL_SIZE) {
150 zft_nr_eof_marks = ((end - start) /
151 sizeof(eof_mark_union));
152 zft_eof_map = (eof_mark_union *)start;
153 } else {
154 TRACE(ft_t_err,
155 "EOF Mark List is too long or damaged!");
156 }
157 } else {
158 TRACE(ft_t_err,
159 "Bad Sector List is too long or damaged !");
160 }
161 } else {
162 zft_eof_map = (eof_mark_union *)&address[FT_FSL];
163 zft_nr_eof_marks = GET2(address, FT_FSL_CNT);
164 }
165 TRACE(ft_t_noise, "number of file marks: %d", zft_nr_eof_marks);
166 if (ftape_fmt_version == 1) {
167 TRACE(ft_t_info, "swapping version 1 fields");
168 /* version 1 format uses swapped sector and segment
169 * fields, correct that !
170 */
171 for (i = 0; i < zft_nr_eof_marks; ++i) {
172 __u16 tmp = GET2(&zft_eof_map[i].mark.segment,0);
173 PUT2(&zft_eof_map[i].mark.segment, 0,
174 GET2(&zft_eof_map[i].mark.date,0));
175 PUT2(&zft_eof_map[i].mark.date, 0, tmp);
176 }
177 }
178 for (i = 0; i < zft_nr_eof_marks; ++i) {
179 TRACE(ft_t_noise, "eof mark: %5d/%2d",
180 GET2(&zft_eof_map[i].mark.segment, 0),
181 GET2(&zft_eof_map[i].mark.date,0));
182 }
183 TRACE_EXIT;
184}
185
186void zft_clear_ftape_file_marks(void)
187{
188 TRACE_FUN(ft_t_flow);
189 /* Clear failed sector log: remove all tape marks. We
190 * don't use old ftape-style EOF-marks.
191 */
192 TRACE(ft_t_info, "Clearing old ftape's eof map");
193 memset(zft_eof_map, 0, zft_nr_eof_marks * sizeof(__u32));
194 zft_nr_eof_marks = 0;
195 PUT2(zft_hseg_buf, FT_FSL_CNT, 0); /* nr of eof-marks */
196 zft_header_changed = 1;
197 zft_update_label(zft_hseg_buf);
198 TRACE_EXIT;
199}
diff --git a/drivers/char/ftape/zftape/zftape-eof.h b/drivers/char/ftape/zftape/zftape-eof.h
deleted file mode 100644
index 26568c26c518..000000000000
--- a/drivers/char/ftape/zftape/zftape-eof.h
+++ /dev/null
@@ -1,52 +0,0 @@
1#ifndef _ZFTAPE_EOF_H
2#define _ZFTAPE_EOF_H
3
4/*
5 * Copyright (C) 1994-1995 Bas Laarhoven.
6 * adaptaed for zftape 1996, 1997 by Claus Heine
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; see the file COPYING. If not, write to
20 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 *
23 * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-eof.h,v $
24 * $Revision: 1.2 $
25 * $Date: 1997/10/05 19:19:03 $
26 *
27 * Definitions and declarations for the end of file markers
28 * for the QIC-40/80 floppy-tape driver for Linux.
29 */
30
31#include <linux/ftape-header-segment.h>
32#include "../zftape/zftape-buffers.h"
33/* failed sector log size (only used if format code != 4).
34 */
35
36typedef union {
37 ft_fsl_entry mark;
38 __u32 entry;
39} eof_mark_union;
40
41/* ftape-eof.c defined global vars.
42 */
43extern int zft_nr_eof_marks;
44extern eof_mark_union *zft_eof_map;
45
46/* ftape-eof.c defined global functions.
47 */
48extern void zft_ftape_extract_file_marks(__u8* address);
49extern int zft_ftape_validate_label(char* label);
50extern void zft_clear_ftape_file_marks(void);
51
52#endif
diff --git a/drivers/char/ftape/zftape/zftape-init.c b/drivers/char/ftape/zftape/zftape-init.c
deleted file mode 100644
index 164a1aa77a2f..000000000000
--- a/drivers/char/ftape/zftape/zftape-init.c
+++ /dev/null
@@ -1,377 +0,0 @@
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 * This file contains the code that registers the zftape frontend
20 * to the ftape floppy tape driver for Linux
21 */
22
23#include <linux/module.h>
24#include <linux/errno.h>
25#include <linux/fs.h>
26#include <linux/kernel.h>
27#include <linux/signal.h>
28#include <linux/major.h>
29#include <linux/slab.h>
30#ifdef CONFIG_KMOD
31#include <linux/kmod.h>
32#endif
33#include <linux/fcntl.h>
34#include <linux/smp_lock.h>
35
36#include <linux/zftape.h>
37#include <linux/init.h>
38#include <linux/device.h>
39
40#include "../zftape/zftape-init.h"
41#include "../zftape/zftape-read.h"
42#include "../zftape/zftape-write.h"
43#include "../zftape/zftape-ctl.h"
44#include "../zftape/zftape-buffers.h"
45
46MODULE_AUTHOR("(c) 1996, 1997 Claus-Justus Heine "
47 "(claus@momo.math.rwth-aachen.de)");
48MODULE_DESCRIPTION(ZFTAPE_VERSION " - "
49 "VFS interface for the Linux floppy tape driver. "
50 "Support for QIC-113 compatible volume table "
51 "and builtin compression (lzrw3 algorithm)");
52MODULE_SUPPORTED_DEVICE("char-major-27");
53MODULE_LICENSE("GPL");
54
55/* Global vars.
56 */
57struct zft_cmpr_ops *zft_cmpr_ops = NULL;
58const ftape_info *zft_status;
59
60/* Local vars.
61 */
62static unsigned long busy_flag;
63
64static sigset_t orig_sigmask;
65
66/* the interface to the kernel vfs layer
67 */
68
69/* Note about llseek():
70 *
71 * st.c and tpqic.c update fp->f_pos but don't implment llseek() and
72 * initialize the llseek component of the file_ops struct with NULL.
73 * This means that the user will get the default seek, but the tape
74 * device will not respect the new position, but happily read from the
75 * old position. Think a zftape specific llseek() function would be
76 * better, returning -ESPIPE. TODO.
77 */
78
79static int zft_open (struct inode *ino, struct file *filep);
80static int zft_close(struct inode *ino, struct file *filep);
81static int zft_ioctl(struct inode *ino, struct file *filep,
82 unsigned int command, unsigned long arg);
83static int zft_mmap(struct file *filep, struct vm_area_struct *vma);
84static ssize_t zft_read (struct file *fp, char __user *buff,
85 size_t req_len, loff_t *ppos);
86static ssize_t zft_write(struct file *fp, const char __user *buff,
87 size_t req_len, loff_t *ppos);
88
89static const struct file_operations zft_cdev =
90{
91 .owner = THIS_MODULE,
92 .read = zft_read,
93 .write = zft_write,
94 .ioctl = zft_ioctl,
95 .mmap = zft_mmap,
96 .open = zft_open,
97 .release = zft_close,
98};
99
100static struct class *zft_class;
101
102/* Open floppy tape device
103 */
104static int zft_open(struct inode *ino, struct file *filep)
105{
106 int result;
107 TRACE_FUN(ft_t_flow);
108
109 nonseekable_open(ino, filep);
110 TRACE(ft_t_flow, "called for minor %d", iminor(ino));
111 if ( test_and_set_bit(0,&busy_flag) ) {
112 TRACE_ABORT(-EBUSY, ft_t_warn, "failed: already busy");
113 }
114 if ((iminor(ino) & ~(ZFT_MINOR_OP_MASK | FTAPE_NO_REWIND))
115 >
116 FTAPE_SEL_D) {
117 clear_bit(0,&busy_flag);
118 TRACE_ABORT(-ENXIO, ft_t_err, "failed: invalid unit nr");
119 }
120 orig_sigmask = current->blocked;
121 sigfillset(&current->blocked);
122 result = _zft_open(iminor(ino), filep->f_flags & O_ACCMODE);
123 if (result < 0) {
124 current->blocked = orig_sigmask; /* restore mask */
125 clear_bit(0,&busy_flag);
126 TRACE_ABORT(result, ft_t_err, "_ftape_open failed");
127 } else {
128 /* Mask signals that will disturb proper operation of the
129 * program that is calling.
130 */
131 current->blocked = orig_sigmask;
132 sigaddsetmask (&current->blocked, _DO_BLOCK);
133 TRACE_EXIT 0;
134 }
135}
136
137/* Close floppy tape device
138 */
139static int zft_close(struct inode *ino, struct file *filep)
140{
141 int result;
142 TRACE_FUN(ft_t_flow);
143
144 if ( !test_bit(0,&busy_flag) || iminor(ino) != zft_unit) {
145 TRACE(ft_t_err, "failed: not busy or wrong unit");
146 TRACE_EXIT 0;
147 }
148 sigfillset(&current->blocked);
149 result = _zft_close();
150 if (result < 0) {
151 TRACE(ft_t_err, "_zft_close failed");
152 }
153 current->blocked = orig_sigmask; /* restore before open state */
154 clear_bit(0,&busy_flag);
155 TRACE_EXIT 0;
156}
157
158/* Ioctl for floppy tape device
159 */
160static int zft_ioctl(struct inode *ino, struct file *filep,
161 unsigned int command, unsigned long arg)
162{
163 int result = -EIO;
164 sigset_t old_sigmask;
165 TRACE_FUN(ft_t_flow);
166
167 if ( !test_bit(0,&busy_flag) || iminor(ino) != zft_unit || ft_failure) {
168 TRACE_ABORT(-EIO, ft_t_err,
169 "failed: not busy, failure or wrong unit");
170 }
171 old_sigmask = current->blocked; /* save mask */
172 sigfillset(&current->blocked);
173 /* This will work as long as sizeof(void *) == sizeof(long) */
174 result = _zft_ioctl(command, (void __user *) arg);
175 current->blocked = old_sigmask; /* restore mask */
176 TRACE_EXIT result;
177}
178
179/* Ioctl for floppy tape device
180 */
181static int zft_mmap(struct file *filep, struct vm_area_struct *vma)
182{
183 int result = -EIO;
184 sigset_t old_sigmask;
185 TRACE_FUN(ft_t_flow);
186
187 if ( !test_bit(0,&busy_flag) ||
188 iminor(filep->f_dentry->d_inode) != zft_unit ||
189 ft_failure)
190 {
191 TRACE_ABORT(-EIO, ft_t_err,
192 "failed: not busy, failure or wrong unit");
193 }
194 old_sigmask = current->blocked; /* save mask */
195 sigfillset(&current->blocked);
196 if ((result = ftape_mmap(vma)) >= 0) {
197#ifndef MSYNC_BUG_WAS_FIXED
198 static struct vm_operations_struct dummy = { NULL, };
199 vma->vm_ops = &dummy;
200#endif
201 }
202 current->blocked = old_sigmask; /* restore mask */
203 TRACE_EXIT result;
204}
205
206/* Read from floppy tape device
207 */
208static ssize_t zft_read(struct file *fp, char __user *buff,
209 size_t req_len, loff_t *ppos)
210{
211 int result = -EIO;
212 sigset_t old_sigmask;
213 struct inode *ino = fp->f_dentry->d_inode;
214 TRACE_FUN(ft_t_flow);
215
216 TRACE(ft_t_data_flow, "called with count: %ld", (unsigned long)req_len);
217 if (!test_bit(0,&busy_flag) || iminor(ino) != zft_unit || ft_failure) {
218 TRACE_ABORT(-EIO, ft_t_err,
219 "failed: not busy, failure or wrong unit");
220 }
221 old_sigmask = current->blocked; /* save mask */
222 sigfillset(&current->blocked);
223 result = _zft_read(buff, req_len);
224 current->blocked = old_sigmask; /* restore mask */
225 TRACE(ft_t_data_flow, "return with count: %d", result);
226 TRACE_EXIT result;
227}
228
229/* Write to tape device
230 */
231static ssize_t zft_write(struct file *fp, const char __user *buff,
232 size_t req_len, loff_t *ppos)
233{
234 int result = -EIO;
235 sigset_t old_sigmask;
236 struct inode *ino = fp->f_dentry->d_inode;
237 TRACE_FUN(ft_t_flow);
238
239 TRACE(ft_t_flow, "called with count: %ld", (unsigned long)req_len);
240 if (!test_bit(0,&busy_flag) || iminor(ino) != zft_unit || ft_failure) {
241 TRACE_ABORT(-EIO, ft_t_err,
242 "failed: not busy, failure or wrong unit");
243 }
244 old_sigmask = current->blocked; /* save mask */
245 sigfillset(&current->blocked);
246 result = _zft_write(buff, req_len);
247 current->blocked = old_sigmask; /* restore mask */
248 TRACE(ft_t_data_flow, "return with count: %d", result);
249 TRACE_EXIT result;
250}
251
252/* END OF VFS INTERFACE
253 *
254 *****************************************************************************/
255
256/* driver/module initialization
257 */
258
259/* the compression module has to call this function to hook into the zftape
260 * code
261 */
262int zft_cmpr_register(struct zft_cmpr_ops *new_ops)
263{
264 TRACE_FUN(ft_t_flow);
265
266 if (zft_cmpr_ops != NULL) {
267 TRACE_EXIT -EBUSY;
268 } else {
269 zft_cmpr_ops = new_ops;
270 TRACE_EXIT 0;
271 }
272}
273
274/* lock the zft-compressor() module.
275 */
276int zft_cmpr_lock(int try_to_load)
277{
278 if (zft_cmpr_ops == NULL) {
279#ifdef CONFIG_KMOD
280 if (try_to_load) {
281 request_module("zft-compressor");
282 if (zft_cmpr_ops == NULL) {
283 return -ENOSYS;
284 }
285 } else {
286 return -ENOSYS;
287 }
288#else
289 return -ENOSYS;
290#endif
291 }
292 (*zft_cmpr_ops->lock)();
293 return 0;
294}
295
296#ifdef CONFIG_ZFT_COMPRESSOR
297extern int zft_compressor_init(void);
298#endif
299
300/* Called by modules package when installing the driver or by kernel
301 * during the initialization phase
302 */
303int __init zft_init(void)
304{
305 int i;
306 TRACE_FUN(ft_t_flow);
307
308#ifdef MODULE
309 printk(KERN_INFO ZFTAPE_VERSION "\n");
310 if (TRACE_LEVEL >= ft_t_info) {
311 printk(
312KERN_INFO
313"(c) 1996, 1997 Claus-Justus Heine (claus@momo.math.rwth-aachen.de)\n"
314KERN_INFO
315"vfs interface for ftape floppy tape driver.\n"
316KERN_INFO
317"Support for QIC-113 compatible volume table, dynamic memory allocation\n"
318KERN_INFO
319"and builtin compression (lzrw3 algorithm).\n");
320 }
321#else /* !MODULE */
322 /* print a short no-nonsense boot message */
323 printk(KERN_INFO ZFTAPE_VERSION "\n");
324#endif /* MODULE */
325 TRACE(ft_t_info, "zft_init @ 0x%p", zft_init);
326 TRACE(ft_t_info,
327 "installing zftape VFS interface for ftape driver ...");
328 TRACE_CATCH(register_chrdev(QIC117_TAPE_MAJOR, "zft", &zft_cdev),);
329
330 zft_class = class_create(THIS_MODULE, "zft");
331 for (i = 0; i < 4; i++) {
332 class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i), NULL, "qft%i", i);
333 class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 4), NULL, "nqft%i", i);
334 class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 16), NULL, "zqft%i", i);
335 class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 20), NULL, "nzqft%i", i);
336 class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 32), NULL, "rawqft%i", i);
337 class_device_create(zft_class, NULL, MKDEV(QIC117_TAPE_MAJOR, i + 36), NULL, "nrawrawqft%i", i);
338 }
339
340#ifdef CONFIG_ZFT_COMPRESSOR
341 (void)zft_compressor_init();
342#endif
343 zft_status = ftape_get_status(); /* fetch global data of ftape
344 * hardware driver
345 */
346 TRACE_EXIT 0;
347}
348
349
350/* Called by modules package when removing the driver
351 */
352static void zft_exit(void)
353{
354 int i;
355 TRACE_FUN(ft_t_flow);
356
357 if (unregister_chrdev(QIC117_TAPE_MAJOR, "zft") != 0) {
358 TRACE(ft_t_warn, "failed");
359 } else {
360 TRACE(ft_t_info, "successful");
361 }
362 for (i = 0; i < 4; i++) {
363 class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i));
364 class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 4));
365 class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 16));
366 class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 20));
367 class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 32));
368 class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 36));
369 }
370 class_destroy(zft_class);
371 zft_uninit_mem(); /* release remaining memory, if any */
372 printk(KERN_INFO "zftape successfully unloaded.\n");
373 TRACE_EXIT;
374}
375
376module_init(zft_init);
377module_exit(zft_exit);
diff --git a/drivers/char/ftape/zftape/zftape-init.h b/drivers/char/ftape/zftape/zftape-init.h
deleted file mode 100644
index 937e5d48c20e..000000000000
--- a/drivers/char/ftape/zftape/zftape-init.h
+++ /dev/null
@@ -1,77 +0,0 @@
1#ifndef _ZFTAPE_INIT_H
2#define _ZFTAPE_INIT_H
3
4/*
5 * Copyright (C) 1996, 1997 Claus Heine.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; see the file COPYING. If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
20
21 *
22 * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-init.h,v $
23 * $Revision: 1.2 $
24 * $Date: 1997/10/05 19:19:05 $
25 *
26 * This file contains definitions and macro for the vfs
27 * interface defined by zftape
28 *
29 */
30
31#include <linux/ftape-header-segment.h>
32
33#include "../lowlevel/ftape-tracing.h"
34#include "../lowlevel/ftape-ctl.h"
35#include "../lowlevel/ftape-read.h"
36#include "../lowlevel/ftape-write.h"
37#include "../lowlevel/ftape-bsm.h"
38#include "../lowlevel/ftape-io.h"
39#include "../lowlevel/ftape-buffer.h"
40#include "../lowlevel/ftape-format.h"
41
42#include "../zftape/zftape-rw.h"
43
44#ifdef MODULE
45#define ftape_status (*zft_status)
46#endif
47
48extern const ftape_info *zft_status; /* needed for zftape-vtbl.h */
49
50#include "../zftape/zftape-vtbl.h"
51
52struct zft_cmpr_ops {
53 int (*write)(int *write_cnt,
54 __u8 *dst_buf, const int seg_sz,
55 const __u8 __user *src_buf, const int req_len,
56 const zft_position *pos, const zft_volinfo *volume);
57 int (*read)(int *read_cnt,
58 __u8 __user *dst_buf, const int req_len,
59 const __u8 *src_buf, const int seg_sz,
60 const zft_position *pos, const zft_volinfo *volume);
61 int (*seek)(unsigned int new_block_pos,
62 zft_position *pos, const zft_volinfo *volume,
63 __u8 *buffer);
64 void (*lock) (void);
65 void (*reset) (void);
66 void (*cleanup)(void);
67};
68
69extern struct zft_cmpr_ops *zft_cmpr_ops;
70/* zftape-init.c defined global functions.
71 */
72extern int zft_cmpr_register(struct zft_cmpr_ops *new_ops);
73extern int zft_cmpr_lock(int try_to_load);
74
75#endif
76
77
diff --git a/drivers/char/ftape/zftape/zftape-read.c b/drivers/char/ftape/zftape/zftape-read.c
deleted file mode 100644
index 214bf03dce68..000000000000
--- a/drivers/char/ftape/zftape/zftape-read.c
+++ /dev/null
@@ -1,377 +0,0 @@
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-read.c,v $
20 * $Revision: 1.2 $
21 * $Date: 1997/10/05 19:19:06 $
22 *
23 * This file contains the high level reading code
24 * for the QIC-117 floppy-tape driver for Linux.
25 */
26
27#include <linux/errno.h>
28#include <linux/mm.h>
29
30#include <linux/zftape.h>
31
32#include <asm/uaccess.h>
33
34#include "../zftape/zftape-init.h"
35#include "../zftape/zftape-eof.h"
36#include "../zftape/zftape-ctl.h"
37#include "../zftape/zftape-write.h"
38#include "../zftape/zftape-read.h"
39#include "../zftape/zftape-rw.h"
40#include "../zftape/zftape-vtbl.h"
41
42/* Global vars.
43 */
44int zft_just_before_eof;
45
46/* Local vars.
47 */
48static int buf_len_rd;
49
50void zft_zap_read_buffers(void)
51{
52 buf_len_rd = 0;
53}
54
55int zft_read_header_segments(void)
56{
57 TRACE_FUN(ft_t_flow);
58
59 zft_header_read = 0;
60 TRACE_CATCH(zft_vmalloc_once(&zft_hseg_buf, FT_SEGMENT_SIZE),);
61 TRACE_CATCH(ftape_read_header_segment(zft_hseg_buf),);
62 TRACE(ft_t_info, "Segments written since first format: %d",
63 (int)GET4(zft_hseg_buf, FT_SEG_CNT));
64 zft_qic113 = (ft_format_code != fmt_normal &&
65 ft_format_code != fmt_1100ft &&
66 ft_format_code != fmt_425ft);
67 TRACE(ft_t_info, "ft_first_data_segment: %d, ft_last_data_segment: %d",
68 ft_first_data_segment, ft_last_data_segment);
69 zft_capacity = zft_get_capacity();
70 zft_old_ftape = zft_ftape_validate_label(&zft_hseg_buf[FT_LABEL]);
71 if (zft_old_ftape) {
72 TRACE(ft_t_info,
73"Found old ftaped tape, emulating eof marks, entering read-only mode");
74 zft_ftape_extract_file_marks(zft_hseg_buf);
75 TRACE_CATCH(zft_fake_volume_headers(zft_eof_map,
76 zft_nr_eof_marks),);
77 } else {
78 /* the specs say that the volume table must be
79 * initialized with zeroes during formatting, so it
80 * MUST be readable, i.e. contain vaid ECC
81 * information.
82 */
83 TRACE_CATCH(ftape_read_segment(ft_first_data_segment,
84 zft_deblock_buf,
85 FT_RD_SINGLE),);
86 TRACE_CATCH(zft_extract_volume_headers(zft_deblock_buf),);
87 }
88 zft_header_read = 1;
89 zft_set_flags(zft_unit);
90 zft_reset_position(&zft_pos);
91 TRACE_EXIT 0;
92}
93
94int zft_fetch_segment_fraction(const unsigned int segment, void *buffer,
95 const ft_read_mode_t read_mode,
96 const unsigned int start,
97 const unsigned int size)
98{
99 int seg_sz;
100 TRACE_FUN(ft_t_flow);
101
102 if (segment == zft_deblock_segment) {
103 TRACE(ft_t_data_flow,
104 "re-using segment %d already in deblock buffer",
105 segment);
106 seg_sz = zft_get_seg_sz(segment);
107 if (start > seg_sz) {
108 TRACE_ABORT(-EINVAL, ft_t_bug,
109 "trying to read beyond end of segment:\n"
110 KERN_INFO "seg_sz : %d\n"
111 KERN_INFO "start : %d\n"
112 KERN_INFO "segment: %d",
113 seg_sz, start, segment);
114 }
115 if ((start + size) > seg_sz) {
116 TRACE_EXIT seg_sz - start;
117 }
118 TRACE_EXIT size;
119 }
120 seg_sz = ftape_read_segment_fraction(segment, buffer, read_mode,
121 start, size);
122 TRACE(ft_t_data_flow, "segment %d, result %d", segment, seg_sz);
123 if ((int)seg_sz >= 0 && start == 0 && size == FT_SEGMENT_SIZE) {
124 /* this implicitly assumes that we are always called with
125 * buffer == zft_deblock_buf
126 */
127 zft_deblock_segment = segment;
128 } else {
129 zft_deblock_segment = -1;
130 }
131 TRACE_EXIT seg_sz;
132}
133
134/*
135 * out:
136 *
137 * int *read_cnt: the number of bytes we removed from the
138 * zft_deblock_buf (result)
139 *
140 * int *to_do : the remaining size of the read-request. Is changed.
141 *
142 * in:
143 *
144 * char *buff : buff is the address of the upper part of the user
145 * buffer, that hasn't been filled with data yet.
146 * int buf_pos_read: copy of buf_pos_rd
147 * int buf_len_read: copy of buf_len_rd
148 * char *zft_deblock_buf: ftape_zft_deblock_buf
149 *
150 * returns the amount of data actually copied to the user-buffer
151 *
152 * to_do MUST NOT SHRINK except to indicate an EOT. In this case to_do
153 * has to be set to 0. We cannot return -ENOSPC, because we return the
154 * amount of data actually * copied to the user-buffer
155 */
156static int zft_simple_read (int *read_cnt,
157 __u8 __user *dst_buf,
158 const int to_do,
159 const __u8 *src_buf,
160 const int seg_sz,
161 const zft_position *pos,
162 const zft_volinfo *volume)
163{
164 TRACE_FUN(ft_t_flow);
165
166 if (seg_sz - pos->seg_byte_pos < to_do) {
167 *read_cnt = seg_sz - pos->seg_byte_pos;
168 } else {
169 *read_cnt = to_do;
170 }
171 if (copy_to_user(dst_buf,
172 src_buf + pos->seg_byte_pos, *read_cnt) != 0) {
173 TRACE_EXIT -EFAULT;
174 }
175 TRACE(ft_t_noise, "nr bytes just read: %d", *read_cnt);
176 TRACE_EXIT *read_cnt;
177}
178
179/* req_len: gets clipped due to EOT of EOF.
180 * req_clipped: is a flag indicating whether req_len was clipped or not
181 * volume: contains information on current volume (blk_sz etc.)
182 */
183static int check_read_access(int *req_len,
184 const zft_volinfo **volume,
185 int *req_clipped,
186 const zft_position *pos)
187{
188 static __s64 remaining;
189 static int eod;
190 TRACE_FUN(ft_t_flow);
191
192 if (zft_io_state != zft_reading) {
193 if (zft_offline) { /* offline includes no_tape */
194 TRACE_ABORT(-ENXIO, ft_t_warn,
195 "tape is offline or no cartridge");
196 }
197 if (!ft_formatted) {
198 TRACE_ABORT(-EACCES,
199 ft_t_warn, "tape is not formatted");
200 }
201 /* now enter defined state, read header segment if not
202 * already done and flush write buffers
203 */
204 TRACE_CATCH(zft_def_idle_state(),);
205 zft_io_state = zft_reading;
206 if (zft_tape_at_eod(pos)) {
207 eod = 1;
208 TRACE_EXIT 1;
209 }
210 eod = 0;
211 *volume = zft_find_volume(pos->seg_pos);
212 /* get the space left until EOF */
213 remaining = zft_check_for_eof(*volume, pos);
214 buf_len_rd = 0;
215 TRACE(ft_t_noise, "remaining: " LL_X ", vol_no: %d",
216 LL(remaining), (*volume)->count);
217 } else if (zft_tape_at_eod(pos)) {
218 if (++eod > 2) {
219 TRACE_EXIT -EIO; /* st.c also returns -EIO */
220 } else {
221 TRACE_EXIT 1;
222 }
223 }
224 if ((*req_len % (*volume)->blk_sz) != 0) {
225 /* this message is informational only. The user gets the
226 * proper return value
227 */
228 TRACE_ABORT(-EINVAL, ft_t_info,
229 "req_len %d not a multiple of block size %d",
230 *req_len, (*volume)->blk_sz);
231 }
232 /* As GNU tar doesn't accept partial read counts when the
233 * multiple volume flag is set, we make sure to return the
234 * requested amount of data. Except, of course, at the end of
235 * the tape or file mark.
236 */
237 remaining -= *req_len;
238 if (remaining <= 0) {
239 TRACE(ft_t_noise,
240 "clipped request from %d to %d.",
241 *req_len, (int)(*req_len + remaining));
242 *req_len += remaining;
243 *req_clipped = 1;
244 } else {
245 *req_clipped = 0;
246 }
247 TRACE_EXIT 0;
248}
249
250/* this_segs_size: the current segment's size.
251 * buff: the USER-SPACE buffer provided by the calling function.
252 * req_len: how much data should be read at most.
253 * volume: contains information on current volume (blk_sz etc.)
254 */
255static int empty_deblock_buf(__u8 __user *usr_buf, const int req_len,
256 const __u8 *src_buf, const int seg_sz,
257 zft_position *pos,
258 const zft_volinfo *volume)
259{
260 int cnt;
261 int result = 0;
262 TRACE_FUN(ft_t_flow);
263
264 TRACE(ft_t_data_flow, "this_segs_size: %d", seg_sz);
265 if (zft_use_compression && volume->use_compression) {
266 TRACE_CATCH(zft_cmpr_lock(1 /* try to load */),);
267 TRACE_CATCH(result= (*zft_cmpr_ops->read)(&cnt,
268 usr_buf, req_len,
269 src_buf, seg_sz,
270 pos, volume),);
271 } else {
272 TRACE_CATCH(result= zft_simple_read (&cnt,
273 usr_buf, req_len,
274 src_buf, seg_sz,
275 pos, volume),);
276 }
277 pos->volume_pos += result;
278 pos->tape_pos += cnt;
279 pos->seg_byte_pos += cnt;
280 buf_len_rd -= cnt; /* remaining bytes in buffer */
281 TRACE(ft_t_data_flow, "buf_len_rd: %d, cnt: %d", buf_len_rd, cnt);
282 if(pos->seg_byte_pos >= seg_sz) {
283 pos->seg_pos++;
284 pos->seg_byte_pos = 0;
285 }
286 TRACE(ft_t_data_flow, "bytes moved out of deblock-buffer: %d", cnt);
287 TRACE_EXIT result;
288}
289
290
291/* note: we store the segment id of the segment that is inside the
292 * deblock buffer. This spares a lot of ftape_read_segment()s when we
293 * use small block-sizes. The block-size may be 1kb (SECTOR_SIZE). In
294 * this case a MTFSR 28 maybe still inside the same segment.
295 */
296int _zft_read(char __user *buff, int req_len)
297{
298 int req_clipped;
299 int result = 0;
300 int bytes_read = 0;
301 static unsigned int seg_sz = 0;
302 static const zft_volinfo *volume = NULL;
303 TRACE_FUN(ft_t_flow);
304
305 zft_resid = req_len;
306 result = check_read_access(&req_len, &volume,
307 &req_clipped, &zft_pos);
308 switch(result) {
309 case 0:
310 break; /* nothing special */
311 case 1:
312 TRACE(ft_t_noise, "EOD reached");
313 TRACE_EXIT 0; /* EOD */
314 default:
315 TRACE_ABORT(result, ft_t_noise,
316 "check_read_access() failed with result %d",
317 result);
318 TRACE_EXIT result;
319 }
320 while (req_len > 0) {
321 /* Allow escape from this loop on signal !
322 */
323 FT_SIGNAL_EXIT(_DONT_BLOCK);
324 /* buf_len_rd == 0 means that we need to read a new
325 * segment.
326 */
327 if (buf_len_rd == 0) {
328 while((result = zft_fetch_segment(zft_pos.seg_pos,
329 zft_deblock_buf,
330 FT_RD_AHEAD)) == 0) {
331 zft_pos.seg_pos ++;
332 zft_pos.seg_byte_pos = 0;
333 }
334 if (result < 0) {
335 zft_resid -= bytes_read;
336 TRACE_ABORT(result, ft_t_noise,
337 "zft_fetch_segment(): %d",
338 result);
339 }
340 seg_sz = result;
341 buf_len_rd = seg_sz - zft_pos.seg_byte_pos;
342 }
343 TRACE_CATCH(result = empty_deblock_buf(buff,
344 req_len,
345 zft_deblock_buf,
346 seg_sz,
347 &zft_pos,
348 volume),
349 zft_resid -= bytes_read);
350 TRACE(ft_t_data_flow, "bytes just read: %d", result);
351 bytes_read += result; /* what we got so far */
352 buff += result; /* index in user-buffer */
353 req_len -= result; /* what's left from req_len */
354 } /* while (req_len > 0) */
355 if (req_clipped) {
356 TRACE(ft_t_data_flow,
357 "maybe partial count because of eof mark");
358 if (zft_just_before_eof && bytes_read == 0) {
359 /* req_len was > 0, but user didn't get
360 * anything the user has read in the eof-mark
361 */
362 zft_move_past_eof(&zft_pos);
363 ftape_abort_operation();
364 } else {
365 /* don't skip to the next file before the user
366 * tried to read a second time past EOF Just
367 * mark that we are at EOF and maybe decrement
368 * zft_seg_pos to stay in the same volume;
369 */
370 zft_just_before_eof = 1;
371 zft_position_before_eof(&zft_pos, volume);
372 TRACE(ft_t_noise, "just before eof");
373 }
374 }
375 zft_resid -= result; /* for MTSTATUS */
376 TRACE_EXIT bytes_read;
377}
diff --git a/drivers/char/ftape/zftape/zftape-read.h b/drivers/char/ftape/zftape/zftape-read.h
deleted file mode 100644
index 42941de0c23a..000000000000
--- a/drivers/char/ftape/zftape/zftape-read.h
+++ /dev/null
@@ -1,53 +0,0 @@
1#ifndef _ZFTAPE_READ_H
2#define _ZFTAPE_READ_H
3
4/*
5 * Copyright (C) 1996, 1997 Claus-Justus Heine
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; see the file COPYING. If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
20
21 *
22 * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-read.h,v $
23 * $Revision: 1.2 $
24 * $Date: 1997/10/05 19:19:07 $
25 *
26 * This file contains the definitions for the read functions
27 * for the zftape driver for Linux.
28 *
29 */
30
31#include "../lowlevel/ftape-read.h"
32
33/* ftape-read.c defined global vars.
34 */
35extern int zft_just_before_eof;
36
37/* ftape-read.c defined global functions.
38 */
39extern void zft_zap_read_buffers(void);
40extern int zft_read_header_segments(void);
41extern int zft_fetch_segment_fraction(const unsigned int segment,
42 void *buffer,
43 const ft_read_mode_t read_mode,
44 const unsigned int start,
45 const unsigned int size);
46#define zft_fetch_segment(segment, address, read_mode) \
47 zft_fetch_segment_fraction(segment, address, read_mode, \
48 0, FT_SEGMENT_SIZE)
49/* hook for the VFS interface
50 */
51extern int _zft_read(char __user *buff, int req_len);
52
53#endif /* _ZFTAPE_READ_H */
diff --git a/drivers/char/ftape/zftape/zftape-rw.c b/drivers/char/ftape/zftape/zftape-rw.c
deleted file mode 100644
index dab634686885..000000000000
--- a/drivers/char/ftape/zftape/zftape-rw.c
+++ /dev/null
@@ -1,375 +0,0 @@
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-rw.c,v $
20 * $Revision: 1.2 $
21 * $Date: 1997/10/05 19:19:08 $
22 *
23 * This file contains some common code for the r/w code for
24 * zftape.
25 */
26
27#include <linux/errno.h>
28#include <linux/mm.h>
29
30#include <linux/zftape.h>
31#include "../zftape/zftape-init.h"
32#include "../zftape/zftape-eof.h"
33#include "../zftape/zftape-ctl.h"
34#include "../zftape/zftape-write.h"
35#include "../zftape/zftape-read.h"
36#include "../zftape/zftape-rw.h"
37#include "../zftape/zftape-vtbl.h"
38
39/* Global vars.
40 */
41
42__u8 *zft_deblock_buf;
43__u8 *zft_hseg_buf;
44int zft_deblock_segment = -1;
45zft_status_enum zft_io_state = zft_idle;
46int zft_header_changed;
47int zft_qic113; /* conform to old specs. and old zftape */
48int zft_use_compression;
49zft_position zft_pos = {
50 -1, /* seg_pos */
51 0, /* seg_byte_pos */
52 0, /* tape_pos */
53 0 /* volume_pos */
54};
55unsigned int zft_blk_sz = CONFIG_ZFT_DFLT_BLK_SZ;
56__s64 zft_capacity;
57
58unsigned int zft_written_segments;
59int zft_label_changed;
60
61/* Local vars.
62 */
63
64unsigned int zft_get_seg_sz(unsigned int segment)
65{
66 int size;
67 TRACE_FUN(ft_t_any);
68
69 size = FT_SEGMENT_SIZE -
70 count_ones(ftape_get_bad_sector_entry(segment))*FT_SECTOR_SIZE;
71 if (size > 0) {
72 TRACE_EXIT (unsigned)size;
73 } else {
74 TRACE_EXIT 0;
75 }
76}
77
78/* ftape_set_flags(). Claus-Justus Heine, 1994/1995
79 */
80void zft_set_flags(unsigned minor_unit)
81{
82 TRACE_FUN(ft_t_flow);
83
84 zft_use_compression = zft_qic_mode = 0;
85 switch (minor_unit & ZFT_MINOR_OP_MASK) {
86 case (ZFT_Q80_MODE | ZFT_ZIP_MODE):
87 case ZFT_ZIP_MODE:
88 zft_use_compression = 1;
89 case 0:
90 case ZFT_Q80_MODE:
91 zft_qic_mode = 1;
92 if (zft_mt_compression) { /* override the default */
93 zft_use_compression = 1;
94 }
95 break;
96 case ZFT_RAW_MODE:
97 TRACE(ft_t_noise, "switching to raw mode");
98 break;
99 default:
100 TRACE(ft_t_warn, "Warning:\n"
101 KERN_INFO "Wrong combination of minor device bits.\n"
102 KERN_INFO "Switching to raw read-only mode.");
103 zft_write_protected = 1;
104 break;
105 }
106 TRACE_EXIT;
107}
108
109/* computes the segment and byte offset inside the segment
110 * corresponding to tape_pos.
111 *
112 * tape_pos gives the offset in bytes from the beginning of the
113 * ft_first_data_segment *seg_byte_pos is the offset in the current
114 * segment in bytes
115 *
116 * Of, if this routine was called often one should cache the last data
117 * pos it was called with, but actually this is only needed in
118 * ftape_seek_block(), that is, almost never.
119 */
120int zft_calc_seg_byte_coord(int *seg_byte_pos, __s64 tape_pos)
121{
122 int segment;
123 int seg_sz;
124 TRACE_FUN(ft_t_flow);
125
126 if (tape_pos == 0) {
127 *seg_byte_pos = 0;
128 segment = ft_first_data_segment;
129 } else {
130 seg_sz = 0;
131
132 for (segment = ft_first_data_segment;
133 ((tape_pos > 0) && (segment <= ft_last_data_segment));
134 segment++) {
135 seg_sz = zft_get_seg_sz(segment);
136 tape_pos -= seg_sz;
137 }
138 if(tape_pos >= 0) {
139 /* the case tape_pos > != 0 means that the
140 * argument tape_pos lies beyond the EOT.
141 */
142 *seg_byte_pos= 0;
143 } else { /* tape_pos < 0 */
144 segment--;
145 *seg_byte_pos= tape_pos + seg_sz;
146 }
147 }
148 TRACE_EXIT(segment);
149}
150
151/* ftape_calc_tape_pos().
152 *
153 * computes the offset in bytes from the beginning of the
154 * ft_first_data_segment inverse to ftape_calc_seg_byte_coord
155 *
156 * We should do some caching. But how:
157 *
158 * Each time the header segments are read in, this routine is called
159 * with ft_tracks_per_tape*segments_per_track argumnet. So this should be
160 * the time to reset the cache.
161 *
162 * Also, it might be in the future that the bad sector map gets
163 * changed. -> reset the cache
164 */
165static int seg_pos;
166static __s64 tape_pos;
167
168__s64 zft_get_capacity(void)
169{
170 seg_pos = ft_first_data_segment;
171 tape_pos = 0;
172
173 while (seg_pos <= ft_last_data_segment) {
174 tape_pos += zft_get_seg_sz(seg_pos ++);
175 }
176 return tape_pos;
177}
178
179__s64 zft_calc_tape_pos(int segment)
180{
181 int d1, d2, d3;
182 TRACE_FUN(ft_t_any);
183
184 if (segment > ft_last_data_segment) {
185 TRACE_EXIT zft_capacity;
186 }
187 if (segment < ft_first_data_segment) {
188 TRACE_EXIT 0;
189 }
190 d2 = segment - seg_pos;
191 if (-d2 > 10) {
192 d1 = segment - ft_first_data_segment;
193 if (-d2 > d1) {
194 tape_pos = 0;
195 seg_pos = ft_first_data_segment;
196 d2 = d1;
197 }
198 }
199 if (d2 > 10) {
200 d3 = ft_last_data_segment - segment;
201 if (d2 > d3) {
202 tape_pos = zft_capacity;
203 seg_pos = ft_last_data_segment + 1;
204 d2 = -d3;
205 }
206 }
207 if (d2 > 0) {
208 while (seg_pos < segment) {
209 tape_pos += zft_get_seg_sz(seg_pos++);
210 }
211 } else {
212 while (seg_pos > segment) {
213 tape_pos -= zft_get_seg_sz(--seg_pos);
214 }
215 }
216 TRACE(ft_t_noise, "new cached pos: %d", seg_pos);
217
218 TRACE_EXIT tape_pos;
219}
220
221/* copy Z-label string to buffer, keeps track of the correct offset in
222 * `buffer'
223 */
224void zft_update_label(__u8 *buffer)
225{
226 TRACE_FUN(ft_t_flow);
227
228 if (strncmp(&buffer[FT_LABEL], ZFTAPE_LABEL,
229 sizeof(ZFTAPE_LABEL)-1) != 0) {
230 TRACE(ft_t_info, "updating label from \"%s\" to \"%s\"",
231 &buffer[FT_LABEL], ZFTAPE_LABEL);
232 strcpy(&buffer[FT_LABEL], ZFTAPE_LABEL);
233 memset(&buffer[FT_LABEL] + sizeof(ZFTAPE_LABEL) - 1, ' ',
234 FT_LABEL_SZ - sizeof(ZFTAPE_LABEL + 1));
235 PUT4(buffer, FT_LABEL_DATE, 0);
236 zft_label_changed = zft_header_changed = 1; /* changed */
237 }
238 TRACE_EXIT;
239}
240
241int zft_verify_write_segments(unsigned int segment,
242 __u8 *data, size_t size,
243 __u8 *buffer)
244{
245 int result;
246 __u8 *write_buf;
247 __u8 *src_buf;
248 int single;
249 int seg_pos;
250 int seg_sz;
251 int remaining;
252 ft_write_mode_t write_mode;
253 TRACE_FUN(ft_t_flow);
254
255 seg_pos = segment;
256 seg_sz = zft_get_seg_sz(seg_pos);
257 src_buf = data;
258 single = size <= seg_sz;
259 remaining = size;
260 do {
261 TRACE(ft_t_noise, "\n"
262 KERN_INFO "remaining: %d\n"
263 KERN_INFO "seg_sz : %d\n"
264 KERN_INFO "segment : %d",
265 remaining, seg_sz, seg_pos);
266 if (remaining == seg_sz) {
267 write_buf = src_buf;
268 write_mode = single ? FT_WR_SINGLE : FT_WR_MULTI;
269 remaining = 0;
270 } else if (remaining > seg_sz) {
271 write_buf = src_buf;
272 write_mode = FT_WR_ASYNC; /* don't start tape */
273 remaining -= seg_sz;
274 } else { /* remaining < seg_sz */
275 write_buf = buffer;
276 memcpy(write_buf, src_buf, remaining);
277 memset(&write_buf[remaining],'\0',seg_sz-remaining);
278 write_mode = single ? FT_WR_SINGLE : FT_WR_MULTI;
279 remaining = 0;
280 }
281 if ((result = ftape_write_segment(seg_pos,
282 write_buf,
283 write_mode)) != seg_sz) {
284 TRACE(ft_t_err, "Error: "
285 "Couldn't write segment %d", seg_pos);
286 TRACE_EXIT result < 0 ? result : -EIO; /* bail out */
287 }
288 zft_written_segments ++;
289 seg_sz = zft_get_seg_sz(++seg_pos);
290 src_buf += result;
291 } while (remaining > 0);
292 if (ftape_get_status()->fti_state == writing) {
293 TRACE_CATCH(ftape_loop_until_writes_done(),);
294 TRACE_CATCH(ftape_abort_operation(),);
295 zft_prevent_flush();
296 }
297 seg_pos = segment;
298 src_buf = data;
299 remaining = size;
300 do {
301 TRACE_CATCH(result = ftape_read_segment(seg_pos, buffer,
302 single ? FT_RD_SINGLE
303 : FT_RD_AHEAD),);
304 if (memcmp(src_buf, buffer,
305 remaining > result ? result : remaining) != 0) {
306 TRACE_ABORT(-EIO, ft_t_err,
307 "Failed to verify written segment %d",
308 seg_pos);
309 }
310 remaining -= result;
311 TRACE(ft_t_noise, "verify successful:\n"
312 KERN_INFO "segment : %d\n"
313 KERN_INFO "segsize : %d\n"
314 KERN_INFO "remaining: %d",
315 seg_pos, result, remaining);
316 src_buf += seg_sz;
317 seg_pos++;
318 } while (remaining > 0);
319 TRACE_EXIT size;
320}
321
322
323/* zft_erase(). implemented compression-handling
324 *
325 * calculate the first data-segment when using/not using compression.
326 *
327 * update header-segment and compression-map-segment.
328 */
329int zft_erase(void)
330{
331 int result = 0;
332 TRACE_FUN(ft_t_flow);
333
334 if (!zft_header_read) {
335 TRACE_CATCH(zft_vmalloc_once((void **)&zft_hseg_buf,
336 FT_SEGMENT_SIZE),);
337 /* no need to read the vtbl and compression map */
338 TRACE_CATCH(ftape_read_header_segment(zft_hseg_buf),);
339 if ((zft_old_ftape =
340 zft_ftape_validate_label(&zft_hseg_buf[FT_LABEL]))) {
341 zft_ftape_extract_file_marks(zft_hseg_buf);
342 }
343 TRACE(ft_t_noise,
344 "ft_first_data_segment: %d, ft_last_data_segment: %d",
345 ft_first_data_segment, ft_last_data_segment);
346 zft_qic113 = (ft_format_code != fmt_normal &&
347 ft_format_code != fmt_1100ft &&
348 ft_format_code != fmt_425ft);
349 }
350 if (zft_old_ftape) {
351 zft_clear_ftape_file_marks();
352 zft_old_ftape = 0; /* no longer old ftape */
353 }
354 PUT2(zft_hseg_buf, FT_CMAP_START, 0);
355 zft_volume_table_changed = 1;
356 zft_capacity = zft_get_capacity();
357 zft_init_vtbl();
358 /* the rest must be done in ftape_update_header_segments
359 */
360 zft_header_read = 1;
361 zft_header_changed = 1; /* force update of timestamp */
362 result = zft_update_header_segments();
363
364 ftape_abort_operation();
365
366 zft_reset_position(&zft_pos);
367 zft_set_flags (zft_unit);
368 TRACE_EXIT result;
369}
370
371unsigned int zft_get_time(void)
372{
373 unsigned int date = FT_TIME_STAMP(2097, 11, 30, 23, 59, 59); /* fun */
374 return date;
375}
diff --git a/drivers/char/ftape/zftape/zftape-rw.h b/drivers/char/ftape/zftape/zftape-rw.h
deleted file mode 100644
index 1ceec22b60bd..000000000000
--- a/drivers/char/ftape/zftape/zftape-rw.h
+++ /dev/null
@@ -1,101 +0,0 @@
1#ifndef _ZFTAPE_RW_H
2#define _ZFTAPE_RW_H
3
4/*
5 * Copyright (C) 1996, 1997 Claus-Justus Heine.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; see the file COPYING. If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
20
21 *
22 * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-rw.h,v $
23 * $Revision: 1.2 $
24 * $Date: 1997/10/05 19:19:09 $
25 *
26 * This file contains the definitions for the read and write
27 * functions for the QIC-117 floppy-tape driver for Linux.
28 *
29 */
30
31#include "../zftape/zftape-buffers.h"
32
33#define SEGMENTS_PER_TAPE (ft_segments_per_track * ft_tracks_per_tape)
34
35/* QIC-113 Rev. G says that `a maximum of 63488 raw bytes may be
36 * compressed into a single frame'.
37 * Maybe we should stick to 32kb to make it more `beautiful'
38 */
39#define ZFT_MAX_BLK_SZ (62*1024) /* bytes */
40#if !defined(CONFIG_ZFT_DFLT_BLK_SZ)
41# define CONFIG_ZFT_DFLT_BLK_SZ (10*1024) /* bytes, default of gnu tar */
42#elif CONFIG_ZFT_DFLT_BLK_SZ == 0
43# undef CONFIG_ZFT_DFLT_BLK_SZ
44# define CONFIG_ZFT_DFLT_BLK_SZ 1
45#elif (CONFIG_ZFT_DFLT_BLK_SZ % 1024) != 0
46# error CONFIG_ZFT_DFLT_BLK_SZ must be 1 or a multiple of 1024
47#endif
48/* The *optional* compression routines need some overhead per tape
49 * block for their purposes. Instead of asking the actual compression
50 * implementation how much it needs, we restrict this overhead to be
51 * maximal of ZFT_CMPT_OVERHEAD size. We need this for EOT
52 * conditions. The tape is assumed to be logical at EOT when the
53 * distance from the physical EOT is less than
54 * one tape block + ZFT_CMPR_OVERHEAD
55 */
56#define ZFT_CMPR_OVERHEAD 16 /* bytes */
57
58typedef enum
59{
60 zft_idle = 0,
61 zft_reading,
62 zft_writing,
63} zft_status_enum;
64
65typedef struct /* all values measured in bytes */
66{
67 int seg_pos; /* segment currently positioned at */
68 int seg_byte_pos; /* offset in current segment */
69 __s64 tape_pos; /* real offset from BOT */
70 __s64 volume_pos; /* pos. in uncompressed data stream in
71 * current volume
72 */
73} zft_position;
74
75extern zft_position zft_pos;
76extern __u8 *zft_deblock_buf;
77extern __u8 *zft_hseg_buf;
78extern int zft_deblock_segment;
79extern zft_status_enum zft_io_state;
80extern int zft_header_changed;
81extern int zft_qic113; /* conform to old specs. and old zftape */
82extern int zft_use_compression;
83extern unsigned int zft_blk_sz;
84extern __s64 zft_capacity;
85extern unsigned int zft_written_segments;
86extern int zft_label_changed;
87
88/* zftape-rw.c exported functions
89 */
90extern unsigned int zft_get_seg_sz(unsigned int segment);
91extern void zft_set_flags(unsigned int minor_unit);
92extern int zft_calc_seg_byte_coord(int *seg_byte_pos, __s64 tape_pos);
93extern __s64 zft_calc_tape_pos(int segment);
94extern __s64 zft_get_capacity(void);
95extern void zft_update_label(__u8 *buffer);
96extern int zft_erase(void);
97extern int zft_verify_write_segments(unsigned int segment,
98 __u8 *data, size_t size, __u8 *buffer);
99extern unsigned int zft_get_time(void);
100#endif /* _ZFTAPE_RW_H */
101
diff --git a/drivers/char/ftape/zftape/zftape-vtbl.c b/drivers/char/ftape/zftape/zftape-vtbl.c
deleted file mode 100644
index ad7f8be6340b..000000000000
--- a/drivers/char/ftape/zftape/zftape-vtbl.c
+++ /dev/null
@@ -1,757 +0,0 @@
1/*
2 * Copyright (c) 1995-1997 Claus-Justus Heine
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License as
6 published by the Free Software Foundation; either version 2, or (at
7 your option) any later version.
8
9 This program is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 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,
17 USA.
18
19 *
20 * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-vtbl.c,v $
21 * $Revision: 1.7.6.1 $
22 * $Date: 1997/11/24 13:48:31 $
23 *
24 * This file defines a volume table as defined in various QIC
25 * standards.
26 *
27 * This is a minimal implementation, just allowing ordinary DOS
28 * :( prgrams to identify the cartridge as used.
29 */
30
31#include <linux/errno.h>
32#include <linux/mm.h>
33#include <linux/slab.h>
34
35#include <linux/zftape.h>
36#include "../zftape/zftape-init.h"
37#include "../zftape/zftape-eof.h"
38#include "../zftape/zftape-ctl.h"
39#include "../zftape/zftape-write.h"
40#include "../zftape/zftape-read.h"
41#include "../zftape/zftape-rw.h"
42#include "../zftape/zftape-vtbl.h"
43
44#define ZFT_CMAP_HACK /* leave this defined to hide the compression map */
45
46/*
47 * global variables
48 */
49int zft_qic_mode = 1; /* use the vtbl */
50int zft_old_ftape; /* prevents old ftaped tapes to be overwritten */
51int zft_volume_table_changed; /* for write_header_segments() */
52
53/*
54 * private variables (only exported for inline functions)
55 */
56LIST_HEAD(zft_vtbl);
57
58/* We could also allocate these dynamically when extracting the volume table
59 * sizeof(zft_volinfo) is about 32 or something close to that
60 */
61static zft_volinfo tape_vtbl;
62static zft_volinfo eot_vtbl;
63static zft_volinfo *cur_vtbl;
64
65static inline void zft_new_vtbl_entry(void)
66{
67 struct list_head *tmp = &zft_last_vtbl->node;
68 zft_volinfo *new = zft_kmalloc(sizeof(zft_volinfo));
69
70 list_add(&new->node, tmp);
71 new->count = zft_eom_vtbl->count ++;
72}
73
74void zft_free_vtbl(void)
75{
76 for (;;) {
77 struct list_head *tmp = zft_vtbl.prev;
78 zft_volinfo *vtbl;
79
80 if (tmp == &zft_vtbl)
81 break;
82 list_del(tmp);
83 vtbl = list_entry(tmp, zft_volinfo, node);
84 zft_kfree(vtbl, sizeof(zft_volinfo));
85 }
86 INIT_LIST_HEAD(&zft_vtbl);
87 cur_vtbl = NULL;
88}
89
90/* initialize vtbl, called by ftape_new_cartridge()
91 */
92void zft_init_vtbl(void)
93{
94 zft_volinfo *new;
95
96 zft_free_vtbl();
97
98 /* Create the two dummy vtbl entries
99 */
100 new = zft_kmalloc(sizeof(zft_volinfo));
101 list_add(&new->node, &zft_vtbl);
102 new = zft_kmalloc(sizeof(zft_volinfo));
103 list_add(&new->node, &zft_vtbl);
104 zft_head_vtbl->end_seg = ft_first_data_segment;
105 zft_head_vtbl->blk_sz = zft_blk_sz;
106 zft_head_vtbl->count = -1;
107 zft_eom_vtbl->start_seg = ft_first_data_segment + 1;
108 zft_eom_vtbl->end_seg = ft_last_data_segment + 1;
109 zft_eom_vtbl->blk_sz = zft_blk_sz;
110 zft_eom_vtbl->count = 0;
111
112 /* Reset the pointer for zft_find_volume()
113 */
114 cur_vtbl = zft_eom_vtbl;
115
116 /* initialize the dummy vtbl entries for zft_qic_mode == 0
117 */
118 eot_vtbl.start_seg = ft_last_data_segment + 1;
119 eot_vtbl.end_seg = ft_last_data_segment + 1;
120 eot_vtbl.blk_sz = zft_blk_sz;
121 eot_vtbl.count = -1;
122 tape_vtbl.start_seg = ft_first_data_segment;
123 tape_vtbl.end_seg = ft_last_data_segment;
124 tape_vtbl.blk_sz = zft_blk_sz;
125 tape_vtbl.size = zft_capacity;
126 tape_vtbl.count = 0;
127}
128
129/* check for a valid VTBL signature.
130 */
131static int vtbl_signature_valid(__u8 signature[4])
132{
133 const char *vtbl_ids[] = VTBL_IDS; /* valid signatures */
134 int j;
135
136 for (j = 0;
137 (j < NR_ITEMS(vtbl_ids)) && (memcmp(signature, vtbl_ids[j], 4) != 0);
138 j++);
139 return j < NR_ITEMS(vtbl_ids);
140}
141
142/* We used to store the block-size of the volume in the volume-label,
143 * using the keyword "blocksize". The blocksize written to the
144 * volume-label is in bytes.
145 *
146 * We use this now only for compatibility with old zftape version. We
147 * store the blocksize directly as binary number in the vendor
148 * extension part of the volume entry.
149 */
150static int check_volume_label(const char *label, int *blk_sz)
151{
152 int valid_format;
153 char *blocksize;
154 TRACE_FUN(ft_t_flow);
155
156 TRACE(ft_t_noise, "called with \"%s\" / \"%s\"", label, ZFT_VOL_NAME);
157 if (strncmp(label, ZFT_VOL_NAME, strlen(ZFT_VOL_NAME)) != 0) {
158 *blk_sz = 1; /* smallest block size that we allow */
159 valid_format = 0;
160 } else {
161 TRACE(ft_t_noise, "got old style zftape vtbl entry");
162 /* get the default blocksize */
163 /* use the kernel strstr() */
164 blocksize= strstr(label, " blocksize ");
165 if (blocksize) {
166 blocksize += strlen(" blocksize ");
167 for(*blk_sz= 0;
168 *blocksize >= '0' && *blocksize <= '9';
169 blocksize++) {
170 *blk_sz *= 10;
171 *blk_sz += *blocksize - '0';
172 }
173 if (*blk_sz > ZFT_MAX_BLK_SZ) {
174 *blk_sz= 1;
175 valid_format= 0;
176 } else {
177 valid_format = 1;
178 }
179 } else {
180 *blk_sz= 1;
181 valid_format= 0;
182 }
183 }
184 TRACE_EXIT valid_format;
185}
186
187/* check for a zftape volume
188 */
189static int check_volume(__u8 *entry, zft_volinfo *volume)
190{
191 TRACE_FUN(ft_t_flow);
192
193 if(strncmp(&entry[VTBL_EXT+EXT_ZFTAPE_SIG], ZFTAPE_SIG,
194 strlen(ZFTAPE_SIG)) == 0) {
195 TRACE(ft_t_noise, "got new style zftape vtbl entry");
196 volume->blk_sz = GET2(entry, VTBL_EXT+EXT_ZFTAPE_BLKSZ);
197 volume->qic113 = entry[VTBL_EXT+EXT_ZFTAPE_QIC113];
198 TRACE_EXIT 1;
199 } else {
200 TRACE_EXIT check_volume_label(&entry[VTBL_DESC], &volume->blk_sz);
201 }
202}
203
204
205/* create zftape specific vtbl entry, the volume bounds are inserted
206 * in the calling function, zft_create_volume_headers()
207 */
208static void create_zft_volume(__u8 *entry, zft_volinfo *vtbl)
209{
210 TRACE_FUN(ft_t_flow);
211
212 memset(entry, 0, VTBL_SIZE);
213 memcpy(&entry[VTBL_SIG], VTBL_ID, 4);
214 sprintf(&entry[VTBL_DESC], ZFT_VOL_NAME" %03d", vtbl->count);
215 entry[VTBL_FLAGS] = (VTBL_FL_NOT_VERIFIED | VTBL_FL_SEG_SPANNING);
216 entry[VTBL_M_NO] = 1; /* multi_cartridge_count */
217 strcpy(&entry[VTBL_EXT+EXT_ZFTAPE_SIG], ZFTAPE_SIG);
218 PUT2(entry, VTBL_EXT+EXT_ZFTAPE_BLKSZ, vtbl->blk_sz);
219 if (zft_qic113) {
220 PUT8(entry, VTBL_DATA_SIZE, vtbl->size);
221 entry[VTBL_CMPR] = VTBL_CMPR_UNREG;
222 if (vtbl->use_compression) { /* use compression: */
223 entry[VTBL_CMPR] |= VTBL_CMPR_USED;
224 }
225 entry[VTBL_EXT+EXT_ZFTAPE_QIC113] = 1;
226 } else {
227 PUT4(entry, VTBL_DATA_SIZE, vtbl->size);
228 entry[VTBL_K_CMPR] = VTBL_CMPR_UNREG;
229 if (vtbl->use_compression) { /* use compression: */
230 entry[VTBL_K_CMPR] |= VTBL_CMPR_USED;
231 }
232 }
233 if (ft_format_code == fmt_big) {
234 /* SCSI like vtbl, store the number of used
235 * segments as 4 byte value
236 */
237 PUT4(entry, VTBL_SCSI_SEGS, vtbl->end_seg-vtbl->start_seg + 1);
238 } else {
239 /* normal, QIC-80MC like vtbl
240 */
241 PUT2(entry, VTBL_START, vtbl->start_seg);
242 PUT2(entry, VTBL_END, vtbl->end_seg);
243 }
244 TRACE_EXIT;
245}
246
247/* this one creates the volume headers for each volume. It is assumed
248 * that buffer already contains the old volume-table, so that vtbl
249 * entries without the zft_volume flag set can savely be ignored.
250 */
251static void zft_create_volume_headers(__u8 *buffer)
252{
253 __u8 *entry;
254 struct list_head *tmp;
255 zft_volinfo *vtbl;
256 TRACE_FUN(ft_t_flow);
257
258#ifdef ZFT_CMAP_HACK
259 if((strncmp(&buffer[VTBL_EXT+EXT_ZFTAPE_SIG], ZFTAPE_SIG,
260 strlen(ZFTAPE_SIG)) == 0) &&
261 buffer[VTBL_EXT+EXT_ZFTAPE_CMAP] != 0) {
262 TRACE(ft_t_noise, "deleting cmap volume");
263 memmove(buffer, buffer + VTBL_SIZE,
264 FT_SEGMENT_SIZE - VTBL_SIZE);
265 }
266#endif
267 entry = buffer;
268 for (tmp = zft_head_vtbl->node.next;
269 tmp != &zft_eom_vtbl->node;
270 tmp = tmp->next) {
271 vtbl = list_entry(tmp, zft_volinfo, node);
272 /* we now fill in the values only for newly created volumes.
273 */
274 if (vtbl->new_volume) {
275 create_zft_volume(entry, vtbl);
276 vtbl->new_volume = 0; /* clear the flag */
277 }
278
279 DUMP_VOLINFO(ft_t_noise, &entry[VTBL_DESC], vtbl);
280 entry += VTBL_SIZE;
281 }
282 memset(entry, 0, FT_SEGMENT_SIZE - zft_eom_vtbl->count * VTBL_SIZE);
283 TRACE_EXIT;
284}
285
286/* write volume table to tape. Calls zft_create_volume_headers()
287 */
288int zft_update_volume_table(unsigned int segment)
289{
290 int result = 0;
291 __u8 *verify_buf = NULL;
292 TRACE_FUN(ft_t_flow);
293
294 TRACE_CATCH(result = ftape_read_segment(ft_first_data_segment,
295 zft_deblock_buf,
296 FT_RD_SINGLE),);
297 zft_create_volume_headers(zft_deblock_buf);
298 TRACE(ft_t_noise, "writing volume table segment %d", segment);
299 if (zft_vmalloc_once(&verify_buf, FT_SEGMENT_SIZE) == 0) {
300 TRACE_CATCH(zft_verify_write_segments(segment,
301 zft_deblock_buf, result,
302 verify_buf),
303 zft_vfree(&verify_buf, FT_SEGMENT_SIZE));
304 zft_vfree(&verify_buf, FT_SEGMENT_SIZE);
305 } else {
306 TRACE_CATCH(ftape_write_segment(segment, zft_deblock_buf,
307 FT_WR_SINGLE),);
308 }
309 TRACE_EXIT 0;
310}
311
312/* non zftape volumes are handled in raw mode. Thus we need to
313 * calculate the raw amount of data contained in those segments.
314 */
315static void extract_alien_volume(__u8 *entry, zft_volinfo *vtbl)
316{
317 TRACE_FUN(ft_t_flow);
318
319 vtbl->size = (zft_calc_tape_pos(zft_last_vtbl->end_seg+1) -
320 zft_calc_tape_pos(zft_last_vtbl->start_seg));
321 vtbl->use_compression = 0;
322 vtbl->qic113 = zft_qic113;
323 if (vtbl->qic113) {
324 TRACE(ft_t_noise,
325 "Fake alien volume's size from " LL_X " to " LL_X,
326 LL(GET8(entry, VTBL_DATA_SIZE)), LL(vtbl->size));
327 } else {
328 TRACE(ft_t_noise,
329 "Fake alien volume's size from %d to " LL_X,
330 (int)GET4(entry, VTBL_DATA_SIZE), LL(vtbl->size));
331 }
332 TRACE_EXIT;
333}
334
335
336/* extract an zftape specific volume
337 */
338static void extract_zft_volume(__u8 *entry, zft_volinfo *vtbl)
339{
340 TRACE_FUN(ft_t_flow);
341
342 if (vtbl->qic113) {
343 vtbl->size = GET8(entry, VTBL_DATA_SIZE);
344 vtbl->use_compression =
345 (entry[VTBL_CMPR] & VTBL_CMPR_USED) != 0;
346 } else {
347 vtbl->size = GET4(entry, VTBL_DATA_SIZE);
348 if (entry[VTBL_K_CMPR] & VTBL_CMPR_UNREG) {
349 vtbl->use_compression =
350 (entry[VTBL_K_CMPR] & VTBL_CMPR_USED) != 0;
351 } else if (entry[VTBL_CMPR] & VTBL_CMPR_UNREG) {
352 vtbl->use_compression =
353 (entry[VTBL_CMPR] & VTBL_CMPR_USED) != 0;
354 } else {
355 TRACE(ft_t_warn, "Geeh! There is something wrong:\n"
356 KERN_INFO "QIC compression (Rev = K): %x\n"
357 KERN_INFO "QIC compression (Rev > K): %x",
358 entry[VTBL_K_CMPR], entry[VTBL_CMPR]);
359 }
360 }
361 TRACE_EXIT;
362}
363
364/* extract the volume table from buffer. "buffer" must already contain
365 * the vtbl-segment
366 */
367int zft_extract_volume_headers(__u8 *buffer)
368{
369 __u8 *entry;
370 TRACE_FUN(ft_t_flow);
371
372 zft_init_vtbl();
373 entry = buffer;
374#ifdef ZFT_CMAP_HACK
375 if ((strncmp(&entry[VTBL_EXT+EXT_ZFTAPE_SIG], ZFTAPE_SIG,
376 strlen(ZFTAPE_SIG)) == 0) &&
377 entry[VTBL_EXT+EXT_ZFTAPE_CMAP] != 0) {
378 TRACE(ft_t_noise, "ignoring cmap volume");
379 entry += VTBL_SIZE;
380 }
381#endif
382 /* the end of the vtbl is indicated by an invalid signature
383 */
384 while (vtbl_signature_valid(&entry[VTBL_SIG]) &&
385 (entry - buffer) < FT_SEGMENT_SIZE) {
386 zft_new_vtbl_entry();
387 if (ft_format_code == fmt_big) {
388 /* SCSI like vtbl, stores only the number of
389 * segments used
390 */
391 unsigned int num_segments= GET4(entry, VTBL_SCSI_SEGS);
392 zft_last_vtbl->start_seg = zft_eom_vtbl->start_seg;
393 zft_last_vtbl->end_seg =
394 zft_last_vtbl->start_seg + num_segments - 1;
395 } else {
396 /* `normal', QIC-80 like vtbl
397 */
398 zft_last_vtbl->start_seg = GET2(entry, VTBL_START);
399 zft_last_vtbl->end_seg = GET2(entry, VTBL_END);
400 }
401 zft_eom_vtbl->start_seg = zft_last_vtbl->end_seg + 1;
402 /* check if we created this volume and get the
403 * blk_sz
404 */
405 zft_last_vtbl->zft_volume = check_volume(entry, zft_last_vtbl);
406 if (zft_last_vtbl->zft_volume == 0) {
407 extract_alien_volume(entry, zft_last_vtbl);
408 } else {
409 extract_zft_volume(entry, zft_last_vtbl);
410 }
411 DUMP_VOLINFO(ft_t_noise, &entry[VTBL_DESC], zft_last_vtbl);
412 entry +=VTBL_SIZE;
413 }
414#if 0
415/*
416 * undefine to test end of tape handling
417 */
418 zft_new_vtbl_entry();
419 zft_last_vtbl->start_seg = zft_eom_vtbl->start_seg;
420 zft_last_vtbl->end_seg = ft_last_data_segment - 10;
421 zft_last_vtbl->blk_sz = zft_blk_sz;
422 zft_last_vtbl->zft_volume = 1;
423 zft_last_vtbl->qic113 = zft_qic113;
424 zft_last_vtbl->size = (zft_calc_tape_pos(zft_last_vtbl->end_seg+1)
425 - zft_calc_tape_pos(zft_last_vtbl->start_seg));
426#endif
427 TRACE_EXIT 0;
428}
429
430/* this functions translates the failed_sector_log, misused as
431 * EOF-marker list, into a virtual volume table. The table mustn't be
432 * written to tape, because this would occupy the first data segment,
433 * which should be the volume table, but is actually the first segment
434 * that is filled with data (when using standard ftape). We assume,
435 * that we get a non-empty failed_sector_log.
436 */
437int zft_fake_volume_headers (eof_mark_union *eof_map, int num_failed_sectors)
438{
439 unsigned int segment, sector;
440 int have_eom = 0;
441 int vol_no;
442 TRACE_FUN(ft_t_flow);
443
444 if ((num_failed_sectors >= 2) &&
445 (GET2(&eof_map[num_failed_sectors - 1].mark.segment, 0)
446 ==
447 GET2(&eof_map[num_failed_sectors - 2].mark.segment, 0) + 1) &&
448 (GET2(&eof_map[num_failed_sectors - 1].mark.date, 0) == 1)) {
449 /* this should be eom. We keep the remainder of the
450 * tape as another volume.
451 */
452 have_eom = 1;
453 }
454 zft_init_vtbl();
455 zft_eom_vtbl->start_seg = ft_first_data_segment;
456 for(vol_no = 0; vol_no < num_failed_sectors - have_eom; vol_no ++) {
457 zft_new_vtbl_entry();
458
459 segment = GET2(&eof_map[vol_no].mark.segment, 0);
460 sector = GET2(&eof_map[vol_no].mark.date, 0);
461
462 zft_last_vtbl->start_seg = zft_eom_vtbl->start_seg;
463 zft_last_vtbl->end_seg = segment;
464 zft_eom_vtbl->start_seg = segment + 1;
465 zft_last_vtbl->blk_sz = 1;
466 zft_last_vtbl->size =
467 (zft_calc_tape_pos(zft_last_vtbl->end_seg)
468 - zft_calc_tape_pos(zft_last_vtbl->start_seg)
469 + (sector-1) * FT_SECTOR_SIZE);
470 TRACE(ft_t_noise,
471 "failed sector log: segment: %d, sector: %d",
472 segment, sector);
473 DUMP_VOLINFO(ft_t_noise, "Faked volume", zft_last_vtbl);
474 }
475 if (!have_eom) {
476 zft_new_vtbl_entry();
477 zft_last_vtbl->start_seg = zft_eom_vtbl->start_seg;
478 zft_last_vtbl->end_seg = ft_last_data_segment;
479 zft_eom_vtbl->start_seg = ft_last_data_segment + 1;
480 zft_last_vtbl->size = zft_capacity;
481 zft_last_vtbl->size -= zft_calc_tape_pos(zft_last_vtbl->start_seg);
482 zft_last_vtbl->blk_sz = 1;
483 DUMP_VOLINFO(ft_t_noise, "Faked volume",zft_last_vtbl);
484 }
485 TRACE_EXIT 0;
486}
487
488/* update the internal volume table
489 *
490 * if before start of last volume: erase all following volumes if
491 * inside a volume: set end of volume to infinity
492 *
493 * this function is intended to be called every time _ftape_write() is
494 * called
495 *
496 * return: 0 if no new volume was created, 1 if a new volume was
497 * created
498 *
499 * NOTE: we don't need to check for zft_mode as ftape_write() does
500 * that already. This function gets never called without accessing
501 * zftape via the *qft* devices
502 */
503
504int zft_open_volume(zft_position *pos, int blk_sz, int use_compression)
505{
506 TRACE_FUN(ft_t_flow);
507
508 if (!zft_qic_mode) {
509 TRACE_EXIT 0;
510 }
511 if (zft_tape_at_lbot(pos)) {
512 zft_init_vtbl();
513 if(zft_old_ftape) {
514 /* clear old ftape's eof marks */
515 zft_clear_ftape_file_marks();
516 zft_old_ftape = 0; /* no longer old ftape */
517 }
518 zft_reset_position(pos);
519 }
520 if (pos->seg_pos != zft_last_vtbl->end_seg + 1) {
521 TRACE_ABORT(-EIO, ft_t_bug,
522 "BUG: seg_pos: %d, zft_last_vtbl->end_seg: %d",
523 pos->seg_pos, zft_last_vtbl->end_seg);
524 }
525 TRACE(ft_t_noise, "create new volume");
526 if (zft_eom_vtbl->count >= ZFT_MAX_VOLUMES) {
527 TRACE_ABORT(-ENOSPC, ft_t_err,
528 "Error: maxmimal number of volumes exhausted "
529 "(maxmimum is %d)", ZFT_MAX_VOLUMES);
530 }
531 zft_new_vtbl_entry();
532 pos->volume_pos = pos->seg_byte_pos = 0;
533 zft_last_vtbl->start_seg = pos->seg_pos;
534 zft_last_vtbl->end_seg = ft_last_data_segment; /* infinity */
535 zft_last_vtbl->blk_sz = blk_sz;
536 zft_last_vtbl->size = zft_capacity;
537 zft_last_vtbl->zft_volume = 1;
538 zft_last_vtbl->use_compression = use_compression;
539 zft_last_vtbl->qic113 = zft_qic113;
540 zft_last_vtbl->new_volume = 1;
541 zft_last_vtbl->open = 1;
542 zft_volume_table_changed = 1;
543 zft_eom_vtbl->start_seg = ft_last_data_segment + 1;
544 TRACE_EXIT 0;
545}
546
547/* perform mtfsf, mtbsf, not allowed without zft_qic_mode
548 */
549int zft_skip_volumes(int count, zft_position *pos)
550{
551 const zft_volinfo *vtbl;
552 TRACE_FUN(ft_t_flow);
553
554 TRACE(ft_t_noise, "count: %d", count);
555
556 vtbl= zft_find_volume(pos->seg_pos);
557 while (count > 0 && vtbl != zft_eom_vtbl) {
558 vtbl = list_entry(vtbl->node.next, zft_volinfo, node);
559 count --;
560 }
561 while (count < 0 && vtbl != zft_first_vtbl) {
562 vtbl = list_entry(vtbl->node.prev, zft_volinfo, node);
563 count ++;
564 }
565 pos->seg_pos = vtbl->start_seg;
566 pos->seg_byte_pos = 0;
567 pos->volume_pos = 0;
568 pos->tape_pos = zft_calc_tape_pos(pos->seg_pos);
569 zft_just_before_eof = vtbl->size == 0;
570 if (zft_cmpr_ops) {
571 (*zft_cmpr_ops->reset)();
572 }
573 zft_deblock_segment = -1; /* no need to keep cache */
574 TRACE(ft_t_noise, "repositioning to:\n"
575 KERN_INFO "zft_seg_pos : %d\n"
576 KERN_INFO "zft_seg_byte_pos : %d\n"
577 KERN_INFO "zft_tape_pos : " LL_X "\n"
578 KERN_INFO "zft_volume_pos : " LL_X "\n"
579 KERN_INFO "file number : %d",
580 pos->seg_pos, pos->seg_byte_pos,
581 LL(pos->tape_pos), LL(pos->volume_pos), vtbl->count);
582 zft_resid = count < 0 ? -count : count;
583 TRACE_EXIT zft_resid ? -EINVAL : 0;
584}
585
586/* the following simply returns the raw data position of the EOM
587 * marker, MTIOCSIZE ioctl
588 */
589__s64 zft_get_eom_pos(void)
590{
591 if (zft_qic_mode) {
592 return zft_calc_tape_pos(zft_eom_vtbl->start_seg);
593 } else {
594 /* there is only one volume in raw mode */
595 return zft_capacity;
596 }
597}
598
599/* skip to eom, used for MTEOM
600 */
601void zft_skip_to_eom(zft_position *pos)
602{
603 TRACE_FUN(ft_t_flow);
604 pos->seg_pos = zft_eom_vtbl->start_seg;
605 pos->seg_byte_pos =
606 pos->volume_pos =
607 zft_just_before_eof = 0;
608 pos->tape_pos = zft_calc_tape_pos(pos->seg_pos);
609 TRACE(ft_t_noise, "ftape positioned to segment %d, data pos " LL_X,
610 pos->seg_pos, LL(pos->tape_pos));
611 TRACE_EXIT;
612}
613
614/* write an EOF-marker by setting zft_last_vtbl->end_seg to seg_pos.
615 * NOTE: this function assumes that zft_last_vtbl points to a valid
616 * vtbl entry
617 *
618 * NOTE: this routine always positions before the EOF marker
619 */
620int zft_close_volume(zft_position *pos)
621{
622 TRACE_FUN(ft_t_any);
623
624 if (zft_vtbl_empty || !zft_last_vtbl->open) { /* should not happen */
625 TRACE(ft_t_noise, "There are no volumes to finish");
626 TRACE_EXIT -EIO;
627 }
628 if (pos->seg_byte_pos == 0 &&
629 pos->seg_pos != zft_last_vtbl->start_seg) {
630 pos->seg_pos --;
631 pos->seg_byte_pos = zft_get_seg_sz(pos->seg_pos);
632 }
633 zft_last_vtbl->end_seg = pos->seg_pos;
634 zft_last_vtbl->size = pos->volume_pos;
635 zft_volume_table_changed = 1;
636 zft_just_before_eof = 1;
637 zft_eom_vtbl->start_seg = zft_last_vtbl->end_seg + 1;
638 zft_last_vtbl->open = 0; /* closed */
639 TRACE_EXIT 0;
640}
641
642/* write count file-marks at current position.
643 *
644 * The tape is positioned after the eof-marker, that is at byte 0 of
645 * the segment following the eof-marker
646 *
647 * this function is only allowed in zft_qic_mode
648 *
649 * Only allowed when tape is at BOT or EOD.
650 */
651int zft_weof(unsigned int count, zft_position *pos)
652{
653
654 TRACE_FUN(ft_t_flow);
655
656 if (!count) { /* write zero EOF marks should be a real no-op */
657 TRACE_EXIT 0;
658 }
659 zft_volume_table_changed = 1;
660 if (zft_tape_at_lbot(pos)) {
661 zft_init_vtbl();
662 if(zft_old_ftape) {
663 /* clear old ftape's eof marks */
664 zft_clear_ftape_file_marks();
665 zft_old_ftape = 0; /* no longer old ftape */
666 }
667 }
668 if (zft_last_vtbl->open) {
669 zft_close_volume(pos);
670 zft_move_past_eof(pos);
671 count --;
672 }
673 /* now it's easy, just append eof-marks, that is empty
674 * volumes, to the end of the already recorded media.
675 */
676 while (count > 0 &&
677 pos->seg_pos <= ft_last_data_segment &&
678 zft_eom_vtbl->count < ZFT_MAX_VOLUMES) {
679 TRACE(ft_t_noise,
680 "Writing zero sized file at segment %d", pos->seg_pos);
681 zft_new_vtbl_entry();
682 zft_last_vtbl->start_seg = pos->seg_pos;
683 zft_last_vtbl->end_seg = pos->seg_pos;
684 zft_last_vtbl->size = 0;
685 zft_last_vtbl->blk_sz = zft_blk_sz;
686 zft_last_vtbl->zft_volume = 1;
687 zft_last_vtbl->use_compression = 0;
688 pos->tape_pos += zft_get_seg_sz(pos->seg_pos);
689 zft_eom_vtbl->start_seg = ++ pos->seg_pos;
690 count --;
691 }
692 if (count > 0) {
693 /* there are two possibilities: end of tape, or the
694 * maximum number of files is exhausted.
695 */
696 zft_resid = count;
697 TRACE(ft_t_noise,"Number of marks NOT written: %d", zft_resid);
698 if (zft_eom_vtbl->count == ZFT_MAX_VOLUMES) {
699 TRACE_ABORT(-EINVAL, ft_t_warn,
700 "maximum allowed number of files "
701 "exhausted: %d", ZFT_MAX_VOLUMES);
702 } else {
703 TRACE_ABORT(-ENOSPC,
704 ft_t_noise, "reached end of tape");
705 }
706 }
707 TRACE_EXIT 0;
708}
709
710const zft_volinfo *zft_find_volume(unsigned int seg_pos)
711{
712 TRACE_FUN(ft_t_flow);
713
714 TRACE(ft_t_any, "called with seg_pos %d",seg_pos);
715 if (!zft_qic_mode) {
716 if (seg_pos > ft_last_data_segment) {
717 TRACE_EXIT &eot_vtbl;
718 }
719 tape_vtbl.blk_sz = zft_blk_sz;
720 TRACE_EXIT &tape_vtbl;
721 }
722 if (seg_pos < zft_first_vtbl->start_seg) {
723 TRACE_EXIT (cur_vtbl = zft_first_vtbl);
724 }
725 while (seg_pos > cur_vtbl->end_seg) {
726 cur_vtbl = list_entry(cur_vtbl->node.next, zft_volinfo, node);
727 TRACE(ft_t_noise, "%d - %d", cur_vtbl->start_seg, cur_vtbl->end_seg);
728 }
729 while (seg_pos < cur_vtbl->start_seg) {
730 cur_vtbl = list_entry(cur_vtbl->node.prev, zft_volinfo, node);
731 TRACE(ft_t_noise, "%d - %d", cur_vtbl->start_seg, cur_vtbl->end_seg);
732 }
733 if (seg_pos > cur_vtbl->end_seg || seg_pos < cur_vtbl->start_seg) {
734 TRACE(ft_t_bug, "This cannot happen");
735 }
736 DUMP_VOLINFO(ft_t_noise, "", cur_vtbl);
737 TRACE_EXIT cur_vtbl;
738}
739
740/* this function really assumes that we are just before eof
741 */
742void zft_move_past_eof(zft_position *pos)
743{
744 TRACE_FUN(ft_t_flow);
745
746 TRACE(ft_t_noise, "old seg. pos: %d", pos->seg_pos);
747 pos->tape_pos += zft_get_seg_sz(pos->seg_pos++) - pos->seg_byte_pos;
748 pos->seg_byte_pos = 0;
749 pos->volume_pos = 0;
750 if (zft_cmpr_ops) {
751 (*zft_cmpr_ops->reset)();
752 }
753 zft_just_before_eof = 0;
754 zft_deblock_segment = -1; /* no need to cache it anymore */
755 TRACE(ft_t_noise, "new seg. pos: %d", pos->seg_pos);
756 TRACE_EXIT;
757}
diff --git a/drivers/char/ftape/zftape/zftape-vtbl.h b/drivers/char/ftape/zftape/zftape-vtbl.h
deleted file mode 100644
index f31d196d1759..000000000000
--- a/drivers/char/ftape/zftape/zftape-vtbl.h
+++ /dev/null
@@ -1,227 +0,0 @@
1#ifndef _ZFTAPE_VTBL_H
2#define _ZFTAPE_VTBL_H
3
4/*
5 * Copyright (c) 1995-1997 Claus-Justus Heine
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2, or (at
10 your option) any later version.
11
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; see the file COPYING. If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
20 USA.
21
22 *
23 * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-vtbl.h,v $
24 * $Revision: 1.3 $
25 * $Date: 1997/10/28 14:30:09 $
26 *
27 * This file defines a volume table as defined in the QIC-80
28 * development standards.
29 */
30
31#include <linux/list.h>
32
33#include "../lowlevel/ftape-tracing.h"
34
35#include "../zftape/zftape-eof.h"
36#include "../zftape/zftape-ctl.h"
37#include "../zftape/zftape-rw.h"
38
39#define VTBL_SIZE 128 /* bytes */
40
41/* The following are offsets in the vtbl. */
42#define VTBL_SIG 0
43#define VTBL_START 4
44#define VTBL_END 6
45#define VTBL_DESC 8
46#define VTBL_DATE 52
47#define VTBL_FLAGS 56
48#define VTBL_FL_VENDOR_SPECIFIC (1<<0)
49#define VTBL_FL_MUTLI_CARTRIDGE (1<<1)
50#define VTBL_FL_NOT_VERIFIED (1<<2)
51#define VTBL_FL_REDIR_INHIBIT (1<<3)
52#define VTBL_FL_SEG_SPANNING (1<<4)
53#define VTBL_FL_DIRECTORY_LAST (1<<5)
54#define VTBL_FL_RESERVED_6 (1<<6)
55#define VTBL_FL_RESERVED_7 (1<<7)
56#define VTBL_M_NO 57
57#define VTBL_EXT 58
58#define EXT_ZFTAPE_SIG 0
59#define EXT_ZFTAPE_BLKSZ 10
60#define EXT_ZFTAPE_CMAP 12
61#define EXT_ZFTAPE_QIC113 13
62#define VTBL_PWD 84
63#define VTBL_DIR_SIZE 92
64#define VTBL_DATA_SIZE 96
65#define VTBL_OS_VERSION 104
66#define VTBL_SRC_DRIVE 106
67#define VTBL_DEV 122
68#define VTBL_RESERVED_1 123
69#define VTBL_CMPR 124
70#define VTBL_CMPR_UNREG 0x3f
71#define VTBL_CMPR_USED 0x80
72#define VTBL_FMT 125
73#define VTBL_RESERVED_2 126
74#define VTBL_RESERVED_3 127
75/* compatibility with pre revision K */
76#define VTBL_K_CMPR 120
77
78/* the next is used by QIC-3020 tapes with format code 6 (>2^16
79 * segments) It is specified in QIC-113, Rev. G, Section 5 (SCSI
80 * volume table). The difference is simply, that we only store the
81 * number of segments used, not the starting segment.
82 */
83#define VTBL_SCSI_SEGS 4 /* is a 4 byte value */
84
85/* one vtbl is 128 bytes, that results in a maximum number of
86 * 29*1024/128 = 232 volumes.
87 */
88#define ZFT_MAX_VOLUMES (FT_SEGMENT_SIZE/VTBL_SIZE)
89#define VTBL_ID "VTBL"
90#define VTBL_IDS { VTBL_ID, "XTBL", "UTID", "EXVT" } /* other valid ids */
91#define ZFT_VOL_NAME "zftape volume" /* volume label used by me */
92#define ZFTAPE_SIG "LINUX ZFT"
93
94/* global variables
95 */
96typedef struct zft_internal_vtbl
97{
98 struct list_head node;
99 int count;
100 unsigned int start_seg; /* 32 bits are enough for now */
101 unsigned int end_seg; /* 32 bits are enough for now */
102 __s64 size; /* uncompressed size */
103 unsigned int blk_sz; /* block size for this volume */
104 unsigned int zft_volume :1; /* zftape created this volume */
105 unsigned int use_compression:1; /* compressed volume */
106 unsigned int qic113 :1; /* layout of compressed block
107 * info and vtbl conforms to
108 * QIC-113, Rev. G
109 */
110 unsigned int new_volume :1; /* it was created by us, this
111 * run. this allows the
112 * fields that aren't really
113 * used by zftape to be filled
114 * in by some user level
115 * program.
116 */
117 unsigned int open :1; /* just in progress of being
118 * written
119 */
120} zft_volinfo;
121
122extern struct list_head zft_vtbl;
123#define zft_head_vtbl list_entry(zft_vtbl.next, zft_volinfo, node)
124#define zft_eom_vtbl list_entry(zft_vtbl.prev, zft_volinfo, node)
125#define zft_last_vtbl list_entry(zft_eom_vtbl->node.prev, zft_volinfo, node)
126#define zft_first_vtbl list_entry(zft_head_vtbl->node.next, zft_volinfo, node)
127#define zft_vtbl_empty (zft_eom_vtbl->node.prev == &zft_head_vtbl->node)
128
129#define DUMP_VOLINFO(level, desc, info) \
130{ \
131 char tmp[21]; \
132 strlcpy(tmp, desc, sizeof(tmp)); \
133 TRACE(level, "Volume %d:\n" \
134 KERN_INFO "description : %s\n" \
135 KERN_INFO "first segment: %d\n" \
136 KERN_INFO "last segment: %d\n" \
137 KERN_INFO "size : " LL_X "\n" \
138 KERN_INFO "block size : %d\n" \
139 KERN_INFO "compression : %d\n" \
140 KERN_INFO "zftape volume: %d\n" \
141 KERN_INFO "QIC-113 conf.: %d", \
142 (info)->count, tmp, (info)->start_seg, (info)->end_seg, \
143 LL((info)->size), (info)->blk_sz, \
144 (info)->use_compression != 0, (info)->zft_volume != 0, \
145 (info)->qic113 != 0); \
146}
147
148extern int zft_qic_mode;
149extern int zft_old_ftape;
150extern int zft_volume_table_changed;
151
152/* exported functions */
153extern void zft_init_vtbl (void);
154extern void zft_free_vtbl (void);
155extern int zft_extract_volume_headers(__u8 *buffer);
156extern int zft_update_volume_table (unsigned int segment);
157extern int zft_open_volume (zft_position *pos,
158 int blk_sz, int use_compression);
159extern int zft_close_volume (zft_position *pos);
160extern const zft_volinfo *zft_find_volume(unsigned int seg_pos);
161extern int zft_skip_volumes (int count, zft_position *pos);
162extern __s64 zft_get_eom_pos (void);
163extern void zft_skip_to_eom (zft_position *pos);
164extern int zft_fake_volume_headers (eof_mark_union *eof_map,
165 int num_failed_sectors);
166extern int zft_weof (unsigned int count, zft_position *pos);
167extern void zft_move_past_eof (zft_position *pos);
168
169static inline int zft_tape_at_eod (const zft_position *pos);
170static inline int zft_tape_at_lbot (const zft_position *pos);
171static inline void zft_position_before_eof (zft_position *pos,
172 const zft_volinfo *volume);
173static inline __s64 zft_check_for_eof(const zft_volinfo *vtbl,
174 const zft_position *pos);
175
176/* this function decrements the zft_seg_pos counter if we are right
177 * at the beginning of a segment. This is to handle fsfm/bsfm -- we
178 * need to position before the eof mark. NOTE: zft_tape_pos is not
179 * changed
180 */
181static inline void zft_position_before_eof(zft_position *pos,
182 const zft_volinfo *volume)
183{
184 TRACE_FUN(ft_t_flow);
185
186 if (pos->seg_pos == volume->end_seg + 1 && pos->seg_byte_pos == 0) {
187 pos->seg_pos --;
188 pos->seg_byte_pos = zft_get_seg_sz(pos->seg_pos);
189 }
190 TRACE_EXIT;
191}
192
193/* Mmmh. Is the position at the end of the last volume, that is right
194 * before the last EOF mark also logical an EOD condition?
195 */
196static inline int zft_tape_at_eod(const zft_position *pos)
197{
198 TRACE_FUN(ft_t_any);
199
200 if (zft_qic_mode) {
201 TRACE_EXIT (pos->seg_pos >= zft_eom_vtbl->start_seg ||
202 zft_last_vtbl->open);
203 } else {
204 TRACE_EXIT pos->seg_pos > ft_last_data_segment;
205 }
206}
207
208static inline int zft_tape_at_lbot(const zft_position *pos)
209{
210 if (zft_qic_mode) {
211 return (pos->seg_pos <= zft_first_vtbl->start_seg &&
212 pos->volume_pos == 0);
213 } else {
214 return (pos->seg_pos <= ft_first_data_segment &&
215 pos->volume_pos == 0);
216 }
217}
218
219/* This one checks for EOF. return remaing space (may be negative)
220 */
221static inline __s64 zft_check_for_eof(const zft_volinfo *vtbl,
222 const zft_position *pos)
223{
224 return (__s64)(vtbl->size - pos->volume_pos);
225}
226
227#endif /* _ZFTAPE_VTBL_H */
diff --git a/drivers/char/ftape/zftape/zftape-write.c b/drivers/char/ftape/zftape/zftape-write.c
deleted file mode 100644
index 94327b8c97b9..000000000000
--- a/drivers/char/ftape/zftape/zftape-write.c
+++ /dev/null
@@ -1,483 +0,0 @@
1/*
2 * Copyright (C) 1996, 1997 Claus 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-write.c,v $
20 * $Revision: 1.3 $
21 * $Date: 1997/11/06 00:50:29 $
22 *
23 * This file contains the writing code
24 * for the QIC-117 floppy-tape driver for Linux.
25 */
26
27#include <linux/errno.h>
28#include <linux/mm.h>
29
30#include <linux/zftape.h>
31
32#include <asm/uaccess.h>
33
34#include "../zftape/zftape-init.h"
35#include "../zftape/zftape-eof.h"
36#include "../zftape/zftape-ctl.h"
37#include "../zftape/zftape-write.h"
38#include "../zftape/zftape-read.h"
39#include "../zftape/zftape-rw.h"
40#include "../zftape/zftape-vtbl.h"
41
42/* Global vars.
43 */
44
45/* Local vars.
46 */
47static int last_write_failed;
48static int need_flush;
49
50void zft_prevent_flush(void)
51{
52 need_flush = 0;
53}
54
55static int zft_write_header_segments(__u8* buffer)
56{
57 int header_1_ok = 0;
58 int header_2_ok = 0;
59 unsigned int time_stamp;
60 TRACE_FUN(ft_t_noise);
61
62 TRACE_CATCH(ftape_abort_operation(),);
63 ftape_seek_to_bot(); /* prevents extra rewind */
64 if (GET4(buffer, 0) != FT_HSEG_MAGIC) {
65 TRACE_ABORT(-EIO, ft_t_err,
66 "wrong header signature found, aborting");
67 }
68 /* Be optimistic: */
69 PUT4(buffer, FT_SEG_CNT,
70 zft_written_segments + GET4(buffer, FT_SEG_CNT) + 2);
71 if ((time_stamp = zft_get_time()) != 0) {
72 PUT4(buffer, FT_WR_DATE, time_stamp);
73 if (zft_label_changed) {
74 PUT4(buffer, FT_LABEL_DATE, time_stamp);
75 }
76 }
77 TRACE(ft_t_noise,
78 "writing first header segment %d", ft_header_segment_1);
79 header_1_ok = zft_verify_write_segments(ft_header_segment_1,
80 buffer, FT_SEGMENT_SIZE,
81 zft_deblock_buf) >= 0;
82 TRACE(ft_t_noise,
83 "writing second header segment %d", ft_header_segment_2);
84 header_2_ok = zft_verify_write_segments(ft_header_segment_2,
85 buffer, FT_SEGMENT_SIZE,
86 zft_deblock_buf) >= 0;
87 if (!header_1_ok) {
88 TRACE(ft_t_warn, "Warning: "
89 "update of first header segment failed");
90 }
91 if (!header_2_ok) {
92 TRACE(ft_t_warn, "Warning: "
93 "update of second header segment failed");
94 }
95 if (!header_1_ok && !header_2_ok) {
96 TRACE_ABORT(-EIO, ft_t_err, "Error: "
97 "update of both header segments failed.");
98 }
99 TRACE_EXIT 0;
100}
101
102int zft_update_header_segments(void)
103{
104 TRACE_FUN(ft_t_noise);
105
106 /* must NOT use zft_write_protected, as it also includes the
107 * file access mode. But we also want to update when soft
108 * write protection is enabled (O_RDONLY)
109 */
110 if (ft_write_protected || zft_old_ftape) {
111 TRACE_ABORT(0, ft_t_noise, "Tape set read-only: no update");
112 }
113 if (!zft_header_read) {
114 TRACE_ABORT(0, ft_t_noise, "Nothing to update");
115 }
116 if (!zft_header_changed) {
117 zft_header_changed = zft_written_segments > 0;
118 }
119 if (!zft_header_changed && !zft_volume_table_changed) {
120 TRACE_ABORT(0, ft_t_noise, "Nothing to update");
121 }
122 TRACE(ft_t_noise, "Updating header segments");
123 if (ftape_get_status()->fti_state == writing) {
124 TRACE_CATCH(ftape_loop_until_writes_done(),);
125 }
126 TRACE_CATCH(ftape_abort_operation(),);
127
128 zft_deblock_segment = -1; /* invalidate the cache */
129 if (zft_header_changed) {
130 TRACE_CATCH(zft_write_header_segments(zft_hseg_buf),);
131 }
132 if (zft_volume_table_changed) {
133 TRACE_CATCH(zft_update_volume_table(ft_first_data_segment),);
134 }
135 zft_header_changed =
136 zft_volume_table_changed =
137 zft_label_changed =
138 zft_written_segments = 0;
139 TRACE_CATCH(ftape_abort_operation(),);
140 ftape_seek_to_bot();
141 TRACE_EXIT 0;
142}
143
144static int read_merge_buffer(int seg_pos, __u8 *buffer, int offset, int seg_sz)
145{
146 int result = 0;
147 const ft_trace_t old_tracing = TRACE_LEVEL;
148 TRACE_FUN(ft_t_flow);
149
150 if (zft_qic_mode) {
151 /* writing in the middle of a volume is NOT allowed
152 *
153 */
154 TRACE(ft_t_noise, "No need to read a segment");
155 memset(buffer + offset, 0, seg_sz - offset);
156 TRACE_EXIT 0;
157 }
158 TRACE(ft_t_any, "waiting");
159 ftape_start_writing(FT_WR_MULTI);
160 TRACE_CATCH(ftape_loop_until_writes_done(),);
161
162 TRACE(ft_t_noise, "trying to read segment %d from offset %d",
163 seg_pos, offset);
164 SET_TRACE_LEVEL(ft_t_bug);
165 result = zft_fetch_segment_fraction(seg_pos, buffer,
166 FT_RD_SINGLE,
167 offset, seg_sz - offset);
168 SET_TRACE_LEVEL(old_tracing);
169 if (result != (seg_sz - offset)) {
170 TRACE(ft_t_noise, "Ignore error: read_segment() result: %d",
171 result);
172 memset(buffer + offset, 0, seg_sz - offset);
173 }
174 TRACE_EXIT 0;
175}
176
177/* flush the write buffer to tape and write an eof-marker at the
178 * current position if not in raw mode. This function always
179 * positions the tape before the eof-marker. _ftape_close() should
180 * then advance to the next segment.
181 *
182 * the parameter "finish_volume" describes whether to position before
183 * or after the possibly created file-mark. We always position after
184 * the file-mark when called from ftape_close() and a flush was needed
185 * (that is ftape_write() was the last tape operation before calling
186 * ftape_flush) But we always position before the file-mark when this
187 * function get's called from outside ftape_close()
188 */
189int zft_flush_buffers(void)
190{
191 int result;
192 int data_remaining;
193 int this_segs_size;
194 TRACE_FUN(ft_t_flow);
195
196 TRACE(ft_t_data_flow,
197 "entered, ftape_state = %d", ftape_get_status()->fti_state);
198 if (ftape_get_status()->fti_state != writing && !need_flush) {
199 TRACE_ABORT(0, ft_t_noise, "no need for flush");
200 }
201 zft_io_state = zft_idle; /* triggers some initializations for the
202 * read and write routines
203 */
204 if (last_write_failed) {
205 ftape_abort_operation();
206 TRACE_EXIT -EIO;
207 }
208 TRACE(ft_t_noise, "flushing write buffers");
209 this_segs_size = zft_get_seg_sz(zft_pos.seg_pos);
210 if (this_segs_size == zft_pos.seg_byte_pos) {
211 zft_pos.seg_pos ++;
212 data_remaining = zft_pos.seg_byte_pos = 0;
213 } else {
214 data_remaining = zft_pos.seg_byte_pos;
215 }
216 /* If there is any data not written to tape yet, append zero's
217 * up to the end of the sector (if using compression) or merge
218 * it with the data existing on the tape Then write the
219 * segment(s) to tape.
220 */
221 TRACE(ft_t_noise, "Position:\n"
222 KERN_INFO "seg_pos : %d\n"
223 KERN_INFO "byte pos : %d\n"
224 KERN_INFO "remaining: %d",
225 zft_pos.seg_pos, zft_pos.seg_byte_pos, data_remaining);
226 if (data_remaining > 0) {
227 do {
228 this_segs_size = zft_get_seg_sz(zft_pos.seg_pos);
229 if (this_segs_size > data_remaining) {
230 TRACE_CATCH(read_merge_buffer(zft_pos.seg_pos,
231 zft_deblock_buf,
232 data_remaining,
233 this_segs_size),
234 last_write_failed = 1);
235 }
236 result = ftape_write_segment(zft_pos.seg_pos,
237 zft_deblock_buf,
238 FT_WR_MULTI);
239 if (result != this_segs_size) {
240 TRACE(ft_t_err, "flush buffers failed");
241 zft_pos.tape_pos -= zft_pos.seg_byte_pos;
242 zft_pos.seg_byte_pos = 0;
243
244 last_write_failed = 1;
245 TRACE_EXIT result;
246 }
247 zft_written_segments ++;
248 TRACE(ft_t_data_flow,
249 "flush, moved out buffer: %d", result);
250 /* need next segment for more data (empty segments?)
251 */
252 if (result < data_remaining) {
253 if (result > 0) {
254 /* move remainder to buffer beginning
255 */
256 memmove(zft_deblock_buf,
257 zft_deblock_buf + result,
258 FT_SEGMENT_SIZE - result);
259 }
260 }
261 data_remaining -= result;
262 zft_pos.seg_pos ++;
263 } while (data_remaining > 0);
264 TRACE(ft_t_any, "result: %d", result);
265 zft_deblock_segment = --zft_pos.seg_pos;
266 if (data_remaining == 0) { /* first byte next segment */
267 zft_pos.seg_byte_pos = this_segs_size;
268 } else { /* after data previous segment, data_remaining < 0 */
269 zft_pos.seg_byte_pos = data_remaining + result;
270 }
271 } else {
272 TRACE(ft_t_noise, "zft_deblock_buf empty");
273 zft_pos.seg_pos --;
274 zft_pos.seg_byte_pos = zft_get_seg_sz (zft_pos.seg_pos);
275 ftape_start_writing(FT_WR_MULTI);
276 }
277 TRACE(ft_t_any, "waiting");
278 if ((result = ftape_loop_until_writes_done()) < 0) {
279 /* that's really bad. What to to with zft_tape_pos?
280 */
281 TRACE(ft_t_err, "flush buffers failed");
282 }
283 TRACE(ft_t_any, "zft_seg_pos: %d, zft_seg_byte_pos: %d",
284 zft_pos.seg_pos, zft_pos.seg_byte_pos);
285 last_write_failed =
286 need_flush = 0;
287 TRACE_EXIT result;
288}
289
290/* return-value: the number of bytes removed from the user-buffer
291 *
292 * out:
293 * int *write_cnt: how much actually has been moved to the
294 * zft_deblock_buf
295 * int req_len : MUST NOT BE CHANGED, except at EOT, in
296 * which case it may be adjusted
297 * in :
298 * char *buff : the user buffer
299 * int buf_pos_write : copy of buf_len_wr int
300 * this_segs_size : the size in bytes of the actual segment
301 * char
302 * *zft_deblock_buf : zft_deblock_buf
303 */
304static int zft_simple_write(int *cnt,
305 __u8 *dst_buf, const int seg_sz,
306 const __u8 __user *src_buf, const int req_len,
307 const zft_position *pos,const zft_volinfo *volume)
308{
309 int space_left;
310 TRACE_FUN(ft_t_flow);
311
312 /* volume->size holds the tape capacity while volume is open */
313 if (pos->tape_pos + volume->blk_sz > volume->size) {
314 TRACE_EXIT -ENOSPC;
315 }
316 /* remaining space in this segment, NOT zft_deblock_buf
317 */
318 space_left = seg_sz - pos->seg_byte_pos;
319 *cnt = req_len < space_left ? req_len : space_left;
320 if (copy_from_user(dst_buf + pos->seg_byte_pos, src_buf, *cnt) != 0) {
321 TRACE_EXIT -EFAULT;
322 }
323 TRACE_EXIT *cnt;
324}
325
326static int check_write_access(int req_len,
327 const zft_volinfo **volume,
328 zft_position *pos,
329 const unsigned int blk_sz)
330{
331 int result;
332 TRACE_FUN(ft_t_flow);
333
334 if ((req_len % zft_blk_sz) != 0) {
335 TRACE_ABORT(-EINVAL, ft_t_info,
336 "write-count %d must be multiple of block-size %d",
337 req_len, blk_sz);
338 }
339 if (zft_io_state == zft_writing) {
340 /* all other error conditions have been checked earlier
341 */
342 TRACE_EXIT 0;
343 }
344 zft_io_state = zft_idle;
345 TRACE_CATCH(zft_check_write_access(pos),);
346 /* If we haven't read the header segment yet, do it now.
347 * This will verify the configuration, get the bad sector
348 * table and read the volume table segment
349 */
350 if (!zft_header_read) {
351 TRACE_CATCH(zft_read_header_segments(),);
352 }
353 /* fine. Now the tape is either at BOT or at EOD,
354 * Write start of volume now
355 */
356 TRACE_CATCH(zft_open_volume(pos, blk_sz, zft_use_compression),);
357 *volume = zft_find_volume(pos->seg_pos);
358 DUMP_VOLINFO(ft_t_noise, "", *volume);
359 zft_just_before_eof = 0;
360 /* now merge with old data if necessary */
361 if (!zft_qic_mode && pos->seg_byte_pos != 0){
362 result = zft_fetch_segment(pos->seg_pos,
363 zft_deblock_buf,
364 FT_RD_SINGLE);
365 if (result < 0) {
366 if (result == -EINTR || result == -ENOSPC) {
367 TRACE_EXIT result;
368 }
369 TRACE(ft_t_noise,
370 "ftape_read_segment() result: %d. "
371 "This might be normal when using "
372 "a newly\nformatted tape", result);
373 memset(zft_deblock_buf, '\0', pos->seg_byte_pos);
374 }
375 }
376 zft_io_state = zft_writing;
377 TRACE_EXIT 0;
378}
379
380static int fill_deblock_buf(__u8 *dst_buf, const int seg_sz,
381 zft_position *pos, const zft_volinfo *volume,
382 const char __user *usr_buf, const int req_len)
383{
384 int cnt = 0;
385 int result = 0;
386 TRACE_FUN(ft_t_flow);
387
388 if (seg_sz == 0) {
389 TRACE_ABORT(0, ft_t_data_flow, "empty segment");
390 }
391 TRACE(ft_t_data_flow, "\n"
392 KERN_INFO "remaining req_len: %d\n"
393 KERN_INFO " buf_pos: %d",
394 req_len, pos->seg_byte_pos);
395 /* zft_deblock_buf will not contain a valid segment any longer */
396 zft_deblock_segment = -1;
397 if (zft_use_compression) {
398 TRACE_CATCH(zft_cmpr_lock(1 /* try to load */),);
399 TRACE_CATCH(result= (*zft_cmpr_ops->write)(&cnt,
400 dst_buf, seg_sz,
401 usr_buf, req_len,
402 pos, volume),);
403 } else {
404 TRACE_CATCH(result= zft_simple_write(&cnt,
405 dst_buf, seg_sz,
406 usr_buf, req_len,
407 pos, volume),);
408 }
409 pos->volume_pos += result;
410 pos->seg_byte_pos += cnt;
411 pos->tape_pos += cnt;
412 TRACE(ft_t_data_flow, "\n"
413 KERN_INFO "removed from user-buffer : %d bytes.\n"
414 KERN_INFO "copied to zft_deblock_buf: %d bytes.\n"
415 KERN_INFO "zft_tape_pos : " LL_X " bytes.",
416 result, cnt, LL(pos->tape_pos));
417 TRACE_EXIT result;
418}
419
420
421/* called by the kernel-interface routine "zft_write()"
422 */
423int _zft_write(const char __user *buff, int req_len)
424{
425 int result = 0;
426 int written = 0;
427 int write_cnt;
428 int seg_sz;
429 static const zft_volinfo *volume = NULL;
430 TRACE_FUN(ft_t_flow);
431
432 zft_resid = req_len;
433 last_write_failed = 1; /* reset to 0 when successful */
434 /* check if write is allowed
435 */
436 TRACE_CATCH(check_write_access(req_len, &volume,&zft_pos,zft_blk_sz),);
437 while (req_len > 0) {
438 /* Allow us to escape from this loop with a signal !
439 */
440 FT_SIGNAL_EXIT(_DONT_BLOCK);
441 seg_sz = zft_get_seg_sz(zft_pos.seg_pos);
442 if ((write_cnt = fill_deblock_buf(zft_deblock_buf,
443 seg_sz,
444 &zft_pos,
445 volume,
446 buff,
447 req_len)) < 0) {
448 zft_resid -= written;
449 if (write_cnt == -ENOSPC) {
450 /* leave the remainder to flush_buffers()
451 */
452 TRACE(ft_t_info, "No space left on device");
453 last_write_failed = 0;
454 if (!need_flush) {
455 need_flush = written > 0;
456 }
457 TRACE_EXIT written > 0 ? written : -ENOSPC;
458 } else {
459 TRACE_EXIT result;
460 }
461 }
462 if (zft_pos.seg_byte_pos == seg_sz) {
463 TRACE_CATCH(ftape_write_segment(zft_pos.seg_pos,
464 zft_deblock_buf,
465 FT_WR_ASYNC),
466 zft_resid -= written);
467 zft_written_segments ++;
468 zft_pos.seg_byte_pos = 0;
469 zft_deblock_segment = zft_pos.seg_pos;
470 ++zft_pos.seg_pos;
471 }
472 written += write_cnt;
473 buff += write_cnt;
474 req_len -= write_cnt;
475 } /* while (req_len > 0) */
476 TRACE(ft_t_data_flow, "remaining in blocking buffer: %d",
477 zft_pos.seg_byte_pos);
478 TRACE(ft_t_data_flow, "just written bytes: %d", written);
479 last_write_failed = 0;
480 zft_resid -= written;
481 need_flush = need_flush || written > 0;
482 TRACE_EXIT written; /* bytes written */
483}
diff --git a/drivers/char/ftape/zftape/zftape-write.h b/drivers/char/ftape/zftape/zftape-write.h
deleted file mode 100644
index ea887015b493..000000000000
--- a/drivers/char/ftape/zftape/zftape-write.h
+++ /dev/null
@@ -1,38 +0,0 @@
1#ifndef _ZFTAPE_WRITE_H
2#define _ZFTAPE_WRITE_H
3
4/*
5 * Copyright (C) 1996, 1997 Claus-Justus Heine
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; see the file COPYING. If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
20
21 *
22 * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-write.h,v $
23 * $Revision: 1.2 $
24 * $Date: 1997/10/05 19:19:13 $
25 *
26 * This file contains the definitions for the write functions
27 * for the zftape driver for Linux.
28 *
29 */
30
31extern int zft_flush_buffers(void);
32extern int zft_update_header_segments(void);
33extern void zft_prevent_flush(void);
34
35/* hook for the VFS interface
36 */
37extern int _zft_write(const char __user *buff, int req_len);
38#endif /* _ZFTAPE_WRITE_H */
diff --git a/drivers/char/ftape/zftape/zftape_syms.c b/drivers/char/ftape/zftape/zftape_syms.c
deleted file mode 100644
index 2db1401682df..000000000000
--- a/drivers/char/ftape/zftape/zftape_syms.c
+++ /dev/null
@@ -1,43 +0,0 @@
1/*
2 * Copyright (C) 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_syms.c,v $
20 * $Revision: 1.3 $
21 * $Date: 1997/10/05 19:19:14 $
22 *
23 * This file contains the symbols that the zftape frontend to
24 * the ftape floppy tape driver exports
25 */
26
27#include <linux/module.h>
28
29#include <linux/zftape.h>
30
31#include "../zftape/zftape-init.h"
32#include "../zftape/zftape-read.h"
33#include "../zftape/zftape-buffers.h"
34#include "../zftape/zftape-ctl.h"
35
36/* zftape-init.c */
37EXPORT_SYMBOL(zft_cmpr_register);
38/* zftape-read.c */
39EXPORT_SYMBOL(zft_fetch_segment_fraction);
40/* zftape-buffers.c */
41EXPORT_SYMBOL(zft_vmalloc_once);
42EXPORT_SYMBOL(zft_vmalloc_always);
43EXPORT_SYMBOL(zft_vfree);