diff options
Diffstat (limited to 'drivers/char/ftape/zftape/zftape-eof.c')
-rw-r--r-- | drivers/char/ftape/zftape/zftape-eof.c | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/drivers/char/ftape/zftape/zftape-eof.c b/drivers/char/ftape/zftape/zftape-eof.c new file mode 100644 index 000000000000..dcadcaee9ac1 --- /dev/null +++ b/drivers/char/ftape/zftape/zftape-eof.c | |||
@@ -0,0 +1,199 @@ | |||
1 | /* | ||
2 | * I use these routines just to decide when I have to fake a | ||
3 | * volume-table to preserve compatibility 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: /homes/cvs/ftape-stacked/ftape/zftape/zftape-eof.c,v $ | ||
25 | * $Revision: 1.2 $ | ||
26 | * $Date: 1997/10/05 19:19:02 $ | ||
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 | ptr += sizeof(__u32); | ||
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 | } | ||