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