16d7a1e15Ssam #ifndef lint
2*ab4ebc48Skarels static char sccsid[] = "@(#)relocate.c	1.7 (Berkeley/CCI) 06/24/90";
36d7a1e15Ssam #endif
46d7a1e15Ssam 
56d7a1e15Ssam #include	"vdfmt.h"
66d7a1e15Ssam #include	"cmd.h"
76d7a1e15Ssam 
86d7a1e15Ssam /*
96d7a1e15Ssam **
106d7a1e15Ssam */
116d7a1e15Ssam 
relocate()126d7a1e15Ssam relocate()
136d7a1e15Ssam {
146d7a1e15Ssam 	extern boolean	is_formatted();
156d7a1e15Ssam 
166d7a1e15Ssam 	cur.state = rel;
17f31d5e62Skarels 	print("Adding flaws to bad sector map on ");
186d7a1e15Ssam 	printf("controller %d, drive %d, ", cur.controller, cur.drive);
19d5d660dcSkarels 	printf("type %s.\n", lab->d_typename);
206d7a1e15Ssam 
216d7a1e15Ssam 	indent();
226d7a1e15Ssam 	if(is_formatted() == true) {
236d7a1e15Ssam 		if(read_bad_sector_map() == true)
24d5d660dcSkarels 			if(bad_map->bs_id != D_INFO->id) {
256d7a1e15Ssam 				print("Drive serial numbers do not match!\n");
266d7a1e15Ssam 				exdent(1);
276d7a1e15Ssam 				_longjmp(abort_environ, 1);
286d7a1e15Ssam 			}
296d7a1e15Ssam 		get_new_relocations();
30319dde04Skarels 		cur.substate = sub_wmap;
316d7a1e15Ssam 		sync_bad_sector_map();
326d7a1e15Ssam 	}
336d7a1e15Ssam 	else
346d7a1e15Ssam 		print("Drive must be formatted befor relocations are done.\n");
356d7a1e15Ssam 	exdent(1);
366d7a1e15Ssam }
376d7a1e15Ssam 
386d7a1e15Ssam 
396d7a1e15Ssam /*
406d7a1e15Ssam **
416d7a1e15Ssam */
426d7a1e15Ssam 
rel_help()436d7a1e15Ssam rel_help()
446d7a1e15Ssam {
456d7a1e15Ssam 	indent();
466d7a1e15Ssam 	print("Relocation commands are in the following form:\n");
476d7a1e15Ssam 	indent();
48e996412dSkarels 	print("[a-h] (block)   -  UNIX file system block (%s-byte) number.\n",
49e996412dSkarels 	    DEV_BSIZE);
506d7a1e15Ssam 	print("SEctor (sector) -  Absolute sector number on disk.\n");
516d7a1e15Ssam 	print("Track (track)   -  Absolute disk track number.\n");
526d7a1e15Ssam 	print("(cylinder) (head) (offset) (length) - CDC flaw map format.\n");
536d7a1e15Ssam 	print("STARt           -  Starts relocation process.\n\n");
546d7a1e15Ssam 	exdent(2);
556d7a1e15Ssam }
566d7a1e15Ssam 
576d7a1e15Ssam 
586d7a1e15Ssam /*
596d7a1e15Ssam **
606d7a1e15Ssam */
616d7a1e15Ssam 
get_new_relocations()626d7a1e15Ssam get_new_relocations()
636d7a1e15Ssam {
646d7a1e15Ssam 	char		line[256];
656d7a1e15Ssam 	char		*ptr;
666d7a1e15Ssam 	bs_entry	entry;
676d7a1e15Ssam 	dskadr		dskaddr;
68319dde04Skarels 	fmt_err		dskerr;
696d7a1e15Ssam 	int		max_track;
70319dde04Skarels 	register int	block;
716d7a1e15Ssam 
72d5d660dcSkarels 	dskaddr.cylinder = lab->d_ncylinders - 1;
73*ab4ebc48Skarels 	dskaddr.track = lab->d_ntracks - 1;
746d7a1e15Ssam 	max_track = to_track(dskaddr);
756d7a1e15Ssam 	for(;;) {
766d7a1e15Ssam 		print("Location? ");
776d7a1e15Ssam 		get_string_cmd(line, rel_help);
786d7a1e15Ssam 		if(kill_processes == true)
796d7a1e15Ssam 			_longjmp(quit_environ, 1);
806d7a1e15Ssam 		if(line[0] == '\0')
816d7a1e15Ssam 			continue;
826d7a1e15Ssam 		ptr = line;
836d7a1e15Ssam 		trim_white(ptr);
846d7a1e15Ssam 		if(!strncmp(ptr, "he", 2) || !strncmp(ptr, "?", 1) ||
856d7a1e15Ssam 		    !strncmp(ptr, "stat", 4) || !strncmp(ptr, "!", 1))
866d7a1e15Ssam 			continue;
876d7a1e15Ssam 		indent();
886d7a1e15Ssam 		if((*ptr >= 'a') && (*ptr <= 'h')) {
896d7a1e15Ssam 			register char	par = *(ptr++);
906d7a1e15Ssam 
91319dde04Skarels 			block = get_next_digit(ptr);
92319dde04Skarels 			dskerr.err_adr = *from_unix((unsigned char)par,
936d7a1e15Ssam 			    (unsigned int)block);
94319dde04Skarels 			if((dskerr.err_adr.cylinder == -1) || (block == -1)) {
956d7a1e15Ssam 				print("Invalid UNIX block number!\n");
966d7a1e15Ssam 				goto next;
976d7a1e15Ssam 			}
986d7a1e15Ssam 			print("Confirm block %d on file-system '%c'",block,par);
99319dde04Skarels 			dskerr.err_stat = DATA_ERROR;
100319dde04Skarels 		doreloc:
101319dde04Skarels 			printf(" (cn %d tn %d sn %d)", dskerr.err_adr.cylinder,
102319dde04Skarels 			    dskerr.err_adr.track, dskerr.err_adr.sector);
1036d7a1e15Ssam 			if(get_yes_no("") == true) {
104319dde04Skarels 				(*C_INFO->code_pos)(&dskerr, &entry);
1056d7a1e15Ssam 				add_user_relocations(&entry);
1066d7a1e15Ssam 			}
1076d7a1e15Ssam 		}
1086d7a1e15Ssam 		else if(*ptr == 't') {
109319dde04Skarels 			block = get_next_digit(ptr);
110319dde04Skarels 			if((block == -1) || (block >= max_track)) {
1116d7a1e15Ssam 				print("Invalid track number!\n");
1126d7a1e15Ssam 				goto next;
1136d7a1e15Ssam 			}
114319dde04Skarels 			dskerr.err_adr = *from_track(block);
115319dde04Skarels 			dskerr.err_stat = HEADER_ERROR;
116319dde04Skarels 			print("Confirm track %d", block);
117319dde04Skarels 			goto doreloc;
1186d7a1e15Ssam 		}
1196d7a1e15Ssam 		else if(!strncmp(ptr, "se", 2)) {
120319dde04Skarels 			block = get_next_digit(ptr);
1216d7a1e15Ssam 
122319dde04Skarels 			if((block == -1) ||
123319dde04Skarels 			    ((lab->d_nsectors*lab->d_ntracks*lab->d_ncylinders)<block)){
1246d7a1e15Ssam 				print("Invalid sector number!\n");
1256d7a1e15Ssam 				goto next;
1266d7a1e15Ssam 			}
127319dde04Skarels 			dskerr.err_adr = *from_sector((unsigned int)block);
128319dde04Skarels 			dskerr.err_stat = DATA_ERROR;
129319dde04Skarels 			goto doreloc;
1306d7a1e15Ssam 		}
1316d7a1e15Ssam 		else if(is_digit(*ptr)) {
1326d7a1e15Ssam 			entry.bs_cyl = get_next_digit(ptr);
1336d7a1e15Ssam 			skipdigits(ptr);
1346d7a1e15Ssam 			finddigit(ptr);
1356d7a1e15Ssam 			entry.bs_trk = get_next_digit(ptr);
1366d7a1e15Ssam 			skipdigits(ptr);
1376d7a1e15Ssam 			finddigit(ptr);
1386d7a1e15Ssam 			entry.bs_offset = get_next_digit(ptr);
1396d7a1e15Ssam 			skipdigits(ptr);
1406d7a1e15Ssam 			finddigit(ptr);
1416d7a1e15Ssam 			entry.bs_length = get_next_digit(ptr);
1426d7a1e15Ssam 			if((entry.bs_trk != -1) && (entry.bs_offset != -1) &&
1436d7a1e15Ssam 			    (entry.bs_length != -1)) {
144d5d660dcSkarels 				if(entry.bs_cyl >= lab->d_ncylinders)
1456d7a1e15Ssam 					print("Cylinder number to high!\n");
146d5d660dcSkarels 				else if(entry.bs_trk >= lab->d_ntracks)
1476d7a1e15Ssam 					print("Head number to high!\n");
148d5d660dcSkarels 				else if(entry.bs_offset >= lab->d_traksize)
1496d7a1e15Ssam 					print("Offset too long!\n");
1506d7a1e15Ssam 				else if(entry.bs_length == 0)
1516d7a1e15Ssam 					print("Can't have a 0 length error!\n");
1526d7a1e15Ssam 				else {
1536d7a1e15Ssam 					print("Confirm  Cyl %d, ",entry.bs_cyl);
1546d7a1e15Ssam 					printf("Head %d, ", entry.bs_trk);
1556d7a1e15Ssam 					printf("offset %d, ", entry.bs_offset);
1566d7a1e15Ssam 					printf("length %d", entry.bs_length);
1576d7a1e15Ssam 					if(get_yes_no("") == true)
1586d7a1e15Ssam 						add_user_relocations(&entry);
1596d7a1e15Ssam 				}
1606d7a1e15Ssam 			}
1616d7a1e15Ssam 			else
1626d7a1e15Ssam 				goto bad;
1636d7a1e15Ssam 		}
164f31d5e62Skarels 		else if(!strncmp(ptr, "start", 4)) {
1656d7a1e15Ssam 			exdent(1);
1666d7a1e15Ssam 			break;
1676d7a1e15Ssam 		}
1686d7a1e15Ssam 		else
1696d7a1e15Ssam bad:			print("What?\n");
1706d7a1e15Ssam next:		exdent(1);
1716d7a1e15Ssam 	}
1726d7a1e15Ssam }
1736d7a1e15Ssam 
check_track_for_relocations(entry,i)1746d7a1e15Ssam dskadr check_track_for_relocations(entry, i)
1756d7a1e15Ssam bs_entry	entry;
1766d7a1e15Ssam register int	i;
1776d7a1e15Ssam {
1786d7a1e15Ssam 	register int	j = i;
1796d7a1e15Ssam 	fmt_err		temp, cmp;
1806d7a1e15Ssam 	boolean		bad_track = false;
1816d7a1e15Ssam 
182319dde04Skarels 	(*C_INFO->decode_pos)(&entry, &cmp);
1836d7a1e15Ssam 	/* Check to see if a alternate track is or will be on this track */
1846d7a1e15Ssam 	while((bad_map->list[j].bs_cyl == entry.bs_cyl) &&
1856d7a1e15Ssam 	    (bad_map->list[j].bs_trk == entry.bs_trk)) {
186319dde04Skarels 		(*C_INFO->decode_pos)(&bad_map->list[j], &temp);
1876d7a1e15Ssam 		if(temp.err_stat & HEADER_ERROR) {
1886d7a1e15Ssam 			bad_track = true;
1896d7a1e15Ssam 			/* if track was mapped out (it can't be us) */
1906d7a1e15Ssam 			if(((bad_map->list[j].bs_alt.cylinder != 0)) ||
1916d7a1e15Ssam 		    	    (bad_map->list[j].bs_alt.track != 0) ||
1926d7a1e15Ssam 		    	    (bad_map->list[j].bs_alt.sector != 0)) {
1936d7a1e15Ssam 				return cmp.err_adr;
1946d7a1e15Ssam 			}
1956d7a1e15Ssam 		}
1966d7a1e15Ssam 		j++;
1976d7a1e15Ssam 	}
1986d7a1e15Ssam 	/*
1996d7a1e15Ssam 	**    If it was a bad track and it was not the current entry
2006d7a1e15Ssam 	** that produced it then then map it
2016d7a1e15Ssam 	** to itself and forget about it for now since it will be taken
2026d7a1e15Ssam 	** care of later.
2036d7a1e15Ssam 	**
2046d7a1e15Ssam 	**    If it was the current entry return zero and the track will be
2056d7a1e15Ssam 	** mapped out correctly.
2066d7a1e15Ssam 	*/
2076d7a1e15Ssam 	if(bad_track == true) {
2086d7a1e15Ssam 		if(cmp.err_stat & HEADER_ERROR)
2096d7a1e15Ssam 			return entry.bs_alt; /* better known as zero */
2106d7a1e15Ssam 		else
2116d7a1e15Ssam 			return cmp.err_adr;
2126d7a1e15Ssam 	}
2136d7a1e15Ssam 	/*
2146d7a1e15Ssam 	**   if we made it through all the bad track stuff then check for
2156d7a1e15Ssam 	** multiple errors on the same sector that are already mapped!
2166d7a1e15Ssam 	*/
2176d7a1e15Ssam 	j = i;
2186d7a1e15Ssam 	while((bad_map->list[j].bs_cyl == entry.bs_cyl) &&
2196d7a1e15Ssam 	    (bad_map->list[j].bs_trk == entry.bs_trk)) {
220319dde04Skarels 		(*C_INFO->decode_pos)(&bad_map->list[j], &temp);
2216d7a1e15Ssam 		if(temp.err_adr.sector == cmp.err_adr.sector) {
2226d7a1e15Ssam 			/* if it is not really the current entry */
2236d7a1e15Ssam 			if((bad_map->list[j].bs_offset != entry.bs_offset) ||
2246d7a1e15Ssam 			    (bad_map->list[j].bs_length != entry.bs_length)) {
2256d7a1e15Ssam 				/* if the sector is already mapped out */
2266d7a1e15Ssam 				if(((bad_map->list[j].bs_alt.cylinder != 0)) ||
2276d7a1e15Ssam 		   	 	    (bad_map->list[j].bs_alt.track != 0) ||
2286d7a1e15Ssam 		    		    (bad_map->list[j].bs_alt.sector != 0)) {
2296d7a1e15Ssam 					return temp.err_adr;
2306d7a1e15Ssam 				}
2316d7a1e15Ssam 			}
2326d7a1e15Ssam 		}
2336d7a1e15Ssam 		j++;
2346d7a1e15Ssam 	}
2356d7a1e15Ssam 	return	entry.bs_alt;
2366d7a1e15Ssam }
2376d7a1e15Ssam 
2386d7a1e15Ssam 
2396d7a1e15Ssam /*
2406d7a1e15Ssam **
2416d7a1e15Ssam */
2426d7a1e15Ssam 
is_relocated(entry)2436d7a1e15Ssam dskadr	is_relocated(entry)
2446d7a1e15Ssam bs_entry	entry;
2456d7a1e15Ssam {
2466d7a1e15Ssam 	register int	i;
2476d7a1e15Ssam 
2486d7a1e15Ssam 	for(i=0; i<bad_map->bs_count; i++)
2496d7a1e15Ssam 		if((bad_map->list[i].bs_cyl == entry.bs_cyl) &&
2506d7a1e15Ssam 		    (bad_map->list[i].bs_trk == entry.bs_trk))
2516d7a1e15Ssam 			return check_track_for_relocations(entry, i);
2526d7a1e15Ssam 	return entry.bs_alt;
2536d7a1e15Ssam }
2546d7a1e15Ssam 
2556d7a1e15Ssam 
2566d7a1e15Ssam 
2576d7a1e15Ssam /*
2586d7a1e15Ssam **
2596d7a1e15Ssam */
2606d7a1e15Ssam 
sync_bad_sector_map()2616d7a1e15Ssam sync_bad_sector_map()
2626d7a1e15Ssam {
2636d7a1e15Ssam 	register int	i;
2646d7a1e15Ssam 	dskadr		dskaddr;
2656d7a1e15Ssam 
2666d7a1e15Ssam 	/*
2676d7a1e15Ssam 	** do all the relocation cylinders first to allocate all flaws in
2686d7a1e15Ssam 	** relocation area.
2696d7a1e15Ssam 	*/
2706d7a1e15Ssam 	for(i=bad_map->bs_count-1; i>=0; i--) {
271d5d660dcSkarels 		if((bad_map->list[i].bs_cyl >= lab->d_ncylinders-NUMSYS) &&
272d5d660dcSkarels 		    (bad_map->list[i].bs_cyl < lab->d_ncylinders-NUMMAP-NUMMNT)) {
2736d7a1e15Ssam 			if((bad_map->list[i].bs_alt.cylinder == 0) &&
2746d7a1e15Ssam 			    (bad_map->list[i].bs_alt.track == 0) &&
2756d7a1e15Ssam 			    (bad_map->list[i].bs_alt.sector == 0)) {
2766d7a1e15Ssam 				bad_map->list[i].bs_alt =
2776d7a1e15Ssam 				    *new_location(&bad_map->list[i]);
2786d7a1e15Ssam 			}
2796d7a1e15Ssam 		}
2806d7a1e15Ssam 	}
2816d7a1e15Ssam 	for(i=bad_map->bs_count-1; i>=0; i--) {
2826d7a1e15Ssam 		if((bad_map->list[i].bs_alt.cylinder == 0) &&
2836d7a1e15Ssam 		    (bad_map->list[i].bs_alt.track == 0) &&
2846d7a1e15Ssam 		    (bad_map->list[i].bs_alt.sector == 0)) {
2856d7a1e15Ssam 			dskaddr = is_relocated(bad_map->list[i]);
2866d7a1e15Ssam 			if((dskaddr.cylinder == 0) && (dskaddr.track == 0) &&
2876d7a1e15Ssam 			    (dskaddr.sector == 0)) {
2886d7a1e15Ssam 				bad_map->list[i].bs_alt =
2896d7a1e15Ssam 				    *new_location(&bad_map->list[i]);
2906d7a1e15Ssam 				do_relocation(bad_map->list[i]);
2916d7a1e15Ssam 			}
2926d7a1e15Ssam 			else
2936d7a1e15Ssam 				bad_map->list[i].bs_alt = dskaddr;
2946d7a1e15Ssam 		}
2956d7a1e15Ssam 	}
2966d7a1e15Ssam 	write_bad_sector_map();
2976d7a1e15Ssam }
2986d7a1e15Ssam 
2996d7a1e15Ssam 
3006d7a1e15Ssam 
3016d7a1e15Ssam /*
3026d7a1e15Ssam **
3036d7a1e15Ssam */
3046d7a1e15Ssam 
do_relocation(entry)3056d7a1e15Ssam do_relocation(entry)
3066d7a1e15Ssam bs_entry	entry;
3076d7a1e15Ssam {
3086d7a1e15Ssam 	fmt_err	temp;
3096d7a1e15Ssam 
310d5d660dcSkarels 	if(entry.bs_cyl >= lab->d_ncylinders-NUMSYS)
311d5d660dcSkarels 		if(entry.bs_cyl != (lab->d_ncylinders - NUMMAP - NUMMNT))
3126d7a1e15Ssam 			return;
313319dde04Skarels 	(*C_INFO->decode_pos)(&entry, &temp);
3146d7a1e15Ssam 	if((entry.bs_alt.cylinder == 0) && (entry.bs_alt.track == 0) &&
3156d7a1e15Ssam 	    (entry.bs_alt.sector == 0))
3166d7a1e15Ssam 		print_unix_block(temp.err_adr);
3176d7a1e15Ssam 	else if(temp.err_stat & HEADER_ERROR)
318d5d660dcSkarels 		if(C_INFO->type == VDTYPE_VDDC) {
3196d7a1e15Ssam 			print("Can't relocate tracks on VDDC controllers.\n");
3206d7a1e15Ssam 			print_unix_block(temp.err_adr);
3216d7a1e15Ssam 		}
3226d7a1e15Ssam 		else
3236d7a1e15Ssam 			relocate_track(entry);
3246d7a1e15Ssam 	else
3256d7a1e15Ssam 		relocate_sector(entry);
3266d7a1e15Ssam }
3276d7a1e15Ssam 
3286d7a1e15Ssam 
3296d7a1e15Ssam /*
3306d7a1e15Ssam **
3316d7a1e15Ssam */
3326d7a1e15Ssam 
relocate_sector(entry)3336d7a1e15Ssam relocate_sector(entry)
3346d7a1e15Ssam bs_entry	entry;
3356d7a1e15Ssam {
3366d7a1e15Ssam 	dskadr		phys, reloc;
3376d7a1e15Ssam 	fmt_err		temp;
3386d7a1e15Ssam 	register long	status;
3396d7a1e15Ssam 
340319dde04Skarels 	(*C_INFO->decode_pos)(&entry, &temp);
3416d7a1e15Ssam 	phys = temp.err_adr;
3426d7a1e15Ssam 	reloc = entry.bs_alt;
3436d7a1e15Ssam 	format_sectors(&phys, &reloc, RELOC_SECTOR, (long)1);
3446d7a1e15Ssam 
3456d7a1e15Ssam 	format_sectors(&reloc, &phys, ALT_SECTOR, (long)1);
34668c7fc27Ssam 	status = access_dsk((char *)save, &temp.err_adr, VDOP_WD, 1, 1);
34768c7fc27Ssam 	if(!((status & DCBS_ATA) && !(status & (DCBS_HARD|DCBS_SOFT)))) {
348f31d5e62Skarels 		print(
349f31d5e62Skarels 		"Sector relocation failed (c %d t %d s %d).  Status = 0x%x.\n",
350f31d5e62Skarels 		    phys.cylinder, phys.track, phys.sector, status);
3516d7a1e15Ssam 		print_unix_block(phys);
3526d7a1e15Ssam 	}
3536d7a1e15Ssam }
3546d7a1e15Ssam 
3556d7a1e15Ssam 
3566d7a1e15Ssam 
3576d7a1e15Ssam /*
3586d7a1e15Ssam **
3596d7a1e15Ssam */
3606d7a1e15Ssam 
relocate_track(entry)3616d7a1e15Ssam relocate_track(entry)
3626d7a1e15Ssam bs_entry	entry;
3636d7a1e15Ssam {
3646d7a1e15Ssam 	dskadr		phys, reloc;
3656d7a1e15Ssam 	fmt_err		temp;
3666d7a1e15Ssam 	register long	status;
3676d7a1e15Ssam 
368319dde04Skarels 	(*C_INFO->decode_pos)(&entry, &temp);
3696d7a1e15Ssam 	temp.err_adr.sector = 0;
3706d7a1e15Ssam 	phys = temp.err_adr;
3716d7a1e15Ssam 	reloc = entry.bs_alt;
3726d7a1e15Ssam 	reloc.sector = 0xff;
373d5d660dcSkarels 	format_sectors(&phys, &reloc, RELOC_SECTOR, (long)lab->d_nsectors);
3746d7a1e15Ssam 
3756d7a1e15Ssam 	reloc.sector = 0x00;
376d5d660dcSkarels 	format_sectors(&reloc, &phys, ALT_SECTOR, (long)lab->d_nsectors);
377d5d660dcSkarels 	status = access_dsk((char *)save, &temp.err_adr, VDOP_WD, lab->d_nsectors, 1);
37868c7fc27Ssam 	if(!((status & DCBS_ATA) && !(status & (DCBS_HARD|DCBS_SOFT)))) {
3796d7a1e15Ssam 		print("Track relocation failed.  Status = 0x%x.\n", status);
3806d7a1e15Ssam 		print_unix_block(phys);
3816d7a1e15Ssam 	}
3826d7a1e15Ssam }
383