1 #ifndef lint
2 static char sccsid[] = "@(#)relocate.c	1.3 (Berkeley/CCI) 06/01/87";
3 #endif
4 
5 #include	"vdfmt.h"
6 #include	"cmd.h"
7 
8 /*
9 **
10 */
11 
12 relocate()
13 {
14 	extern boolean	is_formatted();
15 
16 	cur.state = rel;
17 	print("Adding flaws to bad sector map on ");
18 	printf("controller %d, drive %d, ", cur.controller, cur.drive);
19 	printf("type %s.\n",CURRENT->vc_name);
20 
21 	indent();
22 	if(is_formatted() == true) {
23 		if(read_bad_sector_map() == true)
24 			if(bad_map->bs_id != D_INFO.id) {
25 				print("Drive serial numbers do not match!\n");
26 				exdent(1);
27 				_longjmp(abort_environ, 1);
28 			}
29 		get_new_relocations();
30 		sync_bad_sector_map();
31 	}
32 	else
33 		print("Drive must be formatted befor relocations are done.\n");
34 	exdent(1);
35 }
36 
37 
38 /*
39 **
40 */
41 
42 rel_help()
43 {
44 	indent();
45 	print("Relocation commands are in the following form:\n");
46 	indent();
47 	print("[a-h] (block)   -  UNIX file system format.\n");
48 	print("SEctor (sector) -  Absolute sector number on disk.\n");
49 	print("Track (track)   -  Absolute disk track number.\n");
50 	print("(cylinder) (head) (offset) (length) - CDC flaw map format.\n");
51 	print("STARt           -  Starts relocation process.\n\n");
52 	exdent(2);
53 }
54 
55 
56 /*
57 **
58 */
59 
60 get_new_relocations()
61 {
62 	char		line[256];
63 	char		*ptr;
64 	bs_entry	entry;
65 	dskadr		dskaddr;
66 	int		max_track;
67 
68 	dskaddr.cylinder = CURRENT->vc_ncyl - 1;
69 	dskaddr.cylinder = CURRENT->vc_ntrak - 1;
70 	max_track = to_track(dskaddr);
71 	for(;;) {
72 		print("Location? ");
73 		get_string_cmd(line, rel_help);
74 		if(kill_processes == true)
75 			_longjmp(quit_environ, 1);
76 		if(line[0] == '\0')
77 			continue;
78 		ptr = line;
79 		trim_white(ptr);
80 		if(!strncmp(ptr, "he", 2) || !strncmp(ptr, "?", 1) ||
81 		    !strncmp(ptr, "stat", 4) || !strncmp(ptr, "!", 1))
82 			continue;
83 		indent();
84 		if((*ptr >= 'a') && (*ptr <= 'h')) {
85 			register char	par = *(ptr++);
86 			register int	block = get_next_digit(ptr);
87 
88 			dskaddr = *from_unix((unsigned char)par,
89 			    (unsigned int)block);
90 			if((dskaddr.cylinder == -1) || (block == -1)) {
91 				print("Invalid UNIX block number!\n");
92 				goto next;
93 			}
94 			print("Confirm block %d on file-system '%c'",block,par);
95 			if(get_yes_no("") == true) {
96 				entry=(*C_INFO.code_pos)(dskaddr,HEADER_ERROR);
97 				add_user_relocations(&entry);
98 			}
99 		}
100 		else if(*ptr == 't') {
101 			register int	trk = get_next_digit(ptr);
102 
103 			if((trk == -1) || (trk >= max_track)) {
104 				print("Invalid track number!\n");
105 				goto next;
106 			}
107 			print("Confirm track %d", trk);
108 			if(get_yes_no("") == true) {
109 				dskaddr = *from_track(trk);
110 				entry=(*C_INFO.code_pos)(dskaddr,HEADER_ERROR);
111 				add_user_relocations(&entry);
112 			}
113 		}
114 		else if(!strncmp(ptr, "se", 2)) {
115 			register int	sec = get_next_digit(ptr);
116 
117 			if((sec == -1) ||
118 			    ((CURRENT->vc_nsec*CURRENT->vc_ntrak*CURRENT->vc_ncyl)<sec)){
119 				print("Invalid sector number!\n");
120 				goto next;
121 			}
122 			print("Confirm sector %d", sec);
123 			if(get_yes_no("") == true) {
124 				dskaddr = *from_sector((unsigned int)sec);
125 				entry = (*C_INFO.code_pos)(dskaddr, DATA_ERROR);
126 				add_user_relocations(&entry);
127 			}
128 		}
129 		else if(is_digit(*ptr)) {
130 			entry.bs_cyl = get_next_digit(ptr);
131 			skipdigits(ptr);
132 			finddigit(ptr);
133 			entry.bs_trk = get_next_digit(ptr);
134 			skipdigits(ptr);
135 			finddigit(ptr);
136 			entry.bs_offset = get_next_digit(ptr);
137 			skipdigits(ptr);
138 			finddigit(ptr);
139 			entry.bs_length = get_next_digit(ptr);
140 			if((entry.bs_trk != -1) && (entry.bs_offset != -1) &&
141 			    (entry.bs_length != -1)) {
142 				if(entry.bs_cyl >= CURRENT->vc_ncyl)
143 					print("Cylinder number to high!\n");
144 				else if(entry.bs_trk >= CURRENT->vc_ntrak)
145 					print("Head number to high!\n");
146 				else if(entry.bs_offset >= CURRENT->vc_traksize)
147 					print("Offset too long!\n");
148 				else if(entry.bs_length == 0)
149 					print("Can't have a 0 length error!\n");
150 				else {
151 					print("Confirm  Cyl %d, ",entry.bs_cyl);
152 					printf("Head %d, ", entry.bs_trk);
153 					printf("offset %d, ", entry.bs_offset);
154 					printf("length %d", entry.bs_length);
155 					if(get_yes_no("") == true)
156 						add_user_relocations(&entry);
157 				}
158 			}
159 			else
160 				goto bad;
161 		}
162 		else if(!strncmp(ptr, "start", 4)) {
163 			exdent(1);
164 			break;
165 		}
166 		else
167 bad:			print("What?\n");
168 next:		exdent(1);
169 	}
170 }
171 
172 dskadr check_track_for_relocations(entry, i)
173 bs_entry	entry;
174 register int	i;
175 {
176 	register int	j = i;
177 	fmt_err		temp, cmp;
178 	boolean		bad_track = false;
179 
180 	cmp = (*C_INFO.decode_pos)(entry);
181 	/* Check to see if a alternate track is or will be on this track */
182 	while((bad_map->list[j].bs_cyl == entry.bs_cyl) &&
183 	    (bad_map->list[j].bs_trk == entry.bs_trk)) {
184 		temp = (*C_INFO.decode_pos)(bad_map->list[j]);
185 		if(temp.err_stat & HEADER_ERROR) {
186 			bad_track = true;
187 			/* if track was mapped out (it can't be us) */
188 			if(((bad_map->list[j].bs_alt.cylinder != 0)) ||
189 		    	    (bad_map->list[j].bs_alt.track != 0) ||
190 		    	    (bad_map->list[j].bs_alt.sector != 0)) {
191 				return cmp.err_adr;
192 			}
193 		}
194 		j++;
195 	}
196 	/*
197 	**    If it was a bad track and it was not the current entry
198 	** that produced it then then map it
199 	** to itself and forget about it for now since it will be taken
200 	** care of later.
201 	**
202 	**    If it was the current entry return zero and the track will be
203 	** mapped out correctly.
204 	*/
205 	if(bad_track == true) {
206 		if(cmp.err_stat & HEADER_ERROR)
207 			return entry.bs_alt; /* better known as zero */
208 		else
209 			return cmp.err_adr;
210 	}
211 	/*
212 	**   if we made it through all the bad track stuff then check for
213 	** multiple errors on the same sector that are already mapped!
214 	*/
215 	j = i;
216 	while((bad_map->list[j].bs_cyl == entry.bs_cyl) &&
217 	    (bad_map->list[j].bs_trk == entry.bs_trk)) {
218 		temp = (*C_INFO.decode_pos)(bad_map->list[j]);
219 		if(temp.err_adr.sector == cmp.err_adr.sector) {
220 			/* if it is not really the current entry */
221 			if((bad_map->list[j].bs_offset != entry.bs_offset) ||
222 			    (bad_map->list[j].bs_length != entry.bs_length)) {
223 				/* if the sector is already mapped out */
224 				if(((bad_map->list[j].bs_alt.cylinder != 0)) ||
225 		   	 	    (bad_map->list[j].bs_alt.track != 0) ||
226 		    		    (bad_map->list[j].bs_alt.sector != 0)) {
227 					return temp.err_adr;
228 				}
229 			}
230 		}
231 		j++;
232 	}
233 	return	entry.bs_alt;
234 }
235 
236 
237 /*
238 **
239 */
240 
241 dskadr	is_relocated(entry)
242 bs_entry	entry;
243 {
244 	register int	i;
245 
246 	for(i=0; i<bad_map->bs_count; i++)
247 		if((bad_map->list[i].bs_cyl == entry.bs_cyl) &&
248 		    (bad_map->list[i].bs_trk == entry.bs_trk))
249 			return check_track_for_relocations(entry, i);
250 	return entry.bs_alt;
251 }
252 
253 
254 
255 /*
256 **
257 */
258 
259 sync_bad_sector_map()
260 {
261 	register int	i;
262 	dskadr		dskaddr;
263 
264 	/*
265 	** do all the relocation cylinders first to allocate all flaws in
266 	** relocation area.
267 	*/
268 	for(i=bad_map->bs_count-1; i>=0; i--) {
269 		if((bad_map->list[i].bs_cyl >= CURRENT->vc_ncyl-NUMSYS) &&
270 		    (bad_map->list[i].bs_cyl < CURRENT->vc_ncyl-NUMMAP-NUMMNT)) {
271 			if((bad_map->list[i].bs_alt.cylinder == 0) &&
272 			    (bad_map->list[i].bs_alt.track == 0) &&
273 			    (bad_map->list[i].bs_alt.sector == 0)) {
274 				bad_map->list[i].bs_alt =
275 				    *new_location(&bad_map->list[i]);
276 			}
277 		}
278 	}
279 	for(i=bad_map->bs_count-1; i>=0; i--) {
280 		if((bad_map->list[i].bs_alt.cylinder == 0) &&
281 		    (bad_map->list[i].bs_alt.track == 0) &&
282 		    (bad_map->list[i].bs_alt.sector == 0)) {
283 			dskaddr = is_relocated(bad_map->list[i]);
284 			if((dskaddr.cylinder == 0) && (dskaddr.track == 0) &&
285 			    (dskaddr.sector == 0)) {
286 				bad_map->list[i].bs_alt =
287 				    *new_location(&bad_map->list[i]);
288 				do_relocation(bad_map->list[i]);
289 			}
290 			else
291 				bad_map->list[i].bs_alt = dskaddr;
292 		}
293 	}
294 	write_bad_sector_map();
295 }
296 
297 
298 
299 /*
300 **
301 */
302 
303 do_relocation(entry)
304 bs_entry	entry;
305 {
306 	fmt_err	temp;
307 
308 	if(entry.bs_cyl >= CURRENT->vc_ncyl-NUMSYS)
309 		if(entry.bs_cyl != (CURRENT->vc_ncyl - NUMMAP - NUMMNT))
310 			return;
311 	temp = (*C_INFO.decode_pos)(entry);
312 	if((entry.bs_alt.cylinder == 0) && (entry.bs_alt.track == 0) &&
313 	    (entry.bs_alt.sector == 0))
314 		print_unix_block(temp.err_adr);
315 	else if(temp.err_stat & HEADER_ERROR)
316 		if(C_INFO.type == VDTYPE_VDDC) {
317 			print("Can't relocate tracks on VDDC controllers.\n");
318 			print_unix_block(temp.err_adr);
319 		}
320 		else
321 			relocate_track(entry);
322 	else
323 		relocate_sector(entry);
324 }
325 
326 
327 /*
328 **
329 */
330 
331 relocate_sector(entry)
332 bs_entry	entry;
333 {
334 	dskadr		phys, reloc;
335 	fmt_err		temp;
336 	register long	status;
337 
338 	temp = (*C_INFO.decode_pos)(entry);
339 	phys = temp.err_adr;
340 	reloc = entry.bs_alt;
341 	format_sectors(&phys, &reloc, RELOC_SECTOR, (long)1);
342 
343 	format_sectors(&reloc, &phys, ALT_SECTOR, (long)1);
344 	status = access_dsk((char *)save, &temp.err_adr, VDOP_WD, 1, 1);
345 	if(!((status & DCBS_ATA) && !(status & (DCBS_HARD|DCBS_SOFT)))) {
346 		print(
347 		"Sector relocation failed (c %d t %d s %d).  Status = 0x%x.\n",
348 		    phys.cylinder, phys.track, phys.sector, status);
349 		print_unix_block(phys);
350 	}
351 }
352 
353 
354 
355 /*
356 **
357 */
358 
359 relocate_track(entry)
360 bs_entry	entry;
361 {
362 	dskadr		phys, reloc;
363 	fmt_err		temp;
364 	register long	status;
365 
366 	temp = (*C_INFO.decode_pos)(entry);
367 	temp.err_adr.sector = 0;
368 	phys = temp.err_adr;
369 	reloc = entry.bs_alt;
370 	reloc.sector = 0xff;
371 	format_sectors(&phys, &reloc, RELOC_SECTOR, (long)CURRENT->vc_nsec);
372 
373 	reloc.sector = 0x00;
374 	format_sectors(&reloc, &phys, ALT_SECTOR, (long)CURRENT->vc_nsec);
375 	status = access_dsk((char *)save, &temp.err_adr, VDOP_WD, CURRENT->vc_nsec, 1);
376 	if(!((status & DCBS_ATA) && !(status & (DCBS_HARD|DCBS_SOFT)))) {
377 		print("Track relocation failed.  Status = 0x%x.\n", status);
378 		print_unix_block(phys);
379 	}
380 }
381