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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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