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