1 |
1275 |
phoenix |
/*
|
2 |
|
|
* I use these routines just to decide when I have to fake a
|
3 |
|
|
* volume-table to preserve compatability 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: /home/marcus/revision_ctrl_test/oc_cvs/cvs/or1k/linux/linux-2.4/drivers/char/ftape/zftape/zftape-eof.c,v $
|
25 |
|
|
* $Revision: 1.1.1.1 $
|
26 |
|
|
* $Date: 2004-04-15 02:02:29 $
|
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 |
|
|
*/
|
46 |
|
|
eof_mark_union *zft_eof_map;
|
47 |
|
|
|
48 |
|
|
/* number of eof marks (entries in bad sector log) on tape.
|
49 |
|
|
*/
|
50 |
|
|
int zft_nr_eof_marks = -1;
|
51 |
|
|
|
52 |
|
|
|
53 |
|
|
/* Local vars.
|
54 |
|
|
*/
|
55 |
|
|
|
56 |
|
|
static char linux_tape_label[] = "Linux raw format V";
|
57 |
|
|
enum {
|
58 |
|
|
min_fmt_version = 1, max_fmt_version = 2
|
59 |
|
|
};
|
60 |
|
|
static 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 |
|
|
|
98 |
|
|
int 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 |
|
|
|
121 |
|
|
static __u8 * find_end_of_eof_list(__u8 * ptr, __u8 * limit)
|
122 |
|
|
{
|
123 |
|
|
while (ptr + 3 < limit) {
|
124 |
|
|
|
125 |
|
|
if (get_unaligned((__u32*)ptr)) {
|
126 |
|
|
++(__u32*)ptr;
|
127 |
|
|
} else {
|
128 |
|
|
return ptr;
|
129 |
|
|
}
|
130 |
|
|
}
|
131 |
|
|
return NULL;
|
132 |
|
|
}
|
133 |
|
|
|
134 |
|
|
void 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 |
|
|
|
186 |
|
|
void 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 |
|
|
}
|