xref: /csrg-svn/sys/tahoe/stand/vdformat/maps.c (revision 34667)
129533Ssam #ifndef lint
2*34667Skarels static char sccsid[] = "@(#)maps.c	1.7 (Berkeley/CCI) 06/07/88";
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 */
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
3829981Skarels read_map(flags)
3929533Ssam short	flags;
4029533Ssam {
4129533Ssam 	register int	trk, i;
4229533Ssam 	dskadr		dskaddr;
4329533Ssam 
4432662Skarels 	dskaddr.cylinder = (lab->d_ncylinders - 1) | flags;
4532662Skarels 	for(i=0; i < 100; i++)
4629533Ssam 		scratch[i] = -1;
4732662Skarels 	for(trk=0; trk < lab->d_ntracks; trk++) {
4829533Ssam 		dskaddr.track = trk;
4929533Ssam 		dskaddr.sector = 0;
5031318Ssam 		if(access_dsk((char *)save,&dskaddr, VDOP_RD,
5132662Skarels 		    lab->d_nsectors,1)& VDERR_HARD)
5229533Ssam 			continue;
5334558Skarels 		if(bcmp((char *)scratch, (char *)save, bytes_trk) == true) {
5434558Skarels 			bcopy((char *)save, (char *)bad_map, bytes_trk);
5529533Ssam 			if(bad_map->bs_count <= MAX_FLAWS) {
5632662Skarels 				for(i=0; i < bad_map->bs_count; i++) {
5729533Ssam 					if(bad_map->list[i].bs_cyl >=
5832662Skarels 					    lab->d_ncylinders)
5929533Ssam 						break;
6029533Ssam 					if(bad_map->list[i].bs_trk >=
6132662Skarels 					    lab->d_ntracks)
6229533Ssam 						break;
6329533Ssam 					if(bad_map->list[i].bs_offset >=
6432662Skarels 					    lab->d_traksize)
6529533Ssam 						break;
6629533Ssam 				}
6729533Ssam 				if(i == bad_map->bs_count) {
6829533Ssam 					load_free_table();
6929533Ssam 					return true;
7029533Ssam 				}
7129981Skarels 			}
7234558Skarels 			bzero(bad_map, bytes_trk);
7329533Ssam 			bad_map->bs_id = 0;
7429533Ssam 			bad_map->bs_max = MAX_FLAWS;
7529533Ssam 		}
7634558Skarels 		bcopy((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 
9032662Skarels 	dskaddr.cylinder = lab->d_ncylinders - 1;
9129533Ssam 	dskaddr.track = 0;
9229533Ssam 	dskaddr.sector = 0;
9329533Ssam 	/* start with nothing in map */
9434558Skarels 	bzero(bad_map, bytes_trk);
9529533Ssam 	bad_map->bs_id = 0;
9629533Ssam 	bad_map->bs_max = MAX_FLAWS;
9732662Skarels 	if (C_INFO->type == VDTYPE_SMDE) {
9831318Ssam 		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 */
13132662Skarels 	for(cyl=0; cyl < lab->d_ncylinders - NUMSYS; cyl++) {
13229533Ssam 		dskaddr.cylinder = cyl;
13332662Skarels 		for(trk=0; trk < lab->d_ntracks; trk++) {
13429533Ssam 			dskaddr.track = trk;
13529533Ssam 			status=access_dsk((char *)scratch, &dskaddr,
13632662Skarels 			    VDOP_RD, lab->d_nsectors, 1);
13731318Ssam 			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 
15632662Skarels 	for(dskaddr.sector=0; dskaddr.sector < lab->d_nsectors; dskaddr.sector++) {
15731318Ssam 		status = access_dsk((char *)scratch, &dskaddr, VDOP_RD, 1, 1);
15831318Ssam 		if(status & DCBS_ATA) {
15929533Ssam 			error.err_adr = dskaddr;
16029533Ssam 			error.err_stat = DATA_ERROR;
161*34667Skarels 			(*C_INFO->code_pos)(&error, &temp);
16229533Ssam 			temp.bs_how = operator;
16329533Ssam 			add_flaw(&temp);
16429533Ssam 		}
16529533Ssam 	}
16629533Ssam }
16729533Ssam 
16829533Ssam 
16929533Ssam /*
17029533Ssam **
17129533Ssam */
17229533Ssam 
17329533Ssam remove_user_relocations(entry)
174*34667Skarels bs_entry	*entry;
17529533Ssam {
17629533Ssam 	register int	i, j;
17729533Ssam 	fmt_err		temp;
17829533Ssam 	fmt_err		error;
179*34667Skarels 	register bs_entry *ptr;
18029533Ssam 
181*34667Skarels 	(*C_INFO->decode_pos)(entry, &error);
182*34667Skarels 	ptr = bad_map->list;
183*34667Skarels 	for(i=0; i < bad_map->bs_count; i++) {
184*34667Skarels 		if (ptr->bs_cyl != entry->bs_cyl ||
185*34667Skarels 		    ptr->bs_trk != entry->bs_trk)
186*34667Skarels 			continue;
187*34667Skarels 		(*C_INFO->decode_pos)(ptr, &temp);
188*34667Skarels 		if((ptr->bs_how != flaw_map) &&
189*34667Skarels 		    (temp.err_adr.cylinder == error.err_adr.cylinder) &&
190*34667Skarels 		    (temp.err_adr.track == error.err_adr.track) &&
191*34667Skarels 		    (temp.err_adr.sector == error.err_adr.sector)) {
192*34667Skarels 			if(temp.err_stat & HEADER_ERROR)
193*34667Skarels 				remove_track(&temp, ptr);
194*34667Skarels 			else
195*34667Skarels 				remove_sector(&temp, ptr);
196*34667Skarels 			for(j=i+1; j < bad_map->bs_count; j++)
197*34667Skarels 				bad_map->list[j-1] = bad_map->list[j];
198*34667Skarels 			bad_map->bs_count--;
199*34667Skarels 			return;
200*34667Skarels 		}
201*34667Skarels 		ptr++;
202*34667Skarels 	}
203*34667Skarels 	indent();
204*34667Skarels 	print("Sector %d is not in bad sector map!\n",
205*34667Skarels 	    to_sector(error.err_adr));
206*34667Skarels 	exdent(1);
207*34667Skarels }
208*34667Skarels 
209*34667Skarels clear_relocations(reformat)
210*34667Skarels boolean reformat;
211*34667Skarels {
212*34667Skarels 	fmt_err		temp;
213*34667Skarels 	register bs_entry *ptr1, *ptr2, *end;
214*34667Skarels 	int oldsub = cur.substate;
215*34667Skarels 
216*34667Skarels 	cur.substate = sub_rel;
217*34667Skarels 	ptr1 = bad_map->list;
218*34667Skarels 	ptr2 = bad_map->list;
219*34667Skarels 	end = &bad_map->list[bad_map->bs_count];
220*34667Skarels 	for (; ptr1 < end; ptr1++) {
221*34667Skarels 		if (ptr1->bs_how != flaw_map) {
222*34667Skarels 			if (reformat == true) {
223*34667Skarels 				(*C_INFO->decode_pos)(ptr1, &temp);
22429533Ssam 				if(temp.err_stat & HEADER_ERROR)
225*34667Skarels 					remove_track(&temp, ptr1);
22629533Ssam 				else
227*34667Skarels 					remove_sector(&temp, ptr1);
22829533Ssam 			}
229*34667Skarels 			bad_map->bs_count--;
230*34667Skarels 		} else {
231*34667Skarels 			if (ptr1 != ptr2)
232*34667Skarels 				*ptr2 = *ptr1;
233*34667Skarels 			ptr2++;
23429533Ssam 		}
23529533Ssam 	}
236*34667Skarels 	cur.substate = oldsub;
23729533Ssam }
23829533Ssam 
23929533Ssam 
24029533Ssam /*
24129533Ssam **
24229533Ssam */
24329533Ssam 
24429533Ssam remove_sector(error, entry)
245*34667Skarels fmt_err		*error;
24629533Ssam bs_entry	*entry;
24729533Ssam {
248*34667Skarels 	format_sectors(&error->err_adr, &error->err_adr, NRM, 1);
24929533Ssam 	format_sectors(&entry->bs_alt, &entry->bs_alt, NRM, 1);
25029533Ssam }
25129533Ssam 
25229533Ssam 
25329533Ssam /*
25429533Ssam **
25529533Ssam */
25629533Ssam 
25729533Ssam remove_track(error, entry)
258*34667Skarels fmt_err		*error;
25929533Ssam bs_entry	*entry;
26029533Ssam {
261*34667Skarels 	format_sectors(&error->err_adr,&error->err_adr,NRM,(long)lab->d_nsectors);
26232662Skarels 	format_sectors(&entry->bs_alt,&entry->bs_alt,NRM,(long)lab->d_nsectors);
26329533Ssam }
26429533Ssam 
26529533Ssam 
26629533Ssam /*
26729533Ssam **
26829533Ssam */
26929533Ssam 
27029533Ssam write_bad_sector_map()
27129533Ssam {
27229533Ssam 	register int	trk, sec;
27329533Ssam 	dskadr		dskaddr;
27429533Ssam 
27532662Skarels 	dskaddr.cylinder = (lab->d_ncylinders - NUMMAP);
27632662Skarels 	for(trk=0; trk < lab->d_ntracks; trk++) {
27732662Skarels 		for(sec = 0; sec < lab->d_nsectors; sec++) {
27834558Skarels 			bcopy((char *)bs_map_space + (sec * lab->d_secsize),
27932662Skarels 			    (char *)scratch, lab->d_secsize);
28029533Ssam 			dskaddr.track = trk;
28129533Ssam 			dskaddr.sector = sec;
28229533Ssam 			format_sectors(&dskaddr, &dskaddr, WPT, 1);
28329533Ssam 		}
28429533Ssam 	}
28529533Ssam }
28629533Ssam 
28729533Ssam 
28829533Ssam /*
28929533Ssam **
29029533Ssam */
29129533Ssam 
29229533Ssam zero_bad_sector_map()
29329533Ssam {
29429533Ssam 	bs_map		*bm = bad_map;
29529533Ssam 	register int	i;
29629533Ssam 	dskadr		zero;
29729533Ssam 
29829533Ssam 	zero.cylinder = 0;
29929533Ssam 	zero.track = 0;
30029533Ssam 	zero.sector = 0;
30132662Skarels 	for(i=0; i < bm->bs_count; i++)
30229533Ssam 		bm->list[i].bs_alt = zero;
30329533Ssam 	load_free_table();
30429533Ssam }
30529533Ssam 
30629533Ssam 
30729533Ssam /*
30829533Ssam **
30929533Ssam */
31029533Ssam 
31129533Ssam read_flaw_map()
31229533Ssam {
31329533Ssam 	register int	cyl, trk;
31429533Ssam 	dskadr		dskaddr;
31529533Ssam 	flaw		buffer;
31629533Ssam 
31729533Ssam 	dskaddr.sector = 0;
31832662Skarels 	for  (cyl=0; cyl < lab->d_ncylinders; cyl++) {
31929533Ssam 		dskaddr.cylinder = cyl;
32032662Skarels 		for  (trk=0; trk < lab->d_ntracks; trk++) {
32129533Ssam 			dskaddr.track = trk;
32231318Ssam 			access_dsk(&buffer, &dskaddr, VDOP_RDRAW, 1, 1);
32329533Ssam 			if(align_buf(&buffer, CDCSYNC) == true) {
32429533Ssam 				add_flaw_entries(&buffer);
32529533Ssam 				continue;
32629533Ssam 			}
32729533Ssam 		}
32829533Ssam 	}
32929533Ssam 	load_free_table();
33029533Ssam }
33129533Ssam 
33229533Ssam 
33329533Ssam /*
33429533Ssam **
33529533Ssam */
33629533Ssam 
33729533Ssam get_smde_relocations()
33829533Ssam {
33929533Ssam 	register int	cyl, trk, sec;
34029533Ssam 	smde_hdr	buffer;
34129533Ssam 	dskadr		dskaddr;
34229533Ssam 	fmt_err		bad;
34329533Ssam 	bs_entry	temp;
34429533Ssam 	boolean		bad_track;
34529533Ssam 
34629533Ssam 	/* Read any old drive relocations */
34732662Skarels 	for(cyl=0; cyl < NUMREL; cyl++) {
34832662Skarels 		dskaddr.cylinder = lab->d_ncylinders - NUMSYS + cyl;
34932662Skarels 		for(trk=0; trk < lab->d_ntracks; trk++) {
35029533Ssam 			dskaddr.track = trk;
35129533Ssam 			bad_track = true;
35232662Skarels 			for(sec=0; sec < lab->d_nsectors; sec++) {
35329533Ssam 				dskaddr.sector = sec;
35431318Ssam 				access_dsk(&buffer, &dskaddr, VDOP_RDRAW, 1, 1);
35529533Ssam 				if(align_buf(&buffer, SMDE1SYNC) == false) {
35629533Ssam 					bad_track = false;
35729533Ssam 					break;
35829533Ssam 				}
35929533Ssam 			}
36029533Ssam 			if(bad_track == true) {
36129533Ssam 				dskaddr.sector = 0;
36229533Ssam 				bad.err_adr.cylinder = buffer.alt_cyl;
36329533Ssam 				bad.err_adr.track = buffer.alt_trk;
36429533Ssam 				bad.err_adr.sector = 0;
36529533Ssam 				bad.err_stat = HEADER_ERROR;
366*34667Skarels 				(*C_INFO->code_pos)(&bad, &temp);
36729533Ssam 				temp.bs_alt = dskaddr;
36829533Ssam 				temp.bs_how = scanning;
36929533Ssam 				add_flaw(&temp);
37029533Ssam 				continue;
37129533Ssam 			}
37232662Skarels 			for(sec=0; sec < lab->d_nsectors; sec++) {
37329533Ssam 				dskaddr.sector = sec;
37431318Ssam 				access_dsk(&buffer, &dskaddr, VDOP_RDRAW, 1, 1);
37529533Ssam 				if(align_buf(&buffer, SMDE1SYNC) == true) {
37629533Ssam 					bad.err_adr.cylinder = buffer.alt_cyl;
37729533Ssam 					bad.err_adr.track = buffer.alt_trk;
37829533Ssam 					bad.err_adr.sector = buffer.alt_sec;
37929533Ssam 					bad.err_stat = DATA_ERROR;
380*34667Skarels 					(*C_INFO->code_pos)(&bad, &temp);
38129533Ssam 					temp.bs_alt = dskaddr;
38229533Ssam 					temp.bs_how = scanning;
38329533Ssam 					add_flaw(&temp);
38429533Ssam 				}
38529533Ssam 			}
38629533Ssam 		}
38729533Ssam 	}
38829533Ssam 	load_free_table();
38929533Ssam }
39029533Ssam 
39129533Ssam 
39229533Ssam /*
39329533Ssam **
39429533Ssam */
39529533Ssam 
39629533Ssam add_flaw_entries(buffer)
39729533Ssam flaw	*buffer;
39829533Ssam {
39929533Ssam 	register int	i;
40029533Ssam 	bs_entry	temp;
40129533Ssam 
40229533Ssam 	temp.bs_cyl = buffer->flaw_cyl & 0x7fff; /* clear off bad track bit */
40329533Ssam 	temp.bs_trk = buffer->flaw_trk;
40432662Skarels 	for(i=0; i < 4; i++) {
40529533Ssam 		if(buffer->flaw_pos[i].flaw_length != 0) {
40629533Ssam 			temp.bs_offset = buffer->flaw_pos[i].flaw_offset;
40729533Ssam 			temp.bs_length = buffer->flaw_pos[i].flaw_length;
40829533Ssam 			temp.bs_alt.cylinder = 0;
40929533Ssam 			temp.bs_alt.track = 0;
41029533Ssam 			temp.bs_alt.sector = 0;
41129533Ssam 			temp.bs_how = flaw_map;
41229533Ssam 			add_flaw(&temp);
41329533Ssam 		}
41429533Ssam 	}
41529533Ssam }
41629533Ssam 
41729533Ssam 
41829533Ssam cmp_entry(a, b)
41929533Ssam bs_entry	*a;
42029533Ssam bs_entry	*b;
42129533Ssam {
42229533Ssam 	if(a->bs_cyl == b->bs_cyl) {
42329533Ssam 		if(a->bs_trk == b->bs_trk) {
42429533Ssam 			if(a->bs_offset == b->bs_offset)
42529533Ssam 				return 0;
42629533Ssam 			else if(a->bs_offset < b->bs_offset)
42729533Ssam 				return -1;
42829981Skarels 		 }
42929533Ssam 		else if(a->bs_trk < b->bs_trk)
43029533Ssam 			return -1;
43129533Ssam 	}
43229533Ssam 	else if(a->bs_cyl < b->bs_cyl)
43329533Ssam 		return -1;
43429533Ssam 	return 1;
43529533Ssam }
43629533Ssam 
43729533Ssam 
438*34667Skarels /*
439*34667Skarels  * Add flaw to map.
440*34667Skarels  * Return value:
441*34667Skarels  *   1	OK
442*34667Skarels  *   0	sector was in map
443*34667Skarels  *  -1	failure
444*34667Skarels  */
44529533Ssam add_flaw(entry)
44629533Ssam bs_entry	*entry;
44729533Ssam {
44829533Ssam 	extern	int	cmp_entry();
44929533Ssam 	bs_map		*bm = bad_map;
45029533Ssam 	register int	i;
45129533Ssam 
45229533Ssam 	if(bm->bs_count > MAX_FLAWS)
453*34667Skarels 		return (-1);
45432662Skarels 	if (entry->bs_cyl >= lab->d_ncylinders ||
45532662Skarels 	    entry->bs_trk >= lab->d_ntracks ||
45632662Skarels 	    entry->bs_offset >= lab->d_traksize)
457*34667Skarels 		return (-1);
45832662Skarels 	for(i=0; i < bm->bs_count; i++) {
45929533Ssam 		if(((bm->list[i].bs_cyl == entry->bs_cyl)) &&
46029533Ssam 		    (bm->list[i].bs_trk == entry->bs_trk) &&
46129533Ssam 		    (bm->list[i].bs_offset == entry->bs_offset)) {
46229533Ssam 			if((int)bm->list[i].bs_how > (int)entry->bs_how)
46329533Ssam 				bm->list[i].bs_how = entry->bs_how;
464*34667Skarels 			return (0);
46529533Ssam 		}
46629533Ssam 	}
46729533Ssam 	bm->list[i] = *entry;
46829533Ssam 	bm->list[i].bs_alt.cylinder = 0;
46929533Ssam 	bm->list[i].bs_alt.track = 0;
47029533Ssam 	bm->list[i].bs_alt.sector = 0;
47129533Ssam 	bm->bs_count++;
47229533Ssam 	qsort((char *)&(bm->list[0]), (unsigned)bm->bs_count,
47329533Ssam 	    sizeof(bs_entry), cmp_entry);
474*34667Skarels 	return (1);
47529533Ssam }
47629533Ssam 
47729533Ssam 
47829533Ssam /*
47929533Ssam **	Is_in_map checks to see if a block is known to be bad already.
48029533Ssam */
48129533Ssam 
48229533Ssam boolean is_in_map(dskaddr)
48329533Ssam dskadr	*dskaddr;
48429533Ssam {
48529533Ssam 	register int	i;
48629533Ssam 	fmt_err		temp;
48729533Ssam 
48832662Skarels 	for(i=0; i < bad_map->bs_count; i++) {
489*34667Skarels 		(*C_INFO->decode_pos)(&bad_map->list[i], &temp);
49029533Ssam 		if((temp.err_adr.cylinder == dskaddr->cylinder) &&
49129533Ssam 		    (temp.err_adr.track == dskaddr->track) &&
49229533Ssam 		    (temp.err_adr.sector == dskaddr->sector)) {
49329533Ssam 			return true;
49429533Ssam 		}
49529533Ssam 	}
49629533Ssam 	return false;
49729533Ssam }
49829533Ssam 
49929533Ssam 
50029533Ssam /*
50129533Ssam **
50229533Ssam */
50329533Ssam 
50429533Ssam print_bad_sector_list()
50529533Ssam {
50629533Ssam 	register int	i;
50729533Ssam 	fmt_err		errloc;
508*34667Skarels 	register bs_entry *bad;
50929533Ssam 
51029533Ssam 	if(bad_map->bs_count == 0) {
51129533Ssam 		print("There are no bad sectors in bad sector map.\n");
51229533Ssam 		return;
51329533Ssam 	}
51429533Ssam 	print("The following sector%s known to be bad:\n",
51529533Ssam 	    (bad_map->bs_count == 1) ? " is" : "s are");
51629533Ssam 	indent();
517*34667Skarels 	for(i=0, bad = bad_map->list; i < bad_map->bs_count; i++, bad++) {
518*34667Skarels 		(*C_INFO->decode_pos)(bad, &errloc);
519*34667Skarels 		print("%s %d cn %d tn %d sn %d pos %d len %d ",
520*34667Skarels 			errloc.err_stat & HEADER_ERROR ? "Track@" : "Sector",
521*34667Skarels 			to_sector(errloc.err_adr),
522*34667Skarels 			bad->bs_cyl,
523*34667Skarels 			bad->bs_trk,
524*34667Skarels 			errloc.err_adr.sector,
525*34667Skarels 			bad->bs_offset,
526*34667Skarels 			bad->bs_length);
527*34667Skarels 		if (bad->bs_how == flaw_map)
528*34667Skarels 			printf("(flawmap) ");
529*34667Skarels 		else if (bad->bs_how == scanning)
530*34667Skarels 			printf("(verify) ");
531*34667Skarels 		else
532*34667Skarels 			printf("(operator) ");
533*34667Skarels 		if((bad->bs_alt.cylinder != 0) || (bad->bs_alt.track != 0) ||
534*34667Skarels 		    (bad->bs_alt.sector != 0)) {
535*34667Skarels 			printf("-> ");
536*34667Skarels 			printf("cn %d tn %d sn %d", bad->bs_alt.cylinder,
537*34667Skarels 			    bad->bs_alt.track, bad->bs_alt.sector);
53829533Ssam 		}
539*34667Skarels 		printf("\n");
54029533Ssam 	}
54129533Ssam 	exdent(1);
54229533Ssam }
54329533Ssam 
54429533Ssam 
54529533Ssam /*
546*34667Skarels **	load_free_table checks each block in the bad block relocation area
54729533Ssam ** to see if it is used. If it is, the free relocation block table is updated.
54829533Ssam */
54929533Ssam 
55029533Ssam load_free_table()
55129533Ssam {
55229533Ssam 	register int	i, j;
55329533Ssam 	fmt_err		temp;
55429533Ssam 
55529533Ssam 	/* Clear free table before starting */
55632662Skarels 	for(i = 0; i < (lab->d_ntracks * NUMREL); i++) {
55732662Skarels 		for(j=0; j < lab->d_nsectors; j++)
55829533Ssam 			free_tbl[i][j].free_status = NOTALLOCATED;
55929533Ssam 	}
56032662Skarels 	for(i=0; i < bad_map->bs_count; i++)
56129533Ssam 		if((bad_map->list[i].bs_alt.cylinder != 0) ||
56229533Ssam 		    (bad_map->list[i].bs_alt.track != 0) ||
56329533Ssam 		    (bad_map->list[i].bs_alt.sector != 0)) {
564*34667Skarels 			(*C_INFO->decode_pos)(&bad_map->list[i], &temp);
56529533Ssam 			allocate(&(bad_map->list[i].bs_alt), temp.err_stat);
56629533Ssam 		}
56729533Ssam }
56829533Ssam 
56929533Ssam 
57029533Ssam /*
57129533Ssam **	allocate marks a replacement sector as used.
57229533Ssam */
57329533Ssam 
57429533Ssam allocate(dskaddr, status)
57529533Ssam dskadr	*dskaddr;
57629533Ssam long	status;
57729533Ssam {
57829533Ssam 	register int	trk, sec;
57929533Ssam 
58032662Skarels 	trk = dskaddr->cylinder - (lab->d_ncylinders - NUMSYS);
58129533Ssam 	if((trk < 0) || (trk >= NUMREL))
58229533Ssam 		return;
58332662Skarels 	trk *= lab->d_ntracks;
58429533Ssam 	trk += dskaddr->track;
58529533Ssam 	if(status & HEADER_ERROR)
58632662Skarels 		for(sec=0; sec < lab->d_nsectors; sec++)
58729533Ssam 			free_tbl[trk][sec].free_status = ALLOCATED;
58829533Ssam 	else
58929533Ssam 		free_tbl[trk][dskaddr->sector].free_status = ALLOCATED;
59029533Ssam }
59129533Ssam 
59229533Ssam 
59329533Ssam /*
59429533Ssam **
59529533Ssam */
59629533Ssam 
59729533Ssam boolean mapping_collision(entry)
59829533Ssam bs_entry	*entry;
59929533Ssam {
60029533Ssam 	register int	trk, sec;
60129533Ssam 	fmt_err		temp;
60229533Ssam 
60332662Skarels 	trk = entry->bs_cyl - (lab->d_ncylinders - NUMSYS);
60429533Ssam 	if((trk < 0) || (trk >= NUMREL))
60529533Ssam 		return false;
60632662Skarels 	trk *= lab->d_ntracks;
60729533Ssam 	trk += entry->bs_trk;
608*34667Skarels 	(*C_INFO->decode_pos)(entry, &temp);
60929533Ssam 	/* if this relocation should take up the whole track */
61029533Ssam 	if(temp.err_stat & HEADER_ERROR) {
61132662Skarels 		for(sec=0; sec < lab->d_nsectors; sec++)
61229533Ssam 			if(free_tbl[trk][sec].free_status == ALLOCATED)
61329533Ssam 				return true;
61429533Ssam 	}
61529533Ssam 	/* else just check the current sector */
61629533Ssam 	else {
61729533Ssam 		if(free_tbl[trk][temp.err_adr.sector].free_status == ALLOCATED)
61829533Ssam 			return true;
61929533Ssam 	}
62029533Ssam 	return false;
62129533Ssam }
62229533Ssam 
62329533Ssam 
62429533Ssam /*
62529533Ssam **
62629533Ssam */
62729533Ssam 
62829533Ssam report_collision()
62929533Ssam {
63029533Ssam 	indent();
63129533Ssam 	print("Sector resides in relocation area");
63229533Ssam 	printf("but it has a sector mapped to it already.\n");
63329533Ssam 	print("Please reformat disk with 0 patterns to eliminate problem.\n");
63429533Ssam 	exdent(1);
63529533Ssam }
63629533Ssam 
63729533Ssam 
63829533Ssam /*
63929533Ssam **
64029533Ssam */
64129533Ssam 
64229533Ssam add_user_relocations(entry)
64329533Ssam bs_entry	*entry;
64429533Ssam {
64529533Ssam 	fmt_err		error;
64629533Ssam 
647*34667Skarels 	(*C_INFO->decode_pos)(entry, &error);
64829533Ssam 	if(is_in_map(&error.err_adr) == false) {
64929533Ssam 		if(mapping_collision(entry) == true)
65029533Ssam 			report_collision();
65129533Ssam 		entry->bs_how = operator;
65229533Ssam 		add_flaw(entry);
65329533Ssam 	}
65429533Ssam 	else {
65529533Ssam 		indent();
65629533Ssam 		print("Sector %d is already mapped out!\n",
65729533Ssam 		    to_sector(error.err_adr));
65829533Ssam 		exdent(1);
65929533Ssam 	}
66029533Ssam }
66129533Ssam 
66229533Ssam 
66329533Ssam /*
66429533Ssam ** 	New_location allocates a replacement block given a bad block address.
66529533Ssam **  The algorithm is fairly simple; it simply searches for the first
66629533Ssam **  free sector that has the same sector number of the bad sector.  If no sector
66729533Ssam **  is found then the drive should be considered bad because of a microcode bug
66829533Ssam **  in the controller that forces us to use the same sector number as the bad
66929533Ssam **  sector for relocation purposes.  Using different tracks and cylinders is ok
67029533Ssam **  of course.
67129533Ssam */
67229533Ssam 
67329533Ssam dskadr *new_location(entry)
67429533Ssam bs_entry	*entry;
67529533Ssam {
67629533Ssam 	register int	i, sec;
67729533Ssam 	static fmt_err	temp;
67829533Ssam 	static dskadr	newaddr;
67929533Ssam 
68029533Ssam 	newaddr.cylinder = 0;
68129533Ssam 	newaddr.track = 0;
68229533Ssam 	newaddr.sector = 0;
683*34667Skarels 	(*C_INFO->decode_pos)(entry, &temp);
68429533Ssam 	/* If it is ouside of the user's data area */
68532662Skarels 	if(entry->bs_cyl >= lab->d_ncylinders-NUMSYS) {
68629533Ssam 		/* if it is in the relocation area */
68732662Skarels 		if(entry->bs_cyl < (lab->d_ncylinders - NUMMAP - NUMMNT)) {
68829533Ssam 			/* mark space as allocated */
68929533Ssam 			allocate(&temp.err_adr, temp.err_stat);
69029533Ssam 			return &temp.err_adr;
69129533Ssam 		}
69229533Ssam 		/* if it is in the map area forget about it */
69332662Skarels 		if(entry->bs_cyl != (lab->d_ncylinders - NUMMAP - NUMMNT))
69429533Ssam 			return &temp.err_adr;
69529533Ssam 		/* otherwise treat maintainence cylinder normally */
69629533Ssam 	}
69729533Ssam 	if(temp.err_stat & (HEADER_ERROR)) {
69832662Skarels 		for(i = 0; i < (lab->d_ntracks * NUMREL); i++) {
69932662Skarels 			for(sec=0; sec < lab->d_nsectors; sec++) {
70029533Ssam 				if(free_tbl[i][sec].free_status == ALLOCATED)
70129533Ssam 					break;
70229533Ssam 			}
70332662Skarels 			if(sec == lab->d_nsectors) {
70432662Skarels 				for(sec = 0; sec < lab->d_nsectors; sec++)
70529533Ssam 					free_tbl[i][sec].free_status=ALLOCATED;
70632662Skarels 				newaddr.cylinder = i / lab->d_ntracks +
70732662Skarels 				    (lab->d_ncylinders - NUMSYS);
70832662Skarels 				newaddr.track = i % lab->d_ntracks;
70929533Ssam 				break;
71029533Ssam 			}
71129533Ssam 		}
71229533Ssam 	}
71332662Skarels 	else if(C_INFO->type == VDTYPE_VDDC) {
71432662Skarels 		for(i = 0; i < (lab->d_ntracks * NUMREL); i++) {
71529533Ssam 			if(free_tbl[i][temp.err_adr.sector].free_status !=
71629533Ssam 			    ALLOCATED) {
71729533Ssam 				free_tbl[i][temp.err_adr.sector].free_status =
71829533Ssam 				    ALLOCATED;
71932662Skarels 				newaddr.cylinder = i / lab->d_ntracks +
72032662Skarels 				    (lab->d_ncylinders - NUMSYS);
72132662Skarels 				newaddr.track = i % lab->d_ntracks;
72229533Ssam 				newaddr.sector = temp.err_adr.sector;
72329533Ssam 				break;
72429533Ssam 			}
72529533Ssam 		}
72629533Ssam 	}
72729533Ssam 	else {
72832662Skarels 		for(i = 0; i < (lab->d_ntracks * NUMREL); i++) {
72932662Skarels 			for(sec=0; sec < lab->d_nsectors; sec++)
73029533Ssam 				if(free_tbl[i][sec].free_status != ALLOCATED)
73129533Ssam 					break;
73232662Skarels 			if(sec < lab->d_nsectors) {
73329533Ssam 				free_tbl[i][sec].free_status = ALLOCATED;
73432662Skarels 				newaddr.cylinder = i / lab->d_ntracks +
73532662Skarels 				    (lab->d_ncylinders - NUMSYS);
73632662Skarels 				newaddr.track = i % lab->d_ntracks;
73729533Ssam 				newaddr.sector = sec;
73829533Ssam 				break;
73929533Ssam 			}
74029533Ssam 		}
74129533Ssam 	}
74229533Ssam 	return &newaddr;
74329533Ssam }
744