xref: /titanic_50/usr/src/cmd/addbadsec/ix_altsctr.c (revision 052b6e8a13e1fb4be51ba482db6bb2e9833fa717)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
23*052b6e8aSbg159949  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*	Copyright (c) 1990, 1991 UNIX System Laboratories, Inc.	*/
287c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T	*/
297c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate /*
327c478bd9Sstevel@tonic-gate  * Copyrighted as an unpublished work.
337c478bd9Sstevel@tonic-gate  * (c) Copyright INTERACTIVE Systems Corporation 1986, 1988, 1990
347c478bd9Sstevel@tonic-gate  * All rights reserved.
357c478bd9Sstevel@tonic-gate  */
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate #include <sys/types.h>
407c478bd9Sstevel@tonic-gate #include <ctype.h>
417c478bd9Sstevel@tonic-gate #include <fcntl.h>
427c478bd9Sstevel@tonic-gate #include <malloc.h>
437c478bd9Sstevel@tonic-gate #include <sys/stat.h>
447c478bd9Sstevel@tonic-gate #include <sys/swap.h>
457c478bd9Sstevel@tonic-gate #include <stdio.h>
467c478bd9Sstevel@tonic-gate #include <string.h>
477c478bd9Sstevel@tonic-gate #include <sys/vtoc.h>
487c478bd9Sstevel@tonic-gate #include <sys/param.h>
497c478bd9Sstevel@tonic-gate #include <sys/dkio.h>
507c478bd9Sstevel@tonic-gate #include <sys/dktp/altsctr.h>
517c478bd9Sstevel@tonic-gate #include <sys/dktp/fdisk.h>
527c478bd9Sstevel@tonic-gate #include "badsec.h"
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate #define FAILURE	0
557c478bd9Sstevel@tonic-gate #define	SUCCESS	1
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate #define CMD_READ	0
587c478bd9Sstevel@tonic-gate #define CMD_WRITE	1
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate struct	badsec_lst *badsl_chain;
617c478bd9Sstevel@tonic-gate int	badsl_chain_cnt;
627c478bd9Sstevel@tonic-gate struct	badsec_lst *gbadsl_chain;
637c478bd9Sstevel@tonic-gate int	gbadsl_chain_cnt;
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate extern struct  	dk_geom      	dkg;
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate extern int	alts_fd;
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate struct	alts_mempart alts_part = { 0, NULL, 0 };
707c478bd9Sstevel@tonic-gate struct	alts_mempart *ap = &alts_part;	/* pointer to incore alts tables     */
717c478bd9Sstevel@tonic-gate 
72*052b6e8aSbg159949 static void read_altsctr(struct partition *part, int badok);
73*052b6e8aSbg159949 static void chk_badsec    (void);
74*052b6e8aSbg159949 static void init_altsctr  (void);
75*052b6e8aSbg159949        void wr_altsctr    (void);
76*052b6e8aSbg159949 static void get_badsec    (void);
77*052b6e8aSbg159949 static int  count_badsec  (void);
78*052b6e8aSbg159949 static void gen_alts_ent  (void);
79*052b6e8aSbg159949 static void assign_altsctr(void);
80*052b6e8aSbg159949 static void expand_map    (void);
81*052b6e8aSbg159949 static void compress_map  (void);
82*052b6e8aSbg159949 static int  altsmap_getbit(daddr_t badsec);
83*052b6e8aSbg159949 static int  altsmap_alloc(daddr_t srt_ind, daddr_t end_ind, int cnt, int dir);
84*052b6e8aSbg159949 static void ent_sort(struct alts_ent buf[], int cnt);
85*052b6e8aSbg159949 static void ent_compress(struct alts_ent buf[], int cnt);
86*052b6e8aSbg159949 static int  ent_merge(
87*052b6e8aSbg159949 	struct alts_ent buf[],
88*052b6e8aSbg159949 	struct alts_ent list1[],
89*052b6e8aSbg159949 	int    lcnt1,
90*052b6e8aSbg159949 	struct alts_ent list2[],
91*052b6e8aSbg159949 	int    lcnt2);
92*052b6e8aSbg159949 static int  ent_bsearch(struct alts_ent buf[], int cnt, struct alts_ent *key);
93*052b6e8aSbg159949 static int  chk_bad_altsctr(daddr_t badsec);
94*052b6e8aSbg159949        int  print_altsec(struct partition *part);
95*052b6e8aSbg159949 static void print_altsctr(void);
96*052b6e8aSbg159949 static int  absdsk_io(int fd, uint srtsec, char *bufp, uint len, int ioflag);
97*052b6e8aSbg159949 
987c478bd9Sstevel@tonic-gate /*
997c478bd9Sstevel@tonic-gate  * updatebadsec () -- update bad sector/track mapping tables
1007c478bd9Sstevel@tonic-gate  */
101*052b6e8aSbg159949 int
102*052b6e8aSbg159949 updatebadsec(struct partition *part, int init_flag)
1037c478bd9Sstevel@tonic-gate {
1047c478bd9Sstevel@tonic-gate 	if (init_flag)
1057c478bd9Sstevel@tonic-gate 		ap->ap_flag |= ALTS_ADDPART;
1067c478bd9Sstevel@tonic-gate 	get_badsec();
1077c478bd9Sstevel@tonic-gate 	read_altsctr(part, 1);
1087c478bd9Sstevel@tonic-gate 	ent_sort(ap->ap_gbadp, ap->ap_gbadcnt);
1097c478bd9Sstevel@tonic-gate 	ent_compress(ap->ap_gbadp, ap->ap_gbadcnt);
1107c478bd9Sstevel@tonic-gate 	gen_alts_ent();
1117c478bd9Sstevel@tonic-gate 	compress_map();
1127c478bd9Sstevel@tonic-gate 	return(SUCCESS);
1137c478bd9Sstevel@tonic-gate }
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate /*
1167c478bd9Sstevel@tonic-gate  * read_altsctr( ptr to alternate sector partition )
1177c478bd9Sstevel@tonic-gate  *		-- read the alternate sector partition tables
1187c478bd9Sstevel@tonic-gate  */
119*052b6e8aSbg159949 static void
120*052b6e8aSbg159949 read_altsctr(struct partition *part, int badok)
1217c478bd9Sstevel@tonic-gate {
1227c478bd9Sstevel@tonic-gate 	int ret;
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 	if (ap->ap_tblp == NULL) {
1257c478bd9Sstevel@tonic-gate /*	    allocate buffer for the alts partition table (sector size)	*/
1267c478bd9Sstevel@tonic-gate 	    ap->ap_tbl_secsiz = byte_to_secsiz(ALTS_PARTTBL_SIZE,NBPSCTR);
1277c478bd9Sstevel@tonic-gate 	    ap->ap_tblp = (struct alts_parttbl *)malloc(ap->ap_tbl_secsiz);
1287c478bd9Sstevel@tonic-gate 	    if (ap->ap_tblp == NULL) {
1297c478bd9Sstevel@tonic-gate 		fprintf(stderr, "Unable to malloc alternate partition table.\n");
1307c478bd9Sstevel@tonic-gate 		exit(50);
1317c478bd9Sstevel@tonic-gate 	    }
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate /*	    allocate buffer for the alts partition map (sector size)	*/
1347c478bd9Sstevel@tonic-gate /*	    buffers include the disk image bit map 			*/
1357c478bd9Sstevel@tonic-gate /*	    and the incore transformed char map				*/
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate 	    if ((ap->ap_memmapp = (unchar *)malloc(part->p_size)) == NULL) {
1387c478bd9Sstevel@tonic-gate 		fprintf(stderr, "Unable to malloc incore alternate partition map.\n");
1397c478bd9Sstevel@tonic-gate 		exit(51);
1407c478bd9Sstevel@tonic-gate 	    }
1417c478bd9Sstevel@tonic-gate 	    ap->ap_tblp->alts_map_len = (part->p_size + 8 - 1) / 8;
1427c478bd9Sstevel@tonic-gate 	    ap->ap_map_secsiz=byte_to_secsiz(ap->ap_tblp->alts_map_len,NBPSCTR);
1437c478bd9Sstevel@tonic-gate 	    ap->ap_map_sectot = ap->ap_map_secsiz / NBPSCTR;
1447c478bd9Sstevel@tonic-gate 	    if ((ap->ap_mapp = (unchar *)malloc(ap->ap_map_secsiz)) == NULL) {
1457c478bd9Sstevel@tonic-gate 		fprintf(stderr, "Unable to malloc alternate partition map.\n");
1467c478bd9Sstevel@tonic-gate 		exit(52);
1477c478bd9Sstevel@tonic-gate 	    }
1487c478bd9Sstevel@tonic-gate /*	    clear the buffers to zero					*/
1497c478bd9Sstevel@tonic-gate 	    memset(ap->ap_memmapp,0,part->p_size);
1507c478bd9Sstevel@tonic-gate 	    memset(ap->ap_mapp,0,ap->ap_map_secsiz);
1517c478bd9Sstevel@tonic-gate 	    ap->part = *part;		/* struct copy			*/
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate /*
1547c478bd9Sstevel@tonic-gate  *	    if add alternate partition flag is set, then install the partition
1557c478bd9Sstevel@tonic-gate  *	    otherwise read the alts partition info from disk
1567c478bd9Sstevel@tonic-gate  *	    if failed, then assume the first installation
1577c478bd9Sstevel@tonic-gate  */
1587c478bd9Sstevel@tonic-gate 	    if (ap->ap_flag & ALTS_ADDPART)
1597c478bd9Sstevel@tonic-gate 	    {
1607c478bd9Sstevel@tonic-gate 		fprintf(stderr, "WARNING: Manually initializing alternate table.\n");
1617c478bd9Sstevel@tonic-gate 		init_altsctr();
1627c478bd9Sstevel@tonic-gate 	    }
1637c478bd9Sstevel@tonic-gate 	    else {
1647c478bd9Sstevel@tonic-gate 	    	if (get_altsctr(badok) == SUCCESS)
1657c478bd9Sstevel@tonic-gate 		    chk_badsec();
1667c478bd9Sstevel@tonic-gate 	    	else
1677c478bd9Sstevel@tonic-gate 		    init_altsctr();
1687c478bd9Sstevel@tonic-gate 	    }
1697c478bd9Sstevel@tonic-gate 	}
1707c478bd9Sstevel@tonic-gate }
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate /*
1747c478bd9Sstevel@tonic-gate  *	checking duplicate bad sectors or bad sectors in ALTSCTR partition
1757c478bd9Sstevel@tonic-gate  */
176*052b6e8aSbg159949 static void
177*052b6e8aSbg159949 chk_badsec(void)
1787c478bd9Sstevel@tonic-gate {
1797c478bd9Sstevel@tonic-gate 	daddr_t	badsec;
1807c478bd9Sstevel@tonic-gate 	daddr_t	altsp_srtsec = ap->part.p_start;
1817c478bd9Sstevel@tonic-gate 	daddr_t	altsp_endsec = ap->part.p_start + ap->part.p_size - 1;
1827c478bd9Sstevel@tonic-gate 	int	cnt;
1837c478bd9Sstevel@tonic-gate 	int	status;
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate 	for (cnt=0; cnt < ap->ap_gbadcnt; cnt++) {
1867c478bd9Sstevel@tonic-gate 	    badsec = (ap->ap_gbadp)[cnt].bad_start;
1877c478bd9Sstevel@tonic-gate /*	    if bad sector is within the ATLSCTR partition		*/
1887c478bd9Sstevel@tonic-gate 	    if ((badsec >= altsp_srtsec) && (badsec <= altsp_endsec)) {
1897c478bd9Sstevel@tonic-gate 		if ((ap->ap_memmapp)[badsec - altsp_srtsec] != ALTS_BAD) {
1907c478bd9Sstevel@tonic-gate 		    if ((badsec >= altsp_srtsec) && (badsec <= (altsp_srtsec +
1917c478bd9Sstevel@tonic-gate 			ap->ap_tbl_secsiz / NBPSCTR - 1))) {
1927c478bd9Sstevel@tonic-gate 		    	fprintf(stderr, "Alternate partition information table is bad.\n");
1937c478bd9Sstevel@tonic-gate 		    	exit(53);
1947c478bd9Sstevel@tonic-gate 	    	    }
1957c478bd9Sstevel@tonic-gate 		    if ((badsec >= altsp_srtsec+ap->ap_tblp->alts_map_base) &&
1967c478bd9Sstevel@tonic-gate 			(badsec <= (altsp_srtsec + ap->ap_tblp->alts_map_base +
1977c478bd9Sstevel@tonic-gate 			ap->ap_map_sectot - 1))) {
1987c478bd9Sstevel@tonic-gate 		    	fprintf(stderr, "Alternate partition map is bad.\n");
1997c478bd9Sstevel@tonic-gate 		    	exit(54);
2007c478bd9Sstevel@tonic-gate 	    	    }
2017c478bd9Sstevel@tonic-gate 		    if ((badsec >= altsp_srtsec+ap->ap_tblp->alts_ent_base) &&
2027c478bd9Sstevel@tonic-gate 			(badsec <= (altsp_srtsec + ap->ap_tblp->alts_ent_base +
2037c478bd9Sstevel@tonic-gate 			ap->ap_ent_secsiz / NBPSCTR - 1))) {
2047c478bd9Sstevel@tonic-gate 		    	fprintf(stderr, "Alternate partition entry table is bad.\n");
2057c478bd9Sstevel@tonic-gate 		    	exit(55);
2067c478bd9Sstevel@tonic-gate 	    	    }
2077c478bd9Sstevel@tonic-gate 		    (ap->ap_memmapp)[badsec - altsp_srtsec] = ALTS_BAD;
2087c478bd9Sstevel@tonic-gate 	            (ap->ap_gbadp)[cnt].bad_start = ALTS_ENT_EMPTY;
2097c478bd9Sstevel@tonic-gate 		} else {
2107c478bd9Sstevel@tonic-gate 		    status = chk_bad_altsctr(badsec);
2117c478bd9Sstevel@tonic-gate 	            (ap->ap_gbadp)[cnt].bad_start = ALTS_ENT_EMPTY;
2127c478bd9Sstevel@tonic-gate 		}
2137c478bd9Sstevel@tonic-gate 	    } else {
2147c478bd9Sstevel@tonic-gate /*
2157c478bd9Sstevel@tonic-gate  *		binary search for bad sector in the alts entry table
2167c478bd9Sstevel@tonic-gate  */
2177c478bd9Sstevel@tonic-gate 		status = ent_bsearch(ap->ap_entp, ap->ap_tblp->alts_ent_used,
2187c478bd9Sstevel@tonic-gate 					&((ap->ap_gbadp)[cnt]) );
2197c478bd9Sstevel@tonic-gate /*
2207c478bd9Sstevel@tonic-gate  *		if the bad sector had already been remapped(found in alts_entry)
2217c478bd9Sstevel@tonic-gate  *		then ignore the bad sector
2227c478bd9Sstevel@tonic-gate  */
2237c478bd9Sstevel@tonic-gate 		if (status != -1) {
2247c478bd9Sstevel@tonic-gate 	            (ap->ap_gbadp)[cnt].bad_start = ALTS_ENT_EMPTY;
2257c478bd9Sstevel@tonic-gate 		}
2267c478bd9Sstevel@tonic-gate 	    }
2277c478bd9Sstevel@tonic-gate 	}
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate }
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate /*
2357c478bd9Sstevel@tonic-gate  *	initialize the alternate partition tables
2367c478bd9Sstevel@tonic-gate  */
237*052b6e8aSbg159949 static void
238*052b6e8aSbg159949 init_altsctr(void)
2397c478bd9Sstevel@tonic-gate {
2407c478bd9Sstevel@tonic-gate 	daddr_t	badsec;
2417c478bd9Sstevel@tonic-gate 	daddr_t	altsp_srtsec = ap->part.p_start;
2427c478bd9Sstevel@tonic-gate 	daddr_t	altsp_endsec = ap->part.p_start + ap->part.p_size - 1;
2437c478bd9Sstevel@tonic-gate 	int	cnt;
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate 	ap->ap_entp = NULL;
2467c478bd9Sstevel@tonic-gate 	ap->ap_ent_secsiz = 0;
2477c478bd9Sstevel@tonic-gate 	ap->ap_tblp->alts_sanity = ALTS_SANITY;
2487c478bd9Sstevel@tonic-gate 	ap->ap_tblp->alts_version= ALTS_VERSION1;
2497c478bd9Sstevel@tonic-gate 	ap->ap_tblp->alts_map_len = (ap->part.p_size + 8 - 1) / 8;
2507c478bd9Sstevel@tonic-gate 	ap->ap_tblp->alts_ent_used = 0;
2517c478bd9Sstevel@tonic-gate 	ap->ap_tblp->alts_ent_base = 0;
2527c478bd9Sstevel@tonic-gate 	ap->ap_tblp->alts_ent_end  = 0;
2537c478bd9Sstevel@tonic-gate 	ap->ap_tblp->alts_resv_base = ap->part.p_size - 1;
2547c478bd9Sstevel@tonic-gate 	for (cnt=0; cnt<5; cnt++)
2557c478bd9Sstevel@tonic-gate 	    ap->ap_tblp->alts_pad[cnt]=0;
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate 	for (cnt=0; cnt < ap->ap_gbadcnt; cnt++) {
2587c478bd9Sstevel@tonic-gate 	    badsec = (ap->ap_gbadp)[cnt].bad_start;
2597c478bd9Sstevel@tonic-gate 	    if ((badsec >= altsp_srtsec) && (badsec <= altsp_endsec)) {
2607c478bd9Sstevel@tonic-gate 		if (badsec == altsp_srtsec) {
2617c478bd9Sstevel@tonic-gate 		    fprintf(stderr, "First sector of alternate partition is bad.\n");
2627c478bd9Sstevel@tonic-gate 		    exit(56);
2637c478bd9Sstevel@tonic-gate 	    	}
2647c478bd9Sstevel@tonic-gate 		(ap->ap_memmapp)[badsec - altsp_srtsec] = ALTS_BAD;
2657c478bd9Sstevel@tonic-gate 	        (ap->ap_gbadp)[cnt].bad_start = ALTS_ENT_EMPTY;
2667c478bd9Sstevel@tonic-gate 	    }
2677c478bd9Sstevel@tonic-gate 	}
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate /*	allocate the alts_map on disk skipping possible bad sectors	*/
2707c478bd9Sstevel@tonic-gate 	ap->ap_tblp->alts_map_base =
2717c478bd9Sstevel@tonic-gate 		altsmap_alloc(ap->ap_tbl_secsiz / NBPSCTR,
2727c478bd9Sstevel@tonic-gate 			ap->part.p_size, ap->ap_map_sectot, ALTS_MAP_UP);
2737c478bd9Sstevel@tonic-gate 	if (ap->ap_tblp->alts_map_base == NULL) {
2747c478bd9Sstevel@tonic-gate 	    perror("Unable to allocate alternate map on disk: ");
2757c478bd9Sstevel@tonic-gate 	    exit(57);
2767c478bd9Sstevel@tonic-gate 	}
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate }
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate /*
2827c478bd9Sstevel@tonic-gate  * 	read the alternate partition tables from disk
2837c478bd9Sstevel@tonic-gate  */
2847c478bd9Sstevel@tonic-gate int
2857c478bd9Sstevel@tonic-gate get_altsctr(badok)
2867c478bd9Sstevel@tonic-gate int badok;
2877c478bd9Sstevel@tonic-gate {
2887c478bd9Sstevel@tonic-gate /*	get alts partition table info					*/
2897c478bd9Sstevel@tonic-gate 	if (absdsk_io(alts_fd, 0, (char *)ap->ap_tblp,
2907c478bd9Sstevel@tonic-gate 			ap->ap_tbl_secsiz,CMD_READ)==FAILURE) {
2917c478bd9Sstevel@tonic-gate 	    if (badok)
2927c478bd9Sstevel@tonic-gate 		return(FAILURE);
2937c478bd9Sstevel@tonic-gate 	    perror("Unable to read alternate sector partition: ");
2947c478bd9Sstevel@tonic-gate 	    exit(58);
2957c478bd9Sstevel@tonic-gate 	}
2967c478bd9Sstevel@tonic-gate 	if (ap->ap_tblp->alts_sanity != ALTS_SANITY) {
2977c478bd9Sstevel@tonic-gate 	    if (badok)
2987c478bd9Sstevel@tonic-gate 		return(FAILURE);
2997c478bd9Sstevel@tonic-gate 	    fprintf(stderr, "Bad alternate sector magic number.\n");
3007c478bd9Sstevel@tonic-gate 	    exit(69);
3017c478bd9Sstevel@tonic-gate 	}
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate /*	get the alts map						*/
3047c478bd9Sstevel@tonic-gate 	if (absdsk_io(alts_fd, ap->ap_tblp->alts_map_base,
3057c478bd9Sstevel@tonic-gate 		(char *)ap->ap_mapp, ap->ap_map_secsiz, CMD_READ) == FAILURE) {
3067c478bd9Sstevel@tonic-gate 	    if (badok)
3077c478bd9Sstevel@tonic-gate 		return(FAILURE);
3087c478bd9Sstevel@tonic-gate 	    perror("Unable to read alternate sector partition map: ");
3097c478bd9Sstevel@tonic-gate 	    exit(59);
3107c478bd9Sstevel@tonic-gate 	}
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate /*	transform the disk image bit-map to incore char map		*/
3137c478bd9Sstevel@tonic-gate 	expand_map();
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate 	if (ap->ap_tblp->alts_ent_used == 0) {
3167c478bd9Sstevel@tonic-gate 	    ap->ap_entp = NULL;
3177c478bd9Sstevel@tonic-gate 	    ap->ap_ent_secsiz = 0;
3187c478bd9Sstevel@tonic-gate 	} else {
3197c478bd9Sstevel@tonic-gate 	    ap->ap_ent_secsiz = byte_to_secsiz(
3207c478bd9Sstevel@tonic-gate 			(ap->ap_tblp->alts_ent_used*ALTS_ENT_SIZE),NBPSCTR);
3217c478bd9Sstevel@tonic-gate 	    if ((ap->ap_entp = (struct alts_ent *)malloc(ap->ap_ent_secsiz)) == NULL) {
3227c478bd9Sstevel@tonic-gate 		if (badok)
3237c478bd9Sstevel@tonic-gate 		    return(FAILURE);
3247c478bd9Sstevel@tonic-gate 		fprintf(stderr, "Unable to malloc alternate sector entry table.\n");
3257c478bd9Sstevel@tonic-gate 		exit(60);
3267c478bd9Sstevel@tonic-gate 	    }
3277c478bd9Sstevel@tonic-gate 
3287c478bd9Sstevel@tonic-gate 	    if (absdsk_io(alts_fd, ap->ap_tblp->alts_ent_base,
3297c478bd9Sstevel@tonic-gate 	    			(char *)ap->ap_entp, ap->ap_ent_secsiz,
3307c478bd9Sstevel@tonic-gate 				CMD_READ) ==FAILURE){
3317c478bd9Sstevel@tonic-gate 		if (badok)
3327c478bd9Sstevel@tonic-gate 		    return(FAILURE);
3337c478bd9Sstevel@tonic-gate 		perror("Unable to read alternate sector entry table: ");
3347c478bd9Sstevel@tonic-gate 		exit(61);
3357c478bd9Sstevel@tonic-gate 	    }
3367c478bd9Sstevel@tonic-gate 	}
3377c478bd9Sstevel@tonic-gate 	return(SUCCESS);
3387c478bd9Sstevel@tonic-gate }
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate /*
3427c478bd9Sstevel@tonic-gate  *	update the new alternate partition tables on disk
3437c478bd9Sstevel@tonic-gate  */
344*052b6e8aSbg159949 void
345*052b6e8aSbg159949 wr_altsctr(void)
3467c478bd9Sstevel@tonic-gate {
3477c478bd9Sstevel@tonic-gate 	int	mystatus = FAILURE;
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate 	if (ap->ap_tblp == NULL)
3507c478bd9Sstevel@tonic-gate 		return;
351*052b6e8aSbg159949 	if (absdsk_io(alts_fd, 0, (char *)ap->ap_tblp,
3527c478bd9Sstevel@tonic-gate 		ap->ap_tbl_secsiz, CMD_WRITE) == FAILURE) {
3537c478bd9Sstevel@tonic-gate 	    perror("Unable to write alternate sector partition: ");
3547c478bd9Sstevel@tonic-gate 	    exit(62);
3557c478bd9Sstevel@tonic-gate 	}
3567c478bd9Sstevel@tonic-gate 
3577c478bd9Sstevel@tonic-gate 	if (absdsk_io(alts_fd, ap->ap_tblp->alts_map_base,
358*052b6e8aSbg159949 		(char *)ap->ap_mapp, ap->ap_map_secsiz, CMD_WRITE) == FAILURE) {
3597c478bd9Sstevel@tonic-gate 	    perror("Unable to write alternate sector partition map: ");
3607c478bd9Sstevel@tonic-gate 	    exit(63);
3617c478bd9Sstevel@tonic-gate 	}
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate 	if (ap->ap_tblp->alts_ent_used != 0) {
3647c478bd9Sstevel@tonic-gate 	    if (absdsk_io(alts_fd, ap->ap_tblp->alts_ent_base,
3657c478bd9Sstevel@tonic-gate 	    			(char *)ap->ap_entp, ap->ap_ent_secsiz,
3667c478bd9Sstevel@tonic-gate 				CMD_WRITE) == FAILURE) {
3677c478bd9Sstevel@tonic-gate 		perror("Unable to write alternate sector entry table: ");
3687c478bd9Sstevel@tonic-gate 		exit(64);
3697c478bd9Sstevel@tonic-gate 	    }
3707c478bd9Sstevel@tonic-gate 	}
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate 
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate }
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate /*
3787c478bd9Sstevel@tonic-gate  *	get a list of bad sector
3797c478bd9Sstevel@tonic-gate  */
380*052b6e8aSbg159949 static void
381*052b6e8aSbg159949 get_badsec(void)
3827c478bd9Sstevel@tonic-gate {
3837c478bd9Sstevel@tonic-gate 	int	cnt;
3847c478bd9Sstevel@tonic-gate 	struct	badsec_lst *blc_p;
3857c478bd9Sstevel@tonic-gate 	daddr_t	curbad;
3867c478bd9Sstevel@tonic-gate 	long	maxsec = (long)dkg.dkg_nhead *dkg.dkg_ncyl *dkg.dkg_nsect;
3877c478bd9Sstevel@tonic-gate 	struct	alts_ent *growbadp;
3887c478bd9Sstevel@tonic-gate 	int	i;
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate 	cnt = count_badsec();
3917c478bd9Sstevel@tonic-gate 	if (!cnt) {
3927c478bd9Sstevel@tonic-gate 	    ap->ap_gbadp = NULL;
3937c478bd9Sstevel@tonic-gate 	    ap->ap_gbadcnt = 0;
3947c478bd9Sstevel@tonic-gate 	}
3957c478bd9Sstevel@tonic-gate 	else {
3967c478bd9Sstevel@tonic-gate 	    ap->ap_gbadp = (struct alts_ent *) malloc(cnt*ALTS_ENT_SIZE);
3977c478bd9Sstevel@tonic-gate 	    memset(ap->ap_gbadp,0,cnt*ALTS_ENT_SIZE);
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate 	    for (growbadp=ap->ap_gbadp, cnt=0, blc_p=badsl_chain;
4007c478bd9Sstevel@tonic-gate 		blc_p; blc_p=blc_p->bl_nxt) {
4017c478bd9Sstevel@tonic-gate 		for (i=0; i<blc_p->bl_cnt; i++) {
4027c478bd9Sstevel@tonic-gate 		    curbad = blc_p->bl_sec[i];
4037c478bd9Sstevel@tonic-gate 		    if (curbad < (daddr_t)dkg.dkg_nsect) {
4047c478bd9Sstevel@tonic-gate 		    	fprintf(stderr,
4057c478bd9Sstevel@tonic-gate 			   "Ignoring bad sector %ld which is in first track of the drive.\n", curbad);
4067c478bd9Sstevel@tonic-gate 		    	continue;
4077c478bd9Sstevel@tonic-gate 		    }
4087c478bd9Sstevel@tonic-gate 		    if (curbad >= maxsec) {
4097c478bd9Sstevel@tonic-gate 		    	fprintf(stderr,
4107c478bd9Sstevel@tonic-gate 			   "Ignoring bad sector %ld which is past the end of the drive.\n", curbad);
4117c478bd9Sstevel@tonic-gate 		    	continue;
4127c478bd9Sstevel@tonic-gate 		    }
4137c478bd9Sstevel@tonic-gate 		    growbadp[cnt].bad_start = curbad;
4147c478bd9Sstevel@tonic-gate 		    growbadp[cnt].bad_end = curbad;
4157c478bd9Sstevel@tonic-gate 		    cnt++;
4167c478bd9Sstevel@tonic-gate 		}
4177c478bd9Sstevel@tonic-gate 	    }
4187c478bd9Sstevel@tonic-gate 	}
4197c478bd9Sstevel@tonic-gate 	ap->ap_gbadcnt = cnt;
4207c478bd9Sstevel@tonic-gate }
4217c478bd9Sstevel@tonic-gate 
4227c478bd9Sstevel@tonic-gate /*
4237c478bd9Sstevel@tonic-gate  *	count number of bad sector on list
4247c478bd9Sstevel@tonic-gate  *	merging the bad sector list from surface analysis and the
4257c478bd9Sstevel@tonic-gate  *	one given through the command line
4267c478bd9Sstevel@tonic-gate  */
427*052b6e8aSbg159949 static int
428*052b6e8aSbg159949 count_badsec(void)
4297c478bd9Sstevel@tonic-gate {
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate 	struct badsec_lst *blc_p;
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate 	if (!badsl_chain)
4347c478bd9Sstevel@tonic-gate 		badsl_chain = gbadsl_chain;
4357c478bd9Sstevel@tonic-gate 	else {
4367c478bd9Sstevel@tonic-gate 		for (blc_p = badsl_chain; blc_p->bl_nxt; blc_p=blc_p->bl_nxt)
4377c478bd9Sstevel@tonic-gate 			;
4387c478bd9Sstevel@tonic-gate 		blc_p->bl_nxt = gbadsl_chain;
4397c478bd9Sstevel@tonic-gate 	}
4407c478bd9Sstevel@tonic-gate 
4417c478bd9Sstevel@tonic-gate 	badsl_chain_cnt += gbadsl_chain_cnt;
4427c478bd9Sstevel@tonic-gate 	return(badsl_chain_cnt);
4437c478bd9Sstevel@tonic-gate }
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate /*
4477c478bd9Sstevel@tonic-gate  *	generate alternate entry table by merging the existing and
4487c478bd9Sstevel@tonic-gate  *	the new entry list.
4497c478bd9Sstevel@tonic-gate  */
450*052b6e8aSbg159949 static void
451*052b6e8aSbg159949 gen_alts_ent(void)
452*052b6e8aSbg159949 {
4537c478bd9Sstevel@tonic-gate 	int	ent_used;
4547c478bd9Sstevel@tonic-gate 	struct	alts_ent *entp;
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate 	if (ap->ap_gbadcnt == 0)
4577c478bd9Sstevel@tonic-gate 	    return;
4587c478bd9Sstevel@tonic-gate 
4597c478bd9Sstevel@tonic-gate 	ent_used = ap->ap_tblp->alts_ent_used + ap->ap_gbadcnt;
4607c478bd9Sstevel@tonic-gate 	ap->ap_ent_secsiz = byte_to_secsiz(ent_used*ALTS_ENT_SIZE,NBPSCTR);
4617c478bd9Sstevel@tonic-gate 	entp=(struct alts_ent *) malloc (ap->ap_ent_secsiz);
4627c478bd9Sstevel@tonic-gate 	ent_used = ent_merge(entp, ap->ap_entp, ap->ap_tblp->alts_ent_used,
4637c478bd9Sstevel@tonic-gate 			     ap->ap_gbadp, ap->ap_gbadcnt);
4647c478bd9Sstevel@tonic-gate 	if (ap->ap_entp)
4657c478bd9Sstevel@tonic-gate 	    free(ap->ap_entp);
4667c478bd9Sstevel@tonic-gate 	if (ap->ap_gbadp)
4677c478bd9Sstevel@tonic-gate 	    free(ap->ap_gbadp);
4687c478bd9Sstevel@tonic-gate 	ap->ap_entp = entp;
4697c478bd9Sstevel@tonic-gate 	ap->ap_ent_secsiz = byte_to_secsiz(ent_used*ALTS_ENT_SIZE,NBPSCTR);
4707c478bd9Sstevel@tonic-gate 	ap->ap_tblp->alts_ent_used = ent_used;
4717c478bd9Sstevel@tonic-gate 	ap->ap_gbadp = NULL;
4727c478bd9Sstevel@tonic-gate 	ap->ap_gbadcnt = 0;
4737c478bd9Sstevel@tonic-gate 
4747c478bd9Sstevel@tonic-gate /*	assign alternate sectors to the bad sectors			*/
4757c478bd9Sstevel@tonic-gate 	assign_altsctr();
4767c478bd9Sstevel@tonic-gate 
4777c478bd9Sstevel@tonic-gate /*	allocate the alts_entry on disk skipping possible bad sectors	*/
4787c478bd9Sstevel@tonic-gate 	ap->ap_tblp->alts_ent_base =
4797c478bd9Sstevel@tonic-gate 		altsmap_alloc(ap->ap_tblp->alts_map_base + ap->ap_map_sectot,
4807c478bd9Sstevel@tonic-gate 			ap->part.p_size,
4817c478bd9Sstevel@tonic-gate 			ap->ap_ent_secsiz / NBPSCTR, ALTS_MAP_UP);
4827c478bd9Sstevel@tonic-gate 	if (ap->ap_tblp->alts_ent_base == NULL) {
4837c478bd9Sstevel@tonic-gate 	    perror("Unable to allocate alternate entry table on disk: ");
4847c478bd9Sstevel@tonic-gate 	    exit(65);
4857c478bd9Sstevel@tonic-gate 	}
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate 	ap->ap_tblp->alts_ent_end = ap->ap_tblp->alts_ent_base +
4887c478bd9Sstevel@tonic-gate 			(ap->ap_ent_secsiz / NBPSCTR) - 1;
4897c478bd9Sstevel@tonic-gate }
4907c478bd9Sstevel@tonic-gate 
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate /*
4937c478bd9Sstevel@tonic-gate  *	assign alternate sectors for bad sector mapping
4947c478bd9Sstevel@tonic-gate  */
495*052b6e8aSbg159949 static void
496*052b6e8aSbg159949 assign_altsctr(void)
4977c478bd9Sstevel@tonic-gate {
4987c478bd9Sstevel@tonic-gate 	int	i;
4997c478bd9Sstevel@tonic-gate 	int	j;
5007c478bd9Sstevel@tonic-gate 	daddr_t	alts_ind;
5017c478bd9Sstevel@tonic-gate 	int	cluster;
5027c478bd9Sstevel@tonic-gate 
5037c478bd9Sstevel@tonic-gate 	for (i=0; i<ap->ap_tblp->alts_ent_used; i++) {
5047c478bd9Sstevel@tonic-gate 	    if ((ap->ap_entp)[i].bad_start == ALTS_ENT_EMPTY)
5057c478bd9Sstevel@tonic-gate 		continue;
5067c478bd9Sstevel@tonic-gate 	    if ((ap->ap_entp)[i].good_start != 0)
5077c478bd9Sstevel@tonic-gate 		continue;
5087c478bd9Sstevel@tonic-gate 	    cluster = (ap->ap_entp)[i].bad_end-(ap->ap_entp)[i].bad_start +1;
5097c478bd9Sstevel@tonic-gate 	    alts_ind =
5107c478bd9Sstevel@tonic-gate 		altsmap_alloc(ap->part.p_size-1, ap->ap_tblp->alts_map_base +
5117c478bd9Sstevel@tonic-gate 			ap->ap_map_sectot - 1, cluster, ALTS_MAP_DOWN);
5127c478bd9Sstevel@tonic-gate 	    if (alts_ind == NULL) {
5137c478bd9Sstevel@tonic-gate 	    	fprintf(stderr, "Unable to allocate alternates for bad starting sector %ld.\n", (ap->ap_entp)[i].bad_start);
5147c478bd9Sstevel@tonic-gate 	    	exit(65);
5157c478bd9Sstevel@tonic-gate 	    }
5167c478bd9Sstevel@tonic-gate 	    alts_ind = alts_ind - cluster + 1;
5177c478bd9Sstevel@tonic-gate 	    (ap->ap_entp)[i].good_start =alts_ind +ap->part.p_start;
5187c478bd9Sstevel@tonic-gate 	    for (j=0; j<cluster; j++) {
5197c478bd9Sstevel@tonic-gate 		(ap->ap_memmapp)[alts_ind+j] = ALTS_BAD;
5207c478bd9Sstevel@tonic-gate 	    }
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate 	}
5237c478bd9Sstevel@tonic-gate 
5247c478bd9Sstevel@tonic-gate }
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate /*
5277c478bd9Sstevel@tonic-gate  *	transform the disk image alts bit map to incore char map
5287c478bd9Sstevel@tonic-gate  */
529*052b6e8aSbg159949 static void
530*052b6e8aSbg159949 expand_map(void)
5317c478bd9Sstevel@tonic-gate {
5327c478bd9Sstevel@tonic-gate 	int 	i;
5337c478bd9Sstevel@tonic-gate 
5347c478bd9Sstevel@tonic-gate 	for (i=0; i<ap->part.p_size; i++) {
5357c478bd9Sstevel@tonic-gate 	    (ap->ap_memmapp)[i] = altsmap_getbit(i);
5367c478bd9Sstevel@tonic-gate 	}
5377c478bd9Sstevel@tonic-gate }
5387c478bd9Sstevel@tonic-gate 
5397c478bd9Sstevel@tonic-gate /*
5407c478bd9Sstevel@tonic-gate  *	transform the incore alts char map to the disk image bit map
5417c478bd9Sstevel@tonic-gate  */
542*052b6e8aSbg159949 static void
543*052b6e8aSbg159949 compress_map(void)
5447c478bd9Sstevel@tonic-gate {
5457c478bd9Sstevel@tonic-gate 
5467c478bd9Sstevel@tonic-gate 	int 	i;
5477c478bd9Sstevel@tonic-gate 	int	bytesz;
5487c478bd9Sstevel@tonic-gate 	char	mask = 0;
5497c478bd9Sstevel@tonic-gate 	int	maplen=0;
5507c478bd9Sstevel@tonic-gate 
5517c478bd9Sstevel@tonic-gate 	for (i=0, bytesz=7; i<ap->part.p_size; i++) {
5527c478bd9Sstevel@tonic-gate 	    mask |= ((ap->ap_memmapp)[i] << bytesz--);
5537c478bd9Sstevel@tonic-gate 	    if (bytesz < 0) {
5547c478bd9Sstevel@tonic-gate 		(ap->ap_mapp)[maplen++] = mask;
5557c478bd9Sstevel@tonic-gate 		bytesz = 7;
5567c478bd9Sstevel@tonic-gate 		mask = 0;
5577c478bd9Sstevel@tonic-gate 	    }
5587c478bd9Sstevel@tonic-gate 	}
5597c478bd9Sstevel@tonic-gate /*
5607c478bd9Sstevel@tonic-gate  *	if partition size != multiple number of bytes
5617c478bd9Sstevel@tonic-gate  *	then record the last partial byte
5627c478bd9Sstevel@tonic-gate  */
5637c478bd9Sstevel@tonic-gate 	if (bytesz != 7)
5647c478bd9Sstevel@tonic-gate 	    (ap->ap_mapp)[maplen] = mask;
5657c478bd9Sstevel@tonic-gate 
5667c478bd9Sstevel@tonic-gate }
5677c478bd9Sstevel@tonic-gate 
5687c478bd9Sstevel@tonic-gate /*
5697c478bd9Sstevel@tonic-gate  *	given a bad sector number, search in the alts bit map
5707c478bd9Sstevel@tonic-gate  *	and identify the sector as good or bad
5717c478bd9Sstevel@tonic-gate  */
572*052b6e8aSbg159949 static int
573*052b6e8aSbg159949 altsmap_getbit(daddr_t badsec)
5747c478bd9Sstevel@tonic-gate {
5757c478bd9Sstevel@tonic-gate 	int	slot = badsec / 8;
5767c478bd9Sstevel@tonic-gate 	int	field = badsec % 8;
5777c478bd9Sstevel@tonic-gate 	unchar	mask;
5787c478bd9Sstevel@tonic-gate 
5797c478bd9Sstevel@tonic-gate 	mask = ALTS_BAD<<7;
5807c478bd9Sstevel@tonic-gate 	mask >>= field;
5817c478bd9Sstevel@tonic-gate 	if ((ap->ap_mapp)[slot] & mask)
5827c478bd9Sstevel@tonic-gate 	     return(ALTS_BAD);
5837c478bd9Sstevel@tonic-gate 	return(ALTS_GOOD);
5847c478bd9Sstevel@tonic-gate }
5857c478bd9Sstevel@tonic-gate 
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate /*
5887c478bd9Sstevel@tonic-gate  *	allocate a range of sectors from the alternate partition
5897c478bd9Sstevel@tonic-gate  */
590*052b6e8aSbg159949 static int
591*052b6e8aSbg159949 altsmap_alloc(daddr_t srt_ind, daddr_t end_ind, int cnt, int dir)
5927c478bd9Sstevel@tonic-gate {
5937c478bd9Sstevel@tonic-gate 	int	i;
5947c478bd9Sstevel@tonic-gate 	int	total;
5957c478bd9Sstevel@tonic-gate 	int	first_ind;
5967c478bd9Sstevel@tonic-gate 
5977c478bd9Sstevel@tonic-gate 	for (i=srt_ind, first_ind=srt_ind, total=0; i!=end_ind; i+=dir) {
5987c478bd9Sstevel@tonic-gate 	    if ((ap->ap_memmapp)[i] == ALTS_BAD) {
5997c478bd9Sstevel@tonic-gate 		total = 0;
6007c478bd9Sstevel@tonic-gate 		first_ind = i + dir;
6017c478bd9Sstevel@tonic-gate 		continue;
6027c478bd9Sstevel@tonic-gate 	    }
6037c478bd9Sstevel@tonic-gate 	    total++;
6047c478bd9Sstevel@tonic-gate 	    if (total == cnt)
6057c478bd9Sstevel@tonic-gate 		return(first_ind);
6067c478bd9Sstevel@tonic-gate 
6077c478bd9Sstevel@tonic-gate 	}
608*052b6e8aSbg159949 	return(0);
6097c478bd9Sstevel@tonic-gate }
6107c478bd9Sstevel@tonic-gate 
6117c478bd9Sstevel@tonic-gate 
6127c478bd9Sstevel@tonic-gate 
6137c478bd9Sstevel@tonic-gate /*
6147c478bd9Sstevel@tonic-gate  * 	bubble sort the entry table into ascending order
6157c478bd9Sstevel@tonic-gate  */
616*052b6e8aSbg159949 static void
617*052b6e8aSbg159949 ent_sort(struct alts_ent buf[], int cnt)
6187c478bd9Sstevel@tonic-gate {
6197c478bd9Sstevel@tonic-gate struct	alts_ent temp;
6207c478bd9Sstevel@tonic-gate int	flag;
6217c478bd9Sstevel@tonic-gate int	i,j;
6227c478bd9Sstevel@tonic-gate 
6237c478bd9Sstevel@tonic-gate 	for (i=0; i<cnt-1; i++) {
6247c478bd9Sstevel@tonic-gate 	    temp = buf[cnt-1];
6257c478bd9Sstevel@tonic-gate 	    flag = 1;
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate 	    for (j=cnt-1; j>i; j--) {
6287c478bd9Sstevel@tonic-gate 		if (buf[j-1].bad_start < temp.bad_start) {
6297c478bd9Sstevel@tonic-gate 		    buf[j] = temp;
6307c478bd9Sstevel@tonic-gate 		    temp = buf[j-1];
6317c478bd9Sstevel@tonic-gate 		} else {
6327c478bd9Sstevel@tonic-gate 		    buf[j] = buf[j-1];
6337c478bd9Sstevel@tonic-gate 		    flag = 0;
6347c478bd9Sstevel@tonic-gate 		}
6357c478bd9Sstevel@tonic-gate 	    }
6367c478bd9Sstevel@tonic-gate 	    buf[i] = temp;
6377c478bd9Sstevel@tonic-gate 	    if (flag) break;
6387c478bd9Sstevel@tonic-gate 	}
6397c478bd9Sstevel@tonic-gate 
6407c478bd9Sstevel@tonic-gate }
6417c478bd9Sstevel@tonic-gate 
6427c478bd9Sstevel@tonic-gate 
6437c478bd9Sstevel@tonic-gate /*
6447c478bd9Sstevel@tonic-gate  *	compress all the contiguous bad sectors into a single entry
6457c478bd9Sstevel@tonic-gate  *	in the entry table. The entry table must be sorted into ascending
6467c478bd9Sstevel@tonic-gate  *	before the compression.
6477c478bd9Sstevel@tonic-gate  */
648*052b6e8aSbg159949 static void
649*052b6e8aSbg159949 ent_compress(struct alts_ent buf[], int cnt)
6507c478bd9Sstevel@tonic-gate {
6517c478bd9Sstevel@tonic-gate int	keyp;
6527c478bd9Sstevel@tonic-gate int	movp;
6537c478bd9Sstevel@tonic-gate int	i;
6547c478bd9Sstevel@tonic-gate 
6557c478bd9Sstevel@tonic-gate 	for (i=0; i<cnt; i++) {
6567c478bd9Sstevel@tonic-gate 	    if (buf[i].bad_start == ALTS_ENT_EMPTY)
6577c478bd9Sstevel@tonic-gate 		continue;
6587c478bd9Sstevel@tonic-gate 	    for (keyp=i, movp=i+1; movp<cnt; movp++) {
6597c478bd9Sstevel@tonic-gate 	    	if (buf[movp].bad_start == ALTS_ENT_EMPTY)
6607c478bd9Sstevel@tonic-gate 			continue;
6617c478bd9Sstevel@tonic-gate 		if (buf[keyp].bad_end+1 != buf[movp].bad_start)
6627c478bd9Sstevel@tonic-gate 		    break;
6637c478bd9Sstevel@tonic-gate 		buf[keyp].bad_end++;
6647c478bd9Sstevel@tonic-gate 		buf[movp].bad_start = ALTS_ENT_EMPTY;
6657c478bd9Sstevel@tonic-gate 	    }
6667c478bd9Sstevel@tonic-gate 	    if (movp == cnt) break;
6677c478bd9Sstevel@tonic-gate 	}
6687c478bd9Sstevel@tonic-gate }
6697c478bd9Sstevel@tonic-gate 
6707c478bd9Sstevel@tonic-gate 
6717c478bd9Sstevel@tonic-gate /*
6727c478bd9Sstevel@tonic-gate  *	merging two entry tables into a single table. In addition,
6737c478bd9Sstevel@tonic-gate  *	all empty slots in the entry table will be removed.
6747c478bd9Sstevel@tonic-gate  */
675*052b6e8aSbg159949 static int
676*052b6e8aSbg159949 ent_merge(
677*052b6e8aSbg159949 	struct alts_ent buf[],
678*052b6e8aSbg159949 	struct alts_ent list1[],
679*052b6e8aSbg159949 	int    lcnt1,
680*052b6e8aSbg159949 	struct alts_ent list2[],
681*052b6e8aSbg159949 	int    lcnt2)
6827c478bd9Sstevel@tonic-gate {
6837c478bd9Sstevel@tonic-gate 	int	i;
6847c478bd9Sstevel@tonic-gate 	int	j1,j2;
6857c478bd9Sstevel@tonic-gate 
6867c478bd9Sstevel@tonic-gate 	for (i=0, j1=0, j2=0; j1<lcnt1 && j2<lcnt2;) {
6877c478bd9Sstevel@tonic-gate 	    if (list1[j1].bad_start == ALTS_ENT_EMPTY) {
6887c478bd9Sstevel@tonic-gate 		j1++;
6897c478bd9Sstevel@tonic-gate 		continue;
6907c478bd9Sstevel@tonic-gate 	    }
6917c478bd9Sstevel@tonic-gate 	    if (list2[j2].bad_start == ALTS_ENT_EMPTY) {
6927c478bd9Sstevel@tonic-gate 		j2++;
6937c478bd9Sstevel@tonic-gate 		continue;
6947c478bd9Sstevel@tonic-gate 	    }
6957c478bd9Sstevel@tonic-gate 	    if (list1[j1].bad_start < list2[j2].bad_start)
6967c478bd9Sstevel@tonic-gate 		buf[i++] = list1[j1++];
6977c478bd9Sstevel@tonic-gate 	    else
6987c478bd9Sstevel@tonic-gate 		buf[i++] = list2[j2++];
6997c478bd9Sstevel@tonic-gate 	}
7007c478bd9Sstevel@tonic-gate 	for (; j1<lcnt1; j1++) {
7017c478bd9Sstevel@tonic-gate 	    if (list1[j1].bad_start == ALTS_ENT_EMPTY)
7027c478bd9Sstevel@tonic-gate 		continue;
7037c478bd9Sstevel@tonic-gate 	    buf[i++] = list1[j1];
7047c478bd9Sstevel@tonic-gate 	}
7057c478bd9Sstevel@tonic-gate 	for (; j2<lcnt2; j2++) {
7067c478bd9Sstevel@tonic-gate 	    if (list2[j2].bad_start == ALTS_ENT_EMPTY)
7077c478bd9Sstevel@tonic-gate 		continue;
7087c478bd9Sstevel@tonic-gate 	    buf[i++] = list2[j2];
7097c478bd9Sstevel@tonic-gate 	}
7107c478bd9Sstevel@tonic-gate 	return (i);
7117c478bd9Sstevel@tonic-gate }
7127c478bd9Sstevel@tonic-gate 
7137c478bd9Sstevel@tonic-gate 
7147c478bd9Sstevel@tonic-gate /*
7157c478bd9Sstevel@tonic-gate  *	binary search for bad sector in the alternate entry table
7167c478bd9Sstevel@tonic-gate  */
717*052b6e8aSbg159949 static int
718*052b6e8aSbg159949 ent_bsearch(struct alts_ent buf[], int cnt, struct alts_ent *key)
7197c478bd9Sstevel@tonic-gate {
7207c478bd9Sstevel@tonic-gate 	int	i;
7217c478bd9Sstevel@tonic-gate 	int	ind;
7227c478bd9Sstevel@tonic-gate 	int	interval;
7237c478bd9Sstevel@tonic-gate 	int	mystatus = -1;
7247c478bd9Sstevel@tonic-gate 
7257c478bd9Sstevel@tonic-gate 	if (!cnt) return (mystatus);
7267c478bd9Sstevel@tonic-gate 
7277c478bd9Sstevel@tonic-gate 	for (i=1; i<=cnt; i<<=1)
7287c478bd9Sstevel@tonic-gate 	    ind=i;
7297c478bd9Sstevel@tonic-gate 
7307c478bd9Sstevel@tonic-gate 	for (interval=ind; interval; ) {
7317c478bd9Sstevel@tonic-gate /*
7327c478bd9Sstevel@tonic-gate 	    printf("ind= %d, intv= %d; ",ind, interval);
7337c478bd9Sstevel@tonic-gate */
7347c478bd9Sstevel@tonic-gate 	    if ((key->bad_start >= buf[ind-1].bad_start) &&
7357c478bd9Sstevel@tonic-gate 		(key->bad_start <= buf[ind-1].bad_end)) {
7367c478bd9Sstevel@tonic-gate 		return(mystatus=ind-1);
7377c478bd9Sstevel@tonic-gate 	    } else {
7387c478bd9Sstevel@tonic-gate 	    	interval >>= 1;
7397c478bd9Sstevel@tonic-gate 		if (!interval) break;
7407c478bd9Sstevel@tonic-gate 		if (key->bad_start < buf[ind-1].bad_start) {
7417c478bd9Sstevel@tonic-gate 		    ind = ind - interval;
7427c478bd9Sstevel@tonic-gate 		} else {
7437c478bd9Sstevel@tonic-gate  /* 		    if key is larger than the last element then break	*/
7447c478bd9Sstevel@tonic-gate 		    if (ind == cnt) break;
7457c478bd9Sstevel@tonic-gate 		    if ((ind+interval) <= cnt)
7467c478bd9Sstevel@tonic-gate 		    	ind += interval;
7477c478bd9Sstevel@tonic-gate 		}
7487c478bd9Sstevel@tonic-gate 	    }
7497c478bd9Sstevel@tonic-gate 	}
7507c478bd9Sstevel@tonic-gate 	return(mystatus);
7517c478bd9Sstevel@tonic-gate }
7527c478bd9Sstevel@tonic-gate 
7537c478bd9Sstevel@tonic-gate /*
7547c478bd9Sstevel@tonic-gate  *	check for bad sector in assigned alternate sectors
7557c478bd9Sstevel@tonic-gate  */
756*052b6e8aSbg159949 static int
757*052b6e8aSbg159949 chk_bad_altsctr(daddr_t badsec)
7587c478bd9Sstevel@tonic-gate {
7597c478bd9Sstevel@tonic-gate 	int	i;
7607c478bd9Sstevel@tonic-gate 	int	j;
7617c478bd9Sstevel@tonic-gate 	daddr_t	numsec;
7627c478bd9Sstevel@tonic-gate 	int	mystatus = FAILURE;
7637c478bd9Sstevel@tonic-gate 	int	cnt = ap->ap_tblp->alts_ent_used;
7647c478bd9Sstevel@tonic-gate 	daddr_t intv[3];
7657c478bd9Sstevel@tonic-gate 
7667c478bd9Sstevel@tonic-gate 	for (i=0; i<cnt; i++) {
7677c478bd9Sstevel@tonic-gate 	    numsec = (ap->ap_entp)[i].bad_end - (ap->ap_entp)[i].bad_start;
7687c478bd9Sstevel@tonic-gate 	    if ((badsec >= (ap->ap_entp)[i].good_start) &&
7697c478bd9Sstevel@tonic-gate 		(badsec <= ((ap->ap_entp)[i].good_start + numsec))) {
7707c478bd9Sstevel@tonic-gate 		fprintf(stderr, "Bad sector %ld is an assigned alternate sector.\n", badsec);
7717c478bd9Sstevel@tonic-gate 		exit(66);
7727c478bd9Sstevel@tonic-gate /*
7737c478bd9Sstevel@tonic-gate 		if (!numsec) {
7747c478bd9Sstevel@tonic-gate 		    (ap->ap_entp)[i].good_start = 0;
7757c478bd9Sstevel@tonic-gate 		    return(mystatus);
7767c478bd9Sstevel@tonic-gate 		}
7777c478bd9Sstevel@tonic-gate 		intv[0] = badsec - (ap->ap_entp)[i].good_start;
7787c478bd9Sstevel@tonic-gate 		intv[1] = 1;
7797c478bd9Sstevel@tonic-gate 		intv[2] = (ap->ap_entp)[i].good_start + numsec - badsec;
7807c478bd9Sstevel@tonic-gate */
7817c478bd9Sstevel@tonic-gate 	    }
7827c478bd9Sstevel@tonic-gate 	}
7837c478bd9Sstevel@tonic-gate /*	the bad sector has already been identified as bad		*/
7847c478bd9Sstevel@tonic-gate 	return(mystatus=SUCCESS);
7857c478bd9Sstevel@tonic-gate 
7867c478bd9Sstevel@tonic-gate }
7877c478bd9Sstevel@tonic-gate 
7887c478bd9Sstevel@tonic-gate 
7897c478bd9Sstevel@tonic-gate /*
7907c478bd9Sstevel@tonic-gate  * print_altsec () -- print alternate sector information
7917c478bd9Sstevel@tonic-gate  */
792*052b6e8aSbg159949 int
793*052b6e8aSbg159949 print_altsec(struct partition *part)
7947c478bd9Sstevel@tonic-gate {
7957c478bd9Sstevel@tonic-gate 	ap->ap_tblp = NULL;
7967c478bd9Sstevel@tonic-gate 	ap->ap_flag &= ~ALTS_ADDPART;
7977c478bd9Sstevel@tonic-gate 	read_altsctr(part, 0);
7987c478bd9Sstevel@tonic-gate 	print_altsctr();
7997c478bd9Sstevel@tonic-gate 	return(SUCCESS);
8007c478bd9Sstevel@tonic-gate }
8017c478bd9Sstevel@tonic-gate 
802*052b6e8aSbg159949 static void
803*052b6e8aSbg159949 print_altsctr(void)
8047c478bd9Sstevel@tonic-gate {
8057c478bd9Sstevel@tonic-gate 	int	i;
8067c478bd9Sstevel@tonic-gate 	int	totalloc;
8077c478bd9Sstevel@tonic-gate 	int	avail;
8087c478bd9Sstevel@tonic-gate 
8097c478bd9Sstevel@tonic-gate /*	find # of available alternate sectors				*/
8107c478bd9Sstevel@tonic-gate 	for (i=0, totalloc=0; i<ap->part.p_size; i++) {
8117c478bd9Sstevel@tonic-gate 	    if ((ap->ap_memmapp)[i])
8127c478bd9Sstevel@tonic-gate 		totalloc++;
8137c478bd9Sstevel@tonic-gate 	}
8147c478bd9Sstevel@tonic-gate /*
8157c478bd9Sstevel@tonic-gate  *	available = size of partition - allocated sectors/bad sectors
8167c478bd9Sstevel@tonic-gate  *		    - partition table - partition map
8177c478bd9Sstevel@tonic-gate  *		    - entry table
8187c478bd9Sstevel@tonic-gate  */
8197c478bd9Sstevel@tonic-gate 	avail = ap->part.p_size - totalloc;
8207c478bd9Sstevel@tonic-gate 	avail = avail - (ap->ap_tbl_secsiz/NBPSCTR)
8217c478bd9Sstevel@tonic-gate 		- ap->ap_map_sectot;
8227c478bd9Sstevel@tonic-gate 	avail = avail-(ap->ap_tblp->alts_ent_end -ap->ap_tblp->alts_ent_base+1);
8237c478bd9Sstevel@tonic-gate 	if (avail < 0) avail = 0;
8247c478bd9Sstevel@tonic-gate 
8257c478bd9Sstevel@tonic-gate 	printf("\nALTERNATE SECTOR/TRACK MAPPING TABLE:\n");
8267c478bd9Sstevel@tonic-gate 	printf("\nBad Sector Start\tAlternate Sector Start\t\tCount\n");
8277c478bd9Sstevel@tonic-gate 
8287c478bd9Sstevel@tonic-gate 	for (i=0; i<ap->ap_tblp->alts_ent_used; i++) {
8297c478bd9Sstevel@tonic-gate 	     printf("\t%ld\t     ->\t\t%ld\t\t\t   %ld\n",
8307c478bd9Sstevel@tonic-gate 		(ap->ap_entp)[i].bad_start,
8317c478bd9Sstevel@tonic-gate 		(ap->ap_entp)[i].good_start,
8327c478bd9Sstevel@tonic-gate 		((ap->ap_entp)[i].bad_end - (ap->ap_entp)[i].bad_start + 1));
8337c478bd9Sstevel@tonic-gate 	}
8347c478bd9Sstevel@tonic-gate 	printf("\n      %ld alternate sector(s) left for allocation.\n", avail);
8357c478bd9Sstevel@tonic-gate 
8367c478bd9Sstevel@tonic-gate }
8377c478bd9Sstevel@tonic-gate 
838*052b6e8aSbg159949 static int
839*052b6e8aSbg159949 absdsk_io(int fd, uint srtsec, char *bufp, uint len, int ioflag)
8407c478bd9Sstevel@tonic-gate {
8417c478bd9Sstevel@tonic-gate 	int	rc;
8427c478bd9Sstevel@tonic-gate 
8437c478bd9Sstevel@tonic-gate 	if (lseek (fd, srtsec * NBPSCTR, SEEK_SET) == -1)
8447c478bd9Sstevel@tonic-gate 		return(FAILURE);
8457c478bd9Sstevel@tonic-gate 	switch (ioflag)
8467c478bd9Sstevel@tonic-gate 	{
8477c478bd9Sstevel@tonic-gate 	case CMD_READ:
8487c478bd9Sstevel@tonic-gate 		rc = read (fd, bufp, len);
8497c478bd9Sstevel@tonic-gate 		break;
8507c478bd9Sstevel@tonic-gate 	case CMD_WRITE:
8517c478bd9Sstevel@tonic-gate 		rc = write (fd, bufp, len);
8527c478bd9Sstevel@tonic-gate 		break;
8537c478bd9Sstevel@tonic-gate 	default:
8547c478bd9Sstevel@tonic-gate 		break;
8557c478bd9Sstevel@tonic-gate 	}
8567c478bd9Sstevel@tonic-gate 	if (rc == -1)
8577c478bd9Sstevel@tonic-gate 		return(FAILURE);
8587c478bd9Sstevel@tonic-gate 	return(SUCCESS);
8597c478bd9Sstevel@tonic-gate }
860