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