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