2 * Copyright (C) 1996, 1997 Claus-Justus Heine
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)
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.
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.
19 * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-rw.c,v $
21 * $Date: 1997/10/05 19:19:08 $
23 * This file contains some common code for the r/w code for
27 #include <linux/config.h> /* for CONFIG_ZFT_DFLT_BLK_SZ */
28 #include <linux/errno.h>
31 #include <linux/zftape.h>
32 #include "../zftape/zftape-init.h"
33 #include "../zftape/zftape-eof.h"
34 #include "../zftape/zftape-ctl.h"
35 #include "../zftape/zftape-write.h"
36 #include "../zftape/zftape-read.h"
37 #include "../zftape/zftape-rw.h"
38 #include "../zftape/zftape-vtbl.h"
43 __u8 *zft_deblock_buf;
45 int zft_deblock_segment = -1;
46 zft_status_enum zft_io_state = zft_idle;
47 int zft_header_changed;
48 int zft_bad_sector_map_changed;
49 int zft_qic113; /* conform to old specs. and old zftape */
50 int zft_use_compression;
51 zft_position zft_pos = {
57 unsigned int zft_blk_sz = CONFIG_ZFT_DFLT_BLK_SZ;
60 unsigned int zft_written_segments;
61 int zft_label_changed;
66 unsigned int zft_get_seg_sz(unsigned int segment)
71 size = FT_SEGMENT_SIZE -
72 count_ones(ftape_get_bad_sector_entry(segment))*FT_SECTOR_SIZE;
74 TRACE_EXIT (unsigned)size;
80 /* ftape_set_flags(). Claus-Justus Heine, 1994/1995
82 void zft_set_flags(unsigned minor_unit)
86 zft_use_compression = zft_qic_mode = 0;
87 switch (minor_unit & ZFT_MINOR_OP_MASK) {
88 case (ZFT_Q80_MODE | ZFT_ZIP_MODE):
90 zft_use_compression = 1;
94 if (zft_mt_compression) { /* override the default */
95 zft_use_compression = 1;
99 TRACE(ft_t_noise, "switching to raw mode");
102 TRACE(ft_t_warn, "Warning:\n"
103 KERN_INFO "Wrong combination of minor device bits.\n"
104 KERN_INFO "Switching to raw read-only mode.");
105 zft_write_protected = 1;
111 /* computes the segment and byte offset inside the segment
112 * corresponding to tape_pos.
114 * tape_pos gives the offset in bytes from the beginning of the
115 * ft_first_data_segment *seg_byte_pos is the offset in the current
118 * Of, if this routine was called often one should cache the last data
119 * pos it was called with, but actually this is only needed in
120 * ftape_seek_block(), that is, almost never.
122 int zft_calc_seg_byte_coord(int *seg_byte_pos, __s64 tape_pos)
126 TRACE_FUN(ft_t_flow);
130 segment = ft_first_data_segment;
134 for (segment = ft_first_data_segment;
135 ((tape_pos > 0) && (segment <= ft_last_data_segment));
137 seg_sz = zft_get_seg_sz(segment);
141 /* the case tape_pos > != 0 means that the
142 * argument tape_pos lies beyond the EOT.
145 } else { /* tape_pos < 0 */
147 *seg_byte_pos= tape_pos + seg_sz;
153 /* ftape_calc_tape_pos().
155 * computes the offset in bytes from the beginning of the
156 * ft_first_data_segment inverse to ftape_calc_seg_byte_coord
158 * We should do some caching. But how:
160 * Each time the header segments are read in, this routine is called
161 * with ft_tracks_per_tape*segments_per_track argumnet. So this should be
162 * the time to reset the cache.
164 * Also, it might be in the future that the bad sector map gets
165 * changed. -> reset the cache
168 static __s64 tape_pos;
170 __s64 zft_get_capacity(void)
172 seg_pos = ft_first_data_segment;
175 while (seg_pos <= ft_last_data_segment) {
176 tape_pos += zft_get_seg_sz(seg_pos ++);
181 __s64 zft_calc_tape_pos(int segment)
186 if (segment > ft_last_data_segment) {
187 TRACE_EXIT zft_capacity;
189 if (segment < ft_first_data_segment) {
192 d2 = segment - seg_pos;
194 d1 = segment - ft_first_data_segment;
197 seg_pos = ft_first_data_segment;
202 d3 = ft_last_data_segment - segment;
204 tape_pos = zft_capacity;
205 seg_pos = ft_last_data_segment + 1;
210 while (seg_pos < segment) {
211 tape_pos += zft_get_seg_sz(seg_pos++);
214 while (seg_pos > segment) {
215 tape_pos -= zft_get_seg_sz(--seg_pos);
218 TRACE(ft_t_noise, "new cached pos: %d", seg_pos);
223 /* copy Z-label string to buffer, keeps track of the correct offset in
226 void zft_update_label(__u8 *buffer)
228 TRACE_FUN(ft_t_flow);
230 if (strncmp(&buffer[FT_LABEL], ZFTAPE_LABEL,
231 sizeof(ZFTAPE_LABEL)-1) != 0) {
232 TRACE(ft_t_info, "updating label from \"%s\" to \"%s\"",
233 &buffer[FT_LABEL], ZFTAPE_LABEL);
234 strcpy(&buffer[FT_LABEL], ZFTAPE_LABEL);
235 memset(&buffer[FT_LABEL] + sizeof(ZFTAPE_LABEL) - 1, ' ',
236 FT_LABEL_SZ - sizeof(ZFTAPE_LABEL + 1));
237 PUT4(buffer, FT_LABEL_DATE, 0);
238 zft_label_changed = zft_header_changed = 1; /* changed */
243 int zft_verify_write_segments(unsigned int segment,
244 __u8 *data, size_t size,
254 ft_write_mode_t write_mode;
255 TRACE_FUN(ft_t_flow);
258 seg_sz = zft_get_seg_sz(seg_pos);
260 single = size <= seg_sz;
263 TRACE(ft_t_noise, "\n"
264 KERN_INFO "remaining: %d\n"
265 KERN_INFO "seg_sz : %d\n"
266 KERN_INFO "segment : %d",
267 remaining, seg_sz, seg_pos);
268 if (remaining == seg_sz) {
270 write_mode = single ? FT_WR_SINGLE : FT_WR_MULTI;
272 } else if (remaining > seg_sz) {
274 write_mode = FT_WR_ASYNC; /* don't start tape */
276 } else { /* remaining < seg_sz */
278 memcpy(write_buf, src_buf, remaining);
279 memset(&write_buf[remaining],'\0',seg_sz-remaining);
280 write_mode = single ? FT_WR_SINGLE : FT_WR_MULTI;
283 if ((result = ftape_write_segment(seg_pos,
285 write_mode)) != seg_sz) {
286 TRACE(ft_t_err, "Error: "
287 "Couldn't write segment %d", seg_pos);
288 TRACE_EXIT result < 0 ? result : -EIO; /* bail out */
290 zft_written_segments ++;
291 seg_sz = zft_get_seg_sz(++seg_pos);
293 } while (remaining > 0);
294 if (ftape_get_status()->fti_state == writing) {
295 TRACE_CATCH(ftape_loop_until_writes_done(),);
296 TRACE_CATCH(ftape_abort_operation(),);
303 TRACE_CATCH(result = ftape_read_segment(seg_pos, buffer,
304 single ? FT_RD_SINGLE
306 if (memcmp(src_buf, buffer,
307 remaining > result ? result : remaining) != 0) {
308 TRACE_ABORT(-EIO, ft_t_err,
309 "Failed to verify written segment %d",
313 TRACE(ft_t_noise, "verify successful:\n"
314 KERN_INFO "segment : %d\n"
315 KERN_INFO "segsize : %d\n"
316 KERN_INFO "remaining: %d",
317 seg_pos, result, remaining);
320 } while (remaining > 0);
325 /* zft_erase(). implemented compression-handling
327 * calculate the first data-segment when using/not using compression.
329 * update header-segment and compression-map-segment.
334 TRACE_FUN(ft_t_flow);
336 if (!zft_header_read) {
337 TRACE_CATCH(zft_vmalloc_once((void **)&zft_hseg_buf,
339 /* no need to read the vtbl and compression map */
340 TRACE_CATCH(ftape_read_header_segment(zft_hseg_buf),);
342 zft_ftape_validate_label(&zft_hseg_buf[FT_LABEL]))) {
343 zft_ftape_extract_file_marks(zft_hseg_buf);
346 "ft_first_data_segment: %d, ft_last_data_segment: %d",
347 ft_first_data_segment, ft_last_data_segment);
348 zft_qic113 = (ft_format_code != fmt_normal &&
349 ft_format_code != fmt_1100ft &&
350 ft_format_code != fmt_425ft);
353 zft_clear_ftape_file_marks();
354 zft_old_ftape = 0; /* no longer old ftape */
356 PUT2(zft_hseg_buf, FT_CMAP_START, 0);
357 zft_volume_table_changed = 1;
358 zft_capacity = zft_get_capacity();
360 /* the rest must be done in ftape_update_header_segments
363 zft_header_changed = 1; /* force update of timestamp */
364 result = zft_update_header_segments();
366 ftape_abort_operation();
368 zft_reset_position(&zft_pos);
369 zft_set_flags (zft_unit);
373 unsigned int zft_get_time(void)
375 unsigned int date = FT_TIME_STAMP(2097, 11, 30, 23, 59, 59); /* fun */