xref: /titanic_50/usr/src/cmd/addbadsec/ix_altsctr.c (revision b1dd958f54f8bfa984d306bb8ca8264855761d7b)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 1994 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1990, 1991 UNIX System Laboratories, Inc.	*/
28 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T	*/
29 /*	  All Rights Reserved  	*/
30 
31 /*
32  * Copyrighted as an unpublished work.
33  * (c) Copyright INTERACTIVE Systems Corporation 1986, 1988, 1990
34  * All rights reserved.
35  */
36 
37 #pragma ident	"%Z%%M%	%I%	%E% SMI"
38 
39 #include <sys/types.h>
40 #include <ctype.h>
41 #include <fcntl.h>
42 #include <malloc.h>
43 #include <sys/stat.h>
44 #include <sys/swap.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include <sys/vtoc.h>
48 #include <sys/param.h>
49 #include <sys/dkio.h>
50 #include <sys/dktp/altsctr.h>
51 #include <sys/dktp/fdisk.h>
52 #include "badsec.h"
53 
54 #define FAILURE	0
55 #define	SUCCESS	1
56 
57 #define CMD_READ	0
58 #define CMD_WRITE	1
59 
60 struct	badsec_lst *badsl_chain;
61 int	badsl_chain_cnt;
62 struct	badsec_lst *gbadsl_chain;
63 int	gbadsl_chain_cnt;
64 
65 extern struct  	dk_geom      	dkg;
66 
67 extern int	alts_fd;
68 
69 struct	alts_mempart alts_part = { 0, NULL, 0 };
70 struct	alts_mempart *ap = &alts_part;	/* pointer to incore alts tables     */
71 
72 /*
73  * updatebadsec () -- update bad sector/track mapping tables
74  */
75 updatebadsec(part, init_flag)
76 int	init_flag;
77 struct  partition *part;
78 {
79 	if (init_flag)
80 		ap->ap_flag |= ALTS_ADDPART;
81 	get_badsec();
82 	read_altsctr(part, 1);
83 	ent_sort(ap->ap_gbadp, ap->ap_gbadcnt);
84 	ent_compress(ap->ap_gbadp, ap->ap_gbadcnt);
85 	gen_alts_ent();
86 	compress_map();
87 	return(SUCCESS);
88 }
89 
90 /*
91  * read_altsctr( ptr to alternate sector partition )
92  *		-- read the alternate sector partition tables
93  */
94 read_altsctr(part, badok)
95 struct 	partition *part;
96 int badok;
97 {
98 	int ret;
99 
100 	if (ap->ap_tblp == NULL) {
101 /*	    allocate buffer for the alts partition table (sector size)	*/
102 	    ap->ap_tbl_secsiz = byte_to_secsiz(ALTS_PARTTBL_SIZE,NBPSCTR);
103 	    ap->ap_tblp = (struct alts_parttbl *)malloc(ap->ap_tbl_secsiz);
104 	    if (ap->ap_tblp == NULL) {
105 		fprintf(stderr, "Unable to malloc alternate partition table.\n");
106 		exit(50);
107 	    }
108 
109 /*	    allocate buffer for the alts partition map (sector size)	*/
110 /*	    buffers include the disk image bit map 			*/
111 /*	    and the incore transformed char map				*/
112 
113 	    if ((ap->ap_memmapp = (unchar *)malloc(part->p_size)) == NULL) {
114 		fprintf(stderr, "Unable to malloc incore alternate partition map.\n");
115 		exit(51);
116 	    }
117 	    ap->ap_tblp->alts_map_len = (part->p_size + 8 - 1) / 8;
118 	    ap->ap_map_secsiz=byte_to_secsiz(ap->ap_tblp->alts_map_len,NBPSCTR);
119 	    ap->ap_map_sectot = ap->ap_map_secsiz / NBPSCTR;
120 	    if ((ap->ap_mapp = (unchar *)malloc(ap->ap_map_secsiz)) == NULL) {
121 		fprintf(stderr, "Unable to malloc alternate partition map.\n");
122 		exit(52);
123 	    }
124 /*	    clear the buffers to zero					*/
125 	    memset(ap->ap_memmapp,0,part->p_size);
126 	    memset(ap->ap_mapp,0,ap->ap_map_secsiz);
127 	    ap->part = *part;		/* struct copy			*/
128 
129 /*
130  *	    if add alternate partition flag is set, then install the partition
131  *	    otherwise read the alts partition info from disk
132  *	    if failed, then assume the first installation
133  */
134 	    if (ap->ap_flag & ALTS_ADDPART)
135 	    {
136 		fprintf(stderr, "WARNING: Manually initializing alternate table.\n");
137 		init_altsctr();
138 	    }
139 	    else {
140 	    	if (get_altsctr(badok) == SUCCESS)
141 		    chk_badsec();
142 	    	else
143 		    init_altsctr();
144 	    }
145 	}
146 }
147 
148 
149 /*
150  *	checking duplicate bad sectors or bad sectors in ALTSCTR partition
151  */
152 chk_badsec()
153 {
154 	daddr_t	badsec;
155 	daddr_t	altsp_srtsec = ap->part.p_start;
156 	daddr_t	altsp_endsec = ap->part.p_start + ap->part.p_size - 1;
157 	int	cnt;
158 	int	status;
159 
160 	for (cnt=0; cnt < ap->ap_gbadcnt; cnt++) {
161 	    badsec = (ap->ap_gbadp)[cnt].bad_start;
162 /*	    if bad sector is within the ATLSCTR partition		*/
163 	    if ((badsec >= altsp_srtsec) && (badsec <= altsp_endsec)) {
164 		if ((ap->ap_memmapp)[badsec - altsp_srtsec] != ALTS_BAD) {
165 		    if ((badsec >= altsp_srtsec) && (badsec <= (altsp_srtsec +
166 			ap->ap_tbl_secsiz / NBPSCTR - 1))) {
167 		    	fprintf(stderr, "Alternate partition information table is bad.\n");
168 		    	exit(53);
169 	    	    }
170 		    if ((badsec >= altsp_srtsec+ap->ap_tblp->alts_map_base) &&
171 			(badsec <= (altsp_srtsec + ap->ap_tblp->alts_map_base +
172 			ap->ap_map_sectot - 1))) {
173 		    	fprintf(stderr, "Alternate partition map is bad.\n");
174 		    	exit(54);
175 	    	    }
176 		    if ((badsec >= altsp_srtsec+ap->ap_tblp->alts_ent_base) &&
177 			(badsec <= (altsp_srtsec + ap->ap_tblp->alts_ent_base +
178 			ap->ap_ent_secsiz / NBPSCTR - 1))) {
179 		    	fprintf(stderr, "Alternate partition entry table is bad.\n");
180 		    	exit(55);
181 	    	    }
182 		    (ap->ap_memmapp)[badsec - altsp_srtsec] = ALTS_BAD;
183 	            (ap->ap_gbadp)[cnt].bad_start = ALTS_ENT_EMPTY;
184 		} else {
185 		    status = chk_bad_altsctr(badsec);
186 	            (ap->ap_gbadp)[cnt].bad_start = ALTS_ENT_EMPTY;
187 		}
188 	    } else {
189 /*
190  *		binary search for bad sector in the alts entry table
191  */
192 		status = ent_bsearch(ap->ap_entp, ap->ap_tblp->alts_ent_used,
193 					&((ap->ap_gbadp)[cnt]) );
194 /*
195  *		if the bad sector had already been remapped(found in alts_entry)
196  *		then ignore the bad sector
197  */
198 		if (status != -1) {
199 	            (ap->ap_gbadp)[cnt].bad_start = ALTS_ENT_EMPTY;
200 		}
201 	    }
202 	}
203 
204 
205 
206 
207 }
208 
209 /*
210  *	initialize the alternate partition tables
211  */
212 init_altsctr()
213 {
214 	daddr_t	badsec;
215 	daddr_t	altsp_srtsec = ap->part.p_start;
216 	daddr_t	altsp_endsec = ap->part.p_start + ap->part.p_size - 1;
217 	int	cnt;
218 
219 	ap->ap_entp = NULL;
220 	ap->ap_ent_secsiz = 0;
221 	ap->ap_tblp->alts_sanity = ALTS_SANITY;
222 	ap->ap_tblp->alts_version= ALTS_VERSION1;
223 	ap->ap_tblp->alts_map_len = (ap->part.p_size + 8 - 1) / 8;
224 	ap->ap_tblp->alts_ent_used = 0;
225 	ap->ap_tblp->alts_ent_base = 0;
226 	ap->ap_tblp->alts_ent_end  = 0;
227 	ap->ap_tblp->alts_resv_base = ap->part.p_size - 1;
228 	for (cnt=0; cnt<5; cnt++)
229 	    ap->ap_tblp->alts_pad[cnt]=0;
230 
231 	for (cnt=0; cnt < ap->ap_gbadcnt; cnt++) {
232 	    badsec = (ap->ap_gbadp)[cnt].bad_start;
233 	    if ((badsec >= altsp_srtsec) && (badsec <= altsp_endsec)) {
234 		if (badsec == altsp_srtsec) {
235 		    fprintf(stderr, "First sector of alternate partition is bad.\n");
236 		    exit(56);
237 	    	}
238 		(ap->ap_memmapp)[badsec - altsp_srtsec] = ALTS_BAD;
239 	        (ap->ap_gbadp)[cnt].bad_start = ALTS_ENT_EMPTY;
240 	    }
241 	}
242 
243 /*	allocate the alts_map on disk skipping possible bad sectors	*/
244 	ap->ap_tblp->alts_map_base =
245 		altsmap_alloc(ap->ap_tbl_secsiz / NBPSCTR,
246 			ap->part.p_size, ap->ap_map_sectot, ALTS_MAP_UP);
247 	if (ap->ap_tblp->alts_map_base == NULL) {
248 	    perror("Unable to allocate alternate map on disk: ");
249 	    exit(57);
250 	}
251 
252 }
253 
254 
255 /*
256  * 	read the alternate partition tables from disk
257  */
258 int
259 get_altsctr(badok)
260 int badok;
261 {
262 /*	get alts partition table info					*/
263 	if (absdsk_io(alts_fd, 0, (char *)ap->ap_tblp,
264 			ap->ap_tbl_secsiz,CMD_READ)==FAILURE) {
265 	    if (badok)
266 		return(FAILURE);
267 	    perror("Unable to read alternate sector partition: ");
268 	    exit(58);
269 	}
270 	if (ap->ap_tblp->alts_sanity != ALTS_SANITY) {
271 	    if (badok)
272 		return(FAILURE);
273 	    fprintf(stderr, "Bad alternate sector magic number.\n");
274 	    exit(69);
275 	}
276 
277 /*	get the alts map						*/
278 	if (absdsk_io(alts_fd, ap->ap_tblp->alts_map_base,
279 		(char *)ap->ap_mapp, ap->ap_map_secsiz, CMD_READ) == FAILURE) {
280 	    if (badok)
281 		return(FAILURE);
282 	    perror("Unable to read alternate sector partition map: ");
283 	    exit(59);
284 	}
285 
286 /*	transform the disk image bit-map to incore char map		*/
287 	expand_map();
288 
289 	if (ap->ap_tblp->alts_ent_used == 0) {
290 	    ap->ap_entp = NULL;
291 	    ap->ap_ent_secsiz = 0;
292 	} else {
293 	    ap->ap_ent_secsiz = byte_to_secsiz(
294 			(ap->ap_tblp->alts_ent_used*ALTS_ENT_SIZE),NBPSCTR);
295 	    if ((ap->ap_entp = (struct alts_ent *)malloc(ap->ap_ent_secsiz)) == NULL) {
296 		if (badok)
297 		    return(FAILURE);
298 		fprintf(stderr, "Unable to malloc alternate sector entry table.\n");
299 		exit(60);
300 	    }
301 
302 	    if (absdsk_io(alts_fd, ap->ap_tblp->alts_ent_base,
303 	    			(char *)ap->ap_entp, ap->ap_ent_secsiz,
304 				CMD_READ) ==FAILURE){
305 		if (badok)
306 		    return(FAILURE);
307 		perror("Unable to read alternate sector entry table: ");
308 		exit(61);
309 	    }
310 	}
311 	return(SUCCESS);
312 }
313 
314 
315 /*
316  *	update the new alternate partition tables on disk
317  */
318 wr_altsctr()
319 {
320 	int	mystatus = FAILURE;
321 
322 	if (ap->ap_tblp == NULL)
323 		return;
324 	if (absdsk_io(alts_fd, 0, ap->ap_tblp,
325 		ap->ap_tbl_secsiz, CMD_WRITE) == FAILURE) {
326 	    perror("Unable to write alternate sector partition: ");
327 	    exit(62);
328 	}
329 
330 	if (absdsk_io(alts_fd, ap->ap_tblp->alts_map_base,
331 	    		ap->ap_mapp, ap->ap_map_secsiz, CMD_WRITE) == FAILURE){
332 	    perror("Unable to write alternate sector partition map: ");
333 	    exit(63);
334 	}
335 
336 	if (ap->ap_tblp->alts_ent_used != 0) {
337 	    if (absdsk_io(alts_fd, ap->ap_tblp->alts_ent_base,
338 	    			(char *)ap->ap_entp, ap->ap_ent_secsiz,
339 				CMD_WRITE) == FAILURE) {
340 		perror("Unable to write alternate sector entry table: ");
341 		exit(64);
342 	    }
343 	}
344 
345 
346 
347 }
348 
349 
350 /*
351  *	get a list of bad sector
352  */
353 get_badsec()
354 {
355 	int	cnt;
356 	struct	badsec_lst *blc_p;
357 	daddr_t	curbad;
358 	long	maxsec = (long)dkg.dkg_nhead *dkg.dkg_ncyl *dkg.dkg_nsect;
359 	struct	alts_ent *growbadp;
360 	int	i;
361 
362 	cnt = count_badsec();
363 	if (!cnt) {
364 	    ap->ap_gbadp = NULL;
365 	    ap->ap_gbadcnt = 0;
366 	}
367 	else {
368 	    ap->ap_gbadp = (struct alts_ent *) malloc(cnt*ALTS_ENT_SIZE);
369 	    memset(ap->ap_gbadp,0,cnt*ALTS_ENT_SIZE);
370 
371 	    for (growbadp=ap->ap_gbadp, cnt=0, blc_p=badsl_chain;
372 		blc_p; blc_p=blc_p->bl_nxt) {
373 		for (i=0; i<blc_p->bl_cnt; i++) {
374 		    curbad = blc_p->bl_sec[i];
375 		    if (curbad < (daddr_t)dkg.dkg_nsect) {
376 		    	fprintf(stderr,
377 			   "Ignoring bad sector %ld which is in first track of the drive.\n", curbad);
378 		    	continue;
379 		    }
380 		    if (curbad >= maxsec) {
381 		    	fprintf(stderr,
382 			   "Ignoring bad sector %ld which is past the end of the drive.\n", curbad);
383 		    	continue;
384 		    }
385 		    growbadp[cnt].bad_start = curbad;
386 		    growbadp[cnt].bad_end = curbad;
387 		    cnt++;
388 		}
389 	    }
390 	}
391 	ap->ap_gbadcnt = cnt;
392 }
393 
394 /*
395  *	count number of bad sector on list
396  *	merging the bad sector list from surface analysis and the
397  *	one given through the command line
398  */
399 count_badsec()
400 {
401 
402 	struct badsec_lst *blc_p;
403 
404 	if (!badsl_chain)
405 		badsl_chain = gbadsl_chain;
406 	else {
407 		for (blc_p = badsl_chain; blc_p->bl_nxt; blc_p=blc_p->bl_nxt)
408 			;
409 		blc_p->bl_nxt = gbadsl_chain;
410 	}
411 
412 	badsl_chain_cnt += gbadsl_chain_cnt;
413 	return(badsl_chain_cnt);
414 }
415 
416 
417 /*
418  *	generate alternate entry table by merging the existing and
419  *	the new entry list.
420  */
421 gen_alts_ent() {
422 	int	ent_used;
423 	struct	alts_ent *entp;
424 
425 	if (ap->ap_gbadcnt == 0)
426 	    return;
427 
428 	ent_used = ap->ap_tblp->alts_ent_used + ap->ap_gbadcnt;
429 	ap->ap_ent_secsiz = byte_to_secsiz(ent_used*ALTS_ENT_SIZE,NBPSCTR);
430 	entp=(struct alts_ent *) malloc (ap->ap_ent_secsiz);
431 	ent_used = ent_merge(entp, ap->ap_entp, ap->ap_tblp->alts_ent_used,
432 			     ap->ap_gbadp, ap->ap_gbadcnt);
433 	if (ap->ap_entp)
434 	    free(ap->ap_entp);
435 	if (ap->ap_gbadp)
436 	    free(ap->ap_gbadp);
437 	ap->ap_entp = entp;
438 	ap->ap_ent_secsiz = byte_to_secsiz(ent_used*ALTS_ENT_SIZE,NBPSCTR);
439 	ap->ap_tblp->alts_ent_used = ent_used;
440 	ap->ap_gbadp = NULL;
441 	ap->ap_gbadcnt = 0;
442 
443 /*	assign alternate sectors to the bad sectors			*/
444 	assign_altsctr();
445 
446 /*	allocate the alts_entry on disk skipping possible bad sectors	*/
447 	ap->ap_tblp->alts_ent_base =
448 		altsmap_alloc(ap->ap_tblp->alts_map_base + ap->ap_map_sectot,
449 			ap->part.p_size,
450 			ap->ap_ent_secsiz / NBPSCTR, ALTS_MAP_UP);
451 	if (ap->ap_tblp->alts_ent_base == NULL) {
452 	    perror("Unable to allocate alternate entry table on disk: ");
453 	    exit(65);
454 	}
455 
456 	ap->ap_tblp->alts_ent_end = ap->ap_tblp->alts_ent_base +
457 			(ap->ap_ent_secsiz / NBPSCTR) - 1;
458 }
459 
460 
461 /*
462  *	assign alternate sectors for bad sector mapping
463  */
464 assign_altsctr()
465 {
466 	int	i;
467 	int	j;
468 	daddr_t	alts_ind;
469 	int	cluster;
470 
471 	for (i=0; i<ap->ap_tblp->alts_ent_used; i++) {
472 	    if ((ap->ap_entp)[i].bad_start == ALTS_ENT_EMPTY)
473 		continue;
474 	    if ((ap->ap_entp)[i].good_start != 0)
475 		continue;
476 	    cluster = (ap->ap_entp)[i].bad_end-(ap->ap_entp)[i].bad_start +1;
477 	    alts_ind =
478 		altsmap_alloc(ap->part.p_size-1, ap->ap_tblp->alts_map_base +
479 			ap->ap_map_sectot - 1, cluster, ALTS_MAP_DOWN);
480 	    if (alts_ind == NULL) {
481 	    	fprintf(stderr, "Unable to allocate alternates for bad starting sector %ld.\n", (ap->ap_entp)[i].bad_start);
482 	    	exit(65);
483 	    }
484 	    alts_ind = alts_ind - cluster + 1;
485 	    (ap->ap_entp)[i].good_start =alts_ind +ap->part.p_start;
486 	    for (j=0; j<cluster; j++) {
487 		(ap->ap_memmapp)[alts_ind+j] = ALTS_BAD;
488 	    }
489 
490 	}
491 
492 }
493 
494 /*
495  *	transform the disk image alts bit map to incore char map
496  */
497 expand_map()
498 {
499 	int 	i;
500 
501 	for (i=0; i<ap->part.p_size; i++) {
502 	    (ap->ap_memmapp)[i] = altsmap_getbit(i);
503 	}
504 }
505 
506 /*
507  *	transform the incore alts char map to the disk image bit map
508  */
509 compress_map()
510 {
511 
512 	int 	i;
513 	int	bytesz;
514 	char	mask = 0;
515 	int	maplen=0;
516 
517 	for (i=0, bytesz=7; i<ap->part.p_size; i++) {
518 	    mask |= ((ap->ap_memmapp)[i] << bytesz--);
519 	    if (bytesz < 0) {
520 		(ap->ap_mapp)[maplen++] = mask;
521 		bytesz = 7;
522 		mask = 0;
523 	    }
524 	}
525 /*
526  *	if partition size != multiple number of bytes
527  *	then record the last partial byte
528  */
529 	if (bytesz != 7)
530 	    (ap->ap_mapp)[maplen] = mask;
531 
532 }
533 
534 /*
535  *	given a bad sector number, search in the alts bit map
536  *	and identify the sector as good or bad
537  */
538 altsmap_getbit(badsec)
539 daddr_t	badsec;
540 {
541 	int	slot = badsec / 8;
542 	int	field = badsec % 8;
543 	unchar	mask;
544 
545 	mask = ALTS_BAD<<7;
546 	mask >>= field;
547 	if ((ap->ap_mapp)[slot] & mask)
548 	     return(ALTS_BAD);
549 	return(ALTS_GOOD);
550 }
551 
552 
553 /*
554  *	allocate a range of sectors from the alternate partition
555  */
556 altsmap_alloc(srt_ind, end_ind, cnt, dir)
557 daddr_t	srt_ind;
558 daddr_t	end_ind;
559 int	cnt;
560 int	dir;
561 {
562 	int	i;
563 	int	total;
564 	int	first_ind;
565 
566 	for (i=srt_ind, first_ind=srt_ind, total=0; i!=end_ind; i+=dir) {
567 	    if ((ap->ap_memmapp)[i] == ALTS_BAD) {
568 		total = 0;
569 		first_ind = i + dir;
570 		continue;
571 	    }
572 	    total++;
573 	    if (total == cnt)
574 		return(first_ind);
575 
576 	}
577 	return(NULL);
578 }
579 
580 
581 
582 /*
583  * 	bubble sort the entry table into ascending order
584  */
585 ent_sort(buf, cnt)
586 struct	alts_ent buf[];
587 int	cnt;
588 {
589 struct	alts_ent temp;
590 int	flag;
591 int	i,j;
592 
593 	for (i=0; i<cnt-1; i++) {
594 	    temp = buf[cnt-1];
595 	    flag = 1;
596 
597 	    for (j=cnt-1; j>i; j--) {
598 		if (buf[j-1].bad_start < temp.bad_start) {
599 		    buf[j] = temp;
600 		    temp = buf[j-1];
601 		} else {
602 		    buf[j] = buf[j-1];
603 		    flag = 0;
604 		}
605 	    }
606 	    buf[i] = temp;
607 	    if (flag) break;
608 	}
609 
610 }
611 
612 
613 /*
614  *	compress all the contiguous bad sectors into a single entry
615  *	in the entry table. The entry table must be sorted into ascending
616  *	before the compression.
617  */
618 ent_compress(buf, cnt)
619 struct	alts_ent buf[];
620 int	cnt;
621 {
622 int	keyp;
623 int	movp;
624 int	i;
625 
626 	for (i=0; i<cnt; i++) {
627 	    if (buf[i].bad_start == ALTS_ENT_EMPTY)
628 		continue;
629 	    for (keyp=i, movp=i+1; movp<cnt; movp++) {
630 	    	if (buf[movp].bad_start == ALTS_ENT_EMPTY)
631 			continue;
632 		if (buf[keyp].bad_end+1 != buf[movp].bad_start)
633 		    break;
634 		buf[keyp].bad_end++;
635 		buf[movp].bad_start = ALTS_ENT_EMPTY;
636 	    }
637 	    if (movp == cnt) break;
638 	}
639 }
640 
641 
642 /*
643  *	merging two entry tables into a single table. In addition,
644  *	all empty slots in the entry table will be removed.
645  */
646 ent_merge(buf, list1, lcnt1, list2, lcnt2)
647 struct	alts_ent buf[];
648 struct	alts_ent list1[];
649 int	lcnt1;
650 struct	alts_ent list2[];
651 int	lcnt2;
652 {
653 	int	i;
654 	int	j1,j2;
655 
656 	for (i=0, j1=0, j2=0; j1<lcnt1 && j2<lcnt2;) {
657 	    if (list1[j1].bad_start == ALTS_ENT_EMPTY) {
658 		j1++;
659 		continue;
660 	    }
661 	    if (list2[j2].bad_start == ALTS_ENT_EMPTY) {
662 		j2++;
663 		continue;
664 	    }
665 	    if (list1[j1].bad_start < list2[j2].bad_start)
666 		buf[i++] = list1[j1++];
667 	    else
668 		buf[i++] = list2[j2++];
669 	}
670 	for (; j1<lcnt1; j1++) {
671 	    if (list1[j1].bad_start == ALTS_ENT_EMPTY)
672 		continue;
673 	    buf[i++] = list1[j1];
674 	}
675 	for (; j2<lcnt2; j2++) {
676 	    if (list2[j2].bad_start == ALTS_ENT_EMPTY)
677 		continue;
678 	    buf[i++] = list2[j2];
679 	}
680 	return (i);
681 }
682 
683 
684 /*
685  *	binary search for bad sector in the alternate entry table
686  */
687 ent_bsearch(buf, cnt, key)
688 struct	alts_ent buf[];
689 int	cnt;
690 struct	alts_ent *key;
691 {
692 	int	i;
693 	int	ind;
694 	int	interval;
695 	int	mystatus = -1;
696 
697 	if (!cnt) return (mystatus);
698 
699 	for (i=1; i<=cnt; i<<=1)
700 	    ind=i;
701 
702 	for (interval=ind; interval; ) {
703 /*
704 	    printf("ind= %d, intv= %d; ",ind, interval);
705 */
706 	    if ((key->bad_start >= buf[ind-1].bad_start) &&
707 		(key->bad_start <= buf[ind-1].bad_end)) {
708 		return(mystatus=ind-1);
709 	    } else {
710 	    	interval >>= 1;
711 		if (!interval) break;
712 		if (key->bad_start < buf[ind-1].bad_start) {
713 		    ind = ind - interval;
714 		} else {
715  /* 		    if key is larger than the last element then break	*/
716 		    if (ind == cnt) break;
717 		    if ((ind+interval) <= cnt)
718 		    	ind += interval;
719 		}
720 	    }
721 	}
722 	return(mystatus);
723 }
724 
725 /*
726  *	check for bad sector in assigned alternate sectors
727  */
728 chk_bad_altsctr(badsec)
729 daddr_t	badsec;
730 {
731 	int	i;
732 	int	j;
733 	daddr_t	numsec;
734 	int	mystatus = FAILURE;
735 	int	cnt = ap->ap_tblp->alts_ent_used;
736 	daddr_t intv[3];
737 
738 	for (i=0; i<cnt; i++) {
739 	    numsec = (ap->ap_entp)[i].bad_end - (ap->ap_entp)[i].bad_start;
740 	    if ((badsec >= (ap->ap_entp)[i].good_start) &&
741 		(badsec <= ((ap->ap_entp)[i].good_start + numsec))) {
742 		fprintf(stderr, "Bad sector %ld is an assigned alternate sector.\n", badsec);
743 		exit(66);
744 /*
745 		if (!numsec) {
746 		    (ap->ap_entp)[i].good_start = 0;
747 		    return(mystatus);
748 		}
749 		intv[0] = badsec - (ap->ap_entp)[i].good_start;
750 		intv[1] = 1;
751 		intv[2] = (ap->ap_entp)[i].good_start + numsec - badsec;
752 */
753 	    }
754 	}
755 /*	the bad sector has already been identified as bad		*/
756 	return(mystatus=SUCCESS);
757 
758 }
759 
760 
761 /*
762  * print_altsec () -- print alternate sector information
763  */
764 print_altsec(part)
765 struct  partition *part;
766 {
767 	ap->ap_tblp = NULL;
768 	ap->ap_flag &= ~ALTS_ADDPART;
769 	read_altsctr(part, 0);
770 	print_altsctr();
771 	return(SUCCESS);
772 }
773 
774 print_altsctr()
775 {
776 	int	i;
777 	int	totalloc;
778 	int	avail;
779 
780 /*	find # of available alternate sectors				*/
781 	for (i=0, totalloc=0; i<ap->part.p_size; i++) {
782 	    if ((ap->ap_memmapp)[i])
783 		totalloc++;
784 	}
785 /*
786  *	available = size of partition - allocated sectors/bad sectors
787  *		    - partition table - partition map
788  *		    - entry table
789  */
790 	avail = ap->part.p_size - totalloc;
791 	avail = avail - (ap->ap_tbl_secsiz/NBPSCTR)
792 		- ap->ap_map_sectot;
793 	avail = avail-(ap->ap_tblp->alts_ent_end -ap->ap_tblp->alts_ent_base+1);
794 	if (avail < 0) avail = 0;
795 
796 	printf("\nALTERNATE SECTOR/TRACK MAPPING TABLE:\n");
797 	printf("\nBad Sector Start\tAlternate Sector Start\t\tCount\n");
798 
799 	for (i=0; i<ap->ap_tblp->alts_ent_used; i++) {
800 	     printf("\t%ld\t     ->\t\t%ld\t\t\t   %ld\n",
801 		(ap->ap_entp)[i].bad_start,
802 		(ap->ap_entp)[i].good_start,
803 		((ap->ap_entp)[i].bad_end - (ap->ap_entp)[i].bad_start + 1));
804 	}
805 	printf("\n      %ld alternate sector(s) left for allocation.\n", avail);
806 
807 }
808 
809 absdsk_io(fd, srtsec, bufp, len, ioflag)
810 int	fd;
811 uint	srtsec;
812 char	*bufp;
813 uint	len;
814 int	ioflag;
815 {
816 	int	rc;
817 
818 	if (lseek (fd, srtsec * NBPSCTR, SEEK_SET) == -1)
819 		return(FAILURE);
820 	switch (ioflag)
821 	{
822 	case CMD_READ:
823 		rc = read (fd, bufp, len);
824 		break;
825 	case CMD_WRITE:
826 		rc = write (fd, bufp, len);
827 		break;
828 	default:
829 		break;
830 	}
831 	if (rc == -1)
832 		return(FAILURE);
833 	return(SUCCESS);
834 }
835