This source file includes following definitions.
- fix_tape
- find_end_of_bsm_list
- store_bad_sector_map
- put_sector
- get_sector
- extract_bad_sector_map
- cvt2map
- cvt2segment
- forward_seek_entry
- backwards_seek_entry
- put_bad_sector_entry
- get_bad_sector_entry
- ftape_init_bsm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 #include <linux/ftape.h>
31 #include <linux/string.h>
32
33 #include "tracing.h"
34 #include "ftape-bsm.h"
35 #include "ftape-ctl.h"
36 #include "ftape-rw.h"
37
38
39
40
41 int bad_sector_map_changed = 0;
42
43
44
45 static byte bad_sector_map[BAD_SECTOR_MAP_SIZE];
46 typedef enum {
47 forward, backward
48 } mode_type;
49
50 #if 0
51
52
53
54 void fix_tape(byte * buffer)
55 {
56 static byte list[BAD_SECTOR_MAP_SIZE];
57 unsigned long *src_ptr = (unsigned long *) list;
58 byte *dst_ptr = bad_sector_map;
59 unsigned long map;
60 unsigned sector = 1;
61 int i;
62
63 memcpy(list, bad_sector_map, sizeof(list));
64 memset(bad_sector_map, 0, sizeof(bad_sector_map));
65 while ((byte *) src_ptr - list < sizeof(list)) {
66 map = *src_ptr++;
67 if (map == EMPTY_SEGMENT) {
68 *(unsigned long *) dst_ptr = 0x800000 + sector;
69 dst_ptr += 3;
70 sector += SECTORS_PER_SEGMENT;
71 } else {
72 for (i = 0; i < SECTORS_PER_SEGMENT; ++i) {
73 if (map & 1) {
74 *(unsigned long *) dst_ptr = sector;
75 dst_ptr += 3;
76 }
77 map >>= 1;
78 ++sector;
79 }
80 }
81 }
82 bad_sector_map_changed = 1;
83 *(buffer + 4) = 4;
84 format_code = 4;
85 }
86
87 #endif
88
89 byte *
90 find_end_of_bsm_list(byte * ptr, byte * limit)
91 {
92 while (ptr + 2 < limit) {
93 if (ptr[0] || ptr[1] || ptr[2]) {
94 ptr += 3;
95 } else {
96 return ptr;
97 }
98 }
99 return NULL;
100 }
101
102 void store_bad_sector_map(byte * buffer)
103 {
104 TRACE_FUN(8, "store_bad_sector_map");
105 size_t count;
106 size_t offset;
107
108
109
110 if (format_code == 4) {
111 offset = 256;
112 count = sizeof(bad_sector_map);
113 } else {
114 offset = 2 * SECTOR_SIZE;
115 count = sizeof(bad_sector_map) - (offset - 256);
116 }
117 memcpy(buffer + offset, bad_sector_map, count);
118 TRACE_EXIT;
119 }
120
121 void put_sector(byte ** ptr, unsigned long sector)
122 {
123 *(*ptr)++ = sector & 0xff;
124 sector >>= 8;
125 *(*ptr)++ = sector & 0xff;
126 sector >>= 8;
127 *(*ptr)++ = sector & 0xff;
128 }
129
130 unsigned long get_sector(byte ** ptr, mode_type mode)
131 {
132 unsigned long sector;
133
134 if (mode == forward) {
135 sector = *(*ptr)++;
136 sector += *(*ptr)++ << 8;
137 sector += *(*ptr)++ << 16;
138 } else {
139 sector = *--(*ptr) << 16;
140 sector += *--(*ptr) << 8;
141 sector += *--(*ptr);
142 }
143 return sector;
144 }
145
146 void extract_bad_sector_map(byte * buffer)
147 {
148 TRACE_FUN(8, "extract_bad_sector_map");
149
150
151
152 if (format_code == 4) {
153
154
155
156 memcpy(bad_sector_map, buffer + 256, sizeof(bad_sector_map));
157 } else {
158
159
160
161 memcpy(bad_sector_map, buffer + 256 + FAILED_SECTOR_LOG_SIZE,
162 sizeof(bad_sector_map) - FAILED_SECTOR_LOG_SIZE);
163 }
164 #if 0
165
166
167 ((unsigned long *) bad_sector_map)[segments_per_track * tracks_per_tape - 3] = 0x000003e0;
168 ((unsigned long *) bad_sector_map)[segments_per_track * tracks_per_tape - 2] = 0xff3fffff;
169 ((unsigned long *) bad_sector_map)[segments_per_track * tracks_per_tape - 1] = 0xffffe000;
170 #endif
171 #if 0
172
173
174 ((unsigned long *) bad_sector_map)[30] = 0xfffffffe;
175 ((unsigned long *) bad_sector_map)[32] = 0x7fffffff;
176 ((unsigned long *) bad_sector_map)[34] = 0xfffeffff;
177 ((unsigned long *) bad_sector_map)[36] = 0x55555555;
178 ((unsigned long *) bad_sector_map)[38] = 0xffffffff;
179 ((unsigned long *) bad_sector_map)[50] = 0xffff0000;
180 ((unsigned long *) bad_sector_map)[51] = 0xffffffff;
181 ((unsigned long *) bad_sector_map)[52] = 0xffffffff;
182 ((unsigned long *) bad_sector_map)[53] = 0x0000ffff;
183 #endif
184 #if 0
185
186
187 for (i = first_data_segment; i <= ftape_last_segment.id - 7; ++i) {
188 ((unsigned long *) bad_sector_map)[i] = EMPTY_SEGMENT;
189 }
190 #endif
191 #if 0
192
193
194 for (i = first_data_segment; i <= ftape_last_segment.id; ++i) {
195 ((unsigned long *) bad_sector_map)[i] |= 0x00ff00ff;
196 }
197 #endif
198 if (tracing > 2) {
199 unsigned int map;
200 int good_sectors = 0;
201 int bad_sectors;
202 unsigned int total_bad = 0;
203 int i;
204
205 if (format_code == 4 || format_code == 3) {
206 byte *ptr = bad_sector_map;
207 unsigned sector;
208
209 do {
210 sector = get_sector(&ptr, forward);
211 if (sector != 0) {
212 if (format_code == 4 && sector & 0x800000) {
213 total_bad += SECTORS_PER_SEGMENT - 3;
214 TRACEx1(6, "bad segment at sector: %6d", sector & 0x7fffff);
215 } else {
216 ++total_bad;
217 TRACEx1(6, "bad sector: %6d", sector);
218 }
219 }
220 } while (sector != 0);
221
222
223 do {
224 sector = *((unsigned short *) ptr)++;
225 if (sector) {
226 TRACEx2(4, "eof mark: %4d/%2d", sector,
227 *((unsigned short *) ptr)++);
228 }
229 } while (sector);
230 } else {
231 for (i = first_data_segment;
232 i < segments_per_track * tracks_per_tape; ++i) {
233 map = ((unsigned long *) bad_sector_map)[i];
234 bad_sectors = count_ones(map);
235 if (bad_sectors > 0) {
236 TRACEx2(6, "bsm for segment %4d: 0x%08x", i, map);
237 if (bad_sectors > SECTORS_PER_SEGMENT - 3) {
238 bad_sectors = SECTORS_PER_SEGMENT - 3;
239 }
240 total_bad += bad_sectors;
241 }
242 }
243 }
244 good_sectors = ((segments_per_track * tracks_per_tape - first_data_segment)
245 * (SECTORS_PER_SEGMENT - 3)) - total_bad;
246 TRACEx1(3, "%d Kb usable on this tape",
247 good_sectors - ftape_last_segment.free);
248 if (total_bad == 0) {
249 TRACE(1, "WARNING: this tape has no bad blocks registered !");
250 } else {
251 TRACEx1(2, "%d bad sectors", total_bad);
252 }
253 }
254 TRACE_EXIT;
255 }
256
257 unsigned long cvt2map(int sector)
258 {
259 return 1 << (((sector & 0x7fffff) - 1) % SECTORS_PER_SEGMENT);
260 }
261
262 int cvt2segment(int sector)
263 {
264 return ((sector & 0x7fffff) - 1) / SECTORS_PER_SEGMENT;
265 }
266
267 int forward_seek_entry(int segment_id, byte ** ptr, unsigned long *map)
268 {
269 byte *tmp_ptr;
270 unsigned long sector;
271 int segment;
272 int count;
273
274 do {
275 sector = get_sector(ptr, forward);
276 segment = cvt2segment(sector);
277 } while (sector != 0 && segment < segment_id);
278 tmp_ptr = *ptr - 3;
279
280
281 if (format_code == 4 && (sector & 0x800000) && segment == segment_id) {
282 *map = EMPTY_SEGMENT;
283 count = 32;
284 } else {
285 *map = 0;
286 count = 0;
287 while (sector != 0 && segment == segment_id) {
288 *map |= cvt2map(sector);
289 sector = get_sector(ptr, forward);
290 segment = cvt2segment(sector);
291 ++count;
292 }
293 }
294 *ptr = tmp_ptr;
295 return count;
296 }
297
298 int backwards_seek_entry(int segment_id, byte ** ptr, unsigned long *map)
299 {
300 unsigned long sector;
301 int segment;
302 int count;
303
304 *map = 0;
305 if (*ptr > bad_sector_map) {
306 do {
307 sector = get_sector(ptr, backward);
308 segment = cvt2segment(sector);
309 } while (*ptr > bad_sector_map && segment > segment_id);
310 count = 0;
311 if (segment > segment_id) {
312
313 } else if (segment < segment_id) {
314
315 *ptr += 3;
316 } else {
317
318 if (format_code == 4 && (sector & 0x800000)) {
319 *map = EMPTY_SEGMENT;
320 count = 32;
321 } else {
322 do {
323 *map |= cvt2map(sector);
324 ++count;
325 if (*ptr <= bad_sector_map) {
326 break;
327 }
328 sector = get_sector(ptr, backward);
329 segment = cvt2segment(sector);
330 } while (segment == segment_id);
331 if (segment < segment_id) {
332 *ptr += 3;
333 }
334 }
335 }
336 } else {
337 count = 0;
338 }
339 return count;
340 }
341
342 void put_bad_sector_entry(int segment_id, unsigned long new_map)
343 {
344 byte *ptr = bad_sector_map;
345 int count;
346 int new_count;
347 unsigned long map;
348
349 if (format_code == 3 || format_code == 4) {
350 count = forward_seek_entry(segment_id, &ptr, &map);
351 new_count = count_ones(new_map);
352
353
354 if (new_count == 32 && format_code == 4) {
355 new_count = 1;
356 }
357 if (count != new_count) {
358
359
360
361 byte *hi_ptr = ptr;
362
363 do {
364 } while (get_sector(&hi_ptr, forward) != 0);
365 memmove(ptr + new_count, ptr + count, hi_ptr - (ptr + count));
366 }
367 if (new_count == 1 && new_map == EMPTY_SEGMENT) {
368 put_sector(&ptr, 0x800001 + segment_id * SECTORS_PER_SEGMENT);
369 } else {
370 int i = 0;
371
372 while (new_map) {
373 if (new_map & 1) {
374 put_sector(&ptr, 1 + segment_id * SECTORS_PER_SEGMENT + i);
375 }
376 ++i;
377 new_map >>= 1;
378 }
379 }
380 } else {
381 ((unsigned long *) bad_sector_map)[segment_id] = new_map;
382 }
383 bad_sector_map_changed = 1;
384 }
385
386 unsigned long get_bad_sector_entry(int segment_id)
387 {
388 TRACE_FUN(8, "get_bad_sector_entry");
389 static unsigned long map = 0;
390
391 if (used_header_segment == -1) {
392
393
394 map = 0;
395 } else if (format_code == 3 || format_code == 4) {
396
397
398
399
400
401
402
403
404
405 static int last_reference = -1;
406 static byte *ptr = bad_sector_map;
407
408 if (segment_id > last_reference) {
409
410
411 forward_seek_entry(segment_id, &ptr, &map);
412 } else if (segment_id < last_reference) {
413
414
415 backwards_seek_entry(segment_id, &ptr, &map);
416 }
417 last_reference = segment_id;
418 } else {
419 map = ((unsigned long *) bad_sector_map)[segment_id];
420 }
421 TRACE_EXIT;
422 return map;
423 }
424
425 void ftape_init_bsm(void)
426 {
427 memset(bad_sector_map, 0, sizeof(bad_sector_map));
428 }