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