xref: /csrg-svn/sys/tahoe/stand/vdformat/maps.c (revision 43645)
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