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_qic113
; /* conform to old specs. and old zftape */
49 int zft_use_compression
;
50 zft_position zft_pos
= {
56 unsigned int zft_blk_sz
= CONFIG_ZFT_DFLT_BLK_SZ
;
59 unsigned int zft_written_segments
;
60 int zft_label_changed
;
65 unsigned int zft_get_seg_sz(unsigned int segment
)
70 size
= FT_SEGMENT_SIZE
-
71 count_ones(ftape_get_bad_sector_entry(segment
))*FT_SECTOR_SIZE
;
73 TRACE_EXIT (unsigned)size
;
79 /* ftape_set_flags(). Claus-Justus Heine, 1994/1995
81 void zft_set_flags(unsigned minor_unit
)
85 zft_use_compression
= zft_qic_mode
= 0;
86 switch (minor_unit
& ZFT_MINOR_OP_MASK
) {
87 case (ZFT_Q80_MODE
| ZFT_ZIP_MODE
):
89 zft_use_compression
= 1;
93 if (zft_mt_compression
) { /* override the default */
94 zft_use_compression
= 1;
98 TRACE(ft_t_noise
, "switching to raw mode");
101 TRACE(ft_t_warn
, "Warning:\n"
102 KERN_INFO
"Wrong combination of minor device bits.\n"
103 KERN_INFO
"Switching to raw read-only mode.");
104 zft_write_protected
= 1;
110 /* computes the segment and byte offset inside the segment
111 * corresponding to tape_pos.
113 * tape_pos gives the offset in bytes from the beginning of the
114 * ft_first_data_segment *seg_byte_pos is the offset in the current
117 * Of, if this routine was called often one should cache the last data
118 * pos it was called with, but actually this is only needed in
119 * ftape_seek_block(), that is, almost never.
121 int zft_calc_seg_byte_coord(int *seg_byte_pos
, __s64 tape_pos
)
125 TRACE_FUN(ft_t_flow
);
129 segment
= ft_first_data_segment
;
133 for (segment
= ft_first_data_segment
;
134 ((tape_pos
> 0) && (segment
<= ft_last_data_segment
));
136 seg_sz
= zft_get_seg_sz(segment
);
140 /* the case tape_pos > != 0 means that the
141 * argument tape_pos lies beyond the EOT.
144 } else { /* tape_pos < 0 */
146 *seg_byte_pos
= tape_pos
+ seg_sz
;
152 /* ftape_calc_tape_pos().
154 * computes the offset in bytes from the beginning of the
155 * ft_first_data_segment inverse to ftape_calc_seg_byte_coord
157 * We should do some caching. But how:
159 * Each time the header segments are read in, this routine is called
160 * with ft_tracks_per_tape*segments_per_track argumnet. So this should be
161 * the time to reset the cache.
163 * Also, it might be in the future that the bad sector map gets
164 * changed. -> reset the cache
167 static __s64 tape_pos
;
169 __s64
zft_get_capacity(void)
171 seg_pos
= ft_first_data_segment
;
174 while (seg_pos
<= ft_last_data_segment
) {
175 tape_pos
+= zft_get_seg_sz(seg_pos
++);
180 __s64
zft_calc_tape_pos(int segment
)
185 if (segment
> ft_last_data_segment
) {
186 TRACE_EXIT zft_capacity
;
188 if (segment
< ft_first_data_segment
) {
191 d2
= segment
- seg_pos
;
193 d1
= segment
- ft_first_data_segment
;
196 seg_pos
= ft_first_data_segment
;
201 d3
= ft_last_data_segment
- segment
;
203 tape_pos
= zft_capacity
;
204 seg_pos
= ft_last_data_segment
+ 1;
209 while (seg_pos
< segment
) {
210 tape_pos
+= zft_get_seg_sz(seg_pos
++);
213 while (seg_pos
> segment
) {
214 tape_pos
-= zft_get_seg_sz(--seg_pos
);
217 TRACE(ft_t_noise
, "new cached pos: %d", seg_pos
);
222 /* copy Z-label string to buffer, keeps track of the correct offset in
225 void zft_update_label(__u8
*buffer
)
227 TRACE_FUN(ft_t_flow
);
229 if (strncmp(&buffer
[FT_LABEL
], ZFTAPE_LABEL
,
230 sizeof(ZFTAPE_LABEL
)-1) != 0) {
231 TRACE(ft_t_info
, "updating label from \"%s\" to \"%s\"",
232 &buffer
[FT_LABEL
], ZFTAPE_LABEL
);
233 strcpy(&buffer
[FT_LABEL
], ZFTAPE_LABEL
);
234 memset(&buffer
[FT_LABEL
] + sizeof(ZFTAPE_LABEL
) - 1, ' ',
235 FT_LABEL_SZ
- sizeof(ZFTAPE_LABEL
+ 1));
236 PUT4(buffer
, FT_LABEL_DATE
, 0);
237 zft_label_changed
= zft_header_changed
= 1; /* changed */
242 int zft_verify_write_segments(unsigned int segment
,
243 __u8
*data
, size_t size
,
253 ft_write_mode_t write_mode
;
254 TRACE_FUN(ft_t_flow
);
257 seg_sz
= zft_get_seg_sz(seg_pos
);
259 single
= size
<= seg_sz
;
262 TRACE(ft_t_noise
, "\n"
263 KERN_INFO
"remaining: %d\n"
264 KERN_INFO
"seg_sz : %d\n"
265 KERN_INFO
"segment : %d",
266 remaining
, seg_sz
, seg_pos
);
267 if (remaining
== seg_sz
) {
269 write_mode
= single
? FT_WR_SINGLE
: FT_WR_MULTI
;
271 } else if (remaining
> seg_sz
) {
273 write_mode
= FT_WR_ASYNC
; /* don't start tape */
275 } else { /* remaining < seg_sz */
277 memcpy(write_buf
, src_buf
, remaining
);
278 memset(&write_buf
[remaining
],'\0',seg_sz
-remaining
);
279 write_mode
= single
? FT_WR_SINGLE
: FT_WR_MULTI
;
282 if ((result
= ftape_write_segment(seg_pos
,
284 write_mode
)) != seg_sz
) {
285 TRACE(ft_t_err
, "Error: "
286 "Couldn't write segment %d", seg_pos
);
287 TRACE_EXIT result
< 0 ? result
: -EIO
; /* bail out */
289 zft_written_segments
++;
290 seg_sz
= zft_get_seg_sz(++seg_pos
);
292 } while (remaining
> 0);
293 if (ftape_get_status()->fti_state
== writing
) {
294 TRACE_CATCH(ftape_loop_until_writes_done(),);
295 TRACE_CATCH(ftape_abort_operation(),);
302 TRACE_CATCH(result
= ftape_read_segment(seg_pos
, buffer
,
303 single
? FT_RD_SINGLE
305 if (memcmp(src_buf
, buffer
,
306 remaining
> result
? result
: remaining
) != 0) {
307 TRACE_ABORT(-EIO
, ft_t_err
,
308 "Failed to verify written segment %d",
312 TRACE(ft_t_noise
, "verify successful:\n"
313 KERN_INFO
"segment : %d\n"
314 KERN_INFO
"segsize : %d\n"
315 KERN_INFO
"remaining: %d",
316 seg_pos
, result
, remaining
);
319 } while (remaining
> 0);
324 /* zft_erase(). implemented compression-handling
326 * calculate the first data-segment when using/not using compression.
328 * update header-segment and compression-map-segment.
333 TRACE_FUN(ft_t_flow
);
335 if (!zft_header_read
) {
336 TRACE_CATCH(zft_vmalloc_once((void **)&zft_hseg_buf
,
338 /* no need to read the vtbl and compression map */
339 TRACE_CATCH(ftape_read_header_segment(zft_hseg_buf
),);
341 zft_ftape_validate_label(&zft_hseg_buf
[FT_LABEL
]))) {
342 zft_ftape_extract_file_marks(zft_hseg_buf
);
345 "ft_first_data_segment: %d, ft_last_data_segment: %d",
346 ft_first_data_segment
, ft_last_data_segment
);
347 zft_qic113
= (ft_format_code
!= fmt_normal
&&
348 ft_format_code
!= fmt_1100ft
&&
349 ft_format_code
!= fmt_425ft
);
352 zft_clear_ftape_file_marks();
353 zft_old_ftape
= 0; /* no longer old ftape */
355 PUT2(zft_hseg_buf
, FT_CMAP_START
, 0);
356 zft_volume_table_changed
= 1;
357 zft_capacity
= zft_get_capacity();
359 /* the rest must be done in ftape_update_header_segments
362 zft_header_changed
= 1; /* force update of timestamp */
363 result
= zft_update_header_segments();
365 ftape_abort_operation();
367 zft_reset_position(&zft_pos
);
368 zft_set_flags (zft_unit
);
372 unsigned int zft_get_time(void)
374 unsigned int date
= FT_TIME_STAMP(2097, 11, 30, 23, 59, 59); /* fun */