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