xref: /csrg-svn/sys/tahoe/stand/vdformat/maps.c (revision 32662)
1 #ifndef lint
2 static char sccsid[] = "@(#)maps.c	1.5 (Berkeley/CCI) 11/23/87";
3 #endif
4 
5 
6 #include	"vdfmt.h"
7 
8 
9 /*
10 **
11 */
12 
13 boolean align_buf(buf, sync)
14 unsigned long	*buf;
15 unsigned long	sync;
16 {
17 	register int	i, shift;
18 
19 	/* find shift amount */
20 	for(shift=0; shift < 32; shift++) {
21 		if((*buf >> shift ) == sync) {
22 			for(i=(512/sizeof(long))-1; i >= 0; i--) {
23 				*(buf+i+1) |= *(buf+i) << (32 - shift);
24 				*(buf+i) = *(buf+i) >> shift;
25 			}
26 			return true;
27 		}
28 	}
29 	return false;
30 }
31 
32 
33 /*
34 **	Looks for two maps in a row that are the same.
35 */
36 
37 boolean
38 read_map(flags)
39 short	flags;
40 {
41 	register int	trk, i;
42 	dskadr		dskaddr;
43 
44 	dskaddr.cylinder = (lab->d_ncylinders - 1) | flags;
45 	for(i=0; i < 100; i++)
46 		scratch[i] = -1;
47 	for(trk=0; trk < lab->d_ntracks; trk++) {
48 		dskaddr.track = trk;
49 		dskaddr.sector = 0;
50 		if(access_dsk((char *)save,&dskaddr, VDOP_RD,
51 		    lab->d_nsectors,1)& VDERR_HARD)
52 			continue;
53 		if(blkcmp((char *)scratch, (char *)save, bytes_trk) == true) {
54 			blkcopy((char *)save, (char *)bad_map, bytes_trk);
55 			if(bad_map->bs_count <= MAX_FLAWS) {
56 				for(i=0; i < bad_map->bs_count; i++) {
57 					if(bad_map->list[i].bs_cyl >=
58 					    lab->d_ncylinders)
59 						break;
60 					if(bad_map->list[i].bs_trk >=
61 					    lab->d_ntracks)
62 						break;
63 					if(bad_map->list[i].bs_offset >=
64 					    lab->d_traksize)
65 						break;
66 				}
67 				if(i == bad_map->bs_count) {
68 					load_free_table();
69 					return true;
70 				}
71 			}
72 			blkzero(bad_map, bytes_trk);
73 			bad_map->bs_id = 0;
74 			bad_map->bs_max = MAX_FLAWS;
75 		}
76 		blkcopy((char *)save, (char *)scratch, bytes_trk);
77 	}
78 	return false;
79 }
80 
81 
82 /*
83 **
84 */
85 
86 boolean read_bad_sector_map()
87 {
88 	dskadr		dskaddr;
89 
90 	dskaddr.cylinder = lab->d_ncylinders - 1;
91 	dskaddr.track = 0;
92 	dskaddr.sector = 0;
93 	/* start with nothing in map */
94 	blkzero(bad_map, bytes_trk);
95 	bad_map->bs_id = 0;
96 	bad_map->bs_max = MAX_FLAWS;
97 	if (C_INFO->type == VDTYPE_SMDE) {
98 		access_dsk((char *)save, &dskaddr, VDOP_RDRAW, 1, 1);
99 		if (align_buf((unsigned long *)save, CDCSYNC) == true) {
100 			read_flaw_map();
101 			return (false);
102 		} else if (read_map(NRM) == true) {
103 			return (true);
104 		} else {
105 			get_smde_relocations();
106 			return false;
107 		}
108 	} else {
109 		if (read_map(WPT) == true)
110 			return (true);
111 		else {
112 			get_relocations_the_hard_way();
113 			return (false);
114 		}
115 	}
116 }
117 
118 
119 /*
120 **
121 */
122 
123 get_relocations_the_hard_way()
124 {
125 	register int	cyl, trk;
126 	register int	status;
127 	dskadr		dskaddr;
128 
129 	dskaddr.sector = 0;
130 	/* scan each sector to see if it is relocated and take note if it is */
131 	for(cyl=0; cyl < lab->d_ncylinders - NUMSYS; cyl++) {
132 		dskaddr.cylinder = cyl;
133 		for(trk=0; trk < lab->d_ntracks; trk++) {
134 			dskaddr.track = trk;
135 			status=access_dsk((char *)scratch, &dskaddr,
136 			    VDOP_RD, lab->d_nsectors, 1);
137 			if(status & DCBS_ATA)
138 				get_track_relocations(dskaddr);
139 		}
140 	}
141 	load_free_table();
142 }
143 
144 
145 /*
146 **
147 */
148 
149 get_track_relocations(dskaddr)
150 dskadr	dskaddr;
151 {
152 	register int	status;
153 	bs_entry	temp;
154 	fmt_err		error;
155 
156 	for(dskaddr.sector=0; dskaddr.sector < lab->d_nsectors; dskaddr.sector++) {
157 		status = access_dsk((char *)scratch, &dskaddr, VDOP_RD, 1, 1);
158 		if(status & DCBS_ATA) {
159 			error.err_adr = dskaddr;
160 			error.err_stat = DATA_ERROR;
161 			temp = (*C_INFO->code_pos)(error);
162 			temp.bs_how = operator;
163 			add_flaw(&temp);
164 		}
165 	}
166 }
167 
168 
169 /*
170 **
171 */
172 
173 remove_user_relocations(entry)
174 bs_entry	entry;
175 {
176 	register int	i, j;
177 	fmt_err		temp;
178 	fmt_err		error;
179 	bs_entry	*ptr;
180 
181 	error = (*C_INFO->decode_pos)(entry);
182 	if(is_in_map(&error.err_adr) == true) {
183 		ptr = bad_map->list;
184 		for(i=0; i < bad_map->bs_count; i++) {
185 			temp = (*C_INFO->decode_pos)(*ptr);
186 			if((ptr->bs_how == operator) &&
187 			    (temp.err_adr.cylinder == error.err_adr.cylinder) &&
188 			    (temp.err_adr.track == error.err_adr.track) &&
189 			    (temp.err_adr.sector == error.err_adr.sector)) {
190 				if(temp.err_stat & HEADER_ERROR)
191 					remove_track(temp, ptr);
192 				else
193 					remove_sector(temp, ptr);
194 				for(j=i+1; j < bad_map->bs_count; j++)
195 					bad_map->list[j-1] = bad_map->list[j];
196 				bad_map->bs_count--;
197 				return;
198 			}
199 			ptr++;
200 		}
201 	}
202 	else {
203 		indent();
204 		print("Sector %d is not in bad sector map!\n",
205 		    to_sector(error.err_adr));
206 		exdent(1);
207 	}
208 }
209 
210 
211 /*
212 **
213 */
214 
215 remove_sector(error, entry)
216 fmt_err		error;
217 bs_entry	*entry;
218 {
219 	format_sectors(&error.err_adr, &error.err_adr, NRM, 1);
220 	format_sectors(&entry->bs_alt, &entry->bs_alt, NRM, 1);
221 }
222 
223 
224 /*
225 **
226 */
227 
228 remove_track(error, entry)
229 fmt_err		error;
230 bs_entry	*entry;
231 {
232 	format_sectors(&error.err_adr,&error.err_adr,NRM,(long)lab->d_nsectors);
233 	format_sectors(&entry->bs_alt,&entry->bs_alt,NRM,(long)lab->d_nsectors);
234 }
235 
236 
237 /*
238 **
239 */
240 
241 write_bad_sector_map()
242 {
243 	register int	trk, sec;
244 	dskadr		dskaddr;
245 
246 	dskaddr.cylinder = (lab->d_ncylinders - NUMMAP);
247 	for(trk=0; trk < lab->d_ntracks; trk++) {
248 		for(sec = 0; sec < lab->d_nsectors; sec++) {
249 			blkcopy((char *)bs_map_space + (sec * lab->d_secsize),
250 			    (char *)scratch, lab->d_secsize);
251 			dskaddr.track = trk;
252 			dskaddr.sector = sec;
253 			format_sectors(&dskaddr, &dskaddr, WPT, 1);
254 		}
255 	}
256 }
257 
258 
259 /*
260 **
261 */
262 
263 zero_bad_sector_map()
264 {
265 	bs_map		*bm = bad_map;
266 	register int	i;
267 	dskadr		zero;
268 
269 	zero.cylinder = 0;
270 	zero.track = 0;
271 	zero.sector = 0;
272 	for(i=0; i < bm->bs_count; i++)
273 		bm->list[i].bs_alt = zero;
274 	load_free_table();
275 }
276 
277 
278 /*
279 **
280 */
281 
282 read_flaw_map()
283 {
284 	register int	cyl, trk;
285 	dskadr		dskaddr;
286 	flaw		buffer;
287 
288 	dskaddr.sector = 0;
289 	for  (cyl=0; cyl < lab->d_ncylinders; cyl++) {
290 		dskaddr.cylinder = cyl;
291 		for  (trk=0; trk < lab->d_ntracks; trk++) {
292 			dskaddr.track = trk;
293 			access_dsk(&buffer, &dskaddr, VDOP_RDRAW, 1, 1);
294 			if(align_buf(&buffer, CDCSYNC) == true) {
295 				add_flaw_entries(&buffer);
296 				continue;
297 			}
298 		}
299 	}
300 	load_free_table();
301 }
302 
303 
304 /*
305 **
306 */
307 
308 get_smde_relocations()
309 {
310 	register int	cyl, trk, sec;
311 	smde_hdr	buffer;
312 	dskadr		dskaddr;
313 	fmt_err		bad;
314 	bs_entry	temp;
315 	boolean		bad_track;
316 
317 	/* Read any old drive relocations */
318 	for(cyl=0; cyl < NUMREL; cyl++) {
319 		dskaddr.cylinder = lab->d_ncylinders - NUMSYS + cyl;
320 		for(trk=0; trk < lab->d_ntracks; trk++) {
321 			dskaddr.track = trk;
322 			bad_track = true;
323 			for(sec=0; sec < lab->d_nsectors; sec++) {
324 				dskaddr.sector = sec;
325 				access_dsk(&buffer, &dskaddr, VDOP_RDRAW, 1, 1);
326 				if(align_buf(&buffer, SMDE1SYNC) == false) {
327 					bad_track = false;
328 					break;
329 				}
330 			}
331 			if(bad_track == true) {
332 				dskaddr.sector = 0;
333 				bad.err_adr.cylinder = buffer.alt_cyl;
334 				bad.err_adr.track = buffer.alt_trk;
335 				bad.err_adr.sector = 0;
336 				bad.err_stat = HEADER_ERROR;
337 				temp = (*C_INFO->code_pos)(bad);
338 				temp.bs_alt = dskaddr;
339 				temp.bs_how = scanning;
340 				add_flaw(&temp);
341 				continue;
342 			}
343 			for(sec=0; sec < lab->d_nsectors; sec++) {
344 				dskaddr.sector = sec;
345 				access_dsk(&buffer, &dskaddr, VDOP_RDRAW, 1, 1);
346 				if(align_buf(&buffer, SMDE1SYNC) == true) {
347 					bad.err_adr.cylinder = buffer.alt_cyl;
348 					bad.err_adr.track = buffer.alt_trk;
349 					bad.err_adr.sector = buffer.alt_sec;
350 					bad.err_stat = DATA_ERROR;
351 					temp = (*C_INFO->code_pos)(bad);
352 					temp.bs_alt = dskaddr;
353 					temp.bs_how = scanning;
354 					add_flaw(&temp);
355 				}
356 			}
357 		}
358 	}
359 	load_free_table();
360 }
361 
362 
363 /*
364 **
365 */
366 
367 add_flaw_entries(buffer)
368 flaw	*buffer;
369 {
370 	register int	i;
371 	bs_entry	temp;
372 
373 	temp.bs_cyl = buffer->flaw_cyl & 0x7fff; /* clear off bad track bit */
374 	temp.bs_trk = buffer->flaw_trk;
375 	for(i=0; i < 4; i++) {
376 		if(buffer->flaw_pos[i].flaw_length != 0) {
377 			temp.bs_offset = buffer->flaw_pos[i].flaw_offset;
378 			temp.bs_length = buffer->flaw_pos[i].flaw_length;
379 			temp.bs_alt.cylinder = 0;
380 			temp.bs_alt.track = 0;
381 			temp.bs_alt.sector = 0;
382 			temp.bs_how = flaw_map;
383 			add_flaw(&temp);
384 		}
385 	}
386 }
387 
388 
389 cmp_entry(a, b)
390 bs_entry	*a;
391 bs_entry	*b;
392 {
393 	if(a->bs_cyl == b->bs_cyl) {
394 		if(a->bs_trk == b->bs_trk) {
395 			if(a->bs_offset == b->bs_offset)
396 				return 0;
397 			else if(a->bs_offset < b->bs_offset)
398 				return -1;
399 		 }
400 		else if(a->bs_trk < b->bs_trk)
401 			return -1;
402 	}
403 	else if(a->bs_cyl < b->bs_cyl)
404 		return -1;
405 	return 1;
406 }
407 
408 
409 add_flaw(entry)
410 bs_entry	*entry;
411 {
412 	extern	int	cmp_entry();
413 	bs_map		*bm = bad_map;
414 	register int	i;
415 
416 	if(bm->bs_count > MAX_FLAWS)
417 		return;
418 	if (entry->bs_cyl >= lab->d_ncylinders ||
419 	    entry->bs_trk >= lab->d_ntracks ||
420 	    entry->bs_offset >= lab->d_traksize)
421 		return;
422 	for(i=0; i < bm->bs_count; i++) {
423 		if(((bm->list[i].bs_cyl == entry->bs_cyl)) &&
424 		    (bm->list[i].bs_trk == entry->bs_trk) &&
425 		    (bm->list[i].bs_offset == entry->bs_offset)) {
426 			if((int)bm->list[i].bs_how > (int)entry->bs_how)
427 				bm->list[i].bs_how = entry->bs_how;
428 			return;
429 		}
430 	}
431 	bm->list[i] = *entry;
432 	bm->list[i].bs_alt.cylinder = 0;
433 	bm->list[i].bs_alt.track = 0;
434 	bm->list[i].bs_alt.sector = 0;
435 	bm->bs_count++;
436 	qsort((char *)&(bm->list[0]), (unsigned)bm->bs_count,
437 	    sizeof(bs_entry), cmp_entry);
438 }
439 
440 
441 /*
442 **	Is_in_map checks to see if a block is known to be bad already.
443 */
444 
445 boolean is_in_map(dskaddr)
446 dskadr	*dskaddr;
447 {
448 	register int	i;
449 	fmt_err		temp;
450 
451 	for(i=0; i < bad_map->bs_count; i++) {
452 		temp = (*C_INFO->decode_pos)(bad_map->list[i]);
453 		if((temp.err_adr.cylinder == dskaddr->cylinder) &&
454 		    (temp.err_adr.track == dskaddr->track) &&
455 		    (temp.err_adr.sector == dskaddr->sector)) {
456 			return true;
457 		}
458 	}
459 	return false;
460 }
461 
462 
463 /*
464 **
465 */
466 
467 print_bad_sector_list()
468 {
469 	register int	i;
470 	fmt_err		errloc;
471 
472 	if(bad_map->bs_count == 0) {
473 		print("There are no bad sectors in bad sector map.\n");
474 		return;
475 	}
476 	print("The following sector%s known to be bad:\n",
477 	    (bad_map->bs_count == 1) ? " is" : "s are");
478 	indent();
479 	for(i=0; i < bad_map->bs_count; i++) {
480 		print("cyl %d, head %d, pos %d, len %d ",
481 			bad_map->list[i].bs_cyl,
482 			bad_map->list[i].bs_trk,
483 			bad_map->list[i].bs_offset,
484 			bad_map->list[i].bs_length);
485 		errloc = (*C_INFO->decode_pos)(bad_map->list[i]);
486 		if(errloc.err_stat & HEADER_ERROR) {
487 			printf("(Track #%d)", to_track(errloc.err_adr));
488 		}
489 		else {
490 			printf("(Sector #%d)", to_sector(errloc.err_adr));
491 		}
492 		if((bad_map->list[i].bs_alt.cylinder != 0) ||
493 		    (bad_map->list[i].bs_alt.track != 0) ||
494 		    (bad_map->list[i].bs_alt.sector != 0)) {
495 			indent();
496 			printf(" -> ");
497 			if(errloc.err_stat & HEADER_ERROR) {
498 				printf("Track %d",
499 		    		    to_track(bad_map->list[i].bs_alt));
500 			}
501 			else {
502 				printf("Sector %d",
503 		    		    to_sector(bad_map->list[i].bs_alt));
504 			}
505 			exdent(1);
506 		}
507 		printf(".\n");
508 	}
509 	exdent(1);
510 }
511 
512 
513 /*
514 **	Vdload_free_table checks each block in the bad block relocation area
515 ** to see if it is used. If it is, the free relocation block table is updated.
516 */
517 
518 load_free_table()
519 {
520 	register int	i, j;
521 	fmt_err		temp;
522 
523 	/* Clear free table before starting */
524 	for(i = 0; i < (lab->d_ntracks * NUMREL); i++) {
525 		for(j=0; j < lab->d_nsectors; j++)
526 			free_tbl[i][j].free_status = NOTALLOCATED;
527 	}
528 	for(i=0; i < bad_map->bs_count; i++)
529 		if((bad_map->list[i].bs_alt.cylinder != 0) ||
530 		    (bad_map->list[i].bs_alt.track != 0) ||
531 		    (bad_map->list[i].bs_alt.sector != 0)) {
532 			temp = (*C_INFO->decode_pos)(bad_map->list[i]);
533 			allocate(&(bad_map->list[i].bs_alt), temp.err_stat);
534 		}
535 }
536 
537 
538 /*
539 **	allocate marks a replacement sector as used.
540 */
541 
542 allocate(dskaddr, status)
543 dskadr	*dskaddr;
544 long	status;
545 {
546 	register int	trk, sec;
547 
548 	trk = dskaddr->cylinder - (lab->d_ncylinders - NUMSYS);
549 	if((trk < 0) || (trk >= NUMREL))
550 		return;
551 	trk *= lab->d_ntracks;
552 	trk += dskaddr->track;
553 	if(status & HEADER_ERROR)
554 		for(sec=0; sec < lab->d_nsectors; sec++)
555 			free_tbl[trk][sec].free_status = ALLOCATED;
556 	else
557 		free_tbl[trk][dskaddr->sector].free_status = ALLOCATED;
558 }
559 
560 
561 /*
562 **
563 */
564 
565 boolean mapping_collision(entry)
566 bs_entry	*entry;
567 {
568 	register int	trk, sec;
569 	fmt_err		temp;
570 
571 	trk = entry->bs_cyl - (lab->d_ncylinders - NUMSYS);
572 	if((trk < 0) || (trk >= NUMREL))
573 		return false;
574 	trk *= lab->d_ntracks;
575 	trk += entry->bs_trk;
576 	temp = (*C_INFO->decode_pos)(*entry);
577 	/* if this relocation should take up the whole track */
578 	if(temp.err_stat & HEADER_ERROR) {
579 		for(sec=0; sec < lab->d_nsectors; sec++)
580 			if(free_tbl[trk][sec].free_status == ALLOCATED)
581 				return true;
582 	}
583 	/* else just check the current sector */
584 	else {
585 		if(free_tbl[trk][temp.err_adr.sector].free_status == ALLOCATED)
586 			return true;
587 	}
588 	return false;
589 }
590 
591 
592 /*
593 **
594 */
595 
596 report_collision()
597 {
598 	indent();
599 	print("Sector resides in relocation area");
600 	printf("but it has a sector mapped to it already.\n");
601 	print("Please reformat disk with 0 patterns to eliminate problem.\n");
602 	exdent(1);
603 }
604 
605 
606 /*
607 **
608 */
609 
610 add_user_relocations(entry)
611 bs_entry	*entry;
612 {
613 	fmt_err		error;
614 
615 	error = (*C_INFO->decode_pos)(*entry);
616 	if(is_in_map(&error.err_adr) == false) {
617 		if(mapping_collision(entry) == true)
618 			report_collision();
619 		entry->bs_how = operator;
620 		add_flaw(entry);
621 	}
622 	else {
623 		indent();
624 		print("Sector %d is already mapped out!\n",
625 		    to_sector(error.err_adr));
626 		exdent(1);
627 	}
628 }
629 
630 
631 /*
632 ** 	New_location allocates a replacement block given a bad block address.
633 **  The algorithm is fairly simple; it simply searches for the first
634 **  free sector that has the same sector number of the bad sector.  If no sector
635 **  is found then the drive should be considered bad because of a microcode bug
636 **  in the controller that forces us to use the same sector number as the bad
637 **  sector for relocation purposes.  Using different tracks and cylinders is ok
638 **  of course.
639 */
640 
641 dskadr *new_location(entry)
642 bs_entry	*entry;
643 {
644 	register int	i, sec;
645 	static fmt_err	temp;
646 	static dskadr	newaddr;
647 
648 	newaddr.cylinder = 0;
649 	newaddr.track = 0;
650 	newaddr.sector = 0;
651 	temp = (*C_INFO->decode_pos)(*entry);
652 	/* If it is ouside of the user's data area */
653 	if(entry->bs_cyl >= lab->d_ncylinders-NUMSYS) {
654 		/* if it is in the relocation area */
655 		if(entry->bs_cyl < (lab->d_ncylinders - NUMMAP - NUMMNT)) {
656 			/* mark space as allocated */
657 			allocate(&temp.err_adr, temp.err_stat);
658 			return &temp.err_adr;
659 		}
660 		/* if it is in the map area forget about it */
661 		if(entry->bs_cyl != (lab->d_ncylinders - NUMMAP - NUMMNT))
662 			return &temp.err_adr;
663 		/* otherwise treat maintainence cylinder normally */
664 	}
665 	if(temp.err_stat & (HEADER_ERROR)) {
666 		for(i = 0; i < (lab->d_ntracks * NUMREL); i++) {
667 			for(sec=0; sec < lab->d_nsectors; sec++) {
668 				if(free_tbl[i][sec].free_status == ALLOCATED)
669 					break;
670 			}
671 			if(sec == lab->d_nsectors) {
672 				for(sec = 0; sec < lab->d_nsectors; sec++)
673 					free_tbl[i][sec].free_status=ALLOCATED;
674 				newaddr.cylinder = i / lab->d_ntracks +
675 				    (lab->d_ncylinders - NUMSYS);
676 				newaddr.track = i % lab->d_ntracks;
677 				break;
678 			}
679 		}
680 	}
681 	else if(C_INFO->type == VDTYPE_VDDC) {
682 		for(i = 0; i < (lab->d_ntracks * NUMREL); i++) {
683 			if(free_tbl[i][temp.err_adr.sector].free_status !=
684 			    ALLOCATED) {
685 				free_tbl[i][temp.err_adr.sector].free_status =
686 				    ALLOCATED;
687 				newaddr.cylinder = i / lab->d_ntracks +
688 				    (lab->d_ncylinders - NUMSYS);
689 				newaddr.track = i % lab->d_ntracks;
690 				newaddr.sector = temp.err_adr.sector;
691 				break;
692 			}
693 		}
694 	}
695 	else {
696 		for(i = 0; i < (lab->d_ntracks * NUMREL); i++) {
697 			for(sec=0; sec < lab->d_nsectors; sec++)
698 				if(free_tbl[i][sec].free_status != ALLOCATED)
699 					break;
700 			if(sec < lab->d_nsectors) {
701 				free_tbl[i][sec].free_status = ALLOCATED;
702 				newaddr.cylinder = i / lab->d_ntracks +
703 				    (lab->d_ncylinders - NUMSYS);
704 				newaddr.track = i % lab->d_ntracks;
705 				newaddr.sector = sec;
706 				break;
707 			}
708 		}
709 	}
710 	return &newaddr;
711 }
712