xref: /onnv-gate/usr/src/cmd/format/ix_altsctr.c (revision 7563:84ec90ffc3f7)
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*7563SPrasad.Singamsetty@Sun.COM  * Common Development and Distribution License (the "License").
6*7563SPrasad.Singamsetty@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*7563SPrasad.Singamsetty@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  *
250Sstevel@tonic-gate  * copyright (c) 1990, 1991 UNIX System Laboratories, Inc.
260Sstevel@tonic-gate  * copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T
270Sstevel@tonic-gate  * 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>
430Sstevel@tonic-gate #include <string.h>
440Sstevel@tonic-gate #include <sys/vtoc.h>
450Sstevel@tonic-gate #include <sys/param.h>
460Sstevel@tonic-gate #include <sys/dkio.h>
470Sstevel@tonic-gate #include <sys/dktp/altsctr.h>
480Sstevel@tonic-gate #include <sys/dktp/fdisk.h>
490Sstevel@tonic-gate #include "badsec.h"
500Sstevel@tonic-gate #include "global.h"
510Sstevel@tonic-gate #include "ctlr_ata.h"
520Sstevel@tonic-gate #include "misc.h"
530Sstevel@tonic-gate 
540Sstevel@tonic-gate #define	FAILURE	1
550Sstevel@tonic-gate #define	SUCCESS	0
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 = NULL;
610Sstevel@tonic-gate int	badsl_chain_cnt = 0;
620Sstevel@tonic-gate struct	badsec_lst *gbadsl_chain = NULL;
630Sstevel@tonic-gate int	gbadsl_chain_cnt = 0;
640Sstevel@tonic-gate 
650Sstevel@tonic-gate static struct	alts_mempart alts_part = { 0, NULL, 0 };
660Sstevel@tonic-gate struct	alts_mempart	*ap = &alts_part;	/* pointer to incore */
670Sstevel@tonic-gate 						/*  alts tables	*/
680Sstevel@tonic-gate 
690Sstevel@tonic-gate /* prototypes */
70*7563SPrasad.Singamsetty@Sun.COM int updatebadsec(struct  dkl_partition *, int);
71*7563SPrasad.Singamsetty@Sun.COM int read_altsctr(struct  dkl_partition *);
720Sstevel@tonic-gate static int chk_badsec();
730Sstevel@tonic-gate static int init_altsctr();
740Sstevel@tonic-gate static int get_altsctr();
750Sstevel@tonic-gate int wr_altsctr();
760Sstevel@tonic-gate static void get_badsec();
770Sstevel@tonic-gate static int count_badsec();
780Sstevel@tonic-gate static int gen_alts_ent();
790Sstevel@tonic-gate static int assign_altsctr();
800Sstevel@tonic-gate static void expand_map();
810Sstevel@tonic-gate static void compress_map();
82*7563SPrasad.Singamsetty@Sun.COM static int altsmap_getbit(blkaddr_t);
83*7563SPrasad.Singamsetty@Sun.COM static blkaddr_t altsmap_alloc(blkaddr_t, blkaddr_t, int, int);
840Sstevel@tonic-gate static void ent_sort(struct  alts_ent *, int);
850Sstevel@tonic-gate static void ent_compress(struct  alts_ent *, int);
860Sstevel@tonic-gate static int ent_merge(struct alts_ent *, struct alts_ent *, int,
870Sstevel@tonic-gate 		struct alts_ent *, int);
880Sstevel@tonic-gate static int ent_bsearch(struct  alts_ent *, int, struct  alts_ent *);
89*7563SPrasad.Singamsetty@Sun.COM static int chk_bad_altsctr(blkaddr_t);
900Sstevel@tonic-gate 
910Sstevel@tonic-gate /*
920Sstevel@tonic-gate  * updatebadsec () -- update bad sector/track mapping tables
930Sstevel@tonic-gate  */
940Sstevel@tonic-gate int
updatebadsec(part,init_flag)950Sstevel@tonic-gate updatebadsec(part, init_flag)
960Sstevel@tonic-gate int	init_flag;
97*7563SPrasad.Singamsetty@Sun.COM struct  dkl_partition *part;
980Sstevel@tonic-gate {
990Sstevel@tonic-gate 	if (init_flag)
1000Sstevel@tonic-gate 		ap->ap_flag |= ALTS_ADDPART;
1010Sstevel@tonic-gate 	get_badsec();
1020Sstevel@tonic-gate 	(void) read_altsctr(part);
1030Sstevel@tonic-gate 	ent_sort(ap->ap_gbadp, ap->ap_gbadcnt);
1040Sstevel@tonic-gate 	ent_compress(ap->ap_gbadp, ap->ap_gbadcnt);
1050Sstevel@tonic-gate 	(void) gen_alts_ent();
1060Sstevel@tonic-gate 	compress_map();
1070Sstevel@tonic-gate 	return (SUCCESS);
1080Sstevel@tonic-gate }
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate /*
1110Sstevel@tonic-gate  * read_altsctr( ptr to alternate sector partition )
1120Sstevel@tonic-gate  *		-- read the alternate sector partition tables
1130Sstevel@tonic-gate  */
1140Sstevel@tonic-gate int
read_altsctr(part)1150Sstevel@tonic-gate read_altsctr(part)
116*7563SPrasad.Singamsetty@Sun.COM struct 	dkl_partition *part;
1170Sstevel@tonic-gate {
1180Sstevel@tonic-gate 	if (ap->ap_tblp == NULL) {
1190Sstevel@tonic-gate /*	    allocate buffer for the alts partition table (sector size)	*/
1200Sstevel@tonic-gate 	    ap->ap_tbl_secsiz = byte_to_secsiz(ALTS_PARTTBL_SIZE, NBPSCTR);
1210Sstevel@tonic-gate 	    ap->ap_tblp = (struct alts_parttbl *)malloc(ap->ap_tbl_secsiz);
1220Sstevel@tonic-gate 	    if (ap->ap_tblp == NULL) {
1230Sstevel@tonic-gate 		(void) fprintf(stderr,
1240Sstevel@tonic-gate 			"Unable to malloc alternate partition table.\n");
1250Sstevel@tonic-gate 		return (50);
1260Sstevel@tonic-gate 	    }
1270Sstevel@tonic-gate 
1280Sstevel@tonic-gate /*	    allocate buffer for the alts partition map (sector size)	*/
1290Sstevel@tonic-gate /*	    buffers include the disk image bit map 			*/
1300Sstevel@tonic-gate /*	    and the incore transformed char map				*/
1310Sstevel@tonic-gate 
1320Sstevel@tonic-gate 	    if ((ap->ap_memmapp = (uchar_t *)malloc(part->p_size)) == NULL) {
1330Sstevel@tonic-gate 		(void) fprintf(stderr,
1340Sstevel@tonic-gate 			"Unable to malloc incore alternate partition map.\n");
1350Sstevel@tonic-gate 		return (51);
1360Sstevel@tonic-gate 	    }
1370Sstevel@tonic-gate 	    ap->ap_tblp->alts_map_len = (part->p_size + 8 - 1) / 8;
1380Sstevel@tonic-gate 	    ap->ap_map_secsiz = byte_to_secsiz(ap->ap_tblp->alts_map_len,
1390Sstevel@tonic-gate 						NBPSCTR);
1400Sstevel@tonic-gate 	    ap->ap_map_sectot = ap->ap_map_secsiz / NBPSCTR;
1410Sstevel@tonic-gate 	    if ((ap->ap_mapp = (uchar_t *)malloc(ap->ap_map_secsiz)) == NULL) {
1420Sstevel@tonic-gate 		(void) fprintf(stderr,
1430Sstevel@tonic-gate 				"Unable to malloc alternate partition map.\n");
1440Sstevel@tonic-gate 		return (52);
1450Sstevel@tonic-gate 	    }
1460Sstevel@tonic-gate /*	    clear the buffers to zero					*/
1470Sstevel@tonic-gate 	    (void) memset(ap->ap_memmapp, 0, part->p_size);
1480Sstevel@tonic-gate 	    (void) memset(ap->ap_mapp, 0, ap->ap_map_secsiz);
1490Sstevel@tonic-gate 	    ap->part = *part;		/* struct copy			*/
1500Sstevel@tonic-gate 
1510Sstevel@tonic-gate /*
1520Sstevel@tonic-gate  *	    if add alternate partition flag is set, then install the partition
1530Sstevel@tonic-gate  *	    otherwise read the alts partition info from disk
1540Sstevel@tonic-gate  *	    if failed, then assume the first installation
1550Sstevel@tonic-gate  */
1560Sstevel@tonic-gate 	    if (ap->ap_flag & ALTS_ADDPART)
1570Sstevel@tonic-gate 	    {
1580Sstevel@tonic-gate 		(void) fprintf(stderr,
1590Sstevel@tonic-gate 			"WARNING: Manually initializing alternate table.\n");
1600Sstevel@tonic-gate 		(void) init_altsctr();
1610Sstevel@tonic-gate 	    } else {
1620Sstevel@tonic-gate 		if (get_altsctr() == SUCCESS)
1630Sstevel@tonic-gate 		    (void) chk_badsec();
1640Sstevel@tonic-gate 		else
1650Sstevel@tonic-gate 		    (void) init_altsctr();
1660Sstevel@tonic-gate 	    }
1670Sstevel@tonic-gate 	}
1680Sstevel@tonic-gate 	return (SUCCESS);
1690Sstevel@tonic-gate }
1700Sstevel@tonic-gate 
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate /*
1730Sstevel@tonic-gate  *	checking duplicate bad sectors or bad sectors in ALTSCTR partition
1740Sstevel@tonic-gate  */
1750Sstevel@tonic-gate static int
chk_badsec()1760Sstevel@tonic-gate chk_badsec()
1770Sstevel@tonic-gate {
178*7563SPrasad.Singamsetty@Sun.COM 	blkaddr_t	badsec;
179*7563SPrasad.Singamsetty@Sun.COM 	blkaddr_t	altsp_srtsec = ap->part.p_start;
180*7563SPrasad.Singamsetty@Sun.COM 	blkaddr_t	altsp_endsec = ap->part.p_start + ap->part.p_size - 1;
1810Sstevel@tonic-gate 	int	cnt;
1820Sstevel@tonic-gate 	int	status;
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate 	for (cnt = 0; cnt < ap->ap_gbadcnt; cnt++) {
1850Sstevel@tonic-gate 	    badsec = (ap->ap_gbadp)[cnt].bad_start;
1860Sstevel@tonic-gate 
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 			(void) fprintf(stderr,
1930Sstevel@tonic-gate 			"Alternate partition information table is bad.\n");
1940Sstevel@tonic-gate 			return (53);
1950Sstevel@tonic-gate 		    }
1960Sstevel@tonic-gate 		    if ((badsec >= altsp_srtsec+ap->ap_tblp->alts_map_base) &&
1970Sstevel@tonic-gate 			(badsec <= (altsp_srtsec + ap->ap_tblp->alts_map_base +
1980Sstevel@tonic-gate 			ap->ap_map_sectot - 1))) {
1990Sstevel@tonic-gate 			(void) fprintf(stderr,
2000Sstevel@tonic-gate 					"Alternate partition map is bad.\n");
2010Sstevel@tonic-gate 			return (54);
2020Sstevel@tonic-gate 		    }
2030Sstevel@tonic-gate 		    if ((badsec >= altsp_srtsec+ap->ap_tblp->alts_ent_base) &&
2040Sstevel@tonic-gate 			(badsec <= (altsp_srtsec + ap->ap_tblp->alts_ent_base +
2050Sstevel@tonic-gate 			ap->ap_ent_secsiz / NBPSCTR - 1))) {
2060Sstevel@tonic-gate 			(void) fprintf(stderr,
2070Sstevel@tonic-gate 				"Alternate partition entry table is bad.\n");
2080Sstevel@tonic-gate 			return (55);
2090Sstevel@tonic-gate 		    }
2100Sstevel@tonic-gate 		    (ap->ap_memmapp)[badsec - altsp_srtsec] = ALTS_BAD;
211*7563SPrasad.Singamsetty@Sun.COM 		    (ap->ap_gbadp)[cnt].bad_start = (uint32_t)ALTS_ENT_EMPTY;
2120Sstevel@tonic-gate 		} else {
2130Sstevel@tonic-gate 		    status = chk_bad_altsctr(badsec);
214*7563SPrasad.Singamsetty@Sun.COM 		    (ap->ap_gbadp)[cnt].bad_start = (uint32_t)ALTS_ENT_EMPTY;
2150Sstevel@tonic-gate 		}
2160Sstevel@tonic-gate 	    } else {
2170Sstevel@tonic-gate /*
2180Sstevel@tonic-gate  *		binary search for bad sector in the alts entry table
2190Sstevel@tonic-gate  */
2200Sstevel@tonic-gate 		status = ent_bsearch(ap->ap_entp, ap->ap_tblp->alts_ent_used,
2210Sstevel@tonic-gate 					&((ap->ap_gbadp)[cnt]));
2220Sstevel@tonic-gate /*
2230Sstevel@tonic-gate  *		if the bad sector had already been remapped(found in alts_entry)
2240Sstevel@tonic-gate  *		then ignore the bad sector
2250Sstevel@tonic-gate  */
2260Sstevel@tonic-gate 		if (status != -1) {
227*7563SPrasad.Singamsetty@Sun.COM 		    (ap->ap_gbadp)[cnt].bad_start = (uint32_t)ALTS_ENT_EMPTY;
2280Sstevel@tonic-gate 		}
2290Sstevel@tonic-gate 	    }
2300Sstevel@tonic-gate 	}
2310Sstevel@tonic-gate 	return (SUCCESS);
2320Sstevel@tonic-gate }
2330Sstevel@tonic-gate 
2340Sstevel@tonic-gate /*
2350Sstevel@tonic-gate  *	initialize the alternate partition tables
2360Sstevel@tonic-gate  */
2370Sstevel@tonic-gate static int
init_altsctr()2380Sstevel@tonic-gate init_altsctr()
2390Sstevel@tonic-gate {
240*7563SPrasad.Singamsetty@Sun.COM 	blkaddr_t	badsec;
241*7563SPrasad.Singamsetty@Sun.COM 	blkaddr_t	altsp_srtsec = ap->part.p_start;
242*7563SPrasad.Singamsetty@Sun.COM 	blkaddr_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 		    (void) fprintf(stderr,
2620Sstevel@tonic-gate 			"First sector of alternate partition is bad.\n");
2630Sstevel@tonic-gate 		    return (56);
2640Sstevel@tonic-gate 		}
2650Sstevel@tonic-gate 		(ap->ap_memmapp)[badsec - altsp_srtsec] = ALTS_BAD;
266*7563SPrasad.Singamsetty@Sun.COM 		(ap->ap_gbadp)[cnt].bad_start = (uint32_t)ALTS_ENT_EMPTY;
2670Sstevel@tonic-gate 	    }
2680Sstevel@tonic-gate 	}
2690Sstevel@tonic-gate 
2700Sstevel@tonic-gate /*	allocate the alts_map on disk skipping possible bad sectors	*/
2710Sstevel@tonic-gate 	ap->ap_tblp->alts_map_base =
2720Sstevel@tonic-gate 		altsmap_alloc(ap->ap_tbl_secsiz / NBPSCTR,
2730Sstevel@tonic-gate 			ap->part.p_size, ap->ap_map_sectot, ALTS_MAP_UP);
2740Sstevel@tonic-gate 	if (ap->ap_tblp->alts_map_base == NULL) {
2750Sstevel@tonic-gate 	    perror("Unable to allocate alternate map on disk: ");
2760Sstevel@tonic-gate 	    return (57);
2770Sstevel@tonic-gate 	}
2780Sstevel@tonic-gate 	(void) wr_altsctr();
2790Sstevel@tonic-gate 
2800Sstevel@tonic-gate 	return (SUCCESS);
2810Sstevel@tonic-gate }
2820Sstevel@tonic-gate 
2830Sstevel@tonic-gate 
2840Sstevel@tonic-gate /*
2850Sstevel@tonic-gate  * 	read the alternate partition tables from disk
2860Sstevel@tonic-gate  */
2870Sstevel@tonic-gate static int
get_altsctr()2880Sstevel@tonic-gate get_altsctr()
2890Sstevel@tonic-gate {
2900Sstevel@tonic-gate 	int	mystatus = FAILURE;
2910Sstevel@tonic-gate 	int	status = 0;
2920Sstevel@tonic-gate 
2930Sstevel@tonic-gate /*	get alts partition table info					*/
2940Sstevel@tonic-gate 
2950Sstevel@tonic-gate 	status = ata_rdwr(DIR_READ, cur_file, altsec_offset,
2960Sstevel@tonic-gate 			ap->ap_tbl_secsiz / UBSIZE, (char *)ap->ap_tblp,
2970Sstevel@tonic-gate 			0, NULL);
2980Sstevel@tonic-gate 	if (status == FAILURE) {
2990Sstevel@tonic-gate 	    perror("Unable to read alternate sector partition: ");
3000Sstevel@tonic-gate 	    return (58);
3010Sstevel@tonic-gate 	}
3020Sstevel@tonic-gate 	if (ap->ap_tblp->alts_sanity != ALTS_SANITY)
3030Sstevel@tonic-gate 	    return (mystatus);
3040Sstevel@tonic-gate 
3050Sstevel@tonic-gate /*	get the alts map						*/
3060Sstevel@tonic-gate 	status = ata_rdwr(DIR_READ, cur_file,
3070Sstevel@tonic-gate 		(ap->ap_tblp->alts_map_base) + altsec_offset,
3080Sstevel@tonic-gate 		ap->ap_map_secsiz / UBSIZE, (char *)ap->ap_mapp, 0, NULL);
3090Sstevel@tonic-gate 	if (status == FAILURE) {
3100Sstevel@tonic-gate 	    perror("Unable to read alternate sector partition map: ");
3110Sstevel@tonic-gate 	    return (59);
3120Sstevel@tonic-gate 	}
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate /*	transform the disk image bit-map to incore char map		*/
3150Sstevel@tonic-gate 	expand_map();
3160Sstevel@tonic-gate 
3170Sstevel@tonic-gate 	if (ap->ap_tblp->alts_ent_used == 0) {
3180Sstevel@tonic-gate 	    ap->ap_entp = NULL;
3190Sstevel@tonic-gate 	    ap->ap_ent_secsiz = 0;
3200Sstevel@tonic-gate 	} else {
3210Sstevel@tonic-gate 	    ap->ap_ent_secsiz = byte_to_secsiz(
3220Sstevel@tonic-gate 			(ap->ap_tblp->alts_ent_used*ALTS_ENT_SIZE), NBPSCTR);
3230Sstevel@tonic-gate 	    if ((ap->ap_entp =
3240Sstevel@tonic-gate 		(struct alts_ent *)malloc(ap->ap_ent_secsiz)) == NULL) {
3250Sstevel@tonic-gate 		(void) fprintf(stderr,
3260Sstevel@tonic-gate 			"Unable to malloc alternate sector entry table.\n");
3270Sstevel@tonic-gate 		return (60);
3280Sstevel@tonic-gate 	    }
3290Sstevel@tonic-gate 
3300Sstevel@tonic-gate 	status = ata_rdwr(DIR_READ, cur_file,
3310Sstevel@tonic-gate 			(ap->ap_tblp->alts_ent_base) + altsec_offset,
3320Sstevel@tonic-gate 			ap->ap_ent_secsiz / UBSIZE, (char *)ap->ap_entp,
3330Sstevel@tonic-gate 			0, NULL);
3340Sstevel@tonic-gate 	if (status == FAILURE) {
3350Sstevel@tonic-gate 		perror("Unable to read alternate sector entry table: ");
3360Sstevel@tonic-gate 		return (61);
3370Sstevel@tonic-gate 	    }
3380Sstevel@tonic-gate 	}
3390Sstevel@tonic-gate 
3400Sstevel@tonic-gate 	return (SUCCESS);
3410Sstevel@tonic-gate }
3420Sstevel@tonic-gate 
3430Sstevel@tonic-gate 
3440Sstevel@tonic-gate /*
3450Sstevel@tonic-gate  *	update the new alternate partition tables on disk
3460Sstevel@tonic-gate  */
3470Sstevel@tonic-gate int
wr_altsctr()3480Sstevel@tonic-gate wr_altsctr()
3490Sstevel@tonic-gate {
3500Sstevel@tonic-gate 	int	status;
3510Sstevel@tonic-gate 
3520Sstevel@tonic-gate 	if (ap->ap_tblp == NULL)
3530Sstevel@tonic-gate 		return (0);
3540Sstevel@tonic-gate 	status = ata_rdwr(DIR_WRITE, cur_file, altsec_offset,
3550Sstevel@tonic-gate 	    ap->ap_tbl_secsiz / UBSIZE, (char *)ap->ap_tblp, 0, NULL);
3560Sstevel@tonic-gate 	if (status) {
3570Sstevel@tonic-gate 		(void) printf("ata_rdwr status = %d need = %d\n",
3580Sstevel@tonic-gate 		    status, ap->ap_tbl_secsiz / 512);
3590Sstevel@tonic-gate 		perror("Unable to write with ata_rdwr the alt sector part: ");
3600Sstevel@tonic-gate 		return (62);
3610Sstevel@tonic-gate 	}
3620Sstevel@tonic-gate 
3630Sstevel@tonic-gate 	if (ata_rdwr(DIR_WRITE, cur_file, (ap->ap_tblp->alts_map_base) +
3640Sstevel@tonic-gate 			altsec_offset, ap->ap_map_secsiz / UBSIZE,
3650Sstevel@tonic-gate 			(char *)ap->ap_mapp, 0, NULL) == FAILURE) {
3660Sstevel@tonic-gate 	    perror("Unable to write alternate sector partition map: ");
3670Sstevel@tonic-gate 	    return (63);
3680Sstevel@tonic-gate 	}
3690Sstevel@tonic-gate 
3700Sstevel@tonic-gate 	if (ap->ap_tblp->alts_ent_used != 0) {
3710Sstevel@tonic-gate 	    if (ata_rdwr(DIR_WRITE, cur_file,
3720Sstevel@tonic-gate 				(ap->ap_tblp->alts_ent_base)+ altsec_offset,
3730Sstevel@tonic-gate 				ap->ap_ent_secsiz / UBSIZE,
3740Sstevel@tonic-gate 				(char *)ap->ap_entp, 0, NULL) == FAILURE) {
3750Sstevel@tonic-gate 		perror("Unable to write alternate sector entry table: ");
3760Sstevel@tonic-gate 		return (64);
3770Sstevel@tonic-gate 	    }
3780Sstevel@tonic-gate 	}
3790Sstevel@tonic-gate 	return (0);
3800Sstevel@tonic-gate }
3810Sstevel@tonic-gate 
3820Sstevel@tonic-gate 
3830Sstevel@tonic-gate /*
3840Sstevel@tonic-gate  *	get a list of bad sector
3850Sstevel@tonic-gate  */
3860Sstevel@tonic-gate static void
get_badsec()3870Sstevel@tonic-gate get_badsec()
3880Sstevel@tonic-gate {
3890Sstevel@tonic-gate 	int	cnt;
3900Sstevel@tonic-gate 	struct	badsec_lst *blc_p;
391*7563SPrasad.Singamsetty@Sun.COM 	blkaddr_t	curbad;
392*7563SPrasad.Singamsetty@Sun.COM 	blkaddr_t	maxsec = cur_dtype->dtype_nhead *
3930Sstevel@tonic-gate 				cur_dtype->dtype_ncyl *
3940Sstevel@tonic-gate 				cur_dtype->dtype_nsect;
3950Sstevel@tonic-gate 	struct	alts_ent *growbadp;
3960Sstevel@tonic-gate 	int	i;
3970Sstevel@tonic-gate 
3980Sstevel@tonic-gate 	cnt = count_badsec();
3990Sstevel@tonic-gate 	if (!cnt) {
4000Sstevel@tonic-gate 	    ap->ap_gbadp = NULL;
4010Sstevel@tonic-gate 	    ap->ap_gbadcnt = 0;
4020Sstevel@tonic-gate 	} else {
4030Sstevel@tonic-gate 	    ap->ap_gbadp = malloc(cnt*ALTS_ENT_SIZE);
4040Sstevel@tonic-gate 	    if (ap->ap_gbadp == NULL) {
4050Sstevel@tonic-gate 		    err_print("get_badsec: unable to malloc %d bytes\n",
4060Sstevel@tonic-gate 			cnt*ALTS_ENT_SIZE);
4070Sstevel@tonic-gate 		    fullabort();
4080Sstevel@tonic-gate 	    }
4090Sstevel@tonic-gate 	    (void) memset(ap->ap_gbadp, 0, cnt*ALTS_ENT_SIZE);
4100Sstevel@tonic-gate 
4110Sstevel@tonic-gate 	    for (growbadp = ap->ap_gbadp, cnt = 0, blc_p = badsl_chain;
4120Sstevel@tonic-gate 		blc_p; blc_p = blc_p->bl_nxt) {
4130Sstevel@tonic-gate 		for (i = 0; i < blc_p->bl_cnt; i++) {
4140Sstevel@tonic-gate 		    curbad = blc_p->bl_sec[i];
415*7563SPrasad.Singamsetty@Sun.COM 		    if (curbad < (blkaddr_t)cur_dtype->dtype_nsect) {
4160Sstevel@tonic-gate 			(void) fprintf(stderr,
4170Sstevel@tonic-gate "Ignoring bad sector %ld which is in first track of the drive.\n", curbad);
4180Sstevel@tonic-gate 			continue;
4190Sstevel@tonic-gate 		    }
4200Sstevel@tonic-gate 		    if (curbad >= maxsec) {
4210Sstevel@tonic-gate 			(void) fprintf(stderr,
4220Sstevel@tonic-gate "Ignoring bad sector %ld which is past the end of the drive.\n", curbad);
4230Sstevel@tonic-gate 			continue;
4240Sstevel@tonic-gate 		    }
4250Sstevel@tonic-gate 		    growbadp[cnt].bad_start = curbad;
4260Sstevel@tonic-gate 		    growbadp[cnt].bad_end = curbad;
4270Sstevel@tonic-gate 		    cnt++;
4280Sstevel@tonic-gate 		}
4290Sstevel@tonic-gate 	    }
4300Sstevel@tonic-gate 	}
4310Sstevel@tonic-gate 	ap->ap_gbadcnt = cnt;
4320Sstevel@tonic-gate }
4330Sstevel@tonic-gate 
4340Sstevel@tonic-gate /*
4350Sstevel@tonic-gate  *	count number of bad sector on list
4360Sstevel@tonic-gate  *	merging the bad sector list from surface analysis and the
4370Sstevel@tonic-gate  *	one given through the command line
4380Sstevel@tonic-gate  */
4390Sstevel@tonic-gate static int
count_badsec()4400Sstevel@tonic-gate count_badsec()
4410Sstevel@tonic-gate {
4420Sstevel@tonic-gate 
4430Sstevel@tonic-gate 	struct badsec_lst *blc_p;
4440Sstevel@tonic-gate 
4450Sstevel@tonic-gate 	if (!badsl_chain)
4460Sstevel@tonic-gate 		badsl_chain = gbadsl_chain;
4470Sstevel@tonic-gate 	else {
4480Sstevel@tonic-gate 		for (blc_p = badsl_chain; blc_p->bl_nxt; blc_p = blc_p->bl_nxt)
4490Sstevel@tonic-gate 			;
4500Sstevel@tonic-gate 		blc_p->bl_nxt = gbadsl_chain;
4510Sstevel@tonic-gate 	}
4520Sstevel@tonic-gate 
4530Sstevel@tonic-gate 	badsl_chain_cnt += gbadsl_chain_cnt;
4540Sstevel@tonic-gate 	return (badsl_chain_cnt);
4550Sstevel@tonic-gate }
4560Sstevel@tonic-gate 
4570Sstevel@tonic-gate 
4580Sstevel@tonic-gate /*
4590Sstevel@tonic-gate  *	generate alternate entry table by merging the existing and
4600Sstevel@tonic-gate  *	the new entry list.
4610Sstevel@tonic-gate  */
4620Sstevel@tonic-gate static int
gen_alts_ent()4630Sstevel@tonic-gate gen_alts_ent() {
464*7563SPrasad.Singamsetty@Sun.COM 	uint_t	ent_used;
4650Sstevel@tonic-gate 	struct	alts_ent *entp;
4660Sstevel@tonic-gate 
4670Sstevel@tonic-gate 	if (ap->ap_gbadcnt == 0)
4680Sstevel@tonic-gate 	    return (0);
4690Sstevel@tonic-gate 
4700Sstevel@tonic-gate 	ent_used = ap->ap_tblp->alts_ent_used + ap->ap_gbadcnt;
4710Sstevel@tonic-gate 	ap->ap_ent_secsiz = byte_to_secsiz(ent_used*ALTS_ENT_SIZE, NBPSCTR);
4720Sstevel@tonic-gate 	entp = malloc(ap->ap_ent_secsiz);
4730Sstevel@tonic-gate 	if (entp == NULL) {
4740Sstevel@tonic-gate 		err_print("get_alts_ent: unable to malloc %d bytes\n",
4750Sstevel@tonic-gate 		    ap->ap_ent_secsiz);
4760Sstevel@tonic-gate 		fullabort();
4770Sstevel@tonic-gate 	}
4780Sstevel@tonic-gate 
4790Sstevel@tonic-gate 	ent_used = ent_merge(entp, ap->ap_entp, ap->ap_tblp->alts_ent_used,
4800Sstevel@tonic-gate 			    ap->ap_gbadp, ap->ap_gbadcnt);
4810Sstevel@tonic-gate 	if (ap->ap_entp)
4820Sstevel@tonic-gate 	    free(ap->ap_entp);
4830Sstevel@tonic-gate 	if (ap->ap_gbadp)
4840Sstevel@tonic-gate 	    free(ap->ap_gbadp);
4850Sstevel@tonic-gate 	ap->ap_entp = entp;
4860Sstevel@tonic-gate 	ap->ap_ent_secsiz = byte_to_secsiz(ent_used*ALTS_ENT_SIZE, NBPSCTR);
4870Sstevel@tonic-gate 	ap->ap_tblp->alts_ent_used = ent_used;
4880Sstevel@tonic-gate 	ap->ap_gbadp = NULL;
4890Sstevel@tonic-gate 	ap->ap_gbadcnt = 0;
4900Sstevel@tonic-gate 
4910Sstevel@tonic-gate /*	assign alternate sectors to the bad sectors			*/
4920Sstevel@tonic-gate 	(void) assign_altsctr();
4930Sstevel@tonic-gate 
4940Sstevel@tonic-gate /*	allocate the alts_entry on disk skipping possible bad sectors	*/
4950Sstevel@tonic-gate 	ap->ap_tblp->alts_ent_base =
496*7563SPrasad.Singamsetty@Sun.COM 		altsmap_alloc((blkaddr_t)ap->ap_tblp->alts_map_base +
497*7563SPrasad.Singamsetty@Sun.COM 			ap->ap_map_sectot, (blkaddr_t)ap->part.p_size,
4980Sstevel@tonic-gate 			ap->ap_ent_secsiz / NBPSCTR, ALTS_MAP_UP);
4990Sstevel@tonic-gate 	if (ap->ap_tblp->alts_ent_base == NULL) {
5000Sstevel@tonic-gate 	    perror("Unable to allocate alternate entry table on disk: ");
5010Sstevel@tonic-gate 	    return (65);
5020Sstevel@tonic-gate 	}
5030Sstevel@tonic-gate 
5040Sstevel@tonic-gate 	ap->ap_tblp->alts_ent_end = ap->ap_tblp->alts_ent_base +
5050Sstevel@tonic-gate 			(ap->ap_ent_secsiz / NBPSCTR) - 1;
5060Sstevel@tonic-gate 	return (0);
5070Sstevel@tonic-gate }
5080Sstevel@tonic-gate 
5090Sstevel@tonic-gate 
5100Sstevel@tonic-gate /*
5110Sstevel@tonic-gate  *	assign alternate sectors for bad sector mapping
5120Sstevel@tonic-gate  */
5130Sstevel@tonic-gate static int
assign_altsctr()5140Sstevel@tonic-gate assign_altsctr()
5150Sstevel@tonic-gate {
516*7563SPrasad.Singamsetty@Sun.COM 	uint_t	i;
517*7563SPrasad.Singamsetty@Sun.COM 	uint_t	j;
518*7563SPrasad.Singamsetty@Sun.COM 	blkaddr_t	alts_ind;
519*7563SPrasad.Singamsetty@Sun.COM 	uint_t	cluster;
5200Sstevel@tonic-gate 
5210Sstevel@tonic-gate 	for (i = 0; i < ap->ap_tblp->alts_ent_used; i++) {
522*7563SPrasad.Singamsetty@Sun.COM 	    if ((ap->ap_entp)[i].bad_start == (uint32_t)ALTS_ENT_EMPTY)
5230Sstevel@tonic-gate 		continue;
5240Sstevel@tonic-gate 	    if ((ap->ap_entp)[i].good_start != 0)
5250Sstevel@tonic-gate 		continue;
5260Sstevel@tonic-gate 	    cluster = (ap->ap_entp)[i].bad_end-(ap->ap_entp)[i].bad_start +1;
5270Sstevel@tonic-gate 	    alts_ind =
5280Sstevel@tonic-gate 		altsmap_alloc(ap->part.p_size-1, ap->ap_tblp->alts_map_base +
5290Sstevel@tonic-gate 			ap->ap_map_sectot - 1, cluster, ALTS_MAP_DOWN);
5300Sstevel@tonic-gate 	    if (alts_ind == NULL) {
5310Sstevel@tonic-gate 		(void) fprintf(stderr,
532786Slclee 	"Unable to allocate alternates for bad starting sector %u.\n",
5330Sstevel@tonic-gate 			(ap->ap_entp)[i].bad_start);
5340Sstevel@tonic-gate 		return (65);
5350Sstevel@tonic-gate 	    }
5360Sstevel@tonic-gate 	    alts_ind = alts_ind - cluster + 1;
5370Sstevel@tonic-gate 	    (ap->ap_entp)[i].good_start = alts_ind +ap->part.p_start;
5380Sstevel@tonic-gate 	    for (j = 0; j < cluster; j++) {
5390Sstevel@tonic-gate 		(ap->ap_memmapp)[alts_ind+j] = ALTS_BAD;
5400Sstevel@tonic-gate 	    }
5410Sstevel@tonic-gate 
5420Sstevel@tonic-gate 	}
5430Sstevel@tonic-gate 	return (SUCCESS);
5440Sstevel@tonic-gate }
5450Sstevel@tonic-gate 
5460Sstevel@tonic-gate /*
5470Sstevel@tonic-gate  *	transform the disk image alts bit map to incore char map
5480Sstevel@tonic-gate  */
5490Sstevel@tonic-gate static void
expand_map()5500Sstevel@tonic-gate expand_map()
5510Sstevel@tonic-gate {
5520Sstevel@tonic-gate 	int 	i;
5530Sstevel@tonic-gate 
5540Sstevel@tonic-gate 	for (i = 0; i < ap->part.p_size; i++) {
5550Sstevel@tonic-gate 	    (ap->ap_memmapp)[i] = altsmap_getbit(i);
5560Sstevel@tonic-gate 	}
5570Sstevel@tonic-gate }
5580Sstevel@tonic-gate 
5590Sstevel@tonic-gate /*
5600Sstevel@tonic-gate  *	transform the incore alts char map to the disk image bit map
5610Sstevel@tonic-gate  */
5620Sstevel@tonic-gate static void
compress_map()5630Sstevel@tonic-gate compress_map()
5640Sstevel@tonic-gate {
5650Sstevel@tonic-gate 
5660Sstevel@tonic-gate 	int 	i;
5670Sstevel@tonic-gate 	int	bytesz;
5680Sstevel@tonic-gate 	char	mask = 0;
5690Sstevel@tonic-gate 	int	maplen = 0;
5700Sstevel@tonic-gate 
5710Sstevel@tonic-gate 	for (i = 0, bytesz = 7; i < ap->part.p_size; i++) {
5720Sstevel@tonic-gate 	    mask |= ((ap->ap_memmapp)[i] << bytesz--);
5730Sstevel@tonic-gate 	    if (bytesz < 0) {
5740Sstevel@tonic-gate 		(ap->ap_mapp)[maplen++] = mask;
5750Sstevel@tonic-gate 		bytesz = 7;
5760Sstevel@tonic-gate 		mask = 0;
5770Sstevel@tonic-gate 	    }
5780Sstevel@tonic-gate 	}
5790Sstevel@tonic-gate /*
5800Sstevel@tonic-gate  *	if partition size != multiple number of bytes
5810Sstevel@tonic-gate  *	then record the last partial byte
5820Sstevel@tonic-gate  */
5830Sstevel@tonic-gate 	if (bytesz != 7)
5840Sstevel@tonic-gate 	    (ap->ap_mapp)[maplen] = mask;
5850Sstevel@tonic-gate 
5860Sstevel@tonic-gate }
5870Sstevel@tonic-gate 
5880Sstevel@tonic-gate /*
5890Sstevel@tonic-gate  *	given a bad sector number, search in the alts bit map
5900Sstevel@tonic-gate  *	and identify the sector as good or bad
5910Sstevel@tonic-gate  */
5920Sstevel@tonic-gate static int
altsmap_getbit(badsec)5930Sstevel@tonic-gate altsmap_getbit(badsec)
594*7563SPrasad.Singamsetty@Sun.COM blkaddr_t	badsec;
5950Sstevel@tonic-gate {
596*7563SPrasad.Singamsetty@Sun.COM 	uint_t	slot = badsec / 8;
597*7563SPrasad.Singamsetty@Sun.COM 	uint_t	field = badsec % 8;
5980Sstevel@tonic-gate 	uchar_t	mask;
5990Sstevel@tonic-gate 
6000Sstevel@tonic-gate 	mask = ALTS_BAD<<7;
6010Sstevel@tonic-gate 	mask >>= field;
6020Sstevel@tonic-gate 	if ((ap->ap_mapp)[slot] & mask)
6030Sstevel@tonic-gate 	    return (ALTS_BAD);
6040Sstevel@tonic-gate 	return (ALTS_GOOD);
6050Sstevel@tonic-gate }
6060Sstevel@tonic-gate 
6070Sstevel@tonic-gate 
6080Sstevel@tonic-gate /*
6090Sstevel@tonic-gate  *	allocate a range of sectors from the alternate partition
6100Sstevel@tonic-gate  */
611*7563SPrasad.Singamsetty@Sun.COM static blkaddr_t
altsmap_alloc(srt_ind,end_ind,cnt,dir)6120Sstevel@tonic-gate altsmap_alloc(srt_ind, end_ind, cnt, dir)
613*7563SPrasad.Singamsetty@Sun.COM blkaddr_t	srt_ind;
614*7563SPrasad.Singamsetty@Sun.COM blkaddr_t	end_ind;
6150Sstevel@tonic-gate int	cnt;
6160Sstevel@tonic-gate int	dir;
6170Sstevel@tonic-gate {
618*7563SPrasad.Singamsetty@Sun.COM 	blkaddr_t	i;
619*7563SPrasad.Singamsetty@Sun.COM 	blkaddr_t	total;
620*7563SPrasad.Singamsetty@Sun.COM 	blkaddr_t	first_ind;
6210Sstevel@tonic-gate 
6220Sstevel@tonic-gate 	for (i = srt_ind, first_ind = srt_ind, total = 0;
6230Sstevel@tonic-gate 	    i != end_ind; i += dir) {
6240Sstevel@tonic-gate 	    if ((ap->ap_memmapp)[i] == ALTS_BAD) {
6250Sstevel@tonic-gate 		total = 0;
6260Sstevel@tonic-gate 		first_ind = i + dir;
6270Sstevel@tonic-gate 		continue;
6280Sstevel@tonic-gate 	    }
6290Sstevel@tonic-gate 	    total++;
6300Sstevel@tonic-gate 	    if (total == cnt)
6310Sstevel@tonic-gate 		return (first_ind);
6320Sstevel@tonic-gate 
6330Sstevel@tonic-gate 	}
6340Sstevel@tonic-gate 	return (NULL);
6350Sstevel@tonic-gate }
6360Sstevel@tonic-gate 
6370Sstevel@tonic-gate 
6380Sstevel@tonic-gate 
6390Sstevel@tonic-gate /*
6400Sstevel@tonic-gate  * 	bubble sort the entry table into ascending order
6410Sstevel@tonic-gate  */
6420Sstevel@tonic-gate static void
ent_sort(buf,cnt)6430Sstevel@tonic-gate ent_sort(buf, cnt)
6440Sstevel@tonic-gate struct	alts_ent buf[];
6450Sstevel@tonic-gate int	cnt;
6460Sstevel@tonic-gate {
6470Sstevel@tonic-gate struct	alts_ent temp;
6480Sstevel@tonic-gate int	flag;
6490Sstevel@tonic-gate int	i, j;
6500Sstevel@tonic-gate 
6510Sstevel@tonic-gate 	for (i = 0; i < cnt-1; i++) {
6520Sstevel@tonic-gate 	    temp = buf[cnt-1];
6530Sstevel@tonic-gate 	    flag = 1;
6540Sstevel@tonic-gate 
6550Sstevel@tonic-gate 	    for (j = cnt-1; j > i; j--) {
6560Sstevel@tonic-gate 		if (buf[j-1].bad_start < temp.bad_start) {
6570Sstevel@tonic-gate 		    buf[j] = temp;
6580Sstevel@tonic-gate 		    temp = buf[j-1];
6590Sstevel@tonic-gate 		} else {
6600Sstevel@tonic-gate 		    buf[j] = buf[j-1];
6610Sstevel@tonic-gate 		    flag = 0;
6620Sstevel@tonic-gate 		}
6630Sstevel@tonic-gate 	    }
6640Sstevel@tonic-gate 	    buf[i] = temp;
6650Sstevel@tonic-gate 	    if (flag) break;
6660Sstevel@tonic-gate 	}
6670Sstevel@tonic-gate 
6680Sstevel@tonic-gate }
6690Sstevel@tonic-gate 
6700Sstevel@tonic-gate 
6710Sstevel@tonic-gate /*
6720Sstevel@tonic-gate  *	compress all the contiguous bad sectors into a single entry
6730Sstevel@tonic-gate  *	in the entry table. The entry table must be sorted into ascending
6740Sstevel@tonic-gate  *	before the compression.
6750Sstevel@tonic-gate  */
6760Sstevel@tonic-gate static void
ent_compress(buf,cnt)6770Sstevel@tonic-gate ent_compress(buf, cnt)
6780Sstevel@tonic-gate struct	alts_ent buf[];
6790Sstevel@tonic-gate int	cnt;
6800Sstevel@tonic-gate {
6810Sstevel@tonic-gate int	keyp;
6820Sstevel@tonic-gate int	movp;
6830Sstevel@tonic-gate int	i;
6840Sstevel@tonic-gate 
6850Sstevel@tonic-gate 	for (i = 0; i < cnt; i++) {
686*7563SPrasad.Singamsetty@Sun.COM 	    if (buf[i].bad_start == (uint32_t)ALTS_ENT_EMPTY)
6870Sstevel@tonic-gate 		continue;
6880Sstevel@tonic-gate 	    for (keyp = i, movp = i+1; movp < cnt; movp++) {
689*7563SPrasad.Singamsetty@Sun.COM 		if (buf[movp].bad_start == (uint32_t)ALTS_ENT_EMPTY)
6900Sstevel@tonic-gate 			continue;
6910Sstevel@tonic-gate 		if (buf[keyp].bad_end+1 != buf[movp].bad_start)
6920Sstevel@tonic-gate 		    break;
6930Sstevel@tonic-gate 		buf[keyp].bad_end++;
694*7563SPrasad.Singamsetty@Sun.COM 		buf[movp].bad_start = (uint32_t)ALTS_ENT_EMPTY;
6950Sstevel@tonic-gate 	    }
6960Sstevel@tonic-gate 	    if (movp == cnt) break;
6970Sstevel@tonic-gate 	}
6980Sstevel@tonic-gate }
6990Sstevel@tonic-gate 
7000Sstevel@tonic-gate 
7010Sstevel@tonic-gate /*
7020Sstevel@tonic-gate  *	merging two entry tables into a single table. In addition,
7030Sstevel@tonic-gate  *	all empty slots in the entry table will be removed.
7040Sstevel@tonic-gate  */
7050Sstevel@tonic-gate static int
ent_merge(buf,list1,lcnt1,list2,lcnt2)7060Sstevel@tonic-gate ent_merge(buf, list1, lcnt1, list2, lcnt2)
7070Sstevel@tonic-gate struct	alts_ent buf[];
7080Sstevel@tonic-gate struct	alts_ent list1[];
7090Sstevel@tonic-gate int	lcnt1;
7100Sstevel@tonic-gate struct	alts_ent list2[];
7110Sstevel@tonic-gate int	lcnt2;
7120Sstevel@tonic-gate {
7130Sstevel@tonic-gate 	int	i;
7140Sstevel@tonic-gate 	int	j1, j2;
7150Sstevel@tonic-gate 
7160Sstevel@tonic-gate 	for (i = 0, j1 = 0, j2 = 0; j1 < lcnt1 && j2 < lcnt2; ) {
717*7563SPrasad.Singamsetty@Sun.COM 	    if (list1[j1].bad_start == (uint32_t)ALTS_ENT_EMPTY) {
7180Sstevel@tonic-gate 		j1++;
7190Sstevel@tonic-gate 		continue;
7200Sstevel@tonic-gate 	    }
721*7563SPrasad.Singamsetty@Sun.COM 	    if (list2[j2].bad_start == (uint32_t)ALTS_ENT_EMPTY) {
7220Sstevel@tonic-gate 		j2++;
7230Sstevel@tonic-gate 		continue;
7240Sstevel@tonic-gate 	    }
7250Sstevel@tonic-gate 	    if (list1[j1].bad_start < list2[j2].bad_start)
7260Sstevel@tonic-gate 		buf[i++] = list1[j1++];
7270Sstevel@tonic-gate 	    else
7280Sstevel@tonic-gate 		buf[i++] = list2[j2++];
7290Sstevel@tonic-gate 	}
7300Sstevel@tonic-gate 	for (; j1 < lcnt1; j1++) {
731*7563SPrasad.Singamsetty@Sun.COM 	    if (list1[j1].bad_start == (uint32_t)ALTS_ENT_EMPTY)
7320Sstevel@tonic-gate 		continue;
7330Sstevel@tonic-gate 	    buf[i++] = list1[j1];
7340Sstevel@tonic-gate 	}
7350Sstevel@tonic-gate 	for (; j2 < lcnt2; j2++) {
736*7563SPrasad.Singamsetty@Sun.COM 	    if (list2[j2].bad_start == (uint32_t)ALTS_ENT_EMPTY)
7370Sstevel@tonic-gate 		continue;
7380Sstevel@tonic-gate 	    buf[i++] = list2[j2];
7390Sstevel@tonic-gate 	}
7400Sstevel@tonic-gate 	return (i);
7410Sstevel@tonic-gate }
7420Sstevel@tonic-gate 
7430Sstevel@tonic-gate 
7440Sstevel@tonic-gate /*
7450Sstevel@tonic-gate  *	binary search for bad sector in the alternate entry table
7460Sstevel@tonic-gate  */
7470Sstevel@tonic-gate static int
ent_bsearch(buf,cnt,key)7480Sstevel@tonic-gate ent_bsearch(buf, cnt, key)
7490Sstevel@tonic-gate struct	alts_ent buf[];
7500Sstevel@tonic-gate int	cnt;
7510Sstevel@tonic-gate struct	alts_ent *key;
7520Sstevel@tonic-gate {
7530Sstevel@tonic-gate 	int	i;
7540Sstevel@tonic-gate 	int	ind;
7550Sstevel@tonic-gate 	int	interval;
7560Sstevel@tonic-gate 	int	mystatus = -1;
7570Sstevel@tonic-gate 
7580Sstevel@tonic-gate 	if (!cnt)
7590Sstevel@tonic-gate 	    return (mystatus);
7600Sstevel@tonic-gate 
7610Sstevel@tonic-gate 	for (i = 1; i <= cnt; i <<= 1)
7620Sstevel@tonic-gate 	    ind = i;
7630Sstevel@tonic-gate 
7640Sstevel@tonic-gate 	for (interval = ind; interval; ) {
7650Sstevel@tonic-gate 	    if ((key->bad_start >= buf[ind-1].bad_start) &&
7660Sstevel@tonic-gate 		(key->bad_start <= buf[ind-1].bad_end)) {
7670Sstevel@tonic-gate 		return (mystatus = ind-1);
7680Sstevel@tonic-gate 	    } else {
7690Sstevel@tonic-gate 		interval >>= 1;
7700Sstevel@tonic-gate 		if (!interval) break;
7710Sstevel@tonic-gate 		if (key->bad_start < buf[ind-1].bad_start) {
7720Sstevel@tonic-gate 		    ind = ind - interval;
7730Sstevel@tonic-gate 		} else {
7740Sstevel@tonic-gate /*	if key is larger than the last element then break	*/
7750Sstevel@tonic-gate 		    if (ind == cnt) break;
7760Sstevel@tonic-gate 		    if ((ind+interval) <= cnt)
7770Sstevel@tonic-gate 			ind += interval;
7780Sstevel@tonic-gate 		}
7790Sstevel@tonic-gate 	    }
7800Sstevel@tonic-gate 	}
7810Sstevel@tonic-gate 	return (mystatus);
7820Sstevel@tonic-gate }
7830Sstevel@tonic-gate 
7840Sstevel@tonic-gate /*
7850Sstevel@tonic-gate  *	check for bad sector in assigned alternate sectors
7860Sstevel@tonic-gate  */
7870Sstevel@tonic-gate static int
chk_bad_altsctr(badsec)7880Sstevel@tonic-gate chk_bad_altsctr(badsec)
789*7563SPrasad.Singamsetty@Sun.COM blkaddr_t	badsec;
7900Sstevel@tonic-gate {
7910Sstevel@tonic-gate 	int	i;
792*7563SPrasad.Singamsetty@Sun.COM 	blkaddr_t	numsec;
7930Sstevel@tonic-gate 	int	cnt = ap->ap_tblp->alts_ent_used;
7940Sstevel@tonic-gate /*
7950Sstevel@tonic-gate  *	daddr_t intv[3];
7960Sstevel@tonic-gate  */
7970Sstevel@tonic-gate 
7980Sstevel@tonic-gate 	for (i = 0; i < cnt; i++) {
7990Sstevel@tonic-gate 	    numsec = (ap->ap_entp)[i].bad_end - (ap->ap_entp)[i].bad_start;
8000Sstevel@tonic-gate 	    if ((badsec >= (ap->ap_entp)[i].good_start) &&
8010Sstevel@tonic-gate 		(badsec <= ((ap->ap_entp)[i].good_start + numsec))) {
8020Sstevel@tonic-gate 		(void) fprintf(stderr,
8030Sstevel@tonic-gate 		"Bad sector %ld is an assigned alternate sector.\n", badsec);
8040Sstevel@tonic-gate 		return (66);
8050Sstevel@tonic-gate /*
8060Sstevel@tonic-gate  *		if (!numsec) {
8070Sstevel@tonic-gate  *		    (ap->ap_entp)[i].good_start = 0;
8080Sstevel@tonic-gate  *		    return (FAILURE);
8090Sstevel@tonic-gate  *		}
8100Sstevel@tonic-gate  *		intv[0] = badsec - (ap->ap_entp)[i].good_start;
8110Sstevel@tonic-gate  *		intv[1] = 1;
8120Sstevel@tonic-gate  *		intv[2] = (ap->ap_entp)[i].good_start + numsec - badsec;
8130Sstevel@tonic-gate  */
8140Sstevel@tonic-gate 	    }
8150Sstevel@tonic-gate 	}
8160Sstevel@tonic-gate /*	the bad sector has already been identified as bad		*/
8170Sstevel@tonic-gate 	return (SUCCESS);
8180Sstevel@tonic-gate 
8190Sstevel@tonic-gate }
820