aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/ftape/zftape/zftape-rw.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/ftape/zftape/zftape-rw.c')
-rw-r--r--drivers/char/ftape/zftape/zftape-rw.c375
1 files changed, 0 insertions, 375 deletions
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}