xref: /csrg-svn/sys/tahoe/stand/vdformat/maps.c (revision 29981)
129533Ssam #ifndef lint
2*29981Skarels static char sccsid[] = "@(#)maps.c	1.2 (Berkeley/CCI) 11/04/86";
329533Ssam #endif
429533Ssam 
529533Ssam 
629533Ssam #include	"vdfmt.h"
729533Ssam 
829533Ssam 
929533Ssam /*
1029533Ssam **
1129533Ssam */
1229533Ssam 
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 */
2029533Ssam 	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 
37*29981Skarels boolean
38*29981Skarels read_map(flags)
3929533Ssam short	flags;
4029533Ssam {
4129533Ssam 	register int	trk, i;
4229533Ssam 	dskadr		dskaddr;
4329533Ssam 
4429533Ssam 	dskaddr.cylinder = (CURRENT->vc_ncyl - 1) | flags;
4529533Ssam 	for(i=0; i<100; i++)
4629533Ssam 		scratch[i] = -1;
4729533Ssam 	for(trk=0; trk<CURRENT->vc_ntrak; trk++) {
4829533Ssam 		dskaddr.track = trk;
4929533Ssam 		dskaddr.sector = 0;
5029533Ssam 		if(access_dsk((char *)save,&dskaddr,RD,CURRENT->vc_nsec,1)& HRDERR)
5129533Ssam 			continue;
5229533Ssam 		if(blkcmp((char *)scratch, (char *)save, bytes_trk) == true) {
5329533Ssam 			blkcopy((char *)save, (char *)bad_map, bytes_trk);
5429533Ssam 			if(bad_map->bs_count <= MAX_FLAWS) {
5529533Ssam 				for(i=0; i<bad_map->bs_count; i++) {
5629533Ssam 					if(bad_map->list[i].bs_cyl >=
5729533Ssam 					    CURRENT->vc_ncyl)
5829533Ssam 						break;
5929533Ssam 					if(bad_map->list[i].bs_trk >=
6029533Ssam 					    CURRENT->vc_ntrak)
6129533Ssam 						break;
6229533Ssam 					if(bad_map->list[i].bs_offset >=
6329533Ssam 					    CURRENT->vc_traksize)
6429533Ssam 						break;
6529533Ssam 				}
6629533Ssam 				if(i == bad_map->bs_count) {
6729533Ssam 					load_free_table();
6829533Ssam 					return true;
6929533Ssam 				}
70*29981Skarels else
71*29981Skarels printf("%d: junk, slot %d/%d\n", trk, i, bad_map->bs_count);
72*29981Skarels 			}
7329533Ssam 			blkzero(bad_map, bytes_trk);
7429533Ssam 			bad_map->bs_id = 0;
7529533Ssam 			bad_map->bs_max = MAX_FLAWS;
7629533Ssam 		}
7729533Ssam 		blkcopy((char *)save, (char *)scratch, bytes_trk);
7829533Ssam 	}
7929533Ssam 	return false;
8029533Ssam }
8129533Ssam 
8229533Ssam 
8329533Ssam /*
8429533Ssam **
8529533Ssam */
8629533Ssam 
8729533Ssam boolean read_bad_sector_map()
8829533Ssam {
8929533Ssam 	dskadr		dskaddr;
9029533Ssam 
9129533Ssam 	dskaddr.cylinder = CURRENT->vc_ncyl - 1;
9229533Ssam 	dskaddr.track = 0;
9329533Ssam 	dskaddr.sector = 0;
9429533Ssam 	/* start with nothing in map */
9529533Ssam 	blkzero(bad_map, bytes_trk);
9629533Ssam 	bad_map->bs_id = 0;
9729533Ssam 	bad_map->bs_max = MAX_FLAWS;
98*29981Skarels 	if (C_INFO.type == SMD_ECTLR) {
9929533Ssam 		access_dsk((char *)save, &dskaddr, RD_RAW, 1, 1);
100*29981Skarels 		if (align_buf((unsigned long *)save, CDCSYNC) == true) {
101*29981Skarels printf("Reading manufacturer's flaw maps...");
10229533Ssam 			read_flaw_map();
103*29981Skarels printf("\n");
104*29981Skarels 			return (false);
105*29981Skarels 		} else if (read_map(NRM) == true) {
106*29981Skarels 			return (true);
107*29981Skarels 		} else {
108*29981Skarels printf("Scanning for old relocations...");
10929533Ssam 			get_smde_relocations();
110*29981Skarels printf("\n");
11129533Ssam 			return false;
11229533Ssam 		}
113*29981Skarels 	} else {
114*29981Skarels 		if (read_map(WPT) == true)
115*29981Skarels 			return (true);
116*29981Skarels 		else {
117*29981Skarels printf("Scanning for old relocations...");
118*29981Skarels 			get_relocations_the_hard_way();
119*29981Skarels printf("\n");
120*29981Skarels 			return (false);
121*29981Skarels 		}
12229533Ssam 	}
12329533Ssam }
12429533Ssam 
12529533Ssam 
12629533Ssam /*
12729533Ssam **
12829533Ssam */
12929533Ssam 
13029533Ssam get_relocations_the_hard_way()
13129533Ssam {
13229533Ssam 	register int	cyl, trk;
13329533Ssam 	register int	status;
13429533Ssam 	dskadr		dskaddr;
13529533Ssam 
13629533Ssam 	dskaddr.sector = 0;
13729533Ssam 	/* scan each sector to see if it is relocated and take note if it is */
13829533Ssam 	for(cyl=0; cyl<CURRENT->vc_ncyl-NUMSYS; cyl++) {
13929533Ssam 		dskaddr.cylinder = cyl;
14029533Ssam 		for(trk=0; trk<CURRENT->vc_ntrak; trk++) {
14129533Ssam 			dskaddr.track = trk;
14229533Ssam 			status=access_dsk((char *)scratch, &dskaddr,
14329533Ssam 			    RD, CURRENT->vc_nsec, 1);
14429533Ssam 			if(status & ALTACC)
14529533Ssam 				get_track_relocations(dskaddr);
14629533Ssam 		}
14729533Ssam 	}
14829533Ssam 	load_free_table();
14929533Ssam }
15029533Ssam 
15129533Ssam 
15229533Ssam /*
15329533Ssam **
15429533Ssam */
15529533Ssam 
15629533Ssam get_track_relocations(dskaddr)
15729533Ssam dskadr	dskaddr;
15829533Ssam {
15929533Ssam 	register int	status;
16029533Ssam 	bs_entry	temp;
16129533Ssam 	fmt_err		error;
16229533Ssam 
16329533Ssam 	for(dskaddr.sector=0; dskaddr.sector<CURRENT->vc_nsec; dskaddr.sector++) {
16429533Ssam 		status = access_dsk((char *)scratch, &dskaddr, RD, 1, 1);
16529533Ssam 		if(status & ALTACC) {
16629533Ssam 			error.err_adr = dskaddr;
16729533Ssam 			error.err_stat = DATA_ERROR;
16829533Ssam 			temp = (*C_INFO.code_pos)(error);
16929533Ssam 			temp.bs_how = operator;
17029533Ssam 			add_flaw(&temp);
17129533Ssam 		}
17229533Ssam 	}
17329533Ssam }
17429533Ssam 
17529533Ssam 
17629533Ssam /*
17729533Ssam **
17829533Ssam */
17929533Ssam 
18029533Ssam remove_user_relocations(entry)
18129533Ssam bs_entry	entry;
18229533Ssam {
18329533Ssam 	register int	i, j;
18429533Ssam 	fmt_err		temp;
18529533Ssam 	fmt_err		error;
18629533Ssam 	bs_entry	*ptr;
18729533Ssam 
18829533Ssam 	error = (*C_INFO.decode_pos)(entry);
18929533Ssam 	if(is_in_map(&error.err_adr) == true) {
19029533Ssam 		ptr = bad_map->list;
19129533Ssam 		for(i=0; i<bad_map->bs_count; i++) {
19229533Ssam 			temp = (*C_INFO.decode_pos)(*ptr);
19329533Ssam 			if((ptr->bs_how == operator) &&
19429533Ssam 			    (temp.err_adr.cylinder == error.err_adr.cylinder) &&
19529533Ssam 			    (temp.err_adr.track == error.err_adr.track) &&
19629533Ssam 			    (temp.err_adr.sector == error.err_adr.sector)) {
19729533Ssam 				if(temp.err_stat & HEADER_ERROR)
19829533Ssam 					remove_track(temp, ptr);
19929533Ssam 				else
20029533Ssam 					remove_sector(temp, ptr);
20129533Ssam 				for(j=i+1; j<bad_map->bs_count; j++)
20229533Ssam 					bad_map->list[j-1] = bad_map->list[j];
20329533Ssam 				bad_map->bs_count--;
20429533Ssam 				return;
20529533Ssam 			}
20629533Ssam 			ptr++;
20729533Ssam 		}
20829533Ssam 	}
20929533Ssam 	else {
21029533Ssam 		indent();
21129533Ssam 		print("Sector %d is not in bad sector map!\n",
21229533Ssam 		    to_sector(error.err_adr));
21329533Ssam 		exdent(1);
21429533Ssam 	}
21529533Ssam }
21629533Ssam 
21729533Ssam 
21829533Ssam /*
21929533Ssam **
22029533Ssam */
22129533Ssam 
22229533Ssam remove_sector(error, entry)
22329533Ssam fmt_err		error;
22429533Ssam bs_entry	*entry;
22529533Ssam {
22629533Ssam 	format_sectors(&error.err_adr, &error.err_adr, NRM, 1);
22729533Ssam 	format_sectors(&entry->bs_alt, &entry->bs_alt, NRM, 1);
22829533Ssam }
22929533Ssam 
23029533Ssam 
23129533Ssam /*
23229533Ssam **
23329533Ssam */
23429533Ssam 
23529533Ssam remove_track(error, entry)
23629533Ssam fmt_err		error;
23729533Ssam bs_entry	*entry;
23829533Ssam {
23929533Ssam 	format_sectors(&error.err_adr,&error.err_adr,NRM,(long)CURRENT->vc_nsec);
24029533Ssam 	format_sectors(&entry->bs_alt,&entry->bs_alt,NRM,(long)CURRENT->vc_nsec);
24129533Ssam }
24229533Ssam 
24329533Ssam 
24429533Ssam /*
24529533Ssam **
24629533Ssam */
24729533Ssam 
24829533Ssam write_bad_sector_map()
24929533Ssam {
25029533Ssam 	register int	trk, sec;
25129533Ssam 	dskadr		dskaddr;
25229533Ssam 
25329533Ssam 	dskaddr.cylinder = (CURRENT->vc_ncyl - NUMMAP);
25429533Ssam 	for(trk=0; trk<CURRENT->vc_ntrak; trk++) {
25529533Ssam 		for(sec = 0; sec < CURRENT->vc_nsec; sec++) {
256*29981Skarels 			blkcopy((char *)bs_map_space + (sec * SECSIZ),
25729533Ssam 			    (char *)scratch, SECSIZ);
25829533Ssam 			dskaddr.track = trk;
25929533Ssam 			dskaddr.sector = sec;
26029533Ssam 			format_sectors(&dskaddr, &dskaddr, WPT, 1);
26129533Ssam 		}
26229533Ssam 	}
26329533Ssam }
26429533Ssam 
26529533Ssam 
26629533Ssam /*
26729533Ssam **
26829533Ssam */
26929533Ssam 
27029533Ssam zero_bad_sector_map()
27129533Ssam {
27229533Ssam 	bs_map		*bm = bad_map;
27329533Ssam 	register int	i;
27429533Ssam 	dskadr		zero;
27529533Ssam 
27629533Ssam 	zero.cylinder = 0;
27729533Ssam 	zero.track = 0;
27829533Ssam 	zero.sector = 0;
27929533Ssam 	for(i=0; i<bm->bs_count; i++)
28029533Ssam 		bm->list[i].bs_alt = zero;
28129533Ssam 	load_free_table();
28229533Ssam }
28329533Ssam 
28429533Ssam 
28529533Ssam /*
28629533Ssam **
28729533Ssam */
28829533Ssam 
28929533Ssam read_flaw_map()
29029533Ssam {
29129533Ssam 	register int	cyl, trk;
29229533Ssam 	dskadr		dskaddr;
29329533Ssam 	flaw		buffer;
29429533Ssam 
29529533Ssam 	dskaddr.sector = 0;
29629533Ssam 	for  (cyl=0; cyl<CURRENT->vc_ncyl; cyl++) {
29729533Ssam 		dskaddr.cylinder = cyl;
29829533Ssam 		for  (trk=0; trk<CURRENT->vc_ntrak; trk++) {
29929533Ssam 			dskaddr.track = trk;
30029533Ssam 			access_dsk(&buffer, &dskaddr, RD_RAW, 1, 1);
30129533Ssam 			if(align_buf(&buffer, CDCSYNC) == true) {
30229533Ssam 				add_flaw_entries(&buffer);
30329533Ssam 				continue;
30429533Ssam 			}
30529533Ssam 		}
30629533Ssam 	}
30729533Ssam 	load_free_table();
30829533Ssam }
30929533Ssam 
31029533Ssam 
31129533Ssam /*
31229533Ssam **
31329533Ssam */
31429533Ssam 
31529533Ssam get_smde_relocations()
31629533Ssam {
31729533Ssam 	register int	cyl, trk, sec;
31829533Ssam 	smde_hdr	buffer;
31929533Ssam 	dskadr		dskaddr;
32029533Ssam 	fmt_err		bad;
32129533Ssam 	bs_entry	temp;
32229533Ssam 	boolean		bad_track;
32329533Ssam 
32429533Ssam 	/* Read any old drive relocations */
32529533Ssam 	for(cyl=0; cyl<NUMREL; cyl++) {
32629533Ssam 		dskaddr.cylinder = CURRENT->vc_ncyl - NUMSYS + cyl;
32729533Ssam 		for(trk=0; trk<CURRENT->vc_ntrak; trk++) {
32829533Ssam 			dskaddr.track = trk;
32929533Ssam 			bad_track = true;
33029533Ssam 			for(sec=0; sec<CURRENT->vc_nsec; sec++) {
33129533Ssam 				dskaddr.sector = sec;
33229533Ssam 				access_dsk(&buffer, &dskaddr, RD_RAW, 1, 1);
33329533Ssam 				if(align_buf(&buffer, SMDE1SYNC) == false) {
33429533Ssam 					bad_track = false;
33529533Ssam 					break;
33629533Ssam 				}
33729533Ssam 			}
33829533Ssam 			if(bad_track == true) {
33929533Ssam 				dskaddr.sector = 0;
34029533Ssam 				bad.err_adr.cylinder = buffer.alt_cyl;
34129533Ssam 				bad.err_adr.track = buffer.alt_trk;
34229533Ssam 				bad.err_adr.sector = 0;
34329533Ssam 				bad.err_stat = HEADER_ERROR;
34429533Ssam 				temp = (*C_INFO.code_pos)(bad);
34529533Ssam 				temp.bs_alt = dskaddr;
34629533Ssam 				temp.bs_how = scanning;
34729533Ssam 				add_flaw(&temp);
34829533Ssam 				continue;
34929533Ssam 			}
35029533Ssam 			for(sec=0; sec<CURRENT->vc_nsec; sec++) {
35129533Ssam 				dskaddr.sector = sec;
35229533Ssam 				access_dsk(&buffer, &dskaddr, RD_RAW, 1, 1);
35329533Ssam 				if(align_buf(&buffer, SMDE1SYNC) == true) {
35429533Ssam 					bad.err_adr.cylinder = buffer.alt_cyl;
35529533Ssam 					bad.err_adr.track = buffer.alt_trk;
35629533Ssam 					bad.err_adr.sector = buffer.alt_sec;
35729533Ssam 					bad.err_stat = DATA_ERROR;
35829533Ssam 					temp = (*C_INFO.code_pos)(bad);
35929533Ssam 					temp.bs_alt = dskaddr;
36029533Ssam 					temp.bs_how = scanning;
36129533Ssam 					add_flaw(&temp);
36229533Ssam 				}
36329533Ssam 			}
36429533Ssam 		}
36529533Ssam 	}
36629533Ssam 	load_free_table();
36729533Ssam }
36829533Ssam 
36929533Ssam 
37029533Ssam /*
37129533Ssam **
37229533Ssam */
37329533Ssam 
37429533Ssam add_flaw_entries(buffer)
37529533Ssam flaw	*buffer;
37629533Ssam {
37729533Ssam 	register int	i;
37829533Ssam 	bs_entry	temp;
37929533Ssam 
38029533Ssam 	temp.bs_cyl = buffer->flaw_cyl & 0x7fff; /* clear off bad track bit */
38129533Ssam 	temp.bs_trk = buffer->flaw_trk;
38229533Ssam 	for(i=0; i<4; i++) {
38329533Ssam 		if(buffer->flaw_pos[i].flaw_length != 0) {
38429533Ssam 			temp.bs_offset = buffer->flaw_pos[i].flaw_offset;
38529533Ssam 			temp.bs_length = buffer->flaw_pos[i].flaw_length;
38629533Ssam 			temp.bs_alt.cylinder = 0;
38729533Ssam 			temp.bs_alt.track = 0;
38829533Ssam 			temp.bs_alt.sector = 0;
38929533Ssam 			temp.bs_how = flaw_map;
39029533Ssam 			add_flaw(&temp);
39129533Ssam 		}
39229533Ssam 	}
39329533Ssam }
39429533Ssam 
39529533Ssam 
39629533Ssam cmp_entry(a, b)
39729533Ssam bs_entry	*a;
39829533Ssam bs_entry	*b;
39929533Ssam {
40029533Ssam 	if(a->bs_cyl == b->bs_cyl) {
40129533Ssam 		if(a->bs_trk == b->bs_trk) {
40229533Ssam 			if(a->bs_offset == b->bs_offset)
40329533Ssam 				return 0;
40429533Ssam 			else if(a->bs_offset < b->bs_offset)
40529533Ssam 				return -1;
406*29981Skarels 		 }
40729533Ssam 		else if(a->bs_trk < b->bs_trk)
40829533Ssam 			return -1;
40929533Ssam 	}
41029533Ssam 	else if(a->bs_cyl < b->bs_cyl)
41129533Ssam 		return -1;
41229533Ssam 	return 1;
41329533Ssam }
41429533Ssam 
41529533Ssam 
41629533Ssam add_flaw(entry)
41729533Ssam bs_entry	*entry;
41829533Ssam {
41929533Ssam 	extern	int	cmp_entry();
42029533Ssam 	bs_map		*bm = bad_map;
42129533Ssam 	register int	i;
42229533Ssam 
42329533Ssam 	if(bm->bs_count > MAX_FLAWS)
42429533Ssam 		return;
425*29981Skarels 	if (entry->bs_cyl >= CURRENT->vc_ncyl ||
426*29981Skarels 	    entry->bs_trk >= CURRENT->vc_ntrak ||
427*29981Skarels 	    entry->bs_offset >= CURRENT->vc_traksize)
428*29981Skarels 		return;
42929533Ssam 	for(i=0; i<bm->bs_count; i++) {
43029533Ssam 		if(((bm->list[i].bs_cyl == entry->bs_cyl)) &&
43129533Ssam 		    (bm->list[i].bs_trk == entry->bs_trk) &&
43229533Ssam 		    (bm->list[i].bs_offset == entry->bs_offset)) {
43329533Ssam 			if((int)bm->list[i].bs_how > (int)entry->bs_how)
43429533Ssam 				bm->list[i].bs_how = entry->bs_how;
43529533Ssam 			return;
43629533Ssam 		}
43729533Ssam 	}
43829533Ssam 	bm->list[i] = *entry;
43929533Ssam 	bm->list[i].bs_alt.cylinder = 0;
44029533Ssam 	bm->list[i].bs_alt.track = 0;
44129533Ssam 	bm->list[i].bs_alt.sector = 0;
44229533Ssam 	bm->bs_count++;
44329533Ssam 	qsort((char *)&(bm->list[0]), (unsigned)bm->bs_count,
44429533Ssam 	    sizeof(bs_entry), cmp_entry);
44529533Ssam }
44629533Ssam 
44729533Ssam 
44829533Ssam /*
44929533Ssam **	Is_in_map checks to see if a block is known to be bad already.
45029533Ssam */
45129533Ssam 
45229533Ssam boolean is_in_map(dskaddr)
45329533Ssam dskadr	*dskaddr;
45429533Ssam {
45529533Ssam 	register int	i;
45629533Ssam 	fmt_err		temp;
45729533Ssam 
45829533Ssam 	for(i=0; i<bad_map->bs_count; i++) {
45929533Ssam 		temp = (*C_INFO.decode_pos)(bad_map->list[i]);
46029533Ssam 		if((temp.err_adr.cylinder == dskaddr->cylinder) &&
46129533Ssam 		    (temp.err_adr.track == dskaddr->track) &&
46229533Ssam 		    (temp.err_adr.sector == dskaddr->sector)) {
46329533Ssam 			return true;
46429533Ssam 		}
46529533Ssam 	}
46629533Ssam 	return false;
46729533Ssam }
46829533Ssam 
46929533Ssam 
47029533Ssam /*
47129533Ssam **
47229533Ssam */
47329533Ssam 
47429533Ssam print_bad_sector_list()
47529533Ssam {
47629533Ssam 	register int	i;
47729533Ssam 	fmt_err		errloc;
47829533Ssam 
47929533Ssam 	if(bad_map->bs_count == 0) {
48029533Ssam 		print("There are no bad sectors in bad sector map.\n");
48129533Ssam 		return;
48229533Ssam 	}
48329533Ssam 	print("The following sector%s known to be bad:\n",
48429533Ssam 	    (bad_map->bs_count == 1) ? " is" : "s are");
48529533Ssam 	indent();
48629533Ssam 	for(i=0; i<bad_map->bs_count; i++) {
48729533Ssam 		print("cyl %d, head %d, pos %d, len %d ",
48829533Ssam 			bad_map->list[i].bs_cyl,
48929533Ssam 			bad_map->list[i].bs_trk,
49029533Ssam 			bad_map->list[i].bs_offset,
49129533Ssam 			bad_map->list[i].bs_length);
49229533Ssam 		errloc = (*C_INFO.decode_pos)(bad_map->list[i]);
49329533Ssam 		if(errloc.err_stat & HEADER_ERROR) {
49429533Ssam 			printf("(Track #%d)", to_track(errloc.err_adr));
49529533Ssam 		}
49629533Ssam 		else {
49729533Ssam 			printf("(Sector #%d)", to_sector(errloc.err_adr));
49829533Ssam 		}
49929533Ssam 		if((bad_map->list[i].bs_alt.cylinder != 0) ||
50029533Ssam 		    (bad_map->list[i].bs_alt.track != 0) ||
50129533Ssam 		    (bad_map->list[i].bs_alt.sector != 0)) {
50229533Ssam 			indent();
50329533Ssam 			printf(" -> ");
50429533Ssam 			if(errloc.err_stat & HEADER_ERROR) {
50529533Ssam 				printf("Track %d",
50629533Ssam 		    		    to_track(bad_map->list[i].bs_alt));
50729533Ssam 			}
50829533Ssam 			else {
50929533Ssam 				printf("Sector %d",
51029533Ssam 		    		    to_sector(bad_map->list[i].bs_alt));
51129533Ssam 			}
51229533Ssam 			exdent(1);
51329533Ssam 		}
51429533Ssam 		printf(".\n");
51529533Ssam 	}
51629533Ssam 	exdent(1);
51729533Ssam }
51829533Ssam 
51929533Ssam 
52029533Ssam /*
52129533Ssam **	Vdload_free_table checks each block in the bad block relocation area
52229533Ssam ** to see if it is used. If it is, the free relocation block table is updated.
52329533Ssam */
52429533Ssam 
52529533Ssam load_free_table()
52629533Ssam {
52729533Ssam 	register int	i, j;
52829533Ssam 	fmt_err		temp;
52929533Ssam 
53029533Ssam 	/* Clear free table before starting */
53129533Ssam 	for(i = 0; i < (CURRENT->vc_ntrak * NUMREL); i++) {
53229533Ssam 		for(j=0; j < CURRENT->vc_nsec; j++)
53329533Ssam 			free_tbl[i][j].free_status = NOTALLOCATED;
53429533Ssam 	}
53529533Ssam 	for(i=0; i<bad_map->bs_count; i++)
53629533Ssam 		if((bad_map->list[i].bs_alt.cylinder != 0) ||
53729533Ssam 		    (bad_map->list[i].bs_alt.track != 0) ||
53829533Ssam 		    (bad_map->list[i].bs_alt.sector != 0)) {
53929533Ssam 			temp = (*C_INFO.decode_pos)(bad_map->list[i]);
54029533Ssam 			allocate(&(bad_map->list[i].bs_alt), temp.err_stat);
54129533Ssam 		}
54229533Ssam }
54329533Ssam 
54429533Ssam 
54529533Ssam /*
54629533Ssam **	allocate marks a replacement sector as used.
54729533Ssam */
54829533Ssam 
54929533Ssam allocate(dskaddr, status)
55029533Ssam dskadr	*dskaddr;
55129533Ssam long	status;
55229533Ssam {
55329533Ssam 	register int	trk, sec;
55429533Ssam 
55529533Ssam 	trk = dskaddr->cylinder - (CURRENT->vc_ncyl - NUMSYS);
55629533Ssam 	if((trk < 0) || (trk >= NUMREL))
55729533Ssam 		return;
55829533Ssam 	trk *= CURRENT->vc_ntrak;
55929533Ssam 	trk += dskaddr->track;
56029533Ssam 	if(status & HEADER_ERROR)
56129533Ssam 		for(sec=0; sec<CURRENT->vc_nsec; sec++)
56229533Ssam 			free_tbl[trk][sec].free_status = ALLOCATED;
56329533Ssam 	else
56429533Ssam 		free_tbl[trk][dskaddr->sector].free_status = ALLOCATED;
56529533Ssam }
56629533Ssam 
56729533Ssam 
56829533Ssam /*
56929533Ssam **
57029533Ssam */
57129533Ssam 
57229533Ssam boolean mapping_collision(entry)
57329533Ssam bs_entry	*entry;
57429533Ssam {
57529533Ssam 	register int	trk, sec;
57629533Ssam 	fmt_err		temp;
57729533Ssam 
57829533Ssam 	trk = entry->bs_cyl - (CURRENT->vc_ncyl - NUMSYS);
57929533Ssam 	if((trk < 0) || (trk >= NUMREL))
58029533Ssam 		return false;
58129533Ssam 	trk *= CURRENT->vc_ntrak;
58229533Ssam 	trk += entry->bs_trk;
58329533Ssam 	temp = (*C_INFO.decode_pos)(*entry);
58429533Ssam 	/* if this relocation should take up the whole track */
58529533Ssam 	if(temp.err_stat & HEADER_ERROR) {
58629533Ssam 		for(sec=0; sec<CURRENT->vc_nsec; sec++)
58729533Ssam 			if(free_tbl[trk][sec].free_status == ALLOCATED)
58829533Ssam 				return true;
58929533Ssam 	}
59029533Ssam 	/* else just check the current sector */
59129533Ssam 	else {
59229533Ssam 		if(free_tbl[trk][temp.err_adr.sector].free_status == ALLOCATED)
59329533Ssam 			return true;
59429533Ssam 	}
59529533Ssam 	return false;
59629533Ssam }
59729533Ssam 
59829533Ssam 
59929533Ssam /*
60029533Ssam **
60129533Ssam */
60229533Ssam 
60329533Ssam report_collision()
60429533Ssam {
60529533Ssam 	indent();
60629533Ssam 	print("Sector resides in relocation area");
60729533Ssam 	printf("but it has a sector mapped to it already.\n");
60829533Ssam 	print("Please reformat disk with 0 patterns to eliminate problem.\n");
60929533Ssam 	exdent(1);
61029533Ssam }
61129533Ssam 
61229533Ssam 
61329533Ssam /*
61429533Ssam **
61529533Ssam */
61629533Ssam 
61729533Ssam add_user_relocations(entry)
61829533Ssam bs_entry	*entry;
61929533Ssam {
62029533Ssam 	fmt_err		error;
62129533Ssam 
62229533Ssam 	error = (*C_INFO.decode_pos)(*entry);
62329533Ssam 	if(is_in_map(&error.err_adr) == false) {
62429533Ssam 		if(mapping_collision(entry) == true)
62529533Ssam 			report_collision();
62629533Ssam 		entry->bs_how = operator;
62729533Ssam 		add_flaw(entry);
62829533Ssam 	}
62929533Ssam 	else {
63029533Ssam 		indent();
63129533Ssam 		print("Sector %d is already mapped out!\n",
63229533Ssam 		    to_sector(error.err_adr));
63329533Ssam 		exdent(1);
63429533Ssam 	}
63529533Ssam }
63629533Ssam 
63729533Ssam 
63829533Ssam /*
63929533Ssam ** 	New_location allocates a replacement block given a bad block address.
64029533Ssam **  The algorithm is fairly simple; it simply searches for the first
64129533Ssam **  free sector that has the same sector number of the bad sector.  If no sector
64229533Ssam **  is found then the drive should be considered bad because of a microcode bug
64329533Ssam **  in the controller that forces us to use the same sector number as the bad
64429533Ssam **  sector for relocation purposes.  Using different tracks and cylinders is ok
64529533Ssam **  of course.
64629533Ssam */
64729533Ssam 
64829533Ssam dskadr *new_location(entry)
64929533Ssam bs_entry	*entry;
65029533Ssam {
65129533Ssam 	register int	i, sec;
65229533Ssam 	static fmt_err	temp;
65329533Ssam 	static dskadr	newaddr;
65429533Ssam 
65529533Ssam 	newaddr.cylinder = 0;
65629533Ssam 	newaddr.track = 0;
65729533Ssam 	newaddr.sector = 0;
65829533Ssam 	temp = (*C_INFO.decode_pos)(*entry);
65929533Ssam 	/* If it is ouside of the user's data area */
66029533Ssam 	if(entry->bs_cyl >= CURRENT->vc_ncyl-NUMSYS) {
66129533Ssam 		/* if it is in the relocation area */
66229533Ssam 		if(entry->bs_cyl < (CURRENT->vc_ncyl - NUMMAP - NUMMNT)) {
66329533Ssam 			/* mark space as allocated */
66429533Ssam 			allocate(&temp.err_adr, temp.err_stat);
66529533Ssam 			return &temp.err_adr;
66629533Ssam 		}
66729533Ssam 		/* if it is in the map area forget about it */
66829533Ssam 		if(entry->bs_cyl != (CURRENT->vc_ncyl - NUMMAP - NUMMNT))
66929533Ssam 			return &temp.err_adr;
67029533Ssam 		/* otherwise treat maintainence cylinder normally */
67129533Ssam 	}
67229533Ssam 	if(temp.err_stat & (HEADER_ERROR)) {
67329533Ssam 		for(i = 0; i < (CURRENT->vc_ntrak * NUMREL); i++) {
67429533Ssam 			for(sec=0; sec < CURRENT->vc_nsec; sec++) {
67529533Ssam 				if(free_tbl[i][sec].free_status == ALLOCATED)
67629533Ssam 					break;
67729533Ssam 			}
67829533Ssam 			if(sec == CURRENT->vc_nsec) {
67929533Ssam 				for(sec = 0; sec < CURRENT->vc_nsec; sec++)
68029533Ssam 					free_tbl[i][sec].free_status=ALLOCATED;
68129533Ssam 				newaddr.cylinder = i / CURRENT->vc_ntrak +
68229533Ssam 				    (CURRENT->vc_ncyl - NUMSYS);
68329533Ssam 				newaddr.track = i % CURRENT->vc_ntrak;
68429533Ssam 				break;
68529533Ssam 			}
68629533Ssam 		}
68729533Ssam 	}
68829533Ssam 	else if(C_INFO.type == SMDCTLR) {
68929533Ssam 		for(i = 0; i < (CURRENT->vc_ntrak * NUMREL); i++) {
69029533Ssam 			if(free_tbl[i][temp.err_adr.sector].free_status !=
69129533Ssam 			    ALLOCATED) {
69229533Ssam 				free_tbl[i][temp.err_adr.sector].free_status =
69329533Ssam 				    ALLOCATED;
69429533Ssam 				newaddr.cylinder = i / CURRENT->vc_ntrak +
69529533Ssam 				    (CURRENT->vc_ncyl - NUMSYS);
69629533Ssam 				newaddr.track = i % CURRENT->vc_ntrak;
69729533Ssam 				newaddr.sector = temp.err_adr.sector;
69829533Ssam 				break;
69929533Ssam 			}
70029533Ssam 		}
70129533Ssam 	}
70229533Ssam 	else {
70329533Ssam 		for(i = 0; i < (CURRENT->vc_ntrak * NUMREL); i++) {
70429533Ssam 			for(sec=0; sec < CURRENT->vc_nsec; sec++)
70529533Ssam 				if(free_tbl[i][sec].free_status != ALLOCATED)
70629533Ssam 					break;
70729533Ssam 			if(sec < CURRENT->vc_nsec) {
70829533Ssam 				free_tbl[i][sec].free_status = ALLOCATED;
70929533Ssam 				newaddr.cylinder = i / CURRENT->vc_ntrak +
71029533Ssam 				    (CURRENT->vc_ncyl - NUMSYS);
71129533Ssam 				newaddr.track = i % CURRENT->vc_ntrak;
71229533Ssam 				newaddr.sector = sec;
71329533Ssam 				break;
71429533Ssam 			}
71529533Ssam 		}
71629533Ssam 	}
71729533Ssam 	return &newaddr;
71829533Ssam }
71929533Ssam 
720