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