10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
220Sstevel@tonic-gate /*
23*362Sbg159949  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate /*	Copyright (c) 1990, 1991 UNIX System Laboratories, Inc.	*/
280Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T	*/
290Sstevel@tonic-gate /*	  All Rights Reserved  	*/
300Sstevel@tonic-gate 
310Sstevel@tonic-gate /*
320Sstevel@tonic-gate  * Copyrighted as an unpublished work.
330Sstevel@tonic-gate  * (c) Copyright INTERACTIVE Systems Corporation 1986, 1988, 1990
340Sstevel@tonic-gate  * All rights reserved.
350Sstevel@tonic-gate  */
360Sstevel@tonic-gate 
370Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
380Sstevel@tonic-gate 
390Sstevel@tonic-gate #include <sys/types.h>
400Sstevel@tonic-gate #include <ctype.h>
410Sstevel@tonic-gate #include <fcntl.h>
420Sstevel@tonic-gate #include <malloc.h>
430Sstevel@tonic-gate #include <sys/stat.h>
440Sstevel@tonic-gate #include <sys/swap.h>
450Sstevel@tonic-gate #include <stdio.h>
460Sstevel@tonic-gate #include <string.h>
470Sstevel@tonic-gate #include <sys/vtoc.h>
480Sstevel@tonic-gate #include <sys/param.h>
490Sstevel@tonic-gate #include <sys/dkio.h>
500Sstevel@tonic-gate #include <sys/dktp/altsctr.h>
510Sstevel@tonic-gate #include <sys/dktp/fdisk.h>
520Sstevel@tonic-gate #include "badsec.h"
530Sstevel@tonic-gate 
540Sstevel@tonic-gate #define FAILURE	0
550Sstevel@tonic-gate #define	SUCCESS	1
560Sstevel@tonic-gate 
570Sstevel@tonic-gate #define CMD_READ	0
580Sstevel@tonic-gate #define CMD_WRITE	1
590Sstevel@tonic-gate 
600Sstevel@tonic-gate struct	badsec_lst *badsl_chain;
610Sstevel@tonic-gate int	badsl_chain_cnt;
620Sstevel@tonic-gate struct	badsec_lst *gbadsl_chain;
630Sstevel@tonic-gate int	gbadsl_chain_cnt;
640Sstevel@tonic-gate 
650Sstevel@tonic-gate extern struct  	dk_geom      	dkg;
660Sstevel@tonic-gate 
670Sstevel@tonic-gate extern int	alts_fd;
680Sstevel@tonic-gate 
690Sstevel@tonic-gate struct	alts_mempart alts_part = { 0, NULL, 0 };
700Sstevel@tonic-gate struct	alts_mempart *ap = &alts_part;	/* pointer to incore alts tables     */
710Sstevel@tonic-gate 
72*362Sbg159949 static void read_altsctr(struct partition *part, int badok);
73*362Sbg159949 static void chk_badsec    (void);
74*362Sbg159949 static void init_altsctr  (void);
75*362Sbg159949        void wr_altsctr    (void);
76*362Sbg159949 static void get_badsec    (void);
77*362Sbg159949 static int  count_badsec  (void);
78*362Sbg159949 static void gen_alts_ent  (void);
79*362Sbg159949 static void assign_altsctr(void);
80*362Sbg159949 static void expand_map    (void);
81*362Sbg159949 static void compress_map  (void);
82*362Sbg159949 static int  altsmap_getbit(daddr_t badsec);
83*362Sbg159949 static int  altsmap_alloc(daddr_t srt_ind, daddr_t end_ind, int cnt, int dir);
84*362Sbg159949 static void ent_sort(struct alts_ent buf[], int cnt);
85*362Sbg159949 static void ent_compress(struct alts_ent buf[], int cnt);
86*362Sbg159949 static int  ent_merge(
87*362Sbg159949 	struct alts_ent buf[],
88*362Sbg159949 	struct alts_ent list1[],
89*362Sbg159949 	int    lcnt1,
90*362Sbg159949 	struct alts_ent list2[],
91*362Sbg159949 	int    lcnt2);
92*362Sbg159949 static int  ent_bsearch(struct alts_ent buf[], int cnt, struct alts_ent *key);
93*362Sbg159949 static int  chk_bad_altsctr(daddr_t badsec);
94*362Sbg159949        int  print_altsec(struct partition *part);
95*362Sbg159949 static void print_altsctr(void);
96*362Sbg159949 static int  absdsk_io(int fd, uint srtsec, char *bufp, uint len, int ioflag);
97*362Sbg159949 
980Sstevel@tonic-gate /*
990Sstevel@tonic-gate  * updatebadsec () -- update bad sector/track mapping tables
1000Sstevel@tonic-gate  */
101*362Sbg159949 int
102*362Sbg159949 updatebadsec(struct partition *part, int init_flag)
1030Sstevel@tonic-gate {
1040Sstevel@tonic-gate 	if (init_flag)
1050Sstevel@tonic-gate 		ap->ap_flag |= ALTS_ADDPART;
1060Sstevel@tonic-gate 	get_badsec();
1070Sstevel@tonic-gate 	read_altsctr(part, 1);
1080Sstevel@tonic-gate 	ent_sort(ap->ap_gbadp, ap->ap_gbadcnt);
1090Sstevel@tonic-gate 	ent_compress(ap->ap_gbadp, ap->ap_gbadcnt);
1100Sstevel@tonic-gate 	gen_alts_ent();
1110Sstevel@tonic-gate 	compress_map();
1120Sstevel@tonic-gate 	return(SUCCESS);
1130Sstevel@tonic-gate }
1140Sstevel@tonic-gate 
1150Sstevel@tonic-gate /*
1160Sstevel@tonic-gate  * read_altsctr( ptr to alternate sector partition )
1170Sstevel@tonic-gate  *		-- read the alternate sector partition tables
1180Sstevel@tonic-gate  */
119*362Sbg159949 static void
120*362Sbg159949 read_altsctr(struct partition *part, int badok)
1210Sstevel@tonic-gate {
1220Sstevel@tonic-gate 	int ret;
1230Sstevel@tonic-gate 
1240Sstevel@tonic-gate 	if (ap->ap_tblp == NULL) {
1250Sstevel@tonic-gate /*	    allocate buffer for the alts partition table (sector size)	*/
1260Sstevel@tonic-gate 	    ap->ap_tbl_secsiz = byte_to_secsiz(ALTS_PARTTBL_SIZE,NBPSCTR);
1270Sstevel@tonic-gate 	    ap->ap_tblp = (struct alts_parttbl *)malloc(ap->ap_tbl_secsiz);
1280Sstevel@tonic-gate 	    if (ap->ap_tblp == NULL) {
1290Sstevel@tonic-gate 		fprintf(stderr, "Unable to malloc alternate partition table.\n");
1300Sstevel@tonic-gate 		exit(50);
1310Sstevel@tonic-gate 	    }
1320Sstevel@tonic-gate 
1330Sstevel@tonic-gate /*	    allocate buffer for the alts partition map (sector size)	*/
1340Sstevel@tonic-gate /*	    buffers include the disk image bit map 			*/
1350Sstevel@tonic-gate /*	    and the incore transformed char map				*/
1360Sstevel@tonic-gate 
1370Sstevel@tonic-gate 	    if ((ap->ap_memmapp = (unchar *)malloc(part->p_size)) == NULL) {
1380Sstevel@tonic-gate 		fprintf(stderr, "Unable to malloc incore alternate partition map.\n");
1390Sstevel@tonic-gate 		exit(51);
1400Sstevel@tonic-gate 	    }
1410Sstevel@tonic-gate 	    ap->ap_tblp->alts_map_len = (part->p_size + 8 - 1) / 8;
1420Sstevel@tonic-gate 	    ap->ap_map_secsiz=byte_to_secsiz(ap->ap_tblp->alts_map_len,NBPSCTR);
1430Sstevel@tonic-gate 	    ap->ap_map_sectot = ap->ap_map_secsiz / NBPSCTR;
1440Sstevel@tonic-gate 	    if ((ap->ap_mapp = (unchar *)malloc(ap->ap_map_secsiz)) == NULL) {
1450Sstevel@tonic-gate 		fprintf(stderr, "Unable to malloc alternate partition map.\n");
1460Sstevel@tonic-gate 		exit(52);
1470Sstevel@tonic-gate 	    }
1480Sstevel@tonic-gate /*	    clear the buffers to zero					*/
1490Sstevel@tonic-gate 	    memset(ap->ap_memmapp,0,part->p_size);
1500Sstevel@tonic-gate 	    memset(ap->ap_mapp,0,ap->ap_map_secsiz);
1510Sstevel@tonic-gate 	    ap->part = *part;		/* struct copy			*/
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate /*
1540Sstevel@tonic-gate  *	    if add alternate partition flag is set, then install the partition
1550Sstevel@tonic-gate  *	    otherwise read the alts partition info from disk
1560Sstevel@tonic-gate  *	    if failed, then assume the first installation
1570Sstevel@tonic-gate  */
1580Sstevel@tonic-gate 	    if (ap->ap_flag & ALTS_ADDPART)
1590Sstevel@tonic-gate 	    {
1600Sstevel@tonic-gate 		fprintf(stderr, "WARNING: Manually initializing alternate table.\n");
1610Sstevel@tonic-gate 		init_altsctr();
1620Sstevel@tonic-gate 	    }
1630Sstevel@tonic-gate 	    else {
1640Sstevel@tonic-gate 	    	if (get_altsctr(badok) == SUCCESS)
1650Sstevel@tonic-gate 		    chk_badsec();
1660Sstevel@tonic-gate 	    	else
1670Sstevel@tonic-gate 		    init_altsctr();
1680Sstevel@tonic-gate 	    }
1690Sstevel@tonic-gate 	}
1700Sstevel@tonic-gate }
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate /*
1740Sstevel@tonic-gate  *	checking duplicate bad sectors or bad sectors in ALTSCTR partition
1750Sstevel@tonic-gate  */
176*362Sbg159949 static void
177*362Sbg159949 chk_badsec(void)
1780Sstevel@tonic-gate {
1790Sstevel@tonic-gate 	daddr_t	badsec;
1800Sstevel@tonic-gate 	daddr_t	altsp_srtsec = ap->part.p_start;
1810Sstevel@tonic-gate 	daddr_t	altsp_endsec = ap->part.p_start + ap->part.p_size - 1;
1820Sstevel@tonic-gate 	int	cnt;
1830Sstevel@tonic-gate 	int	status;
1840Sstevel@tonic-gate 
1850Sstevel@tonic-gate 	for (cnt=0; cnt < ap->ap_gbadcnt; cnt++) {
1860Sstevel@tonic-gate 	    badsec = (ap->ap_gbadp)[cnt].bad_start;
1870Sstevel@tonic-gate /*	    if bad sector is within the ATLSCTR partition		*/
1880Sstevel@tonic-gate 	    if ((badsec >= altsp_srtsec) && (badsec <= altsp_endsec)) {
1890Sstevel@tonic-gate 		if ((ap->ap_memmapp)[badsec - altsp_srtsec] != ALTS_BAD) {
1900Sstevel@tonic-gate 		    if ((badsec >= altsp_srtsec) && (badsec <= (altsp_srtsec +
1910Sstevel@tonic-gate 			ap->ap_tbl_secsiz / NBPSCTR - 1))) {
1920Sstevel@tonic-gate 		    	fprintf(stderr, "Alternate partition information table is bad.\n");
1930Sstevel@tonic-gate 		    	exit(53);
1940Sstevel@tonic-gate 	    	    }
1950Sstevel@tonic-gate 		    if ((badsec >= altsp_srtsec+ap->ap_tblp->alts_map_base) &&
1960Sstevel@tonic-gate 			(badsec <= (altsp_srtsec + ap->ap_tblp->alts_map_base +
1970Sstevel@tonic-gate 			ap->ap_map_sectot - 1))) {
1980Sstevel@tonic-gate 		    	fprintf(stderr, "Alternate partition map is bad.\n");
1990Sstevel@tonic-gate 		    	exit(54);
2000Sstevel@tonic-gate 	    	    }
2010Sstevel@tonic-gate 		    if ((badsec >= altsp_srtsec+ap->ap_tblp->alts_ent_base) &&
2020Sstevel@tonic-gate 			(badsec <= (altsp_srtsec + ap->ap_tblp->alts_ent_base +
2030Sstevel@tonic-gate 			ap->ap_ent_secsiz / NBPSCTR - 1))) {
2040Sstevel@tonic-gate 		    	fprintf(stderr, "Alternate partition entry table is bad.\n");
2050Sstevel@tonic-gate 		    	exit(55);
2060Sstevel@tonic-gate 	    	    }
2070Sstevel@tonic-gate 		    (ap->ap_memmapp)[badsec - altsp_srtsec] = ALTS_BAD;
2080Sstevel@tonic-gate 	            (ap->ap_gbadp)[cnt].bad_start = ALTS_ENT_EMPTY;
2090Sstevel@tonic-gate 		} else {
2100Sstevel@tonic-gate 		    status = chk_bad_altsctr(badsec);
2110Sstevel@tonic-gate 	            (ap->ap_gbadp)[cnt].bad_start = ALTS_ENT_EMPTY;
2120Sstevel@tonic-gate 		}
2130Sstevel@tonic-gate 	    } else {
2140Sstevel@tonic-gate /*
2150Sstevel@tonic-gate  *		binary search for bad sector in the alts entry table
2160Sstevel@tonic-gate  */
2170Sstevel@tonic-gate 		status = ent_bsearch(ap->ap_entp, ap->ap_tblp->alts_ent_used,
2180Sstevel@tonic-gate 					&((ap->ap_gbadp)[cnt]) );
2190Sstevel@tonic-gate /*
2200Sstevel@tonic-gate  *		if the bad sector had already been remapped(found in alts_entry)
2210Sstevel@tonic-gate  *		then ignore the bad sector
2220Sstevel@tonic-gate  */
2230Sstevel@tonic-gate 		if (status != -1) {
2240Sstevel@tonic-gate 	            (ap->ap_gbadp)[cnt].bad_start = ALTS_ENT_EMPTY;
2250Sstevel@tonic-gate 		}
2260Sstevel@tonic-gate 	    }
2270Sstevel@tonic-gate 	}
2280Sstevel@tonic-gate 
2290Sstevel@tonic-gate 
2300Sstevel@tonic-gate 
2310Sstevel@tonic-gate 
2320Sstevel@tonic-gate }
2330Sstevel@tonic-gate 
2340Sstevel@tonic-gate /*
2350Sstevel@tonic-gate  *	initialize the alternate partition tables
2360Sstevel@tonic-gate  */
237*362Sbg159949 static void
238*362Sbg159949 init_altsctr(void)
2390Sstevel@tonic-gate {
2400Sstevel@tonic-gate 	daddr_t	badsec;
2410Sstevel@tonic-gate 	daddr_t	altsp_srtsec = ap->part.p_start;
2420Sstevel@tonic-gate 	daddr_t	altsp_endsec = ap->part.p_start + ap->part.p_size - 1;
2430Sstevel@tonic-gate 	int	cnt;
2440Sstevel@tonic-gate 
2450Sstevel@tonic-gate 	ap->ap_entp = NULL;
2460Sstevel@tonic-gate 	ap->ap_ent_secsiz = 0;
2470Sstevel@tonic-gate 	ap->ap_tblp->alts_sanity = ALTS_SANITY;
2480Sstevel@tonic-gate 	ap->ap_tblp->alts_version= ALTS_VERSION1;
2490Sstevel@tonic-gate 	ap->ap_tblp->alts_map_len = (ap->part.p_size + 8 - 1) / 8;
2500Sstevel@tonic-gate 	ap->ap_tblp->alts_ent_used = 0;
2510Sstevel@tonic-gate 	ap->ap_tblp->alts_ent_base = 0;
2520Sstevel@tonic-gate 	ap->ap_tblp->alts_ent_end  = 0;
2530Sstevel@tonic-gate 	ap->ap_tblp->alts_resv_base = ap->part.p_size - 1;
2540Sstevel@tonic-gate 	for (cnt=0; cnt<5; cnt++)
2550Sstevel@tonic-gate 	    ap->ap_tblp->alts_pad[cnt]=0;
2560Sstevel@tonic-gate 
2570Sstevel@tonic-gate 	for (cnt=0; cnt < ap->ap_gbadcnt; cnt++) {
2580Sstevel@tonic-gate 	    badsec = (ap->ap_gbadp)[cnt].bad_start;
2590Sstevel@tonic-gate 	    if ((badsec >= altsp_srtsec) && (badsec <= altsp_endsec)) {
2600Sstevel@tonic-gate 		if (badsec == altsp_srtsec) {
2610Sstevel@tonic-gate 		    fprintf(stderr, "First sector of alternate partition is bad.\n");
2620Sstevel@tonic-gate 		    exit(56);
2630Sstevel@tonic-gate 	    	}
2640Sstevel@tonic-gate 		(ap->ap_memmapp)[badsec - altsp_srtsec] = ALTS_BAD;
2650Sstevel@tonic-gate 	        (ap->ap_gbadp)[cnt].bad_start = ALTS_ENT_EMPTY;
2660Sstevel@tonic-gate 	    }
2670Sstevel@tonic-gate 	}
2680Sstevel@tonic-gate 
2690Sstevel@tonic-gate /*	allocate the alts_map on disk skipping possible bad sectors	*/
2700Sstevel@tonic-gate 	ap->ap_tblp->alts_map_base =
2710Sstevel@tonic-gate 		altsmap_alloc(ap->ap_tbl_secsiz / NBPSCTR,
2720Sstevel@tonic-gate 			ap->part.p_size, ap->ap_map_sectot, ALTS_MAP_UP);
2730Sstevel@tonic-gate 	if (ap->ap_tblp->alts_map_base == NULL) {
2740Sstevel@tonic-gate 	    perror("Unable to allocate alternate map on disk: ");
2750Sstevel@tonic-gate 	    exit(57);
2760Sstevel@tonic-gate 	}
2770Sstevel@tonic-gate 
2780Sstevel@tonic-gate }
2790Sstevel@tonic-gate 
2800Sstevel@tonic-gate 
2810Sstevel@tonic-gate /*
2820Sstevel@tonic-gate  * 	read the alternate partition tables from disk
2830Sstevel@tonic-gate  */
2840Sstevel@tonic-gate int
2850Sstevel@tonic-gate get_altsctr(badok)
2860Sstevel@tonic-gate int badok;
2870Sstevel@tonic-gate {
2880Sstevel@tonic-gate /*	get alts partition table info					*/
2890Sstevel@tonic-gate 	if (absdsk_io(alts_fd, 0, (char *)ap->ap_tblp,
2900Sstevel@tonic-gate 			ap->ap_tbl_secsiz,CMD_READ)==FAILURE) {
2910Sstevel@tonic-gate 	    if (badok)
2920Sstevel@tonic-gate 		return(FAILURE);
2930Sstevel@tonic-gate 	    perror("Unable to read alternate sector partition: ");
2940Sstevel@tonic-gate 	    exit(58);
2950Sstevel@tonic-gate 	}
2960Sstevel@tonic-gate 	if (ap->ap_tblp->alts_sanity != ALTS_SANITY) {
2970Sstevel@tonic-gate 	    if (badok)
2980Sstevel@tonic-gate 		return(FAILURE);
2990Sstevel@tonic-gate 	    fprintf(stderr, "Bad alternate sector magic number.\n");
3000Sstevel@tonic-gate 	    exit(69);
3010Sstevel@tonic-gate 	}
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate /*	get the alts map						*/
3040Sstevel@tonic-gate 	if (absdsk_io(alts_fd, ap->ap_tblp->alts_map_base,
3050Sstevel@tonic-gate 		(char *)ap->ap_mapp, ap->ap_map_secsiz, CMD_READ) == FAILURE) {
3060Sstevel@tonic-gate 	    if (badok)
3070Sstevel@tonic-gate 		return(FAILURE);
3080Sstevel@tonic-gate 	    perror("Unable to read alternate sector partition map: ");
3090Sstevel@tonic-gate 	    exit(59);
3100Sstevel@tonic-gate 	}
3110Sstevel@tonic-gate 
3120Sstevel@tonic-gate /*	transform the disk image bit-map to incore char map		*/
3130Sstevel@tonic-gate 	expand_map();
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate 	if (ap->ap_tblp->alts_ent_used == 0) {
3160Sstevel@tonic-gate 	    ap->ap_entp = NULL;
3170Sstevel@tonic-gate 	    ap->ap_ent_secsiz = 0;
3180Sstevel@tonic-gate 	} else {
3190Sstevel@tonic-gate 	    ap->ap_ent_secsiz = byte_to_secsiz(
3200Sstevel@tonic-gate 			(ap->ap_tblp->alts_ent_used*ALTS_ENT_SIZE),NBPSCTR);
3210Sstevel@tonic-gate 	    if ((ap->ap_entp = (struct alts_ent *)malloc(ap->ap_ent_secsiz)) == NULL) {
3220Sstevel@tonic-gate 		if (badok)
3230Sstevel@tonic-gate 		    return(FAILURE);
3240Sstevel@tonic-gate 		fprintf(stderr, "Unable to malloc alternate sector entry table.\n");
3250Sstevel@tonic-gate 		exit(60);
3260Sstevel@tonic-gate 	    }
3270Sstevel@tonic-gate 
3280Sstevel@tonic-gate 	    if (absdsk_io(alts_fd, ap->ap_tblp->alts_ent_base,
3290Sstevel@tonic-gate 	    			(char *)ap->ap_entp, ap->ap_ent_secsiz,
3300Sstevel@tonic-gate 				CMD_READ) ==FAILURE){
3310Sstevel@tonic-gate 		if (badok)
3320Sstevel@tonic-gate 		    return(FAILURE);
3330Sstevel@tonic-gate 		perror("Unable to read alternate sector entry table: ");
3340Sstevel@tonic-gate 		exit(61);
3350Sstevel@tonic-gate 	    }
3360Sstevel@tonic-gate 	}
3370Sstevel@tonic-gate 	return(SUCCESS);
3380Sstevel@tonic-gate }
3390Sstevel@tonic-gate 
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate /*
3420Sstevel@tonic-gate  *	update the new alternate partition tables on disk
3430Sstevel@tonic-gate  */
344*362Sbg159949 void
345*362Sbg159949 wr_altsctr(void)
3460Sstevel@tonic-gate {
3470Sstevel@tonic-gate 	int	mystatus = FAILURE;
3480Sstevel@tonic-gate 
3490Sstevel@tonic-gate 	if (ap->ap_tblp == NULL)
3500Sstevel@tonic-gate 		return;
351*362Sbg159949 	if (absdsk_io(alts_fd, 0, (char *)ap->ap_tblp,
3520Sstevel@tonic-gate 		ap->ap_tbl_secsiz, CMD_WRITE) == FAILURE) {
3530Sstevel@tonic-gate 	    perror("Unable to write alternate sector partition: ");
3540Sstevel@tonic-gate 	    exit(62);
3550Sstevel@tonic-gate 	}
3560Sstevel@tonic-gate 
3570Sstevel@tonic-gate 	if (absdsk_io(alts_fd, ap->ap_tblp->alts_map_base,
358*362Sbg159949 		(char *)ap->ap_mapp, ap->ap_map_secsiz, CMD_WRITE) == FAILURE) {
3590Sstevel@tonic-gate 	    perror("Unable to write alternate sector partition map: ");
3600Sstevel@tonic-gate 	    exit(63);
3610Sstevel@tonic-gate 	}
3620Sstevel@tonic-gate 
3630Sstevel@tonic-gate 	if (ap->ap_tblp->alts_ent_used != 0) {
3640Sstevel@tonic-gate 	    if (absdsk_io(alts_fd, ap->ap_tblp->alts_ent_base,
3650Sstevel@tonic-gate 	    			(char *)ap->ap_entp, ap->ap_ent_secsiz,
3660Sstevel@tonic-gate 				CMD_WRITE) == FAILURE) {
3670Sstevel@tonic-gate 		perror("Unable to write alternate sector entry table: ");
3680Sstevel@tonic-gate 		exit(64);
3690Sstevel@tonic-gate 	    }
3700Sstevel@tonic-gate 	}
3710Sstevel@tonic-gate 
3720Sstevel@tonic-gate 
3730Sstevel@tonic-gate 
3740Sstevel@tonic-gate }
3750Sstevel@tonic-gate 
3760Sstevel@tonic-gate 
3770Sstevel@tonic-gate /*
3780Sstevel@tonic-gate  *	get a list of bad sector
3790Sstevel@tonic-gate  */
380*362Sbg159949 static void
381*362Sbg159949 get_badsec(void)
3820Sstevel@tonic-gate {
3830Sstevel@tonic-gate 	int	cnt;
3840Sstevel@tonic-gate 	struct	badsec_lst *blc_p;
3850Sstevel@tonic-gate 	daddr_t	curbad;
3860Sstevel@tonic-gate 	long	maxsec = (long)dkg.dkg_nhead *dkg.dkg_ncyl *dkg.dkg_nsect;
3870Sstevel@tonic-gate 	struct	alts_ent *growbadp;
3880Sstevel@tonic-gate 	int	i;
3890Sstevel@tonic-gate 
3900Sstevel@tonic-gate 	cnt = count_badsec();
3910Sstevel@tonic-gate 	if (!cnt) {
3920Sstevel@tonic-gate 	    ap->ap_gbadp = NULL;
3930Sstevel@tonic-gate 	    ap->ap_gbadcnt = 0;
3940Sstevel@tonic-gate 	}
3950Sstevel@tonic-gate 	else {
3960Sstevel@tonic-gate 	    ap->ap_gbadp = (struct alts_ent *) malloc(cnt*ALTS_ENT_SIZE);
3970Sstevel@tonic-gate 	    memset(ap->ap_gbadp,0,cnt*ALTS_ENT_SIZE);
3980Sstevel@tonic-gate 
3990Sstevel@tonic-gate 	    for (growbadp=ap->ap_gbadp, cnt=0, blc_p=badsl_chain;
4000Sstevel@tonic-gate 		blc_p; blc_p=blc_p->bl_nxt) {
4010Sstevel@tonic-gate 		for (i=0; i<blc_p->bl_cnt; i++) {
4020Sstevel@tonic-gate 		    curbad = blc_p->bl_sec[i];
4030Sstevel@tonic-gate 		    if (curbad < (daddr_t)dkg.dkg_nsect) {
4040Sstevel@tonic-gate 		    	fprintf(stderr,
4050Sstevel@tonic-gate 			   "Ignoring bad sector %ld which is in first track of the drive.\n", curbad);
4060Sstevel@tonic-gate 		    	continue;
4070Sstevel@tonic-gate 		    }
4080Sstevel@tonic-gate 		    if (curbad >= maxsec) {
4090Sstevel@tonic-gate 		    	fprintf(stderr,
4100Sstevel@tonic-gate 			   "Ignoring bad sector %ld which is past the end of the drive.\n", curbad);
4110Sstevel@tonic-gate 		    	continue;
4120Sstevel@tonic-gate 		    }
4130Sstevel@tonic-gate 		    growbadp[cnt].bad_start = curbad;
4140Sstevel@tonic-gate 		    growbadp[cnt].bad_end = curbad;
4150Sstevel@tonic-gate 		    cnt++;
4160Sstevel@tonic-gate 		}
4170Sstevel@tonic-gate 	    }
4180Sstevel@tonic-gate 	}
4190Sstevel@tonic-gate 	ap->ap_gbadcnt = cnt;
4200Sstevel@tonic-gate }
4210Sstevel@tonic-gate 
4220Sstevel@tonic-gate /*
4230Sstevel@tonic-gate  *	count number of bad sector on list
4240Sstevel@tonic-gate  *	merging the bad sector list from surface analysis and the
4250Sstevel@tonic-gate  *	one given through the command line
4260Sstevel@tonic-gate  */
427*362Sbg159949 static int
428*362Sbg159949 count_badsec(void)
4290Sstevel@tonic-gate {
4300Sstevel@tonic-gate 
4310Sstevel@tonic-gate 	struct badsec_lst *blc_p;
4320Sstevel@tonic-gate 
4330Sstevel@tonic-gate 	if (!badsl_chain)
4340Sstevel@tonic-gate 		badsl_chain = gbadsl_chain;
4350Sstevel@tonic-gate 	else {
4360Sstevel@tonic-gate 		for (blc_p = badsl_chain; blc_p->bl_nxt; blc_p=blc_p->bl_nxt)
4370Sstevel@tonic-gate 			;
4380Sstevel@tonic-gate 		blc_p->bl_nxt = gbadsl_chain;
4390Sstevel@tonic-gate 	}
4400Sstevel@tonic-gate 
4410Sstevel@tonic-gate 	badsl_chain_cnt += gbadsl_chain_cnt;
4420Sstevel@tonic-gate 	return(badsl_chain_cnt);
4430Sstevel@tonic-gate }
4440Sstevel@tonic-gate 
4450Sstevel@tonic-gate 
4460Sstevel@tonic-gate /*
4470Sstevel@tonic-gate  *	generate alternate entry table by merging the existing and
4480Sstevel@tonic-gate  *	the new entry list.
4490Sstevel@tonic-gate  */
450*362Sbg159949 static void
451*362Sbg159949 gen_alts_ent(void)
452*362Sbg159949 {
4530Sstevel@tonic-gate 	int	ent_used;
4540Sstevel@tonic-gate 	struct	alts_ent *entp;
4550Sstevel@tonic-gate 
4560Sstevel@tonic-gate 	if (ap->ap_gbadcnt == 0)
4570Sstevel@tonic-gate 	    return;
4580Sstevel@tonic-gate 
4590Sstevel@tonic-gate 	ent_used = ap->ap_tblp->alts_ent_used + ap->ap_gbadcnt;
4600Sstevel@tonic-gate 	ap->ap_ent_secsiz = byte_to_secsiz(ent_used*ALTS_ENT_SIZE,NBPSCTR);
4610Sstevel@tonic-gate 	entp=(struct alts_ent *) malloc (ap->ap_ent_secsiz);
4620Sstevel@tonic-gate 	ent_used = ent_merge(entp, ap->ap_entp, ap->ap_tblp->alts_ent_used,
4630Sstevel@tonic-gate 			     ap->ap_gbadp, ap->ap_gbadcnt);
4640Sstevel@tonic-gate 	if (ap->ap_entp)
4650Sstevel@tonic-gate 	    free(ap->ap_entp);
4660Sstevel@tonic-gate 	if (ap->ap_gbadp)
4670Sstevel@tonic-gate 	    free(ap->ap_gbadp);
4680Sstevel@tonic-gate 	ap->ap_entp = entp;
4690Sstevel@tonic-gate 	ap->ap_ent_secsiz = byte_to_secsiz(ent_used*ALTS_ENT_SIZE,NBPSCTR);
4700Sstevel@tonic-gate 	ap->ap_tblp->alts_ent_used = ent_used;
4710Sstevel@tonic-gate 	ap->ap_gbadp = NULL;
4720Sstevel@tonic-gate 	ap->ap_gbadcnt = 0;
4730Sstevel@tonic-gate 
4740Sstevel@tonic-gate /*	assign alternate sectors to the bad sectors			*/
4750Sstevel@tonic-gate 	assign_altsctr();
4760Sstevel@tonic-gate 
4770Sstevel@tonic-gate /*	allocate the alts_entry on disk skipping possible bad sectors	*/
4780Sstevel@tonic-gate 	ap->ap_tblp->alts_ent_base =
4790Sstevel@tonic-gate 		altsmap_alloc(ap->ap_tblp->alts_map_base + ap->ap_map_sectot,
4800Sstevel@tonic-gate 			ap->part.p_size,
4810Sstevel@tonic-gate 			ap->ap_ent_secsiz / NBPSCTR, ALTS_MAP_UP);
4820Sstevel@tonic-gate 	if (ap->ap_tblp->alts_ent_base == NULL) {
4830Sstevel@tonic-gate 	    perror("Unable to allocate alternate entry table on disk: ");
4840Sstevel@tonic-gate 	    exit(65);
4850Sstevel@tonic-gate 	}
4860Sstevel@tonic-gate 
4870Sstevel@tonic-gate 	ap->ap_tblp->alts_ent_end = ap->ap_tblp->alts_ent_base +
4880Sstevel@tonic-gate 			(ap->ap_ent_secsiz / NBPSCTR) - 1;
4890Sstevel@tonic-gate }
4900Sstevel@tonic-gate 
4910Sstevel@tonic-gate 
4920Sstevel@tonic-gate /*
4930Sstevel@tonic-gate  *	assign alternate sectors for bad sector mapping
4940Sstevel@tonic-gate  */
495*362Sbg159949 static void
496*362Sbg159949 assign_altsctr(void)
4970Sstevel@tonic-gate {
4980Sstevel@tonic-gate 	int	i;
4990Sstevel@tonic-gate 	int	j;
5000Sstevel@tonic-gate 	daddr_t	alts_ind;
5010Sstevel@tonic-gate 	int	cluster;
5020Sstevel@tonic-gate 
5030Sstevel@tonic-gate 	for (i=0; i<ap->ap_tblp->alts_ent_used; i++) {
5040Sstevel@tonic-gate 	    if ((ap->ap_entp)[i].bad_start == ALTS_ENT_EMPTY)
5050Sstevel@tonic-gate 		continue;
5060Sstevel@tonic-gate 	    if ((ap->ap_entp)[i].good_start != 0)
5070Sstevel@tonic-gate 		continue;
5080Sstevel@tonic-gate 	    cluster = (ap->ap_entp)[i].bad_end-(ap->ap_entp)[i].bad_start +1;
5090Sstevel@tonic-gate 	    alts_ind =
5100Sstevel@tonic-gate 		altsmap_alloc(ap->part.p_size-1, ap->ap_tblp->alts_map_base +
5110Sstevel@tonic-gate 			ap->ap_map_sectot - 1, cluster, ALTS_MAP_DOWN);
5120Sstevel@tonic-gate 	    if (alts_ind == NULL) {
5130Sstevel@tonic-gate 	    	fprintf(stderr, "Unable to allocate alternates for bad starting sector %ld.\n", (ap->ap_entp)[i].bad_start);
5140Sstevel@tonic-gate 	    	exit(65);
5150Sstevel@tonic-gate 	    }
5160Sstevel@tonic-gate 	    alts_ind = alts_ind - cluster + 1;
5170Sstevel@tonic-gate 	    (ap->ap_entp)[i].good_start =alts_ind +ap->part.p_start;
5180Sstevel@tonic-gate 	    for (j=0; j<cluster; j++) {
5190Sstevel@tonic-gate 		(ap->ap_memmapp)[alts_ind+j] = ALTS_BAD;
5200Sstevel@tonic-gate 	    }
5210Sstevel@tonic-gate 
5220Sstevel@tonic-gate 	}
5230Sstevel@tonic-gate 
5240Sstevel@tonic-gate }
5250Sstevel@tonic-gate 
5260Sstevel@tonic-gate /*
5270Sstevel@tonic-gate  *	transform the disk image alts bit map to incore char map
5280Sstevel@tonic-gate  */
529*362Sbg159949 static void
530*362Sbg159949 expand_map(void)
5310Sstevel@tonic-gate {
5320Sstevel@tonic-gate 	int 	i;
5330Sstevel@tonic-gate 
5340Sstevel@tonic-gate 	for (i=0; i<ap->part.p_size; i++) {
5350Sstevel@tonic-gate 	    (ap->ap_memmapp)[i] = altsmap_getbit(i);
5360Sstevel@tonic-gate 	}
5370Sstevel@tonic-gate }
5380Sstevel@tonic-gate 
5390Sstevel@tonic-gate /*
5400Sstevel@tonic-gate  *	transform the incore alts char map to the disk image bit map
5410Sstevel@tonic-gate  */
542*362Sbg159949 static void
543*362Sbg159949 compress_map(void)
5440Sstevel@tonic-gate {
5450Sstevel@tonic-gate 
5460Sstevel@tonic-gate 	int 	i;
5470Sstevel@tonic-gate 	int	bytesz;
5480Sstevel@tonic-gate 	char	mask = 0;
5490Sstevel@tonic-gate 	int	maplen=0;
5500Sstevel@tonic-gate 
5510Sstevel@tonic-gate 	for (i=0, bytesz=7; i<ap->part.p_size; i++) {
5520Sstevel@tonic-gate 	    mask |= ((ap->ap_memmapp)[i] << bytesz--);
5530Sstevel@tonic-gate 	    if (bytesz < 0) {
5540Sstevel@tonic-gate 		(ap->ap_mapp)[maplen++] = mask;
5550Sstevel@tonic-gate 		bytesz = 7;
5560Sstevel@tonic-gate 		mask = 0;
5570Sstevel@tonic-gate 	    }
5580Sstevel@tonic-gate 	}
5590Sstevel@tonic-gate /*
5600Sstevel@tonic-gate  *	if partition size != multiple number of bytes
5610Sstevel@tonic-gate  *	then record the last partial byte
5620Sstevel@tonic-gate  */
5630Sstevel@tonic-gate 	if (bytesz != 7)
5640Sstevel@tonic-gate 	    (ap->ap_mapp)[maplen] = mask;
5650Sstevel@tonic-gate 
5660Sstevel@tonic-gate }
5670Sstevel@tonic-gate 
5680Sstevel@tonic-gate /*
5690Sstevel@tonic-gate  *	given a bad sector number, search in the alts bit map
5700Sstevel@tonic-gate  *	and identify the sector as good or bad
5710Sstevel@tonic-gate  */
572*362Sbg159949 static int
573*362Sbg159949 altsmap_getbit(daddr_t badsec)
5740Sstevel@tonic-gate {
5750Sstevel@tonic-gate 	int	slot = badsec / 8;
5760Sstevel@tonic-gate 	int	field = badsec % 8;
5770Sstevel@tonic-gate 	unchar	mask;
5780Sstevel@tonic-gate 
5790Sstevel@tonic-gate 	mask = ALTS_BAD<<7;
5800Sstevel@tonic-gate 	mask >>= field;
5810Sstevel@tonic-gate 	if ((ap->ap_mapp)[slot] & mask)
5820Sstevel@tonic-gate 	     return(ALTS_BAD);
5830Sstevel@tonic-gate 	return(ALTS_GOOD);
5840Sstevel@tonic-gate }
5850Sstevel@tonic-gate 
5860Sstevel@tonic-gate 
5870Sstevel@tonic-gate /*
5880Sstevel@tonic-gate  *	allocate a range of sectors from the alternate partition
5890Sstevel@tonic-gate  */
590*362Sbg159949 static int
591*362Sbg159949 altsmap_alloc(daddr_t srt_ind, daddr_t end_ind, int cnt, int dir)
5920Sstevel@tonic-gate {
5930Sstevel@tonic-gate 	int	i;
5940Sstevel@tonic-gate 	int	total;
5950Sstevel@tonic-gate 	int	first_ind;
5960Sstevel@tonic-gate 
5970Sstevel@tonic-gate 	for (i=srt_ind, first_ind=srt_ind, total=0; i!=end_ind; i+=dir) {
5980Sstevel@tonic-gate 	    if ((ap->ap_memmapp)[i] == ALTS_BAD) {
5990Sstevel@tonic-gate 		total = 0;
6000Sstevel@tonic-gate 		first_ind = i + dir;
6010Sstevel@tonic-gate 		continue;
6020Sstevel@tonic-gate 	    }
6030Sstevel@tonic-gate 	    total++;
6040Sstevel@tonic-gate 	    if (total == cnt)
6050Sstevel@tonic-gate 		return(first_ind);
6060Sstevel@tonic-gate 
6070Sstevel@tonic-gate 	}
608*362Sbg159949 	return(0);
6090Sstevel@tonic-gate }
6100Sstevel@tonic-gate 
6110Sstevel@tonic-gate 
6120Sstevel@tonic-gate 
6130Sstevel@tonic-gate /*
6140Sstevel@tonic-gate  * 	bubble sort the entry table into ascending order
6150Sstevel@tonic-gate  */
616*362Sbg159949 static void
617*362Sbg159949 ent_sort(struct alts_ent buf[], int cnt)
6180Sstevel@tonic-gate {
6190Sstevel@tonic-gate struct	alts_ent temp;
6200Sstevel@tonic-gate int	flag;
6210Sstevel@tonic-gate int	i,j;
6220Sstevel@tonic-gate 
6230Sstevel@tonic-gate 	for (i=0; i<cnt-1; i++) {
6240Sstevel@tonic-gate 	    temp = buf[cnt-1];
6250Sstevel@tonic-gate 	    flag = 1;
6260Sstevel@tonic-gate 
6270Sstevel@tonic-gate 	    for (j=cnt-1; j>i; j--) {
6280Sstevel@tonic-gate 		if (buf[j-1].bad_start < temp.bad_start) {
6290Sstevel@tonic-gate 		    buf[j] = temp;
6300Sstevel@tonic-gate 		    temp = buf[j-1];
6310Sstevel@tonic-gate 		} else {
6320Sstevel@tonic-gate 		    buf[j] = buf[j-1];
6330Sstevel@tonic-gate 		    flag = 0;
6340Sstevel@tonic-gate 		}
6350Sstevel@tonic-gate 	    }
6360Sstevel@tonic-gate 	    buf[i] = temp;
6370Sstevel@tonic-gate 	    if (flag) break;
6380Sstevel@tonic-gate 	}
6390Sstevel@tonic-gate 
6400Sstevel@tonic-gate }
6410Sstevel@tonic-gate 
6420Sstevel@tonic-gate 
6430Sstevel@tonic-gate /*
6440Sstevel@tonic-gate  *	compress all the contiguous bad sectors into a single entry
6450Sstevel@tonic-gate  *	in the entry table. The entry table must be sorted into ascending
6460Sstevel@tonic-gate  *	before the compression.
6470Sstevel@tonic-gate  */
648*362Sbg159949 static void
649*362Sbg159949 ent_compress(struct alts_ent buf[], int cnt)
6500Sstevel@tonic-gate {
6510Sstevel@tonic-gate int	keyp;
6520Sstevel@tonic-gate int	movp;
6530Sstevel@tonic-gate int	i;
6540Sstevel@tonic-gate 
6550Sstevel@tonic-gate 	for (i=0; i<cnt; i++) {
6560Sstevel@tonic-gate 	    if (buf[i].bad_start == ALTS_ENT_EMPTY)
6570Sstevel@tonic-gate 		continue;
6580Sstevel@tonic-gate 	    for (keyp=i, movp=i+1; movp<cnt; movp++) {
6590Sstevel@tonic-gate 	    	if (buf[movp].bad_start == ALTS_ENT_EMPTY)
6600Sstevel@tonic-gate 			continue;
6610Sstevel@tonic-gate 		if (buf[keyp].bad_end+1 != buf[movp].bad_start)
6620Sstevel@tonic-gate 		    break;
6630Sstevel@tonic-gate 		buf[keyp].bad_end++;
6640Sstevel@tonic-gate 		buf[movp].bad_start = ALTS_ENT_EMPTY;
6650Sstevel@tonic-gate 	    }
6660Sstevel@tonic-gate 	    if (movp == cnt) break;
6670Sstevel@tonic-gate 	}
6680Sstevel@tonic-gate }
6690Sstevel@tonic-gate 
6700Sstevel@tonic-gate 
6710Sstevel@tonic-gate /*
6720Sstevel@tonic-gate  *	merging two entry tables into a single table. In addition,
6730Sstevel@tonic-gate  *	all empty slots in the entry table will be removed.
6740Sstevel@tonic-gate  */
675*362Sbg159949 static int
676*362Sbg159949 ent_merge(
677*362Sbg159949 	struct alts_ent buf[],
678*362Sbg159949 	struct alts_ent list1[],
679*362Sbg159949 	int    lcnt1,
680*362Sbg159949 	struct alts_ent list2[],
681*362Sbg159949 	int    lcnt2)
6820Sstevel@tonic-gate {
6830Sstevel@tonic-gate 	int	i;
6840Sstevel@tonic-gate 	int	j1,j2;
6850Sstevel@tonic-gate 
6860Sstevel@tonic-gate 	for (i=0, j1=0, j2=0; j1<lcnt1 && j2<lcnt2;) {
6870Sstevel@tonic-gate 	    if (list1[j1].bad_start == ALTS_ENT_EMPTY) {
6880Sstevel@tonic-gate 		j1++;
6890Sstevel@tonic-gate 		continue;
6900Sstevel@tonic-gate 	    }
6910Sstevel@tonic-gate 	    if (list2[j2].bad_start == ALTS_ENT_EMPTY) {
6920Sstevel@tonic-gate 		j2++;
6930Sstevel@tonic-gate 		continue;
6940Sstevel@tonic-gate 	    }
6950Sstevel@tonic-gate 	    if (list1[j1].bad_start < list2[j2].bad_start)
6960Sstevel@tonic-gate 		buf[i++] = list1[j1++];
6970Sstevel@tonic-gate 	    else
6980Sstevel@tonic-gate 		buf[i++] = list2[j2++];
6990Sstevel@tonic-gate 	}
7000Sstevel@tonic-gate 	for (; j1<lcnt1; j1++) {
7010Sstevel@tonic-gate 	    if (list1[j1].bad_start == ALTS_ENT_EMPTY)
7020Sstevel@tonic-gate 		continue;
7030Sstevel@tonic-gate 	    buf[i++] = list1[j1];
7040Sstevel@tonic-gate 	}
7050Sstevel@tonic-gate 	for (; j2<lcnt2; j2++) {
7060Sstevel@tonic-gate 	    if (list2[j2].bad_start == ALTS_ENT_EMPTY)
7070Sstevel@tonic-gate 		continue;
7080Sstevel@tonic-gate 	    buf[i++] = list2[j2];
7090Sstevel@tonic-gate 	}
7100Sstevel@tonic-gate 	return (i);
7110Sstevel@tonic-gate }
7120Sstevel@tonic-gate 
7130Sstevel@tonic-gate 
7140Sstevel@tonic-gate /*
7150Sstevel@tonic-gate  *	binary search for bad sector in the alternate entry table
7160Sstevel@tonic-gate  */
717*362Sbg159949 static int
718*362Sbg159949 ent_bsearch(struct alts_ent buf[], int cnt, struct alts_ent *key)
7190Sstevel@tonic-gate {
7200Sstevel@tonic-gate 	int	i;
7210Sstevel@tonic-gate 	int	ind;
7220Sstevel@tonic-gate 	int	interval;
7230Sstevel@tonic-gate 	int	mystatus = -1;
7240Sstevel@tonic-gate 
7250Sstevel@tonic-gate 	if (!cnt) return (mystatus);
7260Sstevel@tonic-gate 
7270Sstevel@tonic-gate 	for (i=1; i<=cnt; i<<=1)
7280Sstevel@tonic-gate 	    ind=i;
7290Sstevel@tonic-gate 
7300Sstevel@tonic-gate 	for (interval=ind; interval; ) {
7310Sstevel@tonic-gate /*
7320Sstevel@tonic-gate 	    printf("ind= %d, intv= %d; ",ind, interval);
7330Sstevel@tonic-gate */
7340Sstevel@tonic-gate 	    if ((key->bad_start >= buf[ind-1].bad_start) &&
7350Sstevel@tonic-gate 		(key->bad_start <= buf[ind-1].bad_end)) {
7360Sstevel@tonic-gate 		return(mystatus=ind-1);
7370Sstevel@tonic-gate 	    } else {
7380Sstevel@tonic-gate 	    	interval >>= 1;
7390Sstevel@tonic-gate 		if (!interval) break;
7400Sstevel@tonic-gate 		if (key->bad_start < buf[ind-1].bad_start) {
7410Sstevel@tonic-gate 		    ind = ind - interval;
7420Sstevel@tonic-gate 		} else {
7430Sstevel@tonic-gate  /* 		    if key is larger than the last element then break	*/
7440Sstevel@tonic-gate 		    if (ind == cnt) break;
7450Sstevel@tonic-gate 		    if ((ind+interval) <= cnt)
7460Sstevel@tonic-gate 		    	ind += interval;
7470Sstevel@tonic-gate 		}
7480Sstevel@tonic-gate 	    }
7490Sstevel@tonic-gate 	}
7500Sstevel@tonic-gate 	return(mystatus);
7510Sstevel@tonic-gate }
7520Sstevel@tonic-gate 
7530Sstevel@tonic-gate /*
7540Sstevel@tonic-gate  *	check for bad sector in assigned alternate sectors
7550Sstevel@tonic-gate  */
756*362Sbg159949 static int
757*362Sbg159949 chk_bad_altsctr(daddr_t badsec)
7580Sstevel@tonic-gate {
7590Sstevel@tonic-gate 	int	i;
7600Sstevel@tonic-gate 	int	j;
7610Sstevel@tonic-gate 	daddr_t	numsec;
7620Sstevel@tonic-gate 	int	mystatus = FAILURE;
7630Sstevel@tonic-gate 	int	cnt = ap->ap_tblp->alts_ent_used;
7640Sstevel@tonic-gate 	daddr_t intv[3];
7650Sstevel@tonic-gate 
7660Sstevel@tonic-gate 	for (i=0; i<cnt; i++) {
7670Sstevel@tonic-gate 	    numsec = (ap->ap_entp)[i].bad_end - (ap->ap_entp)[i].bad_start;
7680Sstevel@tonic-gate 	    if ((badsec >= (ap->ap_entp)[i].good_start) &&
7690Sstevel@tonic-gate 		(badsec <= ((ap->ap_entp)[i].good_start + numsec))) {
7700Sstevel@tonic-gate 		fprintf(stderr, "Bad sector %ld is an assigned alternate sector.\n", badsec);
7710Sstevel@tonic-gate 		exit(66);
7720Sstevel@tonic-gate /*
7730Sstevel@tonic-gate 		if (!numsec) {
7740Sstevel@tonic-gate 		    (ap->ap_entp)[i].good_start = 0;
7750Sstevel@tonic-gate 		    return(mystatus);
7760Sstevel@tonic-gate 		}
7770Sstevel@tonic-gate 		intv[0] = badsec - (ap->ap_entp)[i].good_start;
7780Sstevel@tonic-gate 		intv[1] = 1;
7790Sstevel@tonic-gate 		intv[2] = (ap->ap_entp)[i].good_start + numsec - badsec;
7800Sstevel@tonic-gate */
7810Sstevel@tonic-gate 	    }
7820Sstevel@tonic-gate 	}
7830Sstevel@tonic-gate /*	the bad sector has already been identified as bad		*/
7840Sstevel@tonic-gate 	return(mystatus=SUCCESS);
7850Sstevel@tonic-gate 
7860Sstevel@tonic-gate }
7870Sstevel@tonic-gate 
7880Sstevel@tonic-gate 
7890Sstevel@tonic-gate /*
7900Sstevel@tonic-gate  * print_altsec () -- print alternate sector information
7910Sstevel@tonic-gate  */
792*362Sbg159949 int
793*362Sbg159949 print_altsec(struct partition *part)
7940Sstevel@tonic-gate {
7950Sstevel@tonic-gate 	ap->ap_tblp = NULL;
7960Sstevel@tonic-gate 	ap->ap_flag &= ~ALTS_ADDPART;
7970Sstevel@tonic-gate 	read_altsctr(part, 0);
7980Sstevel@tonic-gate 	print_altsctr();
7990Sstevel@tonic-gate 	return(SUCCESS);
8000Sstevel@tonic-gate }
8010Sstevel@tonic-gate 
802*362Sbg159949 static void
803*362Sbg159949 print_altsctr(void)
8040Sstevel@tonic-gate {
8050Sstevel@tonic-gate 	int	i;
8060Sstevel@tonic-gate 	int	totalloc;
8070Sstevel@tonic-gate 	int	avail;
8080Sstevel@tonic-gate 
8090Sstevel@tonic-gate /*	find # of available alternate sectors				*/
8100Sstevel@tonic-gate 	for (i=0, totalloc=0; i<ap->part.p_size; i++) {
8110Sstevel@tonic-gate 	    if ((ap->ap_memmapp)[i])
8120Sstevel@tonic-gate 		totalloc++;
8130Sstevel@tonic-gate 	}
8140Sstevel@tonic-gate /*
8150Sstevel@tonic-gate  *	available = size of partition - allocated sectors/bad sectors
8160Sstevel@tonic-gate  *		    - partition table - partition map
8170Sstevel@tonic-gate  *		    - entry table
8180Sstevel@tonic-gate  */
8190Sstevel@tonic-gate 	avail = ap->part.p_size - totalloc;
8200Sstevel@tonic-gate 	avail = avail - (ap->ap_tbl_secsiz/NBPSCTR)
8210Sstevel@tonic-gate 		- ap->ap_map_sectot;
8220Sstevel@tonic-gate 	avail = avail-(ap->ap_tblp->alts_ent_end -ap->ap_tblp->alts_ent_base+1);
8230Sstevel@tonic-gate 	if (avail < 0) avail = 0;
8240Sstevel@tonic-gate 
8250Sstevel@tonic-gate 	printf("\nALTERNATE SECTOR/TRACK MAPPING TABLE:\n");
8260Sstevel@tonic-gate 	printf("\nBad Sector Start\tAlternate Sector Start\t\tCount\n");
8270Sstevel@tonic-gate 
8280Sstevel@tonic-gate 	for (i=0; i<ap->ap_tblp->alts_ent_used; i++) {
8290Sstevel@tonic-gate 	     printf("\t%ld\t     ->\t\t%ld\t\t\t   %ld\n",
8300Sstevel@tonic-gate 		(ap->ap_entp)[i].bad_start,
8310Sstevel@tonic-gate 		(ap->ap_entp)[i].good_start,
8320Sstevel@tonic-gate 		((ap->ap_entp)[i].bad_end - (ap->ap_entp)[i].bad_start + 1));
8330Sstevel@tonic-gate 	}
8340Sstevel@tonic-gate 	printf("\n      %ld alternate sector(s) left for allocation.\n", avail);
8350Sstevel@tonic-gate 
8360Sstevel@tonic-gate }
8370Sstevel@tonic-gate 
838*362Sbg159949 static int
839*362Sbg159949 absdsk_io(int fd, uint srtsec, char *bufp, uint len, int ioflag)
8400Sstevel@tonic-gate {
8410Sstevel@tonic-gate 	int	rc;
8420Sstevel@tonic-gate 
8430Sstevel@tonic-gate 	if (lseek (fd, srtsec * NBPSCTR, SEEK_SET) == -1)
8440Sstevel@tonic-gate 		return(FAILURE);
8450Sstevel@tonic-gate 	switch (ioflag)
8460Sstevel@tonic-gate 	{
8470Sstevel@tonic-gate 	case CMD_READ:
8480Sstevel@tonic-gate 		rc = read (fd, bufp, len);
8490Sstevel@tonic-gate 		break;
8500Sstevel@tonic-gate 	case CMD_WRITE:
8510Sstevel@tonic-gate 		rc = write (fd, bufp, len);
8520Sstevel@tonic-gate 		break;
8530Sstevel@tonic-gate 	default:
8540Sstevel@tonic-gate 		break;
8550Sstevel@tonic-gate 	}
8560Sstevel@tonic-gate 	if (rc == -1)
8570Sstevel@tonic-gate 		return(FAILURE);
8580Sstevel@tonic-gate 	return(SUCCESS);
8590Sstevel@tonic-gate }
860