xref: /onnv-gate/usr/src/cmd/addbadsec/ix_altsctr.c (revision 7821:144c1a7abd32)
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
5*7821SMark.Logan@Sun.COM  * Common Development and Distribution License (the "License").
6*7821SMark.Logan@Sun.COM  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*7821SMark.Logan@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
24*7821SMark.Logan@Sun.COM  *
25*7821SMark.Logan@Sun.COM  * copyright (c) 1990, 1991 UNIX System Laboratories, Inc.
26*7821SMark.Logan@Sun.COM  * copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T
27*7821SMark.Logan@Sun.COM  * All rights reserved.
280Sstevel@tonic-gate  */
290Sstevel@tonic-gate 
300Sstevel@tonic-gate /*
310Sstevel@tonic-gate  * Copyrighted as an unpublished work.
320Sstevel@tonic-gate  * (c) Copyright INTERACTIVE Systems Corporation 1986, 1988, 1990
330Sstevel@tonic-gate  * All rights reserved.
340Sstevel@tonic-gate  */
350Sstevel@tonic-gate 
360Sstevel@tonic-gate #include <sys/types.h>
370Sstevel@tonic-gate #include <ctype.h>
380Sstevel@tonic-gate #include <fcntl.h>
390Sstevel@tonic-gate #include <malloc.h>
400Sstevel@tonic-gate #include <sys/stat.h>
410Sstevel@tonic-gate #include <sys/swap.h>
420Sstevel@tonic-gate #include <stdio.h>
43*7821SMark.Logan@Sun.COM #include <stdlib.h>
44*7821SMark.Logan@Sun.COM #include <unistd.h>
450Sstevel@tonic-gate #include <string.h>
460Sstevel@tonic-gate #include <sys/vtoc.h>
470Sstevel@tonic-gate #include <sys/param.h>
480Sstevel@tonic-gate #include <sys/dkio.h>
490Sstevel@tonic-gate #include <sys/dktp/altsctr.h>
500Sstevel@tonic-gate #include <sys/dktp/fdisk.h>
510Sstevel@tonic-gate #include "badsec.h"
520Sstevel@tonic-gate 
53*7821SMark.Logan@Sun.COM #define	FAILURE	0
540Sstevel@tonic-gate #define	SUCCESS	1
550Sstevel@tonic-gate 
56*7821SMark.Logan@Sun.COM #define	CMD_READ	0
57*7821SMark.Logan@Sun.COM #define	CMD_WRITE	1
580Sstevel@tonic-gate 
590Sstevel@tonic-gate struct	badsec_lst *badsl_chain;
600Sstevel@tonic-gate int	badsl_chain_cnt;
610Sstevel@tonic-gate struct	badsec_lst *gbadsl_chain;
620Sstevel@tonic-gate int	gbadsl_chain_cnt;
630Sstevel@tonic-gate 
64*7821SMark.Logan@Sun.COM extern struct dk_geom	dkg;
650Sstevel@tonic-gate extern int	alts_fd;
660Sstevel@tonic-gate 
670Sstevel@tonic-gate struct	alts_mempart alts_part = { 0, NULL, 0 };
68*7821SMark.Logan@Sun.COM struct	alts_mempart *ap = &alts_part;	/* pointer to incore alts tables */
690Sstevel@tonic-gate 
70*7821SMark.Logan@Sun.COM static void read_altsctr(struct extpartition *part, int badok);
71*7821SMark.Logan@Sun.COM static void chk_badsec(void);
72*7821SMark.Logan@Sun.COM static void init_altsctr(void);
73*7821SMark.Logan@Sun.COM void wr_altsctr(void);
74*7821SMark.Logan@Sun.COM static void get_badsec(void);
75*7821SMark.Logan@Sun.COM static int count_badsec(void);
76*7821SMark.Logan@Sun.COM static void gen_alts_ent(void);
77362Sbg159949 static void assign_altsctr(void);
78*7821SMark.Logan@Sun.COM static void expand_map(void);
79*7821SMark.Logan@Sun.COM static void compress_map(void);
80*7821SMark.Logan@Sun.COM static int altsmap_getbit(blkaddr_t badsec);
81*7821SMark.Logan@Sun.COM static blkaddr_t altsmap_alloc(blkaddr_t srt_ind, blkaddr_t end_ind,
82*7821SMark.Logan@Sun.COM 	int cnt, int dir);
83362Sbg159949 static void ent_sort(struct alts_ent buf[], int cnt);
84362Sbg159949 static void ent_compress(struct alts_ent buf[], int cnt);
85362Sbg159949 static int  ent_merge(
86362Sbg159949 	struct alts_ent buf[],
87362Sbg159949 	struct alts_ent list1[],
88362Sbg159949 	int    lcnt1,
89362Sbg159949 	struct alts_ent list2[],
90362Sbg159949 	int    lcnt2);
91362Sbg159949 static int  ent_bsearch(struct alts_ent buf[], int cnt, struct alts_ent *key);
92*7821SMark.Logan@Sun.COM static int  chk_bad_altsctr(blkaddr_t badsec);
93*7821SMark.Logan@Sun.COM int	print_altsec(struct extpartition *part);
94*7821SMark.Logan@Sun.COM int	get_altsctr(int);
95362Sbg159949 static void print_altsctr(void);
96*7821SMark.Logan@Sun.COM static int  absdsk_io(int fd, uint_t srtsec, char *bufp, uint_t len,
97*7821SMark.Logan@Sun.COM 	int ioflag);
98362Sbg159949 
990Sstevel@tonic-gate /*
1000Sstevel@tonic-gate  * updatebadsec () -- update bad sector/track mapping tables
1010Sstevel@tonic-gate  */
102362Sbg159949 int
updatebadsec(struct extpartition * part,int init_flag)103*7821SMark.Logan@Sun.COM updatebadsec(struct extpartition *part, int init_flag)
1040Sstevel@tonic-gate {
1050Sstevel@tonic-gate 	if (init_flag)
1060Sstevel@tonic-gate 		ap->ap_flag |= ALTS_ADDPART;
1070Sstevel@tonic-gate 	get_badsec();
1080Sstevel@tonic-gate 	read_altsctr(part, 1);
1090Sstevel@tonic-gate 	ent_sort(ap->ap_gbadp, ap->ap_gbadcnt);
1100Sstevel@tonic-gate 	ent_compress(ap->ap_gbadp, ap->ap_gbadcnt);
1110Sstevel@tonic-gate 	gen_alts_ent();
1120Sstevel@tonic-gate 	compress_map();
113*7821SMark.Logan@Sun.COM 	return (SUCCESS);
1140Sstevel@tonic-gate }
1150Sstevel@tonic-gate 
1160Sstevel@tonic-gate /*
1170Sstevel@tonic-gate  * read_altsctr( ptr to alternate sector partition )
1180Sstevel@tonic-gate  *		-- read the alternate sector partition tables
1190Sstevel@tonic-gate  */
120362Sbg159949 static void
read_altsctr(struct extpartition * part,int badok)121*7821SMark.Logan@Sun.COM read_altsctr(struct extpartition *part, int badok)
1220Sstevel@tonic-gate {
1230Sstevel@tonic-gate 	if (ap->ap_tblp == NULL) {
1240Sstevel@tonic-gate /*	    allocate buffer for the alts partition table (sector size)	*/
125*7821SMark.Logan@Sun.COM 	    ap->ap_tbl_secsiz = byte_to_secsiz(ALTS_PARTTBL_SIZE, NBPSCTR);
1260Sstevel@tonic-gate 	    ap->ap_tblp = (struct alts_parttbl *)malloc(ap->ap_tbl_secsiz);
1270Sstevel@tonic-gate 	    if (ap->ap_tblp == NULL) {
128*7821SMark.Logan@Sun.COM 		(void) fprintf(stderr,
129*7821SMark.Logan@Sun.COM 			"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 
137*7821SMark.Logan@Sun.COM 	    if ((ap->ap_memmapp = (uchar_t *)malloc(part->p_size)) == NULL) {
138*7821SMark.Logan@Sun.COM 		(void) fprintf(stderr,
139*7821SMark.Logan@Sun.COM 			"Unable to malloc incore alternate partition map.\n");
1400Sstevel@tonic-gate 		exit(51);
1410Sstevel@tonic-gate 	    }
1420Sstevel@tonic-gate 	    ap->ap_tblp->alts_map_len = (part->p_size + 8 - 1) / 8;
143*7821SMark.Logan@Sun.COM 	    ap->ap_map_secsiz = byte_to_secsiz(ap->ap_tblp->alts_map_len,
144*7821SMark.Logan@Sun.COM 		NBPSCTR);
1450Sstevel@tonic-gate 	    ap->ap_map_sectot = ap->ap_map_secsiz / NBPSCTR;
146*7821SMark.Logan@Sun.COM 	    if ((ap->ap_mapp = (uchar_t *)malloc(ap->ap_map_secsiz)) == NULL) {
147*7821SMark.Logan@Sun.COM 		(void) fprintf(stderr,
148*7821SMark.Logan@Sun.COM 		    "Unable to malloc alternate partition map.\n");
1490Sstevel@tonic-gate 		exit(52);
1500Sstevel@tonic-gate 	    }
1510Sstevel@tonic-gate /*	    clear the buffers to zero					*/
152*7821SMark.Logan@Sun.COM 	    (void) memset(ap->ap_memmapp, 0, part->p_size);
153*7821SMark.Logan@Sun.COM 	    (void) memset(ap->ap_mapp, 0, ap->ap_map_secsiz);
1540Sstevel@tonic-gate 	    ap->part = *part;		/* struct copy			*/
155*7821SMark.Logan@Sun.COM 
1560Sstevel@tonic-gate /*
1570Sstevel@tonic-gate  *	    if add alternate partition flag is set, then install the partition
1580Sstevel@tonic-gate  *	    otherwise read the alts partition info from disk
159*7821SMark.Logan@Sun.COM  *	    if failed, then assume the first installation
1600Sstevel@tonic-gate  */
161*7821SMark.Logan@Sun.COM 	    if (ap->ap_flag & ALTS_ADDPART) {
162*7821SMark.Logan@Sun.COM 		(void) fprintf(stderr,
163*7821SMark.Logan@Sun.COM 		    "WARNING: Manually initializing alternate table.\n");
1640Sstevel@tonic-gate 		init_altsctr();
165*7821SMark.Logan@Sun.COM 	    } else {
1660Sstevel@tonic-gate 	    	if (get_altsctr(badok) == SUCCESS)
167*7821SMark.Logan@Sun.COM 		    chk_badsec();
1680Sstevel@tonic-gate 	    	else
1690Sstevel@tonic-gate 		    init_altsctr();
1700Sstevel@tonic-gate 	    }
1710Sstevel@tonic-gate 	}
1720Sstevel@tonic-gate }
1730Sstevel@tonic-gate 
1740Sstevel@tonic-gate 
1750Sstevel@tonic-gate /*
1760Sstevel@tonic-gate  *	checking duplicate bad sectors or bad sectors in ALTSCTR partition
1770Sstevel@tonic-gate  */
178362Sbg159949 static void
chk_badsec(void)179362Sbg159949 chk_badsec(void)
1800Sstevel@tonic-gate {
181*7821SMark.Logan@Sun.COM 	blkaddr_t	badsec;
182*7821SMark.Logan@Sun.COM 	blkaddr_t	altsp_srtsec = ap->part.p_start;
183*7821SMark.Logan@Sun.COM 	blkaddr_t	altsp_endsec = ap->part.p_start + ap->part.p_size - 1;
1840Sstevel@tonic-gate 	int	cnt;
1850Sstevel@tonic-gate 	int	status;
1860Sstevel@tonic-gate 
187*7821SMark.Logan@Sun.COM 	for (cnt = 0; cnt < ap->ap_gbadcnt; cnt++) {
1880Sstevel@tonic-gate 	    badsec = (ap->ap_gbadp)[cnt].bad_start;
189*7821SMark.Logan@Sun.COM 
190*7821SMark.Logan@Sun.COM 	    /* if bad sector is within the ATLSCTR partition */
1910Sstevel@tonic-gate 	    if ((badsec >= altsp_srtsec) && (badsec <= altsp_endsec)) {
1920Sstevel@tonic-gate 		if ((ap->ap_memmapp)[badsec - altsp_srtsec] != ALTS_BAD) {
1930Sstevel@tonic-gate 		    if ((badsec >= altsp_srtsec) && (badsec <= (altsp_srtsec +
1940Sstevel@tonic-gate 			ap->ap_tbl_secsiz / NBPSCTR - 1))) {
195*7821SMark.Logan@Sun.COM 		    	(void) fprintf(stderr,
196*7821SMark.Logan@Sun.COM 			    "Alternate partition information table is bad.\n");
1970Sstevel@tonic-gate 		    	exit(53);
1980Sstevel@tonic-gate 	    	    }
199*7821SMark.Logan@Sun.COM 		    if ((badsec >= altsp_srtsec+ap->ap_tblp->alts_map_base) &&
2000Sstevel@tonic-gate 			(badsec <= (altsp_srtsec + ap->ap_tblp->alts_map_base +
2010Sstevel@tonic-gate 			ap->ap_map_sectot - 1))) {
202*7821SMark.Logan@Sun.COM 		    	(void) fprintf(stderr,
203*7821SMark.Logan@Sun.COM 			    "Alternate partition map is bad.\n");
2040Sstevel@tonic-gate 		    	exit(54);
2050Sstevel@tonic-gate 	    	    }
206*7821SMark.Logan@Sun.COM 		    if ((badsec >= altsp_srtsec+ap->ap_tblp->alts_ent_base) &&
2070Sstevel@tonic-gate 			(badsec <= (altsp_srtsec + ap->ap_tblp->alts_ent_base +
2080Sstevel@tonic-gate 			ap->ap_ent_secsiz / NBPSCTR - 1))) {
209*7821SMark.Logan@Sun.COM 		    	(void) fprintf(stderr,
210*7821SMark.Logan@Sun.COM 			    "Alternate partition entry table is bad.\n");
2110Sstevel@tonic-gate 		    	exit(55);
2120Sstevel@tonic-gate 	    	    }
2130Sstevel@tonic-gate 		    (ap->ap_memmapp)[badsec - altsp_srtsec] = ALTS_BAD;
214*7821SMark.Logan@Sun.COM 		    (ap->ap_gbadp)[cnt].bad_start = (uint32_t)ALTS_ENT_EMPTY;
2150Sstevel@tonic-gate 		} else {
2160Sstevel@tonic-gate 		    status = chk_bad_altsctr(badsec);
217*7821SMark.Logan@Sun.COM 		    (ap->ap_gbadp)[cnt].bad_start = (uint32_t)ALTS_ENT_EMPTY;
2180Sstevel@tonic-gate 		}
2190Sstevel@tonic-gate 	    } else {
2200Sstevel@tonic-gate /*
2210Sstevel@tonic-gate  *		binary search for bad sector in the alts entry table
2220Sstevel@tonic-gate  */
2230Sstevel@tonic-gate 		status = ent_bsearch(ap->ap_entp, ap->ap_tblp->alts_ent_used,
224*7821SMark.Logan@Sun.COM 					&((ap->ap_gbadp)[cnt]));
2250Sstevel@tonic-gate /*
2260Sstevel@tonic-gate  *		if the bad sector had already been remapped(found in alts_entry)
2270Sstevel@tonic-gate  *		then ignore the bad sector
2280Sstevel@tonic-gate  */
2290Sstevel@tonic-gate 		if (status != -1) {
230*7821SMark.Logan@Sun.COM 		    (ap->ap_gbadp)[cnt].bad_start = (uint32_t)ALTS_ENT_EMPTY;
2310Sstevel@tonic-gate 		}
2320Sstevel@tonic-gate 	    }
2330Sstevel@tonic-gate 	}
2340Sstevel@tonic-gate 
2350Sstevel@tonic-gate }
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate /*
2380Sstevel@tonic-gate  *	initialize the alternate partition tables
2390Sstevel@tonic-gate  */
240362Sbg159949 static void
init_altsctr(void)241362Sbg159949 init_altsctr(void)
2420Sstevel@tonic-gate {
243*7821SMark.Logan@Sun.COM 	blkaddr_t	badsec;
244*7821SMark.Logan@Sun.COM 	blkaddr_t	altsp_srtsec = ap->part.p_start;
245*7821SMark.Logan@Sun.COM 	blkaddr_t	altsp_endsec = ap->part.p_start + ap->part.p_size - 1;
2460Sstevel@tonic-gate 	int	cnt;
2470Sstevel@tonic-gate 
2480Sstevel@tonic-gate 	ap->ap_entp = NULL;
2490Sstevel@tonic-gate 	ap->ap_ent_secsiz = 0;
2500Sstevel@tonic-gate 	ap->ap_tblp->alts_sanity = ALTS_SANITY;
251*7821SMark.Logan@Sun.COM 	ap->ap_tblp->alts_version = ALTS_VERSION1;
2520Sstevel@tonic-gate 	ap->ap_tblp->alts_map_len = (ap->part.p_size + 8 - 1) / 8;
2530Sstevel@tonic-gate 	ap->ap_tblp->alts_ent_used = 0;
2540Sstevel@tonic-gate 	ap->ap_tblp->alts_ent_base = 0;
2550Sstevel@tonic-gate 	ap->ap_tblp->alts_ent_end  = 0;
2560Sstevel@tonic-gate 	ap->ap_tblp->alts_resv_base = ap->part.p_size - 1;
257*7821SMark.Logan@Sun.COM 	for (cnt = 0; cnt < 5; cnt++)
258*7821SMark.Logan@Sun.COM 	    ap->ap_tblp->alts_pad[cnt] = 0;
2590Sstevel@tonic-gate 
260*7821SMark.Logan@Sun.COM 	for (cnt = 0; cnt < ap->ap_gbadcnt; cnt++) {
2610Sstevel@tonic-gate 	    badsec = (ap->ap_gbadp)[cnt].bad_start;
2620Sstevel@tonic-gate 	    if ((badsec >= altsp_srtsec) && (badsec <= altsp_endsec)) {
2630Sstevel@tonic-gate 		if (badsec == altsp_srtsec) {
264*7821SMark.Logan@Sun.COM 		    (void) fprintf(stderr,
265*7821SMark.Logan@Sun.COM 			"First sector of alternate partition is bad.\n");
2660Sstevel@tonic-gate 		    exit(56);
2670Sstevel@tonic-gate 	    	}
2680Sstevel@tonic-gate 		(ap->ap_memmapp)[badsec - altsp_srtsec] = ALTS_BAD;
269*7821SMark.Logan@Sun.COM 		(ap->ap_gbadp)[cnt].bad_start = (uint32_t)ALTS_ENT_EMPTY;
2700Sstevel@tonic-gate 	    }
2710Sstevel@tonic-gate 	}
272*7821SMark.Logan@Sun.COM 
2730Sstevel@tonic-gate /*	allocate the alts_map on disk skipping possible bad sectors	*/
274*7821SMark.Logan@Sun.COM 	ap->ap_tblp->alts_map_base =
275*7821SMark.Logan@Sun.COM 		altsmap_alloc(ap->ap_tbl_secsiz / NBPSCTR,
2760Sstevel@tonic-gate 			ap->part.p_size, ap->ap_map_sectot, ALTS_MAP_UP);
2770Sstevel@tonic-gate 	if (ap->ap_tblp->alts_map_base == NULL) {
2780Sstevel@tonic-gate 	    perror("Unable to allocate alternate map on disk: ");
2790Sstevel@tonic-gate 	    exit(57);
2800Sstevel@tonic-gate 	}
2810Sstevel@tonic-gate 
2820Sstevel@tonic-gate }
2830Sstevel@tonic-gate 
2840Sstevel@tonic-gate 
2850Sstevel@tonic-gate /*
2860Sstevel@tonic-gate  * 	read the alternate partition tables from disk
2870Sstevel@tonic-gate  */
2880Sstevel@tonic-gate int
get_altsctr(badok)2890Sstevel@tonic-gate get_altsctr(badok)
2900Sstevel@tonic-gate int badok;
2910Sstevel@tonic-gate {
2920Sstevel@tonic-gate /*	get alts partition table info					*/
293*7821SMark.Logan@Sun.COM 	if (absdsk_io(alts_fd, 0, (char *)ap->ap_tblp,
294*7821SMark.Logan@Sun.COM 			ap->ap_tbl_secsiz, CMD_READ) == FAILURE) {
2950Sstevel@tonic-gate 	    if (badok)
2960Sstevel@tonic-gate 		return(FAILURE);
2970Sstevel@tonic-gate 	    perror("Unable to read alternate sector partition: ");
2980Sstevel@tonic-gate 	    exit(58);
2990Sstevel@tonic-gate 	}
3000Sstevel@tonic-gate 	if (ap->ap_tblp->alts_sanity != ALTS_SANITY) {
3010Sstevel@tonic-gate 	    if (badok)
3020Sstevel@tonic-gate 		return(FAILURE);
303*7821SMark.Logan@Sun.COM 	    (void) fprintf(stderr, "Bad alternate sector magic number.\n");
3040Sstevel@tonic-gate 	    exit(69);
3050Sstevel@tonic-gate 	}
3060Sstevel@tonic-gate 
3070Sstevel@tonic-gate /*	get the alts map						*/
3080Sstevel@tonic-gate 	if (absdsk_io(alts_fd, ap->ap_tblp->alts_map_base,
3090Sstevel@tonic-gate 		(char *)ap->ap_mapp, ap->ap_map_secsiz, CMD_READ) == FAILURE) {
3100Sstevel@tonic-gate 	    if (badok)
3110Sstevel@tonic-gate 		return(FAILURE);
3120Sstevel@tonic-gate 	    perror("Unable to read alternate sector partition map: ");
3130Sstevel@tonic-gate 	    exit(59);
3140Sstevel@tonic-gate 	}
3150Sstevel@tonic-gate 
3160Sstevel@tonic-gate /*	transform the disk image bit-map to incore char map		*/
3170Sstevel@tonic-gate 	expand_map();
3180Sstevel@tonic-gate 
3190Sstevel@tonic-gate 	if (ap->ap_tblp->alts_ent_used == 0) {
3200Sstevel@tonic-gate 	    ap->ap_entp = NULL;
3210Sstevel@tonic-gate 	    ap->ap_ent_secsiz = 0;
3220Sstevel@tonic-gate 	} else {
3230Sstevel@tonic-gate 	    ap->ap_ent_secsiz = byte_to_secsiz(
3240Sstevel@tonic-gate 			(ap->ap_tblp->alts_ent_used*ALTS_ENT_SIZE),NBPSCTR);
325*7821SMark.Logan@Sun.COM 	    if ((ap->ap_entp =
326*7821SMark.Logan@Sun.COM 		(struct alts_ent *)malloc(ap->ap_ent_secsiz)) == NULL) {
3270Sstevel@tonic-gate 		if (badok)
3280Sstevel@tonic-gate 		    return(FAILURE);
329*7821SMark.Logan@Sun.COM 		(void) fprintf(stderr,
330*7821SMark.Logan@Sun.COM 		    "Unable to malloc alternate sector entry table.\n");
3310Sstevel@tonic-gate 		exit(60);
3320Sstevel@tonic-gate 	    }
3330Sstevel@tonic-gate 
3340Sstevel@tonic-gate 	    if (absdsk_io(alts_fd, ap->ap_tblp->alts_ent_base,
335*7821SMark.Logan@Sun.COM 	    	(char *)ap->ap_entp, ap->ap_ent_secsiz,
336*7821SMark.Logan@Sun.COM 		CMD_READ) ==FAILURE){
3370Sstevel@tonic-gate 		if (badok)
3380Sstevel@tonic-gate 		    return(FAILURE);
3390Sstevel@tonic-gate 		perror("Unable to read alternate sector entry table: ");
3400Sstevel@tonic-gate 		exit(61);
3410Sstevel@tonic-gate 	    }
3420Sstevel@tonic-gate 	}
3430Sstevel@tonic-gate 	return(SUCCESS);
3440Sstevel@tonic-gate }
3450Sstevel@tonic-gate 
3460Sstevel@tonic-gate 
3470Sstevel@tonic-gate /*
3480Sstevel@tonic-gate  *	update the new alternate partition tables on disk
3490Sstevel@tonic-gate  */
350362Sbg159949 void
wr_altsctr(void)351362Sbg159949 wr_altsctr(void)
3520Sstevel@tonic-gate {
3530Sstevel@tonic-gate 	if (ap->ap_tblp == NULL)
3540Sstevel@tonic-gate 		return;
355362Sbg159949 	if (absdsk_io(alts_fd, 0, (char *)ap->ap_tblp,
3560Sstevel@tonic-gate 		ap->ap_tbl_secsiz, CMD_WRITE) == FAILURE) {
3570Sstevel@tonic-gate 	    perror("Unable to write alternate sector partition: ");
3580Sstevel@tonic-gate 	    exit(62);
3590Sstevel@tonic-gate 	}
3600Sstevel@tonic-gate 
3610Sstevel@tonic-gate 	if (absdsk_io(alts_fd, ap->ap_tblp->alts_map_base,
362362Sbg159949 		(char *)ap->ap_mapp, ap->ap_map_secsiz, CMD_WRITE) == FAILURE) {
3630Sstevel@tonic-gate 	    perror("Unable to write alternate sector partition map: ");
3640Sstevel@tonic-gate 	    exit(63);
3650Sstevel@tonic-gate 	}
3660Sstevel@tonic-gate 
3670Sstevel@tonic-gate 	if (ap->ap_tblp->alts_ent_used != 0) {
3680Sstevel@tonic-gate 	    if (absdsk_io(alts_fd, ap->ap_tblp->alts_ent_base,
3690Sstevel@tonic-gate 	    			(char *)ap->ap_entp, ap->ap_ent_secsiz,
3700Sstevel@tonic-gate 				CMD_WRITE) == FAILURE) {
3710Sstevel@tonic-gate 		perror("Unable to write alternate sector entry table: ");
3720Sstevel@tonic-gate 		exit(64);
3730Sstevel@tonic-gate 	    }
3740Sstevel@tonic-gate 	}
3750Sstevel@tonic-gate }
3760Sstevel@tonic-gate 
3770Sstevel@tonic-gate 
3780Sstevel@tonic-gate /*
3790Sstevel@tonic-gate  *	get a list of bad sector
3800Sstevel@tonic-gate  */
381362Sbg159949 static void
get_badsec(void)382362Sbg159949 get_badsec(void)
3830Sstevel@tonic-gate {
3840Sstevel@tonic-gate 	int	cnt;
3850Sstevel@tonic-gate 	struct	badsec_lst *blc_p;
386*7821SMark.Logan@Sun.COM 	blkaddr_t	curbad;
387*7821SMark.Logan@Sun.COM 	blkaddr_t	maxsec = (blkaddr_t)dkg.dkg_nhead *
388*7821SMark.Logan@Sun.COM 					dkg.dkg_ncyl * dkg.dkg_nsect;
3890Sstevel@tonic-gate 	struct	alts_ent *growbadp;
3900Sstevel@tonic-gate 	int	i;
3910Sstevel@tonic-gate 
3920Sstevel@tonic-gate 	cnt = count_badsec();
3930Sstevel@tonic-gate 	if (!cnt) {
3940Sstevel@tonic-gate 	    ap->ap_gbadp = NULL;
3950Sstevel@tonic-gate 	    ap->ap_gbadcnt = 0;
396*7821SMark.Logan@Sun.COM 	} else {
397*7821SMark.Logan@Sun.COM 	    ap->ap_gbadp = (struct alts_ent *)malloc(cnt*ALTS_ENT_SIZE);
398*7821SMark.Logan@Sun.COM 	    (void) memset(ap->ap_gbadp,0,cnt*ALTS_ENT_SIZE);
3990Sstevel@tonic-gate 
400*7821SMark.Logan@Sun.COM 	    for (growbadp = ap->ap_gbadp, cnt=0, blc_p=badsl_chain;
4010Sstevel@tonic-gate 		blc_p; blc_p=blc_p->bl_nxt) {
4020Sstevel@tonic-gate 		for (i=0; i<blc_p->bl_cnt; i++) {
4030Sstevel@tonic-gate 		    curbad = blc_p->bl_sec[i];
404*7821SMark.Logan@Sun.COM 		    if (curbad < (blkaddr_t)dkg.dkg_nsect) {
405*7821SMark.Logan@Sun.COM 		    	(void) fprintf(stderr,
406*7821SMark.Logan@Sun.COM 			    "Ignoring bad sector %ld which is in first"
407*7821SMark.Logan@Sun.COM 			    " track of the drive.\n", curbad);
4080Sstevel@tonic-gate 		    	continue;
4090Sstevel@tonic-gate 		    }
4100Sstevel@tonic-gate 		    if (curbad >= maxsec) {
411*7821SMark.Logan@Sun.COM 		    	(void) fprintf(stderr,
412*7821SMark.Logan@Sun.COM 			    "Ignoring bad sector %ld which is past"
413*7821SMark.Logan@Sun.COM 			    " the end of the drive.\n", curbad);
4140Sstevel@tonic-gate 		    	continue;
4150Sstevel@tonic-gate 		    }
4160Sstevel@tonic-gate 		    growbadp[cnt].bad_start = curbad;
4170Sstevel@tonic-gate 		    growbadp[cnt].bad_end = curbad;
4180Sstevel@tonic-gate 		    cnt++;
4190Sstevel@tonic-gate 		}
4200Sstevel@tonic-gate 	    }
4210Sstevel@tonic-gate 	}
4220Sstevel@tonic-gate 	ap->ap_gbadcnt = cnt;
4230Sstevel@tonic-gate }
4240Sstevel@tonic-gate 
4250Sstevel@tonic-gate /*
4260Sstevel@tonic-gate  *	count number of bad sector on list
4270Sstevel@tonic-gate  *	merging the bad sector list from surface analysis and the
4280Sstevel@tonic-gate  *	one given through the command line
4290Sstevel@tonic-gate  */
430362Sbg159949 static int
count_badsec(void)431362Sbg159949 count_badsec(void)
4320Sstevel@tonic-gate {
4330Sstevel@tonic-gate 
4340Sstevel@tonic-gate 	struct badsec_lst *blc_p;
4350Sstevel@tonic-gate 
4360Sstevel@tonic-gate 	if (!badsl_chain)
4370Sstevel@tonic-gate 		badsl_chain = gbadsl_chain;
4380Sstevel@tonic-gate 	else {
439*7821SMark.Logan@Sun.COM 		for (blc_p = badsl_chain; blc_p->bl_nxt; blc_p = blc_p->bl_nxt)
4400Sstevel@tonic-gate 			;
4410Sstevel@tonic-gate 		blc_p->bl_nxt = gbadsl_chain;
4420Sstevel@tonic-gate 	}
4430Sstevel@tonic-gate 
4440Sstevel@tonic-gate 	badsl_chain_cnt += gbadsl_chain_cnt;
4450Sstevel@tonic-gate 	return(badsl_chain_cnt);
4460Sstevel@tonic-gate }
4470Sstevel@tonic-gate 
4480Sstevel@tonic-gate 
4490Sstevel@tonic-gate /*
4500Sstevel@tonic-gate  *	generate alternate entry table by merging the existing and
4510Sstevel@tonic-gate  *	the new entry list.
4520Sstevel@tonic-gate  */
453362Sbg159949 static void
gen_alts_ent(void)454362Sbg159949 gen_alts_ent(void)
455362Sbg159949 {
456*7821SMark.Logan@Sun.COM 	uint_t	ent_used;
4570Sstevel@tonic-gate 	struct	alts_ent *entp;
4580Sstevel@tonic-gate 
4590Sstevel@tonic-gate 	if (ap->ap_gbadcnt == 0)
4600Sstevel@tonic-gate 	    return;
4610Sstevel@tonic-gate 
4620Sstevel@tonic-gate 	ent_used = ap->ap_tblp->alts_ent_used + ap->ap_gbadcnt;
4630Sstevel@tonic-gate 	ap->ap_ent_secsiz = byte_to_secsiz(ent_used*ALTS_ENT_SIZE,NBPSCTR);
4640Sstevel@tonic-gate 	entp=(struct alts_ent *) malloc (ap->ap_ent_secsiz);
4650Sstevel@tonic-gate 	ent_used = ent_merge(entp, ap->ap_entp, ap->ap_tblp->alts_ent_used,
4660Sstevel@tonic-gate 			     ap->ap_gbadp, ap->ap_gbadcnt);
467*7821SMark.Logan@Sun.COM 	if (ap->ap_entp)
4680Sstevel@tonic-gate 	    free(ap->ap_entp);
469*7821SMark.Logan@Sun.COM 	if (ap->ap_gbadp)
4700Sstevel@tonic-gate 	    free(ap->ap_gbadp);
4710Sstevel@tonic-gate 	ap->ap_entp = entp;
472*7821SMark.Logan@Sun.COM 	ap->ap_ent_secsiz = byte_to_secsiz(ent_used*ALTS_ENT_SIZE, NBPSCTR);
4730Sstevel@tonic-gate 	ap->ap_tblp->alts_ent_used = ent_used;
4740Sstevel@tonic-gate 	ap->ap_gbadp = NULL;
4750Sstevel@tonic-gate 	ap->ap_gbadcnt = 0;
4760Sstevel@tonic-gate 
4770Sstevel@tonic-gate /*	assign alternate sectors to the bad sectors			*/
4780Sstevel@tonic-gate 	assign_altsctr();
4790Sstevel@tonic-gate 
4800Sstevel@tonic-gate /*	allocate the alts_entry on disk skipping possible bad sectors	*/
481*7821SMark.Logan@Sun.COM 	ap->ap_tblp->alts_ent_base =
4820Sstevel@tonic-gate 		altsmap_alloc(ap->ap_tblp->alts_map_base + ap->ap_map_sectot,
483*7821SMark.Logan@Sun.COM 			ap->part.p_size,
4840Sstevel@tonic-gate 			ap->ap_ent_secsiz / NBPSCTR, ALTS_MAP_UP);
4850Sstevel@tonic-gate 	if (ap->ap_tblp->alts_ent_base == NULL) {
4860Sstevel@tonic-gate 	    perror("Unable to allocate alternate entry table on disk: ");
4870Sstevel@tonic-gate 	    exit(65);
4880Sstevel@tonic-gate 	}
4890Sstevel@tonic-gate 
490*7821SMark.Logan@Sun.COM 	ap->ap_tblp->alts_ent_end = ap->ap_tblp->alts_ent_base +
491*7821SMark.Logan@Sun.COM 			(ap->ap_ent_secsiz / NBPSCTR) - 1;
4920Sstevel@tonic-gate }
4930Sstevel@tonic-gate 
4940Sstevel@tonic-gate 
4950Sstevel@tonic-gate /*
4960Sstevel@tonic-gate  *	assign alternate sectors for bad sector mapping
4970Sstevel@tonic-gate  */
498362Sbg159949 static void
assign_altsctr(void)499362Sbg159949 assign_altsctr(void)
5000Sstevel@tonic-gate {
501*7821SMark.Logan@Sun.COM 	uint_t	i;
502*7821SMark.Logan@Sun.COM 	uint_t	j;
503*7821SMark.Logan@Sun.COM 	blkaddr_t	alts_ind;
504*7821SMark.Logan@Sun.COM 	uint_t	cluster;
5050Sstevel@tonic-gate 
506*7821SMark.Logan@Sun.COM 	for (i = 0; i < ap->ap_tblp->alts_ent_used; i++) {
507*7821SMark.Logan@Sun.COM 	    if ((ap->ap_entp)[i].bad_start == (uint32_t)ALTS_ENT_EMPTY)
5080Sstevel@tonic-gate 		continue;
5090Sstevel@tonic-gate 	    if ((ap->ap_entp)[i].good_start != 0)
5100Sstevel@tonic-gate 		continue;
511*7821SMark.Logan@Sun.COM 	    cluster = (ap->ap_entp)[i].bad_end-(ap->ap_entp)[i].bad_start +1;
512*7821SMark.Logan@Sun.COM 	    alts_ind =
513*7821SMark.Logan@Sun.COM 		altsmap_alloc(ap->part.p_size-1, ap->ap_tblp->alts_map_base +
5140Sstevel@tonic-gate 			ap->ap_map_sectot - 1, cluster, ALTS_MAP_DOWN);
5150Sstevel@tonic-gate 	    if (alts_ind == NULL) {
516*7821SMark.Logan@Sun.COM 	    	(void) fprintf(stderr,
517*7821SMark.Logan@Sun.COM 		    "Unable to allocate alternates for bad starting"
518*7821SMark.Logan@Sun.COM 		    " sector %u.\n", (ap->ap_entp)[i].bad_start);
5190Sstevel@tonic-gate 	    	exit(65);
5200Sstevel@tonic-gate 	    }
5210Sstevel@tonic-gate 	    alts_ind = alts_ind - cluster + 1;
522*7821SMark.Logan@Sun.COM 	    (ap->ap_entp)[i].good_start = alts_ind + ap->part.p_start;
523*7821SMark.Logan@Sun.COM 	    for (j = 0; j < cluster; j++) {
5240Sstevel@tonic-gate 		(ap->ap_memmapp)[alts_ind+j] = ALTS_BAD;
5250Sstevel@tonic-gate 	    }
5260Sstevel@tonic-gate 
5270Sstevel@tonic-gate 	}
5280Sstevel@tonic-gate 
5290Sstevel@tonic-gate }
5300Sstevel@tonic-gate 
5310Sstevel@tonic-gate /*
5320Sstevel@tonic-gate  *	transform the disk image alts bit map to incore char map
5330Sstevel@tonic-gate  */
534362Sbg159949 static void
expand_map(void)535362Sbg159949 expand_map(void)
5360Sstevel@tonic-gate {
5370Sstevel@tonic-gate 	int 	i;
5380Sstevel@tonic-gate 
539*7821SMark.Logan@Sun.COM 	for (i = 0; i < ap->part.p_size; i++) {
5400Sstevel@tonic-gate 	    (ap->ap_memmapp)[i] = altsmap_getbit(i);
5410Sstevel@tonic-gate 	}
5420Sstevel@tonic-gate }
5430Sstevel@tonic-gate 
5440Sstevel@tonic-gate /*
5450Sstevel@tonic-gate  *	transform the incore alts char map to the disk image bit map
5460Sstevel@tonic-gate  */
547362Sbg159949 static void
compress_map(void)548362Sbg159949 compress_map(void)
5490Sstevel@tonic-gate {
5500Sstevel@tonic-gate 
5510Sstevel@tonic-gate 	int 	i;
5520Sstevel@tonic-gate 	int	bytesz;
5530Sstevel@tonic-gate 	char	mask = 0;
554*7821SMark.Logan@Sun.COM 	int	maplen = 0;
5550Sstevel@tonic-gate 
556*7821SMark.Logan@Sun.COM 	for (i = 0, bytesz = 7; i < ap->part.p_size; i++) {
5570Sstevel@tonic-gate 	    mask |= ((ap->ap_memmapp)[i] << bytesz--);
5580Sstevel@tonic-gate 	    if (bytesz < 0) {
5590Sstevel@tonic-gate 		(ap->ap_mapp)[maplen++] = mask;
5600Sstevel@tonic-gate 		bytesz = 7;
5610Sstevel@tonic-gate 		mask = 0;
5620Sstevel@tonic-gate 	    }
5630Sstevel@tonic-gate 	}
5640Sstevel@tonic-gate /*
565*7821SMark.Logan@Sun.COM  *	if partition size != multiple number of bytes
566*7821SMark.Logan@Sun.COM  *	then record the last partial byte
5670Sstevel@tonic-gate  */
5680Sstevel@tonic-gate 	if (bytesz != 7)
5690Sstevel@tonic-gate 	    (ap->ap_mapp)[maplen] = mask;
570*7821SMark.Logan@Sun.COM 
5710Sstevel@tonic-gate }
5720Sstevel@tonic-gate 
5730Sstevel@tonic-gate /*
5740Sstevel@tonic-gate  *	given a bad sector number, search in the alts bit map
5750Sstevel@tonic-gate  *	and identify the sector as good or bad
5760Sstevel@tonic-gate  */
577362Sbg159949 static int
altsmap_getbit(blkaddr_t badsec)578*7821SMark.Logan@Sun.COM altsmap_getbit(blkaddr_t badsec)
5790Sstevel@tonic-gate {
580*7821SMark.Logan@Sun.COM 	uint_t	slot = badsec / 8;
581*7821SMark.Logan@Sun.COM 	uint_t	field = badsec % 8;
582*7821SMark.Logan@Sun.COM 	uchar_t	mask;
5830Sstevel@tonic-gate 
584*7821SMark.Logan@Sun.COM 	mask = ALTS_BAD<<7;
5850Sstevel@tonic-gate 	mask >>= field;
5860Sstevel@tonic-gate 	if ((ap->ap_mapp)[slot] & mask)
5870Sstevel@tonic-gate 	     return(ALTS_BAD);
5880Sstevel@tonic-gate 	return(ALTS_GOOD);
5890Sstevel@tonic-gate }
5900Sstevel@tonic-gate 
5910Sstevel@tonic-gate 
5920Sstevel@tonic-gate /*
5930Sstevel@tonic-gate  *	allocate a range of sectors from the alternate partition
5940Sstevel@tonic-gate  */
595*7821SMark.Logan@Sun.COM static blkaddr_t
altsmap_alloc(blkaddr_t srt_ind,blkaddr_t end_ind,int cnt,int dir)596*7821SMark.Logan@Sun.COM altsmap_alloc(blkaddr_t srt_ind, blkaddr_t end_ind, int cnt, int dir)
5970Sstevel@tonic-gate {
598*7821SMark.Logan@Sun.COM 	blkaddr_t	i;
599*7821SMark.Logan@Sun.COM 	blkaddr_t	total;
600*7821SMark.Logan@Sun.COM 	blkaddr_t	first_ind;
6010Sstevel@tonic-gate 
602*7821SMark.Logan@Sun.COM 	for (i = srt_ind, first_ind = srt_ind, total = 0;
603*7821SMark.Logan@Sun.COM 	    i != end_ind; i += dir) {
6040Sstevel@tonic-gate 	    if ((ap->ap_memmapp)[i] == ALTS_BAD) {
6050Sstevel@tonic-gate 		total = 0;
6060Sstevel@tonic-gate 		first_ind = i + dir;
6070Sstevel@tonic-gate 		continue;
6080Sstevel@tonic-gate 	    }
6090Sstevel@tonic-gate 	    total++;
6100Sstevel@tonic-gate 	    if (total == cnt)
6110Sstevel@tonic-gate 		return(first_ind);
6120Sstevel@tonic-gate 
6130Sstevel@tonic-gate 	}
614362Sbg159949 	return(0);
6150Sstevel@tonic-gate }
6160Sstevel@tonic-gate 
6170Sstevel@tonic-gate 
6180Sstevel@tonic-gate 
6190Sstevel@tonic-gate /*
6200Sstevel@tonic-gate  * 	bubble sort the entry table into ascending order
6210Sstevel@tonic-gate  */
622362Sbg159949 static void
ent_sort(struct alts_ent buf[],int cnt)623362Sbg159949 ent_sort(struct alts_ent buf[], int cnt)
6240Sstevel@tonic-gate {
6250Sstevel@tonic-gate struct	alts_ent temp;
6260Sstevel@tonic-gate int	flag;
627*7821SMark.Logan@Sun.COM int	i, j;
6280Sstevel@tonic-gate 
629*7821SMark.Logan@Sun.COM 	for (i = 0; i < cnt-1; i++) {
6300Sstevel@tonic-gate 	    temp = buf[cnt-1];
6310Sstevel@tonic-gate 	    flag = 1;
632*7821SMark.Logan@Sun.COM 
633*7821SMark.Logan@Sun.COM 	    for (j = cnt-1; j > i; j--) {
6340Sstevel@tonic-gate 		if (buf[j-1].bad_start < temp.bad_start) {
6350Sstevel@tonic-gate 		    buf[j] = temp;
6360Sstevel@tonic-gate 		    temp = buf[j-1];
6370Sstevel@tonic-gate 		} else {
6380Sstevel@tonic-gate 		    buf[j] = buf[j-1];
6390Sstevel@tonic-gate 		    flag = 0;
6400Sstevel@tonic-gate 		}
6410Sstevel@tonic-gate 	    }
6420Sstevel@tonic-gate 	    buf[i] = temp;
6430Sstevel@tonic-gate 	    if (flag) break;
6440Sstevel@tonic-gate 	}
6450Sstevel@tonic-gate 
6460Sstevel@tonic-gate }
6470Sstevel@tonic-gate 
6480Sstevel@tonic-gate 
6490Sstevel@tonic-gate /*
650*7821SMark.Logan@Sun.COM  *	compress all the contiguous bad sectors into a single entry
6510Sstevel@tonic-gate  *	in the entry table. The entry table must be sorted into ascending
6520Sstevel@tonic-gate  *	before the compression.
6530Sstevel@tonic-gate  */
654362Sbg159949 static void
ent_compress(struct alts_ent buf[],int cnt)655362Sbg159949 ent_compress(struct alts_ent buf[], int cnt)
6560Sstevel@tonic-gate {
6570Sstevel@tonic-gate int	keyp;
6580Sstevel@tonic-gate int	movp;
6590Sstevel@tonic-gate int	i;
6600Sstevel@tonic-gate 
661*7821SMark.Logan@Sun.COM 	for (i = 0; i < cnt; i++) {
662*7821SMark.Logan@Sun.COM 	    if (buf[i].bad_start == (uint32_t)ALTS_ENT_EMPTY)
6630Sstevel@tonic-gate 		continue;
664*7821SMark.Logan@Sun.COM 	    for (keyp = i, movp = i+1; movp < cnt; movp++) {
665*7821SMark.Logan@Sun.COM 		if (buf[movp].bad_start == (uint32_t)ALTS_ENT_EMPTY)
6660Sstevel@tonic-gate 			continue;
6670Sstevel@tonic-gate 		if (buf[keyp].bad_end+1 != buf[movp].bad_start)
6680Sstevel@tonic-gate 		    break;
6690Sstevel@tonic-gate 		buf[keyp].bad_end++;
670*7821SMark.Logan@Sun.COM 		buf[movp].bad_start = (uint32_t)ALTS_ENT_EMPTY;
6710Sstevel@tonic-gate 	    }
6720Sstevel@tonic-gate 	    if (movp == cnt) break;
6730Sstevel@tonic-gate 	}
6740Sstevel@tonic-gate }
6750Sstevel@tonic-gate 
6760Sstevel@tonic-gate 
6770Sstevel@tonic-gate /*
6780Sstevel@tonic-gate  *	merging two entry tables into a single table. In addition,
6790Sstevel@tonic-gate  *	all empty slots in the entry table will be removed.
6800Sstevel@tonic-gate  */
681362Sbg159949 static int
ent_merge(struct alts_ent buf[],struct alts_ent list1[],int lcnt1,struct alts_ent list2[],int lcnt2)682362Sbg159949 ent_merge(
683362Sbg159949 	struct alts_ent buf[],
684362Sbg159949 	struct alts_ent list1[],
685362Sbg159949 	int    lcnt1,
686362Sbg159949 	struct alts_ent list2[],
687362Sbg159949 	int    lcnt2)
6880Sstevel@tonic-gate {
6890Sstevel@tonic-gate 	int	i;
690*7821SMark.Logan@Sun.COM 	int	j1, j2;
6910Sstevel@tonic-gate 
692*7821SMark.Logan@Sun.COM 	for (i = 0, j1 = 0, j2 = 0; j1 < lcnt1 && j2 < lcnt2; ) {
693*7821SMark.Logan@Sun.COM 	    if (list1[j1].bad_start == (uint32_t)ALTS_ENT_EMPTY) {
6940Sstevel@tonic-gate 		j1++;
695*7821SMark.Logan@Sun.COM 		continue;
6960Sstevel@tonic-gate 	    }
697*7821SMark.Logan@Sun.COM 	    if (list2[j2].bad_start == (uint32_t)ALTS_ENT_EMPTY) {
6980Sstevel@tonic-gate 		j2++;
6990Sstevel@tonic-gate 		continue;
7000Sstevel@tonic-gate 	    }
7010Sstevel@tonic-gate 	    if (list1[j1].bad_start < list2[j2].bad_start)
7020Sstevel@tonic-gate 		buf[i++] = list1[j1++];
703*7821SMark.Logan@Sun.COM 	    else
7040Sstevel@tonic-gate 		buf[i++] = list2[j2++];
7050Sstevel@tonic-gate 	}
706*7821SMark.Logan@Sun.COM 	for (; j1 < lcnt1; j1++) {
707*7821SMark.Logan@Sun.COM 	    if (list1[j1].bad_start == (uint32_t)ALTS_ENT_EMPTY)
708*7821SMark.Logan@Sun.COM 		continue;
7090Sstevel@tonic-gate 	    buf[i++] = list1[j1];
7100Sstevel@tonic-gate 	}
711*7821SMark.Logan@Sun.COM 	for (; j2 < lcnt2; j2++) {
712*7821SMark.Logan@Sun.COM 	    if (list2[j2].bad_start == (uint32_t)ALTS_ENT_EMPTY)
713*7821SMark.Logan@Sun.COM 		continue;
7140Sstevel@tonic-gate 	    buf[i++] = list2[j2];
7150Sstevel@tonic-gate 	}
7160Sstevel@tonic-gate 	return (i);
7170Sstevel@tonic-gate }
7180Sstevel@tonic-gate 
7190Sstevel@tonic-gate 
7200Sstevel@tonic-gate /*
7210Sstevel@tonic-gate  *	binary search for bad sector in the alternate entry table
7220Sstevel@tonic-gate  */
723362Sbg159949 static int
ent_bsearch(struct alts_ent buf[],int cnt,struct alts_ent * key)724362Sbg159949 ent_bsearch(struct alts_ent buf[], int cnt, struct alts_ent *key)
7250Sstevel@tonic-gate {
7260Sstevel@tonic-gate 	int	i;
7270Sstevel@tonic-gate 	int	ind;
7280Sstevel@tonic-gate 	int	interval;
7290Sstevel@tonic-gate 	int	mystatus = -1;
7300Sstevel@tonic-gate 
731*7821SMark.Logan@Sun.COM 	if (!cnt)
732*7821SMark.Logan@Sun.COM 		return(mystatus);
7330Sstevel@tonic-gate 
734*7821SMark.Logan@Sun.COM 	for (i = 1; i <= cnt; i <<= 1)
735*7821SMark.Logan@Sun.COM 	    ind = i;
7360Sstevel@tonic-gate 
737*7821SMark.Logan@Sun.COM 	for (interval = ind; interval; ) {
7380Sstevel@tonic-gate /*
7390Sstevel@tonic-gate 	    printf("ind= %d, intv= %d; ",ind, interval);
7400Sstevel@tonic-gate */
741*7821SMark.Logan@Sun.COM 	    if ((key->bad_start >= buf[ind-1].bad_start) &&
7420Sstevel@tonic-gate 		(key->bad_start <= buf[ind-1].bad_end)) {
743*7821SMark.Logan@Sun.COM 		return(mystatus = ind-1);
7440Sstevel@tonic-gate 	    } else {
745*7821SMark.Logan@Sun.COM 		interval >>= 1;
7460Sstevel@tonic-gate 		if (!interval) break;
7470Sstevel@tonic-gate 		if (key->bad_start < buf[ind-1].bad_start) {
7480Sstevel@tonic-gate 		    ind = ind - interval;
7490Sstevel@tonic-gate 		} else {
7500Sstevel@tonic-gate  /* 		    if key is larger than the last element then break	*/
7510Sstevel@tonic-gate 		    if (ind == cnt) break;
7520Sstevel@tonic-gate 		    if ((ind+interval) <= cnt)
7530Sstevel@tonic-gate 		    	ind += interval;
7540Sstevel@tonic-gate 		}
7550Sstevel@tonic-gate 	    }
7560Sstevel@tonic-gate 	}
7570Sstevel@tonic-gate 	return(mystatus);
7580Sstevel@tonic-gate }
7590Sstevel@tonic-gate 
7600Sstevel@tonic-gate /*
7610Sstevel@tonic-gate  *	check for bad sector in assigned alternate sectors
7620Sstevel@tonic-gate  */
763362Sbg159949 static int
chk_bad_altsctr(blkaddr_t badsec)764*7821SMark.Logan@Sun.COM chk_bad_altsctr(blkaddr_t badsec)
7650Sstevel@tonic-gate {
7660Sstevel@tonic-gate 	int	i;
767*7821SMark.Logan@Sun.COM 	blkaddr_t	numsec;
7680Sstevel@tonic-gate 	int	cnt = ap->ap_tblp->alts_ent_used;
769*7821SMark.Logan@Sun.COM /*
770*7821SMark.Logan@Sun.COM  *	blkaddr_t intv[3];
771*7821SMark.Logan@Sun.COM  */
7720Sstevel@tonic-gate 
773*7821SMark.Logan@Sun.COM 	for (i = 0; i < cnt; i++) {
7740Sstevel@tonic-gate 	    numsec = (ap->ap_entp)[i].bad_end - (ap->ap_entp)[i].bad_start;
7750Sstevel@tonic-gate 	    if ((badsec >= (ap->ap_entp)[i].good_start) &&
7760Sstevel@tonic-gate 		(badsec <= ((ap->ap_entp)[i].good_start + numsec))) {
777*7821SMark.Logan@Sun.COM 		(void) fprintf(stderr, "Bad sector %ld is an assigned"
778*7821SMark.Logan@Sun.COM 		    " alternate sector.\n", badsec);
7790Sstevel@tonic-gate 		exit(66);
7800Sstevel@tonic-gate /*
781*7821SMark.Logan@Sun.COM  *		if (!numsec) {
782*7821SMark.Logan@Sun.COM  *		    (ap->ap_entp)[i].good_start = 0;
783*7821SMark.Logan@Sun.COM  *		    return (FAILURE);
784*7821SMark.Logan@Sun.COM  *		}
785*7821SMark.Logan@Sun.COM  *		intv[0] = badsec - (ap->ap_entp)[i].good_start;
786*7821SMark.Logan@Sun.COM  *		intv[1] = 1;
787*7821SMark.Logan@Sun.COM  *		intv[2] = (ap->ap_entp)[i].good_start + numsec - badsec;
788*7821SMark.Logan@Sun.COM  */
789*7821SMark.Logan@Sun.COM 	    }
7900Sstevel@tonic-gate 	}
791*7821SMark.Logan@Sun.COM 	/* the bad sector has already been identified as bad */
792*7821SMark.Logan@Sun.COM 	return(SUCCESS);
7930Sstevel@tonic-gate }
7940Sstevel@tonic-gate 
7950Sstevel@tonic-gate 
7960Sstevel@tonic-gate /*
7970Sstevel@tonic-gate  * print_altsec () -- print alternate sector information
7980Sstevel@tonic-gate  */
799362Sbg159949 int
print_altsec(struct extpartition * part)800*7821SMark.Logan@Sun.COM print_altsec(struct extpartition *part)
8010Sstevel@tonic-gate {
8020Sstevel@tonic-gate 	ap->ap_tblp = NULL;
8030Sstevel@tonic-gate 	ap->ap_flag &= ~ALTS_ADDPART;
8040Sstevel@tonic-gate 	read_altsctr(part, 0);
8050Sstevel@tonic-gate 	print_altsctr();
8060Sstevel@tonic-gate 	return(SUCCESS);
8070Sstevel@tonic-gate }
8080Sstevel@tonic-gate 
809362Sbg159949 static void
print_altsctr(void)810362Sbg159949 print_altsctr(void)
8110Sstevel@tonic-gate {
8120Sstevel@tonic-gate 	int	i;
8130Sstevel@tonic-gate 	int	totalloc;
8140Sstevel@tonic-gate 	int	avail;
8150Sstevel@tonic-gate 
8160Sstevel@tonic-gate /*	find # of available alternate sectors				*/
8170Sstevel@tonic-gate 	for (i=0, totalloc=0; i<ap->part.p_size; i++) {
8180Sstevel@tonic-gate 	    if ((ap->ap_memmapp)[i])
8190Sstevel@tonic-gate 		totalloc++;
8200Sstevel@tonic-gate 	}
8210Sstevel@tonic-gate /*
8220Sstevel@tonic-gate  *	available = size of partition - allocated sectors/bad sectors
8230Sstevel@tonic-gate  *		    - partition table - partition map
8240Sstevel@tonic-gate  *		    - entry table
8250Sstevel@tonic-gate  */
8260Sstevel@tonic-gate 	avail = ap->part.p_size - totalloc;
827*7821SMark.Logan@Sun.COM 	avail = avail - (ap->ap_tbl_secsiz/NBPSCTR)
8280Sstevel@tonic-gate 		- ap->ap_map_sectot;
8290Sstevel@tonic-gate 	avail = avail-(ap->ap_tblp->alts_ent_end -ap->ap_tblp->alts_ent_base+1);
8300Sstevel@tonic-gate 	if (avail < 0) avail = 0;
8310Sstevel@tonic-gate 
832*7821SMark.Logan@Sun.COM 	(void) printf("\nALTERNATE SECTOR/TRACK MAPPING TABLE:\n");
833*7821SMark.Logan@Sun.COM 	(void) printf("\nBad Sector Start\tAlternate Sector Start\t\tCount\n");
8340Sstevel@tonic-gate 
8350Sstevel@tonic-gate 	for (i=0; i<ap->ap_tblp->alts_ent_used; i++) {
836*7821SMark.Logan@Sun.COM 	     (void) printf("\t%u\t     ->\t\t%u\t\t\t   %u\n",
8370Sstevel@tonic-gate 		(ap->ap_entp)[i].bad_start,
8380Sstevel@tonic-gate 		(ap->ap_entp)[i].good_start,
8390Sstevel@tonic-gate 		((ap->ap_entp)[i].bad_end - (ap->ap_entp)[i].bad_start + 1));
8400Sstevel@tonic-gate 	}
841*7821SMark.Logan@Sun.COM 	(void) printf("\n      %d alternate sector(s) left for allocation.\n",
842*7821SMark.Logan@Sun.COM 	    avail);
8430Sstevel@tonic-gate 
8440Sstevel@tonic-gate }
8450Sstevel@tonic-gate 
846362Sbg159949 static int
absdsk_io(int fd,uint_t srtsec,char * bufp,uint_t len,int ioflag)847*7821SMark.Logan@Sun.COM absdsk_io(int fd, uint_t srtsec, char *bufp, uint_t len, int ioflag)
8480Sstevel@tonic-gate {
8490Sstevel@tonic-gate 	int	rc;
8500Sstevel@tonic-gate 
851*7821SMark.Logan@Sun.COM 	if (llseek (fd, (offset_t)srtsec * NBPSCTR, SEEK_SET) == -1)
8520Sstevel@tonic-gate 		return(FAILURE);
8530Sstevel@tonic-gate 	switch (ioflag)
8540Sstevel@tonic-gate 	{
8550Sstevel@tonic-gate 	case CMD_READ:
8560Sstevel@tonic-gate 		rc = read (fd, bufp, len);
8570Sstevel@tonic-gate 		break;
8580Sstevel@tonic-gate 	case CMD_WRITE:
8590Sstevel@tonic-gate 		rc = write (fd, bufp, len);
8600Sstevel@tonic-gate 		break;
8610Sstevel@tonic-gate 	default:
8620Sstevel@tonic-gate 		break;
8630Sstevel@tonic-gate 	}
8640Sstevel@tonic-gate 	if (rc == -1)
8650Sstevel@tonic-gate 		return(FAILURE);
8660Sstevel@tonic-gate 	return(SUCCESS);
8670Sstevel@tonic-gate }
868