129533Ssam #ifndef lint
2*43645Skarels static char sccsid[] = "@(#)maps.c 1.8 (Berkeley/CCI) 06/24/90";
329533Ssam #endif
429533Ssam
529533Ssam
629533Ssam #include "vdfmt.h"
729533Ssam
829533Ssam
929533Ssam /*
1029533Ssam **
1129533Ssam */
1229533Ssam
align_buf(buf,sync)1329533Ssam boolean align_buf(buf, sync)
1429533Ssam unsigned long *buf;
1529533Ssam unsigned long sync;
1629533Ssam {
1729533Ssam register int i, shift;
1829533Ssam
1929533Ssam /* find shift amount */
2032662Skarels for(shift=0; shift < 32; shift++) {
2129533Ssam if((*buf >> shift ) == sync) {
2229533Ssam for(i=(512/sizeof(long))-1; i >= 0; i--) {
2329533Ssam *(buf+i+1) |= *(buf+i) << (32 - shift);
2429533Ssam *(buf+i) = *(buf+i) >> shift;
2529533Ssam }
2629533Ssam return true;
2729533Ssam }
2829533Ssam }
2929533Ssam return false;
3029533Ssam }
3129533Ssam
3229533Ssam
3329533Ssam /*
3429533Ssam ** Looks for two maps in a row that are the same.
3529533Ssam */
3629533Ssam
3729981Skarels boolean
read_map(flags)3829981Skarels read_map(flags)
3929533Ssam short flags;
4029533Ssam {
4129533Ssam register int trk, i;
42*43645Skarels register bs_map *map;
4329533Ssam dskadr dskaddr;
4429533Ssam
4532662Skarels dskaddr.cylinder = (lab->d_ncylinders - 1) | flags;
4632662Skarels for(trk=0; trk < lab->d_ntracks; trk++) {
4729533Ssam dskaddr.track = trk;
4829533Ssam dskaddr.sector = 0;
49*43645Skarels if(access_dsk((char *)map_space, &dskaddr, VDOP_RD,
50*43645Skarels lab->d_nsectors, 1) & VDERR_HARD)
5129533Ssam continue;
52*43645Skarels map = &norm_bad_map;
53*43645Skarels /*
54*43645Skarels * If this doesn't look like a new-style map,
55*43645Skarels * but (as an old-style map) bs_count and bs_max are sensible,
56*43645Skarels * munge pointer to prepend fields missing in old map.
57*43645Skarels */
58*43645Skarels if (map->bs_magic != BSMAGIC &&
59*43645Skarels map->bs_cksum <= MAX_FLAWMAP(bytes_trk) /* bs_count */
60*43645Skarels && map->bs_id <= MAX_FLAWMAP(bytes_trk)) /* bs_max */
61*43645Skarels map = &offset_bad_map;
62*43645Skarels if (trk > 0 &&
63*43645Skarels bcmp((char *)map_space, (char *)save, bytes_trk) == 0 &&
64*43645Skarels map->bs_count <= MAX_FLAWMAP(bytes_trk)) {
65*43645Skarels for (i=0; i < map->bs_count; i++) {
66*43645Skarels if (map->list[i].bs_cyl >=
67*43645Skarels lab->d_ncylinders)
68*43645Skarels break;
69*43645Skarels if (map->list[i].bs_trk >=
70*43645Skarels lab->d_ntracks)
71*43645Skarels break;
72*43645Skarels if (map->list[i].bs_offset >=
73*43645Skarels lab->d_traksize)
74*43645Skarels break;
7529981Skarels }
76*43645Skarels if (i == map->bs_count) {
77*43645Skarels bad_map = map;
78*43645Skarels load_free_table();
79*43645Skarels return true;
80*43645Skarels }
8129533Ssam }
82*43645Skarels bcopy((char *)map_space, (char *)save, bytes_trk);
8329533Ssam }
84*43645Skarels map = &norm_bad_map;
85*43645Skarels bad_map = map;
86*43645Skarels bzero((char *)map, bytes_trk);
87*43645Skarels map->bs_magic = BSMAGIC;
88*43645Skarels map->bs_id = 0;
89*43645Skarels map->bs_max = MAX_FLAWS;
9029533Ssam return false;
9129533Ssam }
9229533Ssam
9329533Ssam
9429533Ssam /*
9529533Ssam **
9629533Ssam */
9729533Ssam
read_bad_sector_map()9829533Ssam boolean read_bad_sector_map()
9929533Ssam {
10029533Ssam dskadr dskaddr;
10129533Ssam
10232662Skarels dskaddr.cylinder = lab->d_ncylinders - 1;
10329533Ssam dskaddr.track = 0;
10429533Ssam dskaddr.sector = 0;
105*43645Skarels offset_bad_map.bs_magic = BSMAGIC;
106*43645Skarels offset_bad_map.bs_cksum = 0;
107*43645Skarels bad_map = &norm_bad_map;
10829533Ssam /* start with nothing in map */
109*43645Skarels bzero(map_space, bytes_trk);
110*43645Skarels bad_map->bs_magic = BSMAGIC;
11129533Ssam bad_map->bs_id = 0;
11229533Ssam bad_map->bs_max = MAX_FLAWS;
11332662Skarels if (C_INFO->type == VDTYPE_SMDE) {
11431318Ssam access_dsk((char *)save, &dskaddr, VDOP_RDRAW, 1, 1);
11529981Skarels if (align_buf((unsigned long *)save, CDCSYNC) == true) {
11629533Ssam read_flaw_map();
11729981Skarels return (false);
11829981Skarels } else if (read_map(NRM) == true) {
11929981Skarels return (true);
12029981Skarels } else {
12129533Ssam get_smde_relocations();
12229533Ssam return false;
12329533Ssam }
12429981Skarels } else {
12529981Skarels if (read_map(WPT) == true)
12629981Skarels return (true);
12729981Skarels else {
12829981Skarels get_relocations_the_hard_way();
12929981Skarels return (false);
13029981Skarels }
13129533Ssam }
13229533Ssam }
13329533Ssam
13429533Ssam
13529533Ssam /*
13629533Ssam **
13729533Ssam */
13829533Ssam
get_relocations_the_hard_way()13929533Ssam get_relocations_the_hard_way()
14029533Ssam {
14129533Ssam register int cyl, trk;
14229533Ssam register int status;
14329533Ssam dskadr dskaddr;
14429533Ssam
14529533Ssam dskaddr.sector = 0;
14629533Ssam /* scan each sector to see if it is relocated and take note if it is */
14732662Skarels for(cyl=0; cyl < lab->d_ncylinders - NUMSYS; cyl++) {
14829533Ssam dskaddr.cylinder = cyl;
14932662Skarels for(trk=0; trk < lab->d_ntracks; trk++) {
15029533Ssam dskaddr.track = trk;
15129533Ssam status=access_dsk((char *)scratch, &dskaddr,
15232662Skarels VDOP_RD, lab->d_nsectors, 1);
15331318Ssam if(status & DCBS_ATA)
15429533Ssam get_track_relocations(dskaddr);
15529533Ssam }
15629533Ssam }
15729533Ssam load_free_table();
15829533Ssam }
15929533Ssam
16029533Ssam
16129533Ssam /*
16229533Ssam **
16329533Ssam */
16429533Ssam
get_track_relocations(dskaddr)16529533Ssam get_track_relocations(dskaddr)
16629533Ssam dskadr dskaddr;
16729533Ssam {
16829533Ssam register int status;
16929533Ssam bs_entry temp;
17029533Ssam fmt_err error;
17129533Ssam
17232662Skarels for(dskaddr.sector=0; dskaddr.sector < lab->d_nsectors; dskaddr.sector++) {
17331318Ssam status = access_dsk((char *)scratch, &dskaddr, VDOP_RD, 1, 1);
17431318Ssam if(status & DCBS_ATA) {
17529533Ssam error.err_adr = dskaddr;
17629533Ssam error.err_stat = DATA_ERROR;
17734667Skarels (*C_INFO->code_pos)(&error, &temp);
17829533Ssam temp.bs_how = operator;
17929533Ssam add_flaw(&temp);
18029533Ssam }
18129533Ssam }
18229533Ssam }
18329533Ssam
18429533Ssam
18529533Ssam /*
18629533Ssam **
18729533Ssam */
18829533Ssam
remove_user_relocations(entry)18929533Ssam remove_user_relocations(entry)
19034667Skarels bs_entry *entry;
19129533Ssam {
19229533Ssam register int i, j;
19329533Ssam fmt_err temp;
19429533Ssam fmt_err error;
19534667Skarels register bs_entry *ptr;
19629533Ssam
19734667Skarels (*C_INFO->decode_pos)(entry, &error);
19834667Skarels ptr = bad_map->list;
19934667Skarels for(i=0; i < bad_map->bs_count; i++) {
20034667Skarels if (ptr->bs_cyl != entry->bs_cyl ||
20134667Skarels ptr->bs_trk != entry->bs_trk)
20234667Skarels continue;
20334667Skarels (*C_INFO->decode_pos)(ptr, &temp);
20434667Skarels if((ptr->bs_how != flaw_map) &&
20534667Skarels (temp.err_adr.cylinder == error.err_adr.cylinder) &&
20634667Skarels (temp.err_adr.track == error.err_adr.track) &&
20734667Skarels (temp.err_adr.sector == error.err_adr.sector)) {
20834667Skarels if(temp.err_stat & HEADER_ERROR)
20934667Skarels remove_track(&temp, ptr);
21034667Skarels else
21134667Skarels remove_sector(&temp, ptr);
21234667Skarels for(j=i+1; j < bad_map->bs_count; j++)
21334667Skarels bad_map->list[j-1] = bad_map->list[j];
21434667Skarels bad_map->bs_count--;
21534667Skarels return;
21634667Skarels }
21734667Skarels ptr++;
21834667Skarels }
21934667Skarels indent();
22034667Skarels print("Sector %d is not in bad sector map!\n",
22134667Skarels to_sector(error.err_adr));
22234667Skarels exdent(1);
22334667Skarels }
22434667Skarels
clear_relocations(reformat)22534667Skarels clear_relocations(reformat)
22634667Skarels boolean reformat;
22734667Skarels {
22834667Skarels fmt_err temp;
22934667Skarels register bs_entry *ptr1, *ptr2, *end;
23034667Skarels int oldsub = cur.substate;
23134667Skarels
23234667Skarels cur.substate = sub_rel;
23334667Skarels ptr1 = bad_map->list;
23434667Skarels ptr2 = bad_map->list;
23534667Skarels end = &bad_map->list[bad_map->bs_count];
23634667Skarels for (; ptr1 < end; ptr1++) {
23734667Skarels if (ptr1->bs_how != flaw_map) {
23834667Skarels if (reformat == true) {
23934667Skarels (*C_INFO->decode_pos)(ptr1, &temp);
24029533Ssam if(temp.err_stat & HEADER_ERROR)
24134667Skarels remove_track(&temp, ptr1);
24229533Ssam else
24334667Skarels remove_sector(&temp, ptr1);
24429533Ssam }
24534667Skarels bad_map->bs_count--;
24634667Skarels } else {
24734667Skarels if (ptr1 != ptr2)
24834667Skarels *ptr2 = *ptr1;
24934667Skarels ptr2++;
25029533Ssam }
25129533Ssam }
25234667Skarels cur.substate = oldsub;
25329533Ssam }
25429533Ssam
25529533Ssam
25629533Ssam /*
25729533Ssam **
25829533Ssam */
25929533Ssam
remove_sector(error,entry)26029533Ssam remove_sector(error, entry)
26134667Skarels fmt_err *error;
26229533Ssam bs_entry *entry;
26329533Ssam {
26434667Skarels format_sectors(&error->err_adr, &error->err_adr, NRM, 1);
26529533Ssam format_sectors(&entry->bs_alt, &entry->bs_alt, NRM, 1);
26629533Ssam }
26729533Ssam
26829533Ssam
26929533Ssam /*
27029533Ssam **
27129533Ssam */
27229533Ssam
remove_track(error,entry)27329533Ssam remove_track(error, entry)
27434667Skarels fmt_err *error;
27529533Ssam bs_entry *entry;
27629533Ssam {
27734667Skarels format_sectors(&error->err_adr,&error->err_adr,NRM,(long)lab->d_nsectors);
27832662Skarels format_sectors(&entry->bs_alt,&entry->bs_alt,NRM,(long)lab->d_nsectors);
27929533Ssam }
28029533Ssam
28129533Ssam
28229533Ssam /*
28329533Ssam **
28429533Ssam */
28529533Ssam
write_bad_sector_map()28629533Ssam write_bad_sector_map()
28729533Ssam {
28829533Ssam register int trk, sec;
28929533Ssam dskadr dskaddr;
29029533Ssam
291*43645Skarels bad_map->bs_magic = BSMAGIC;
292*43645Skarels bad_map->bs_id = 0;
29332662Skarels dskaddr.cylinder = (lab->d_ncylinders - NUMMAP);
29432662Skarels for(trk=0; trk < lab->d_ntracks; trk++) {
29532662Skarels for(sec = 0; sec < lab->d_nsectors; sec++) {
296*43645Skarels bcopy((char *)bad_map + (sec * lab->d_secsize),
29732662Skarels (char *)scratch, lab->d_secsize);
29829533Ssam dskaddr.track = trk;
29929533Ssam dskaddr.sector = sec;
30029533Ssam format_sectors(&dskaddr, &dskaddr, WPT, 1);
30129533Ssam }
30229533Ssam }
30329533Ssam }
30429533Ssam
30529533Ssam
30629533Ssam /*
30729533Ssam **
30829533Ssam */
30929533Ssam
zero_bad_sector_map()31029533Ssam zero_bad_sector_map()
31129533Ssam {
31229533Ssam bs_map *bm = bad_map;
31329533Ssam register int i;
31429533Ssam dskadr zero;
31529533Ssam
31629533Ssam zero.cylinder = 0;
31729533Ssam zero.track = 0;
31829533Ssam zero.sector = 0;
31932662Skarels for(i=0; i < bm->bs_count; i++)
32029533Ssam bm->list[i].bs_alt = zero;
32129533Ssam load_free_table();
32229533Ssam }
32329533Ssam
32429533Ssam
32529533Ssam /*
32629533Ssam **
32729533Ssam */
32829533Ssam
read_flaw_map()32929533Ssam read_flaw_map()
33029533Ssam {
33129533Ssam register int cyl, trk;
33229533Ssam dskadr dskaddr;
33329533Ssam flaw buffer;
33429533Ssam
33529533Ssam dskaddr.sector = 0;
33632662Skarels for (cyl=0; cyl < lab->d_ncylinders; cyl++) {
33729533Ssam dskaddr.cylinder = cyl;
33832662Skarels for (trk=0; trk < lab->d_ntracks; trk++) {
33929533Ssam dskaddr.track = trk;
34031318Ssam access_dsk(&buffer, &dskaddr, VDOP_RDRAW, 1, 1);
34129533Ssam if(align_buf(&buffer, CDCSYNC) == true) {
34229533Ssam add_flaw_entries(&buffer);
34329533Ssam continue;
34429533Ssam }
34529533Ssam }
34629533Ssam }
34729533Ssam load_free_table();
34829533Ssam }
34929533Ssam
35029533Ssam
35129533Ssam /*
35229533Ssam **
35329533Ssam */
35429533Ssam
get_smde_relocations()35529533Ssam get_smde_relocations()
35629533Ssam {
35729533Ssam register int cyl, trk, sec;
35829533Ssam smde_hdr buffer;
35929533Ssam dskadr dskaddr;
36029533Ssam fmt_err bad;
36129533Ssam bs_entry temp;
36229533Ssam boolean bad_track;
36329533Ssam
36429533Ssam /* Read any old drive relocations */
36532662Skarels for(cyl=0; cyl < NUMREL; cyl++) {
36632662Skarels dskaddr.cylinder = lab->d_ncylinders - NUMSYS + cyl;
36732662Skarels for(trk=0; trk < lab->d_ntracks; trk++) {
36829533Ssam dskaddr.track = trk;
36929533Ssam bad_track = true;
37032662Skarels for(sec=0; sec < lab->d_nsectors; sec++) {
37129533Ssam dskaddr.sector = sec;
37231318Ssam access_dsk(&buffer, &dskaddr, VDOP_RDRAW, 1, 1);
37329533Ssam if(align_buf(&buffer, SMDE1SYNC) == false) {
37429533Ssam bad_track = false;
37529533Ssam break;
37629533Ssam }
37729533Ssam }
37829533Ssam if(bad_track == true) {
37929533Ssam dskaddr.sector = 0;
38029533Ssam bad.err_adr.cylinder = buffer.alt_cyl;
38129533Ssam bad.err_adr.track = buffer.alt_trk;
38229533Ssam bad.err_adr.sector = 0;
38329533Ssam bad.err_stat = HEADER_ERROR;
38434667Skarels (*C_INFO->code_pos)(&bad, &temp);
38529533Ssam temp.bs_alt = dskaddr;
38629533Ssam temp.bs_how = scanning;
38729533Ssam add_flaw(&temp);
38829533Ssam continue;
38929533Ssam }
39032662Skarels for(sec=0; sec < lab->d_nsectors; sec++) {
39129533Ssam dskaddr.sector = sec;
39231318Ssam access_dsk(&buffer, &dskaddr, VDOP_RDRAW, 1, 1);
39329533Ssam if(align_buf(&buffer, SMDE1SYNC) == true) {
39429533Ssam bad.err_adr.cylinder = buffer.alt_cyl;
39529533Ssam bad.err_adr.track = buffer.alt_trk;
39629533Ssam bad.err_adr.sector = buffer.alt_sec;
39729533Ssam bad.err_stat = DATA_ERROR;
39834667Skarels (*C_INFO->code_pos)(&bad, &temp);
39929533Ssam temp.bs_alt = dskaddr;
40029533Ssam temp.bs_how = scanning;
40129533Ssam add_flaw(&temp);
40229533Ssam }
40329533Ssam }
40429533Ssam }
40529533Ssam }
40629533Ssam load_free_table();
40729533Ssam }
40829533Ssam
40929533Ssam
41029533Ssam /*
41129533Ssam **
41229533Ssam */
41329533Ssam
add_flaw_entries(buffer)41429533Ssam add_flaw_entries(buffer)
41529533Ssam flaw *buffer;
41629533Ssam {
41729533Ssam register int i;
41829533Ssam bs_entry temp;
41929533Ssam
42029533Ssam temp.bs_cyl = buffer->flaw_cyl & 0x7fff; /* clear off bad track bit */
42129533Ssam temp.bs_trk = buffer->flaw_trk;
42232662Skarels for(i=0; i < 4; i++) {
42329533Ssam if(buffer->flaw_pos[i].flaw_length != 0) {
42429533Ssam temp.bs_offset = buffer->flaw_pos[i].flaw_offset;
42529533Ssam temp.bs_length = buffer->flaw_pos[i].flaw_length;
42629533Ssam temp.bs_alt.cylinder = 0;
42729533Ssam temp.bs_alt.track = 0;
42829533Ssam temp.bs_alt.sector = 0;
42929533Ssam temp.bs_how = flaw_map;
43029533Ssam add_flaw(&temp);
43129533Ssam }
43229533Ssam }
43329533Ssam }
43429533Ssam
43529533Ssam
cmp_entry(a,b)43629533Ssam cmp_entry(a, b)
43729533Ssam bs_entry *a;
43829533Ssam bs_entry *b;
43929533Ssam {
44029533Ssam if(a->bs_cyl == b->bs_cyl) {
44129533Ssam if(a->bs_trk == b->bs_trk) {
44229533Ssam if(a->bs_offset == b->bs_offset)
44329533Ssam return 0;
44429533Ssam else if(a->bs_offset < b->bs_offset)
44529533Ssam return -1;
44629981Skarels }
44729533Ssam else if(a->bs_trk < b->bs_trk)
44829533Ssam return -1;
44929533Ssam }
45029533Ssam else if(a->bs_cyl < b->bs_cyl)
45129533Ssam return -1;
45229533Ssam return 1;
45329533Ssam }
45429533Ssam
45529533Ssam
45634667Skarels /*
45734667Skarels * Add flaw to map.
45834667Skarels * Return value:
45934667Skarels * 1 OK
46034667Skarels * 0 sector was in map
46134667Skarels * -1 failure
46234667Skarels */
add_flaw(entry)46329533Ssam add_flaw(entry)
46429533Ssam bs_entry *entry;
46529533Ssam {
46629533Ssam extern int cmp_entry();
46729533Ssam bs_map *bm = bad_map;
46829533Ssam register int i;
46929533Ssam
47029533Ssam if(bm->bs_count > MAX_FLAWS)
47134667Skarels return (-1);
47232662Skarels if (entry->bs_cyl >= lab->d_ncylinders ||
47332662Skarels entry->bs_trk >= lab->d_ntracks ||
47432662Skarels entry->bs_offset >= lab->d_traksize)
47534667Skarels return (-1);
47632662Skarels for(i=0; i < bm->bs_count; i++) {
47729533Ssam if(((bm->list[i].bs_cyl == entry->bs_cyl)) &&
47829533Ssam (bm->list[i].bs_trk == entry->bs_trk) &&
47929533Ssam (bm->list[i].bs_offset == entry->bs_offset)) {
48029533Ssam if((int)bm->list[i].bs_how > (int)entry->bs_how)
48129533Ssam bm->list[i].bs_how = entry->bs_how;
48234667Skarels return (0);
48329533Ssam }
48429533Ssam }
48529533Ssam bm->list[i] = *entry;
48629533Ssam bm->list[i].bs_alt.cylinder = 0;
48729533Ssam bm->list[i].bs_alt.track = 0;
48829533Ssam bm->list[i].bs_alt.sector = 0;
48929533Ssam bm->bs_count++;
49029533Ssam qsort((char *)&(bm->list[0]), (unsigned)bm->bs_count,
49129533Ssam sizeof(bs_entry), cmp_entry);
49234667Skarels return (1);
49329533Ssam }
49429533Ssam
49529533Ssam
49629533Ssam /*
49729533Ssam ** Is_in_map checks to see if a block is known to be bad already.
49829533Ssam */
49929533Ssam
is_in_map(dskaddr)50029533Ssam boolean is_in_map(dskaddr)
50129533Ssam dskadr *dskaddr;
50229533Ssam {
50329533Ssam register int i;
50429533Ssam fmt_err temp;
50529533Ssam
50632662Skarels for(i=0; i < bad_map->bs_count; i++) {
50734667Skarels (*C_INFO->decode_pos)(&bad_map->list[i], &temp);
50829533Ssam if((temp.err_adr.cylinder == dskaddr->cylinder) &&
50929533Ssam (temp.err_adr.track == dskaddr->track) &&
51029533Ssam (temp.err_adr.sector == dskaddr->sector)) {
51129533Ssam return true;
51229533Ssam }
51329533Ssam }
51429533Ssam return false;
51529533Ssam }
51629533Ssam
51729533Ssam
51829533Ssam /*
51929533Ssam **
52029533Ssam */
52129533Ssam
print_bad_sector_list()52229533Ssam print_bad_sector_list()
52329533Ssam {
52429533Ssam register int i;
52529533Ssam fmt_err errloc;
52634667Skarels register bs_entry *bad;
52729533Ssam
528*43645Skarels if(bad_map->bs_magic != BSMAGIC)
529*43645Skarels print("Bad-sector map magic number wrong! (%x != %x)\n",
530*43645Skarels bad_map->bs_magic, BSMAGIC);
53129533Ssam if(bad_map->bs_count == 0) {
53229533Ssam print("There are no bad sectors in bad sector map.\n");
53329533Ssam return;
53429533Ssam }
535*43645Skarels print("The following %d sector%s known to be bad:\n",
536*43645Skarels bad_map->bs_count, (bad_map->bs_count == 1) ? " is" : "s are");
537*43645Skarels exdent(0);
53834667Skarels for(i=0, bad = bad_map->list; i < bad_map->bs_count; i++, bad++) {
53934667Skarels (*C_INFO->decode_pos)(bad, &errloc);
540*43645Skarels print("%c %d cn %d tn %d sn %d pos %d len %d ",
541*43645Skarels errloc.err_stat & HEADER_ERROR ? 'T' : 'S',
54234667Skarels to_sector(errloc.err_adr),
54334667Skarels bad->bs_cyl,
54434667Skarels bad->bs_trk,
54534667Skarels errloc.err_adr.sector,
54634667Skarels bad->bs_offset,
54734667Skarels bad->bs_length);
54834667Skarels if (bad->bs_how == flaw_map)
54934667Skarels printf("(flawmap) ");
55034667Skarels else if (bad->bs_how == scanning)
55134667Skarels printf("(verify) ");
55234667Skarels else
55334667Skarels printf("(operator) ");
55434667Skarels if((bad->bs_alt.cylinder != 0) || (bad->bs_alt.track != 0) ||
55534667Skarels (bad->bs_alt.sector != 0)) {
55634667Skarels printf("-> ");
55734667Skarels printf("cn %d tn %d sn %d", bad->bs_alt.cylinder,
55834667Skarels bad->bs_alt.track, bad->bs_alt.sector);
55929533Ssam }
56034667Skarels printf("\n");
56129533Ssam }
56229533Ssam }
56329533Ssam
56429533Ssam
56529533Ssam /*
56634667Skarels ** load_free_table checks each block in the bad block relocation area
56729533Ssam ** to see if it is used. If it is, the free relocation block table is updated.
56829533Ssam */
56929533Ssam
load_free_table()57029533Ssam load_free_table()
57129533Ssam {
57229533Ssam register int i, j;
57329533Ssam fmt_err temp;
57429533Ssam
57529533Ssam /* Clear free table before starting */
57632662Skarels for(i = 0; i < (lab->d_ntracks * NUMREL); i++) {
57732662Skarels for(j=0; j < lab->d_nsectors; j++)
57829533Ssam free_tbl[i][j].free_status = NOTALLOCATED;
57929533Ssam }
58032662Skarels for(i=0; i < bad_map->bs_count; i++)
58129533Ssam if((bad_map->list[i].bs_alt.cylinder != 0) ||
58229533Ssam (bad_map->list[i].bs_alt.track != 0) ||
58329533Ssam (bad_map->list[i].bs_alt.sector != 0)) {
58434667Skarels (*C_INFO->decode_pos)(&bad_map->list[i], &temp);
58529533Ssam allocate(&(bad_map->list[i].bs_alt), temp.err_stat);
58629533Ssam }
58729533Ssam }
58829533Ssam
58929533Ssam
59029533Ssam /*
59129533Ssam ** allocate marks a replacement sector as used.
59229533Ssam */
59329533Ssam
allocate(dskaddr,status)59429533Ssam allocate(dskaddr, status)
59529533Ssam dskadr *dskaddr;
59629533Ssam long status;
59729533Ssam {
59829533Ssam register int trk, sec;
59929533Ssam
60032662Skarels trk = dskaddr->cylinder - (lab->d_ncylinders - NUMSYS);
60129533Ssam if((trk < 0) || (trk >= NUMREL))
60229533Ssam return;
60332662Skarels trk *= lab->d_ntracks;
60429533Ssam trk += dskaddr->track;
60529533Ssam if(status & HEADER_ERROR)
60632662Skarels for(sec=0; sec < lab->d_nsectors; sec++)
60729533Ssam free_tbl[trk][sec].free_status = ALLOCATED;
60829533Ssam else
60929533Ssam free_tbl[trk][dskaddr->sector].free_status = ALLOCATED;
61029533Ssam }
61129533Ssam
61229533Ssam
61329533Ssam /*
61429533Ssam **
61529533Ssam */
61629533Ssam
mapping_collision(entry)61729533Ssam boolean mapping_collision(entry)
61829533Ssam bs_entry *entry;
61929533Ssam {
62029533Ssam register int trk, sec;
62129533Ssam fmt_err temp;
62229533Ssam
62332662Skarels trk = entry->bs_cyl - (lab->d_ncylinders - NUMSYS);
62429533Ssam if((trk < 0) || (trk >= NUMREL))
62529533Ssam return false;
62632662Skarels trk *= lab->d_ntracks;
62729533Ssam trk += entry->bs_trk;
62834667Skarels (*C_INFO->decode_pos)(entry, &temp);
62929533Ssam /* if this relocation should take up the whole track */
63029533Ssam if(temp.err_stat & HEADER_ERROR) {
63132662Skarels for(sec=0; sec < lab->d_nsectors; sec++)
63229533Ssam if(free_tbl[trk][sec].free_status == ALLOCATED)
63329533Ssam return true;
63429533Ssam }
63529533Ssam /* else just check the current sector */
63629533Ssam else {
63729533Ssam if(free_tbl[trk][temp.err_adr.sector].free_status == ALLOCATED)
63829533Ssam return true;
63929533Ssam }
64029533Ssam return false;
64129533Ssam }
64229533Ssam
64329533Ssam
64429533Ssam /*
64529533Ssam **
64629533Ssam */
64729533Ssam
report_collision()64829533Ssam report_collision()
64929533Ssam {
65029533Ssam indent();
65129533Ssam print("Sector resides in relocation area");
65229533Ssam printf("but it has a sector mapped to it already.\n");
65329533Ssam print("Please reformat disk with 0 patterns to eliminate problem.\n");
65429533Ssam exdent(1);
65529533Ssam }
65629533Ssam
65729533Ssam
65829533Ssam /*
65929533Ssam **
66029533Ssam */
66129533Ssam
add_user_relocations(entry)66229533Ssam add_user_relocations(entry)
66329533Ssam bs_entry *entry;
66429533Ssam {
66529533Ssam fmt_err error;
66629533Ssam
66734667Skarels (*C_INFO->decode_pos)(entry, &error);
66829533Ssam if(is_in_map(&error.err_adr) == false) {
66929533Ssam if(mapping_collision(entry) == true)
67029533Ssam report_collision();
67129533Ssam entry->bs_how = operator;
67229533Ssam add_flaw(entry);
67329533Ssam }
67429533Ssam else {
67529533Ssam indent();
67629533Ssam print("Sector %d is already mapped out!\n",
67729533Ssam to_sector(error.err_adr));
67829533Ssam exdent(1);
67929533Ssam }
68029533Ssam }
68129533Ssam
68229533Ssam
68329533Ssam /*
68429533Ssam ** New_location allocates a replacement block given a bad block address.
68529533Ssam ** The algorithm is fairly simple; it simply searches for the first
68629533Ssam ** free sector that has the same sector number of the bad sector. If no sector
68729533Ssam ** is found then the drive should be considered bad because of a microcode bug
68829533Ssam ** in the controller that forces us to use the same sector number as the bad
68929533Ssam ** sector for relocation purposes. Using different tracks and cylinders is ok
69029533Ssam ** of course.
69129533Ssam */
69229533Ssam
new_location(entry)69329533Ssam dskadr *new_location(entry)
69429533Ssam bs_entry *entry;
69529533Ssam {
69629533Ssam register int i, sec;
69729533Ssam static fmt_err temp;
69829533Ssam static dskadr newaddr;
69929533Ssam
70029533Ssam newaddr.cylinder = 0;
70129533Ssam newaddr.track = 0;
70229533Ssam newaddr.sector = 0;
70334667Skarels (*C_INFO->decode_pos)(entry, &temp);
70429533Ssam /* If it is ouside of the user's data area */
70532662Skarels if(entry->bs_cyl >= lab->d_ncylinders-NUMSYS) {
70629533Ssam /* if it is in the relocation area */
70732662Skarels if(entry->bs_cyl < (lab->d_ncylinders - NUMMAP - NUMMNT)) {
70829533Ssam /* mark space as allocated */
70929533Ssam allocate(&temp.err_adr, temp.err_stat);
71029533Ssam return &temp.err_adr;
71129533Ssam }
71229533Ssam /* if it is in the map area forget about it */
71332662Skarels if(entry->bs_cyl != (lab->d_ncylinders - NUMMAP - NUMMNT))
71429533Ssam return &temp.err_adr;
71529533Ssam /* otherwise treat maintainence cylinder normally */
71629533Ssam }
71729533Ssam if(temp.err_stat & (HEADER_ERROR)) {
71832662Skarels for(i = 0; i < (lab->d_ntracks * NUMREL); i++) {
71932662Skarels for(sec=0; sec < lab->d_nsectors; sec++) {
72029533Ssam if(free_tbl[i][sec].free_status == ALLOCATED)
72129533Ssam break;
72229533Ssam }
72332662Skarels if(sec == lab->d_nsectors) {
72432662Skarels for(sec = 0; sec < lab->d_nsectors; sec++)
72529533Ssam free_tbl[i][sec].free_status=ALLOCATED;
72632662Skarels newaddr.cylinder = i / lab->d_ntracks +
72732662Skarels (lab->d_ncylinders - NUMSYS);
72832662Skarels newaddr.track = i % lab->d_ntracks;
72929533Ssam break;
73029533Ssam }
73129533Ssam }
73229533Ssam }
73332662Skarels else if(C_INFO->type == VDTYPE_VDDC) {
73432662Skarels for(i = 0; i < (lab->d_ntracks * NUMREL); i++) {
73529533Ssam if(free_tbl[i][temp.err_adr.sector].free_status !=
73629533Ssam ALLOCATED) {
73729533Ssam free_tbl[i][temp.err_adr.sector].free_status =
73829533Ssam ALLOCATED;
73932662Skarels newaddr.cylinder = i / lab->d_ntracks +
74032662Skarels (lab->d_ncylinders - NUMSYS);
74132662Skarels newaddr.track = i % lab->d_ntracks;
74229533Ssam newaddr.sector = temp.err_adr.sector;
74329533Ssam break;
74429533Ssam }
74529533Ssam }
74629533Ssam }
74729533Ssam else {
74832662Skarels for(i = 0; i < (lab->d_ntracks * NUMREL); i++) {
74932662Skarels for(sec=0; sec < lab->d_nsectors; sec++)
75029533Ssam if(free_tbl[i][sec].free_status != ALLOCATED)
75129533Ssam break;
75232662Skarels if(sec < lab->d_nsectors) {
75329533Ssam free_tbl[i][sec].free_status = ALLOCATED;
75432662Skarels newaddr.cylinder = i / lab->d_ntracks +
75532662Skarels (lab->d_ncylinders - NUMSYS);
75632662Skarels newaddr.track = i % lab->d_ntracks;
75729533Ssam newaddr.sector = sec;
75829533Ssam break;
75929533Ssam }
76029533Ssam }
76129533Ssam }
76229533Ssam return &newaddr;
76329533Ssam }
764