|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)maps.c 1.8 (Berkeley/CCI) 6/24/90";
3: #endif
4:
5:
6: #include "vdfmt.h"
7:
8:
9: /*
10: **
11: */
12:
13: boolean align_buf(buf, sync)
14: unsigned long *buf;
15: unsigned long sync;
16: {
17: register int i, shift;
18:
19: /* find shift amount */
20: for(shift=0; shift < 32; shift++) {
21: if((*buf >> shift ) == sync) {
22: for(i=(512/sizeof(long))-1; i >= 0; i--) {
23: *(buf+i+1) |= *(buf+i) << (32 - shift);
24: *(buf+i) = *(buf+i) >> shift;
25: }
26: return true;
27: }
28: }
29: return false;
30: }
31:
32:
33: /*
34: ** Looks for two maps in a row that are the same.
35: */
36:
37: boolean
38: read_map(flags)
39: short flags;
40: {
41: register int trk, i;
42: register bs_map *map;
43: dskadr dskaddr;
44:
45: dskaddr.cylinder = (lab->d_ncylinders - 1) | flags;
46: for(trk=0; trk < lab->d_ntracks; trk++) {
47: dskaddr.track = trk;
48: dskaddr.sector = 0;
49: if(access_dsk((char *)map_space, &dskaddr, VDOP_RD,
50: lab->d_nsectors, 1) & VDERR_HARD)
51: continue;
52: map = &norm_bad_map;
53: /*
54: * If this doesn't look like a new-style map,
55: * but (as an old-style map) bs_count and bs_max are sensible,
56: * munge pointer to prepend fields missing in old map.
57: */
58: if (map->bs_magic != BSMAGIC &&
59: map->bs_cksum <= MAX_FLAWMAP(bytes_trk) /* bs_count */
60: && map->bs_id <= MAX_FLAWMAP(bytes_trk)) /* bs_max */
61: map = &offset_bad_map;
62: if (trk > 0 &&
63: bcmp((char *)map_space, (char *)save, bytes_trk) == 0 &&
64: map->bs_count <= MAX_FLAWMAP(bytes_trk)) {
65: for (i=0; i < map->bs_count; i++) {
66: if (map->list[i].bs_cyl >=
67: lab->d_ncylinders)
68: break;
69: if (map->list[i].bs_trk >=
70: lab->d_ntracks)
71: break;
72: if (map->list[i].bs_offset >=
73: lab->d_traksize)
74: break;
75: }
76: if (i == map->bs_count) {
77: bad_map = map;
78: load_free_table();
79: return true;
80: }
81: }
82: bcopy((char *)map_space, (char *)save, bytes_trk);
83: }
84: map = &norm_bad_map;
85: bad_map = map;
86: bzero((char *)map, bytes_trk);
87: map->bs_magic = BSMAGIC;
88: map->bs_id = 0;
89: map->bs_max = MAX_FLAWS;
90: return false;
91: }
92:
93:
94: /*
95: **
96: */
97:
98: boolean read_bad_sector_map()
99: {
100: dskadr dskaddr;
101:
102: dskaddr.cylinder = lab->d_ncylinders - 1;
103: dskaddr.track = 0;
104: dskaddr.sector = 0;
105: offset_bad_map.bs_magic = BSMAGIC;
106: offset_bad_map.bs_cksum = 0;
107: bad_map = &norm_bad_map;
108: /* start with nothing in map */
109: bzero(map_space, bytes_trk);
110: bad_map->bs_magic = BSMAGIC;
111: bad_map->bs_id = 0;
112: bad_map->bs_max = MAX_FLAWS;
113: if (C_INFO->type == VDTYPE_SMDE) {
114: access_dsk((char *)save, &dskaddr, VDOP_RDRAW, 1, 1);
115: if (align_buf((unsigned long *)save, CDCSYNC) == true) {
116: read_flaw_map();
117: return (false);
118: } else if (read_map(NRM) == true) {
119: return (true);
120: } else {
121: get_smde_relocations();
122: return false;
123: }
124: } else {
125: if (read_map(WPT) == true)
126: return (true);
127: else {
128: get_relocations_the_hard_way();
129: return (false);
130: }
131: }
132: }
133:
134:
135: /*
136: **
137: */
138:
139: get_relocations_the_hard_way()
140: {
141: register int cyl, trk;
142: register int status;
143: dskadr dskaddr;
144:
145: dskaddr.sector = 0;
146: /* scan each sector to see if it is relocated and take note if it is */
147: for(cyl=0; cyl < lab->d_ncylinders - NUMSYS; cyl++) {
148: dskaddr.cylinder = cyl;
149: for(trk=0; trk < lab->d_ntracks; trk++) {
150: dskaddr.track = trk;
151: status=access_dsk((char *)scratch, &dskaddr,
152: VDOP_RD, lab->d_nsectors, 1);
153: if(status & DCBS_ATA)
154: get_track_relocations(dskaddr);
155: }
156: }
157: load_free_table();
158: }
159:
160:
161: /*
162: **
163: */
164:
165: get_track_relocations(dskaddr)
166: dskadr dskaddr;
167: {
168: register int status;
169: bs_entry temp;
170: fmt_err error;
171:
172: for(dskaddr.sector=0; dskaddr.sector < lab->d_nsectors; dskaddr.sector++) {
173: status = access_dsk((char *)scratch, &dskaddr, VDOP_RD, 1, 1);
174: if(status & DCBS_ATA) {
175: error.err_adr = dskaddr;
176: error.err_stat = DATA_ERROR;
177: (*C_INFO->code_pos)(&error, &temp);
178: temp.bs_how = operator;
179: add_flaw(&temp);
180: }
181: }
182: }
183:
184:
185: /*
186: **
187: */
188:
189: remove_user_relocations(entry)
190: bs_entry *entry;
191: {
192: register int i, j;
193: fmt_err temp;
194: fmt_err error;
195: register bs_entry *ptr;
196:
197: (*C_INFO->decode_pos)(entry, &error);
198: ptr = bad_map->list;
199: for(i=0; i < bad_map->bs_count; i++) {
200: if (ptr->bs_cyl != entry->bs_cyl ||
201: ptr->bs_trk != entry->bs_trk)
202: continue;
203: (*C_INFO->decode_pos)(ptr, &temp);
204: if((ptr->bs_how != flaw_map) &&
205: (temp.err_adr.cylinder == error.err_adr.cylinder) &&
206: (temp.err_adr.track == error.err_adr.track) &&
207: (temp.err_adr.sector == error.err_adr.sector)) {
208: if(temp.err_stat & HEADER_ERROR)
209: remove_track(&temp, ptr);
210: else
211: remove_sector(&temp, ptr);
212: for(j=i+1; j < bad_map->bs_count; j++)
213: bad_map->list[j-1] = bad_map->list[j];
214: bad_map->bs_count--;
215: return;
216: }
217: ptr++;
218: }
219: indent();
220: print("Sector %d is not in bad sector map!\n",
221: to_sector(error.err_adr));
222: exdent(1);
223: }
224:
225: clear_relocations(reformat)
226: boolean reformat;
227: {
228: fmt_err temp;
229: register bs_entry *ptr1, *ptr2, *end;
230: int oldsub = cur.substate;
231:
232: cur.substate = sub_rel;
233: ptr1 = bad_map->list;
234: ptr2 = bad_map->list;
235: end = &bad_map->list[bad_map->bs_count];
236: for (; ptr1 < end; ptr1++) {
237: if (ptr1->bs_how != flaw_map) {
238: if (reformat == true) {
239: (*C_INFO->decode_pos)(ptr1, &temp);
240: if(temp.err_stat & HEADER_ERROR)
241: remove_track(&temp, ptr1);
242: else
243: remove_sector(&temp, ptr1);
244: }
245: bad_map->bs_count--;
246: } else {
247: if (ptr1 != ptr2)
248: *ptr2 = *ptr1;
249: ptr2++;
250: }
251: }
252: cur.substate = oldsub;
253: }
254:
255:
256: /*
257: **
258: */
259:
260: remove_sector(error, entry)
261: fmt_err *error;
262: bs_entry *entry;
263: {
264: format_sectors(&error->err_adr, &error->err_adr, NRM, 1);
265: format_sectors(&entry->bs_alt, &entry->bs_alt, NRM, 1);
266: }
267:
268:
269: /*
270: **
271: */
272:
273: remove_track(error, entry)
274: fmt_err *error;
275: bs_entry *entry;
276: {
277: format_sectors(&error->err_adr,&error->err_adr,NRM,(long)lab->d_nsectors);
278: format_sectors(&entry->bs_alt,&entry->bs_alt,NRM,(long)lab->d_nsectors);
279: }
280:
281:
282: /*
283: **
284: */
285:
286: write_bad_sector_map()
287: {
288: register int trk, sec;
289: dskadr dskaddr;
290:
291: bad_map->bs_magic = BSMAGIC;
292: bad_map->bs_id = 0;
293: dskaddr.cylinder = (lab->d_ncylinders - NUMMAP);
294: for(trk=0; trk < lab->d_ntracks; trk++) {
295: for(sec = 0; sec < lab->d_nsectors; sec++) {
296: bcopy((char *)bad_map + (sec * lab->d_secsize),
297: (char *)scratch, lab->d_secsize);
298: dskaddr.track = trk;
299: dskaddr.sector = sec;
300: format_sectors(&dskaddr, &dskaddr, WPT, 1);
301: }
302: }
303: }
304:
305:
306: /*
307: **
308: */
309:
310: zero_bad_sector_map()
311: {
312: bs_map *bm = bad_map;
313: register int i;
314: dskadr zero;
315:
316: zero.cylinder = 0;
317: zero.track = 0;
318: zero.sector = 0;
319: for(i=0; i < bm->bs_count; i++)
320: bm->list[i].bs_alt = zero;
321: load_free_table();
322: }
323:
324:
325: /*
326: **
327: */
328:
329: read_flaw_map()
330: {
331: register int cyl, trk;
332: dskadr dskaddr;
333: flaw buffer;
334:
335: dskaddr.sector = 0;
336: for (cyl=0; cyl < lab->d_ncylinders; cyl++) {
337: dskaddr.cylinder = cyl;
338: for (trk=0; trk < lab->d_ntracks; trk++) {
339: dskaddr.track = trk;
340: access_dsk(&buffer, &dskaddr, VDOP_RDRAW, 1, 1);
341: if(align_buf(&buffer, CDCSYNC) == true) {
342: add_flaw_entries(&buffer);
343: continue;
344: }
345: }
346: }
347: load_free_table();
348: }
349:
350:
351: /*
352: **
353: */
354:
355: get_smde_relocations()
356: {
357: register int cyl, trk, sec;
358: smde_hdr buffer;
359: dskadr dskaddr;
360: fmt_err bad;
361: bs_entry temp;
362: boolean bad_track;
363:
364: /* Read any old drive relocations */
365: for(cyl=0; cyl < NUMREL; cyl++) {
366: dskaddr.cylinder = lab->d_ncylinders - NUMSYS + cyl;
367: for(trk=0; trk < lab->d_ntracks; trk++) {
368: dskaddr.track = trk;
369: bad_track = true;
370: for(sec=0; sec < lab->d_nsectors; sec++) {
371: dskaddr.sector = sec;
372: access_dsk(&buffer, &dskaddr, VDOP_RDRAW, 1, 1);
373: if(align_buf(&buffer, SMDE1SYNC) == false) {
374: bad_track = false;
375: break;
376: }
377: }
378: if(bad_track == true) {
379: dskaddr.sector = 0;
380: bad.err_adr.cylinder = buffer.alt_cyl;
381: bad.err_adr.track = buffer.alt_trk;
382: bad.err_adr.sector = 0;
383: bad.err_stat = HEADER_ERROR;
384: (*C_INFO->code_pos)(&bad, &temp);
385: temp.bs_alt = dskaddr;
386: temp.bs_how = scanning;
387: add_flaw(&temp);
388: continue;
389: }
390: for(sec=0; sec < lab->d_nsectors; sec++) {
391: dskaddr.sector = sec;
392: access_dsk(&buffer, &dskaddr, VDOP_RDRAW, 1, 1);
393: if(align_buf(&buffer, SMDE1SYNC) == true) {
394: bad.err_adr.cylinder = buffer.alt_cyl;
395: bad.err_adr.track = buffer.alt_trk;
396: bad.err_adr.sector = buffer.alt_sec;
397: bad.err_stat = DATA_ERROR;
398: (*C_INFO->code_pos)(&bad, &temp);
399: temp.bs_alt = dskaddr;
400: temp.bs_how = scanning;
401: add_flaw(&temp);
402: }
403: }
404: }
405: }
406: load_free_table();
407: }
408:
409:
410: /*
411: **
412: */
413:
414: add_flaw_entries(buffer)
415: flaw *buffer;
416: {
417: register int i;
418: bs_entry temp;
419:
420: temp.bs_cyl = buffer->flaw_cyl & 0x7fff; /* clear off bad track bit */
421: temp.bs_trk = buffer->flaw_trk;
422: for(i=0; i < 4; i++) {
423: if(buffer->flaw_pos[i].flaw_length != 0) {
424: temp.bs_offset = buffer->flaw_pos[i].flaw_offset;
425: temp.bs_length = buffer->flaw_pos[i].flaw_length;
426: temp.bs_alt.cylinder = 0;
427: temp.bs_alt.track = 0;
428: temp.bs_alt.sector = 0;
429: temp.bs_how = flaw_map;
430: add_flaw(&temp);
431: }
432: }
433: }
434:
435:
436: cmp_entry(a, b)
437: bs_entry *a;
438: bs_entry *b;
439: {
440: if(a->bs_cyl == b->bs_cyl) {
441: if(a->bs_trk == b->bs_trk) {
442: if(a->bs_offset == b->bs_offset)
443: return 0;
444: else if(a->bs_offset < b->bs_offset)
445: return -1;
446: }
447: else if(a->bs_trk < b->bs_trk)
448: return -1;
449: }
450: else if(a->bs_cyl < b->bs_cyl)
451: return -1;
452: return 1;
453: }
454:
455:
456: /*
457: * Add flaw to map.
458: * Return value:
459: * 1 OK
460: * 0 sector was in map
461: * -1 failure
462: */
463: add_flaw(entry)
464: bs_entry *entry;
465: {
466: extern int cmp_entry();
467: bs_map *bm = bad_map;
468: register int i;
469:
470: if(bm->bs_count > MAX_FLAWS)
471: return (-1);
472: if (entry->bs_cyl >= lab->d_ncylinders ||
473: entry->bs_trk >= lab->d_ntracks ||
474: entry->bs_offset >= lab->d_traksize)
475: return (-1);
476: for(i=0; i < bm->bs_count; i++) {
477: if(((bm->list[i].bs_cyl == entry->bs_cyl)) &&
478: (bm->list[i].bs_trk == entry->bs_trk) &&
479: (bm->list[i].bs_offset == entry->bs_offset)) {
480: if((int)bm->list[i].bs_how > (int)entry->bs_how)
481: bm->list[i].bs_how = entry->bs_how;
482: return (0);
483: }
484: }
485: bm->list[i] = *entry;
486: bm->list[i].bs_alt.cylinder = 0;
487: bm->list[i].bs_alt.track = 0;
488: bm->list[i].bs_alt.sector = 0;
489: bm->bs_count++;
490: qsort((char *)&(bm->list[0]), (unsigned)bm->bs_count,
491: sizeof(bs_entry), cmp_entry);
492: return (1);
493: }
494:
495:
496: /*
497: ** Is_in_map checks to see if a block is known to be bad already.
498: */
499:
500: boolean is_in_map(dskaddr)
501: dskadr *dskaddr;
502: {
503: register int i;
504: fmt_err temp;
505:
506: for(i=0; i < bad_map->bs_count; i++) {
507: (*C_INFO->decode_pos)(&bad_map->list[i], &temp);
508: if((temp.err_adr.cylinder == dskaddr->cylinder) &&
509: (temp.err_adr.track == dskaddr->track) &&
510: (temp.err_adr.sector == dskaddr->sector)) {
511: return true;
512: }
513: }
514: return false;
515: }
516:
517:
518: /*
519: **
520: */
521:
522: print_bad_sector_list()
523: {
524: register int i;
525: fmt_err errloc;
526: register bs_entry *bad;
527:
528: if(bad_map->bs_magic != BSMAGIC)
529: print("Bad-sector map magic number wrong! (%x != %x)\n",
530: bad_map->bs_magic, BSMAGIC);
531: if(bad_map->bs_count == 0) {
532: print("There are no bad sectors in bad sector map.\n");
533: return;
534: }
535: print("The following %d sector%s known to be bad:\n",
536: bad_map->bs_count, (bad_map->bs_count == 1) ? " is" : "s are");
537: exdent(0);
538: for(i=0, bad = bad_map->list; i < bad_map->bs_count; i++, bad++) {
539: (*C_INFO->decode_pos)(bad, &errloc);
540: print("%c %d cn %d tn %d sn %d pos %d len %d ",
541: errloc.err_stat & HEADER_ERROR ? 'T' : 'S',
542: to_sector(errloc.err_adr),
543: bad->bs_cyl,
544: bad->bs_trk,
545: errloc.err_adr.sector,
546: bad->bs_offset,
547: bad->bs_length);
548: if (bad->bs_how == flaw_map)
549: printf("(flawmap) ");
550: else if (bad->bs_how == scanning)
551: printf("(verify) ");
552: else
553: printf("(operator) ");
554: if((bad->bs_alt.cylinder != 0) || (bad->bs_alt.track != 0) ||
555: (bad->bs_alt.sector != 0)) {
556: printf("-> ");
557: printf("cn %d tn %d sn %d", bad->bs_alt.cylinder,
558: bad->bs_alt.track, bad->bs_alt.sector);
559: }
560: printf("\n");
561: }
562: }
563:
564:
565: /*
566: ** load_free_table checks each block in the bad block relocation area
567: ** to see if it is used. If it is, the free relocation block table is updated.
568: */
569:
570: load_free_table()
571: {
572: register int i, j;
573: fmt_err temp;
574:
575: /* Clear free table before starting */
576: for(i = 0; i < (lab->d_ntracks * NUMREL); i++) {
577: for(j=0; j < lab->d_nsectors; j++)
578: free_tbl[i][j].free_status = NOTALLOCATED;
579: }
580: for(i=0; i < bad_map->bs_count; i++)
581: if((bad_map->list[i].bs_alt.cylinder != 0) ||
582: (bad_map->list[i].bs_alt.track != 0) ||
583: (bad_map->list[i].bs_alt.sector != 0)) {
584: (*C_INFO->decode_pos)(&bad_map->list[i], &temp);
585: allocate(&(bad_map->list[i].bs_alt), temp.err_stat);
586: }
587: }
588:
589:
590: /*
591: ** allocate marks a replacement sector as used.
592: */
593:
594: allocate(dskaddr, status)
595: dskadr *dskaddr;
596: long status;
597: {
598: register int trk, sec;
599:
600: trk = dskaddr->cylinder - (lab->d_ncylinders - NUMSYS);
601: if((trk < 0) || (trk >= NUMREL))
602: return;
603: trk *= lab->d_ntracks;
604: trk += dskaddr->track;
605: if(status & HEADER_ERROR)
606: for(sec=0; sec < lab->d_nsectors; sec++)
607: free_tbl[trk][sec].free_status = ALLOCATED;
608: else
609: free_tbl[trk][dskaddr->sector].free_status = ALLOCATED;
610: }
611:
612:
613: /*
614: **
615: */
616:
617: boolean mapping_collision(entry)
618: bs_entry *entry;
619: {
620: register int trk, sec;
621: fmt_err temp;
622:
623: trk = entry->bs_cyl - (lab->d_ncylinders - NUMSYS);
624: if((trk < 0) || (trk >= NUMREL))
625: return false;
626: trk *= lab->d_ntracks;
627: trk += entry->bs_trk;
628: (*C_INFO->decode_pos)(entry, &temp);
629: /* if this relocation should take up the whole track */
630: if(temp.err_stat & HEADER_ERROR) {
631: for(sec=0; sec < lab->d_nsectors; sec++)
632: if(free_tbl[trk][sec].free_status == ALLOCATED)
633: return true;
634: }
635: /* else just check the current sector */
636: else {
637: if(free_tbl[trk][temp.err_adr.sector].free_status == ALLOCATED)
638: return true;
639: }
640: return false;
641: }
642:
643:
644: /*
645: **
646: */
647:
648: report_collision()
649: {
650: indent();
651: print("Sector resides in relocation area");
652: printf("but it has a sector mapped to it already.\n");
653: print("Please reformat disk with 0 patterns to eliminate problem.\n");
654: exdent(1);
655: }
656:
657:
658: /*
659: **
660: */
661:
662: add_user_relocations(entry)
663: bs_entry *entry;
664: {
665: fmt_err error;
666:
667: (*C_INFO->decode_pos)(entry, &error);
668: if(is_in_map(&error.err_adr) == false) {
669: if(mapping_collision(entry) == true)
670: report_collision();
671: entry->bs_how = operator;
672: add_flaw(entry);
673: }
674: else {
675: indent();
676: print("Sector %d is already mapped out!\n",
677: to_sector(error.err_adr));
678: exdent(1);
679: }
680: }
681:
682:
683: /*
684: ** New_location allocates a replacement block given a bad block address.
685: ** The algorithm is fairly simple; it simply searches for the first
686: ** free sector that has the same sector number of the bad sector. If no sector
687: ** is found then the drive should be considered bad because of a microcode bug
688: ** in the controller that forces us to use the same sector number as the bad
689: ** sector for relocation purposes. Using different tracks and cylinders is ok
690: ** of course.
691: */
692:
693: dskadr *new_location(entry)
694: bs_entry *entry;
695: {
696: register int i, sec;
697: static fmt_err temp;
698: static dskadr newaddr;
699:
700: newaddr.cylinder = 0;
701: newaddr.track = 0;
702: newaddr.sector = 0;
703: (*C_INFO->decode_pos)(entry, &temp);
704: /* If it is ouside of the user's data area */
705: if(entry->bs_cyl >= lab->d_ncylinders-NUMSYS) {
706: /* if it is in the relocation area */
707: if(entry->bs_cyl < (lab->d_ncylinders - NUMMAP - NUMMNT)) {
708: /* mark space as allocated */
709: allocate(&temp.err_adr, temp.err_stat);
710: return &temp.err_adr;
711: }
712: /* if it is in the map area forget about it */
713: if(entry->bs_cyl != (lab->d_ncylinders - NUMMAP - NUMMNT))
714: return &temp.err_adr;
715: /* otherwise treat maintainence cylinder normally */
716: }
717: if(temp.err_stat & (HEADER_ERROR)) {
718: for(i = 0; i < (lab->d_ntracks * NUMREL); i++) {
719: for(sec=0; sec < lab->d_nsectors; sec++) {
720: if(free_tbl[i][sec].free_status == ALLOCATED)
721: break;
722: }
723: if(sec == lab->d_nsectors) {
724: for(sec = 0; sec < lab->d_nsectors; sec++)
725: free_tbl[i][sec].free_status=ALLOCATED;
726: newaddr.cylinder = i / lab->d_ntracks +
727: (lab->d_ncylinders - NUMSYS);
728: newaddr.track = i % lab->d_ntracks;
729: break;
730: }
731: }
732: }
733: else if(C_INFO->type == VDTYPE_VDDC) {
734: for(i = 0; i < (lab->d_ntracks * NUMREL); i++) {
735: if(free_tbl[i][temp.err_adr.sector].free_status !=
736: ALLOCATED) {
737: free_tbl[i][temp.err_adr.sector].free_status =
738: ALLOCATED;
739: newaddr.cylinder = i / lab->d_ntracks +
740: (lab->d_ncylinders - NUMSYS);
741: newaddr.track = i % lab->d_ntracks;
742: newaddr.sector = temp.err_adr.sector;
743: break;
744: }
745: }
746: }
747: else {
748: for(i = 0; i < (lab->d_ntracks * NUMREL); i++) {
749: for(sec=0; sec < lab->d_nsectors; sec++)
750: if(free_tbl[i][sec].free_status != ALLOCATED)
751: break;
752: if(sec < lab->d_nsectors) {
753: free_tbl[i][sec].free_status = ALLOCATED;
754: newaddr.cylinder = i / lab->d_ntracks +
755: (lab->d_ncylinders - NUMSYS);
756: newaddr.track = i % lab->d_ntracks;
757: newaddr.sector = sec;
758: break;
759: }
760: }
761: }
762: return &newaddr;
763: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.