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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *      Copyright (C) 1996, 1997 Claus-Justus Heine
3
 
4
 This program is free software; you can redistribute it and/or modify
5
 it under the terms of the GNU General Public License as published by
6
 the Free Software Foundation; either version 2, or (at your option)
7
 any later version.
8
 
9
 This program is distributed in the hope that it will be useful,
10
 but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 GNU General Public License for more details.
13
 
14
 You should have received a copy of the GNU General Public License
15
 along with this program; see the file COPYING.  If not, write to
16
 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
17
 
18
 *
19
 * $Source: /home/marcus/revision_ctrl_test/oc_cvs/cvs/or1k/linux/linux-2.4/drivers/char/ftape/zftape/zftape-rw.c,v $
20
 * $Revision: 1.1.1.1 $
21
 * $Date: 2004-04-15 02:02:31 $
22
 *
23
 *      This file contains some common code for the r/w code for
24
 *      zftape.
25
 */
26
 
27
#include <linux/config.h> /* for CONFIG_ZFT_DFLT_BLK_SZ */
28
#include <linux/errno.h>
29
#include <linux/mm.h>
30
#include <asm/segment.h>
31
 
32
#include <linux/zftape.h>
33
#include "../zftape/zftape-init.h"
34
#include "../zftape/zftape-eof.h"
35
#include "../zftape/zftape-ctl.h"
36
#include "../zftape/zftape-write.h"
37
#include "../zftape/zftape-read.h"
38
#include "../zftape/zftape-rw.h"
39
#include "../zftape/zftape-vtbl.h"
40
 
41
/*      Global vars.
42
 */
43
 
44
__u8 *zft_deblock_buf;
45
__u8 *zft_hseg_buf;
46
int zft_deblock_segment = -1;
47
zft_status_enum zft_io_state = zft_idle;
48
int zft_header_changed;
49
int zft_bad_sector_map_changed;
50
int zft_qic113; /* conform to old specs. and old zftape */
51
int zft_use_compression;
52
zft_position zft_pos = {
53
        -1, /* seg_pos */
54
        0,  /* seg_byte_pos */
55
        0,  /* tape_pos */
56
 
57
};
58
unsigned int zft_blk_sz = CONFIG_ZFT_DFLT_BLK_SZ;
59
__s64 zft_capacity;
60
 
61
unsigned int zft_written_segments;
62
int zft_label_changed;
63
 
64
/*      Local vars.
65
 */
66
 
67
unsigned int zft_get_seg_sz(unsigned int segment)
68
{
69
        int size;
70
        TRACE_FUN(ft_t_any);
71
 
72
        size = FT_SEGMENT_SIZE -
73
                count_ones(ftape_get_bad_sector_entry(segment))*FT_SECTOR_SIZE;
74
        if (size > 0) {
75
                TRACE_EXIT (unsigned)size;
76
        } else {
77
                TRACE_EXIT 0;
78
        }
79
}
80
 
81
/* ftape_set_flags(). Claus-Justus Heine, 1994/1995
82
 */
83
void zft_set_flags(unsigned minor_unit)
84
{
85
        TRACE_FUN(ft_t_flow);
86
 
87
        zft_use_compression = zft_qic_mode = 0;
88
        switch (minor_unit & ZFT_MINOR_OP_MASK) {
89
        case (ZFT_Q80_MODE | ZFT_ZIP_MODE):
90
        case ZFT_ZIP_MODE:
91
                zft_use_compression = 1;
92
        case 0:
93
        case ZFT_Q80_MODE:
94
                zft_qic_mode = 1;
95
                if (zft_mt_compression) { /* override the default */
96
                        zft_use_compression = 1;
97
                }
98
                break;
99
        case ZFT_RAW_MODE:
100
                TRACE(ft_t_noise, "switching to raw mode");
101
                break;
102
        default:
103
                TRACE(ft_t_warn, "Warning:\n"
104
                      KERN_INFO "Wrong combination of minor device bits.\n"
105
                      KERN_INFO "Switching to raw read-only mode.");
106
                zft_write_protected = 1;
107
                break;
108
        }
109
        TRACE_EXIT;
110
}
111
 
112
/* computes the segment and byte offset inside the segment
113
 * corresponding to tape_pos.
114
 *
115
 * tape_pos gives the offset in bytes from the beginning of the
116
 * ft_first_data_segment *seg_byte_pos is the offset in the current
117
 * segment in bytes
118
 *
119
 * Of, if this routine was called often one should cache the last data
120
 * pos it was called with, but actually this is only needed in
121
 * ftape_seek_block(), that is, almost never.
122
 */
123
int zft_calc_seg_byte_coord(int *seg_byte_pos, __s64 tape_pos)
124
{
125
        int segment;
126
        int seg_sz;
127
        TRACE_FUN(ft_t_flow);
128
 
129
        if (tape_pos == 0) {
130
                *seg_byte_pos = 0;
131
                segment = ft_first_data_segment;
132
        } else {
133
                seg_sz = 0;
134
 
135
                for (segment = ft_first_data_segment;
136
                     ((tape_pos > 0) && (segment <= ft_last_data_segment));
137
                     segment++) {
138
                        seg_sz = zft_get_seg_sz(segment);
139
                        tape_pos -= seg_sz;
140
                }
141
                if(tape_pos >= 0) {
142
                        /* the case tape_pos > != 0 means that the
143
                         * argument tape_pos lies beyond the EOT.
144
                         */
145
                        *seg_byte_pos= 0;
146
                } else { /* tape_pos < 0 */
147
                        segment--;
148
                        *seg_byte_pos= tape_pos + seg_sz;
149
                }
150
        }
151
        TRACE_EXIT(segment);
152
}
153
 
154
/* ftape_calc_tape_pos().
155
 *
156
 * computes the offset in bytes from the beginning of the
157
 * ft_first_data_segment inverse to ftape_calc_seg_byte_coord
158
 *
159
 * We should do some caching. But how:
160
 *
161
 * Each time the header segments are read in, this routine is called
162
 * with ft_tracks_per_tape*segments_per_track argumnet. So this should be
163
 * the time to reset the cache.
164
 *
165
 * Also, it might be in the future that the bad sector map gets
166
 * changed.  -> reset the cache
167
 */
168
static int seg_pos;
169
static __s64 tape_pos;
170
 
171
__s64 zft_get_capacity(void)
172
{
173
        seg_pos  = ft_first_data_segment;
174
        tape_pos = 0;
175
 
176
        while (seg_pos <= ft_last_data_segment) {
177
                tape_pos += zft_get_seg_sz(seg_pos ++);
178
        }
179
        return tape_pos;
180
}
181
 
182
__s64 zft_calc_tape_pos(int segment)
183
{
184
        int d1, d2, d3;
185
        TRACE_FUN(ft_t_any);
186
 
187
        if (segment > ft_last_data_segment) {
188
                TRACE_EXIT zft_capacity;
189
        }
190
        if (segment < ft_first_data_segment) {
191
                TRACE_EXIT 0;
192
        }
193
        d2 = segment - seg_pos;
194
        if (-d2 > 10) {
195
                d1 = segment - ft_first_data_segment;
196
                if (-d2 > d1) {
197
                        tape_pos = 0;
198
                        seg_pos = ft_first_data_segment;
199
                        d2 = d1;
200
                }
201
        }
202
        if (d2 > 10) {
203
                d3 = ft_last_data_segment - segment;
204
                if (d2 > d3) {
205
                        tape_pos = zft_capacity;
206
                        seg_pos  = ft_last_data_segment + 1;
207
                        d2 = -d3;
208
                }
209
        }
210
        if (d2 > 0) {
211
                while (seg_pos < segment) {
212
                        tape_pos +=  zft_get_seg_sz(seg_pos++);
213
                }
214
        } else {
215
                while (seg_pos > segment) {
216
                        tape_pos -=  zft_get_seg_sz(--seg_pos);
217
                }
218
        }
219
        TRACE(ft_t_noise, "new cached pos: %d", seg_pos);
220
 
221
        TRACE_EXIT tape_pos;
222
}
223
 
224
/* copy Z-label string to buffer, keeps track of the correct offset in
225
 * `buffer'
226
 */
227
void zft_update_label(__u8 *buffer)
228
{
229
        TRACE_FUN(ft_t_flow);
230
 
231
        if (strncmp(&buffer[FT_LABEL], ZFTAPE_LABEL,
232
                    sizeof(ZFTAPE_LABEL)-1) != 0) {
233
                TRACE(ft_t_info, "updating label from \"%s\" to \"%s\"",
234
                      &buffer[FT_LABEL], ZFTAPE_LABEL);
235
                strcpy(&buffer[FT_LABEL], ZFTAPE_LABEL);
236
                memset(&buffer[FT_LABEL] + sizeof(ZFTAPE_LABEL) - 1, ' ',
237
                       FT_LABEL_SZ - sizeof(ZFTAPE_LABEL + 1));
238
                PUT4(buffer, FT_LABEL_DATE, 0);
239
                zft_label_changed = zft_header_changed = 1; /* changed */
240
        }
241
        TRACE_EXIT;
242
}
243
 
244
int zft_verify_write_segments(unsigned int segment,
245
                              __u8 *data, size_t size,
246
                              __u8 *buffer)
247
{
248
        int result;
249
        __u8 *write_buf;
250
        __u8 *src_buf;
251
        int single;
252
        int seg_pos;
253
        int seg_sz;
254
        int remaining;
255
        ft_write_mode_t write_mode;
256
        TRACE_FUN(ft_t_flow);
257
 
258
        seg_pos   = segment;
259
        seg_sz    = zft_get_seg_sz(seg_pos);
260
        src_buf   = data;
261
        single    = size <= seg_sz;
262
        remaining = size;
263
        do {
264
                TRACE(ft_t_noise, "\n"
265
                      KERN_INFO "remaining: %d\n"
266
                      KERN_INFO "seg_sz   : %d\n"
267
                      KERN_INFO "segment  : %d",
268
                      remaining, seg_sz, seg_pos);
269
                if (remaining == seg_sz) {
270
                        write_buf = src_buf;
271
                        write_mode = single ? FT_WR_SINGLE : FT_WR_MULTI;
272
                        remaining = 0;
273
                } else if (remaining > seg_sz) {
274
                        write_buf = src_buf;
275
                        write_mode = FT_WR_ASYNC; /* don't start tape */
276
                        remaining -= seg_sz;
277
                } else { /* remaining < seg_sz */
278
                        write_buf = buffer;
279
                        memcpy(write_buf, src_buf, remaining);
280
                        memset(&write_buf[remaining],'\0',seg_sz-remaining);
281
                        write_mode = single ? FT_WR_SINGLE : FT_WR_MULTI;
282
                        remaining = 0;
283
                }
284
                if ((result = ftape_write_segment(seg_pos,
285
                                                  write_buf,
286
                                                  write_mode)) != seg_sz) {
287
                        TRACE(ft_t_err, "Error: "
288
                              "Couldn't write segment %d", seg_pos);
289
                        TRACE_EXIT result < 0 ? result : -EIO; /* bail out */
290
                }
291
                zft_written_segments ++;
292
                seg_sz = zft_get_seg_sz(++seg_pos);
293
                src_buf += result;
294
        } while (remaining > 0);
295
        if (ftape_get_status()->fti_state == writing) {
296
                TRACE_CATCH(ftape_loop_until_writes_done(),);
297
                TRACE_CATCH(ftape_abort_operation(),);
298
                zft_prevent_flush();
299
        }
300
        seg_pos = segment;
301
        src_buf = data;
302
        remaining = size;
303
        do {
304
                TRACE_CATCH(result = ftape_read_segment(seg_pos, buffer,
305
                                                        single ? FT_RD_SINGLE
306
                                                        : FT_RD_AHEAD),);
307
                if (memcmp(src_buf, buffer,
308
                           remaining > result ? result : remaining) != 0) {
309
                        TRACE_ABORT(-EIO, ft_t_err,
310
                                    "Failed to verify written segment %d",
311
                                    seg_pos);
312
                }
313
                remaining -= result;
314
                TRACE(ft_t_noise, "verify successful:\n"
315
                      KERN_INFO "segment  : %d\n"
316
                      KERN_INFO "segsize  : %d\n"
317
                      KERN_INFO "remaining: %d",
318
                      seg_pos, result, remaining);
319
                src_buf   += seg_sz;
320
                seg_pos++;
321
        } while (remaining > 0);
322
        TRACE_EXIT size;
323
}
324
 
325
 
326
/* zft_erase().  implemented compression-handling
327
 *
328
 * calculate the first data-segment when using/not using compression.
329
 *
330
 * update header-segment and compression-map-segment.
331
 */
332
int zft_erase(void)
333
{
334
        int result = 0;
335
        TRACE_FUN(ft_t_flow);
336
 
337
        if (!zft_header_read) {
338
                TRACE_CATCH(zft_vmalloc_once((void **)&zft_hseg_buf,
339
                                             FT_SEGMENT_SIZE),);
340
                /* no need to read the vtbl and compression map */
341
                TRACE_CATCH(ftape_read_header_segment(zft_hseg_buf),);
342
                if ((zft_old_ftape =
343
                     zft_ftape_validate_label(&zft_hseg_buf[FT_LABEL]))) {
344
                        zft_ftape_extract_file_marks(zft_hseg_buf);
345
                }
346
                TRACE(ft_t_noise,
347
                      "ft_first_data_segment: %d, ft_last_data_segment: %d",
348
                      ft_first_data_segment, ft_last_data_segment);
349
                zft_qic113 = (ft_format_code != fmt_normal &&
350
                              ft_format_code != fmt_1100ft &&
351
                              ft_format_code != fmt_425ft);
352
        }
353
        if (zft_old_ftape) {
354
                zft_clear_ftape_file_marks();
355
                zft_old_ftape = 0; /* no longer old ftape */
356
        }
357
        PUT2(zft_hseg_buf, FT_CMAP_START, 0);
358
        zft_volume_table_changed = 1;
359
        zft_capacity = zft_get_capacity();
360
        zft_init_vtbl();
361
        /* the rest must be done in ftape_update_header_segments
362
         */
363
        zft_header_read = 1;
364
        zft_header_changed = 1; /* force update of timestamp */
365
        result = zft_update_header_segments();
366
 
367
        ftape_abort_operation();
368
 
369
        zft_reset_position(&zft_pos);
370
        zft_set_flags (zft_unit);
371
        TRACE_EXIT result;
372
}
373
 
374
unsigned int zft_get_time(void)
375
{
376
        unsigned int date = FT_TIME_STAMP(2097, 11, 30, 23, 59, 59); /* fun */
377
        return date;
378
}

powered by: WebSVN 2.1.0

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