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