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*7563SPrasad.Singamsetty@Sun.COM * Common Development and Distribution License (the "License").
6*7563SPrasad.Singamsetty@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*7563SPrasad.Singamsetty@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate *
250Sstevel@tonic-gate * copyright (c) 1990, 1991 UNIX System Laboratories, Inc.
260Sstevel@tonic-gate * copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T
270Sstevel@tonic-gate * 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>
430Sstevel@tonic-gate #include <string.h>
440Sstevel@tonic-gate #include <sys/vtoc.h>
450Sstevel@tonic-gate #include <sys/param.h>
460Sstevel@tonic-gate #include <sys/dkio.h>
470Sstevel@tonic-gate #include <sys/dktp/altsctr.h>
480Sstevel@tonic-gate #include <sys/dktp/fdisk.h>
490Sstevel@tonic-gate #include "badsec.h"
500Sstevel@tonic-gate #include "global.h"
510Sstevel@tonic-gate #include "ctlr_ata.h"
520Sstevel@tonic-gate #include "misc.h"
530Sstevel@tonic-gate
540Sstevel@tonic-gate #define FAILURE 1
550Sstevel@tonic-gate #define SUCCESS 0
560Sstevel@tonic-gate
570Sstevel@tonic-gate #define CMD_READ 0
580Sstevel@tonic-gate #define CMD_WRITE 1
590Sstevel@tonic-gate
600Sstevel@tonic-gate struct badsec_lst *badsl_chain = NULL;
610Sstevel@tonic-gate int badsl_chain_cnt = 0;
620Sstevel@tonic-gate struct badsec_lst *gbadsl_chain = NULL;
630Sstevel@tonic-gate int gbadsl_chain_cnt = 0;
640Sstevel@tonic-gate
650Sstevel@tonic-gate static struct alts_mempart alts_part = { 0, NULL, 0 };
660Sstevel@tonic-gate struct alts_mempart *ap = &alts_part; /* pointer to incore */
670Sstevel@tonic-gate /* alts tables */
680Sstevel@tonic-gate
690Sstevel@tonic-gate /* prototypes */
70*7563SPrasad.Singamsetty@Sun.COM int updatebadsec(struct dkl_partition *, int);
71*7563SPrasad.Singamsetty@Sun.COM int read_altsctr(struct dkl_partition *);
720Sstevel@tonic-gate static int chk_badsec();
730Sstevel@tonic-gate static int init_altsctr();
740Sstevel@tonic-gate static int get_altsctr();
750Sstevel@tonic-gate int wr_altsctr();
760Sstevel@tonic-gate static void get_badsec();
770Sstevel@tonic-gate static int count_badsec();
780Sstevel@tonic-gate static int gen_alts_ent();
790Sstevel@tonic-gate static int assign_altsctr();
800Sstevel@tonic-gate static void expand_map();
810Sstevel@tonic-gate static void compress_map();
82*7563SPrasad.Singamsetty@Sun.COM static int altsmap_getbit(blkaddr_t);
83*7563SPrasad.Singamsetty@Sun.COM static blkaddr_t altsmap_alloc(blkaddr_t, blkaddr_t, int, int);
840Sstevel@tonic-gate static void ent_sort(struct alts_ent *, int);
850Sstevel@tonic-gate static void ent_compress(struct alts_ent *, int);
860Sstevel@tonic-gate static int ent_merge(struct alts_ent *, struct alts_ent *, int,
870Sstevel@tonic-gate struct alts_ent *, int);
880Sstevel@tonic-gate static int ent_bsearch(struct alts_ent *, int, struct alts_ent *);
89*7563SPrasad.Singamsetty@Sun.COM static int chk_bad_altsctr(blkaddr_t);
900Sstevel@tonic-gate
910Sstevel@tonic-gate /*
920Sstevel@tonic-gate * updatebadsec () -- update bad sector/track mapping tables
930Sstevel@tonic-gate */
940Sstevel@tonic-gate int
updatebadsec(part,init_flag)950Sstevel@tonic-gate updatebadsec(part, init_flag)
960Sstevel@tonic-gate int init_flag;
97*7563SPrasad.Singamsetty@Sun.COM struct dkl_partition *part;
980Sstevel@tonic-gate {
990Sstevel@tonic-gate if (init_flag)
1000Sstevel@tonic-gate ap->ap_flag |= ALTS_ADDPART;
1010Sstevel@tonic-gate get_badsec();
1020Sstevel@tonic-gate (void) read_altsctr(part);
1030Sstevel@tonic-gate ent_sort(ap->ap_gbadp, ap->ap_gbadcnt);
1040Sstevel@tonic-gate ent_compress(ap->ap_gbadp, ap->ap_gbadcnt);
1050Sstevel@tonic-gate (void) gen_alts_ent();
1060Sstevel@tonic-gate compress_map();
1070Sstevel@tonic-gate return (SUCCESS);
1080Sstevel@tonic-gate }
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate /*
1110Sstevel@tonic-gate * read_altsctr( ptr to alternate sector partition )
1120Sstevel@tonic-gate * -- read the alternate sector partition tables
1130Sstevel@tonic-gate */
1140Sstevel@tonic-gate int
read_altsctr(part)1150Sstevel@tonic-gate read_altsctr(part)
116*7563SPrasad.Singamsetty@Sun.COM struct dkl_partition *part;
1170Sstevel@tonic-gate {
1180Sstevel@tonic-gate if (ap->ap_tblp == NULL) {
1190Sstevel@tonic-gate /* allocate buffer for the alts partition table (sector size) */
1200Sstevel@tonic-gate ap->ap_tbl_secsiz = byte_to_secsiz(ALTS_PARTTBL_SIZE, NBPSCTR);
1210Sstevel@tonic-gate ap->ap_tblp = (struct alts_parttbl *)malloc(ap->ap_tbl_secsiz);
1220Sstevel@tonic-gate if (ap->ap_tblp == NULL) {
1230Sstevel@tonic-gate (void) fprintf(stderr,
1240Sstevel@tonic-gate "Unable to malloc alternate partition table.\n");
1250Sstevel@tonic-gate return (50);
1260Sstevel@tonic-gate }
1270Sstevel@tonic-gate
1280Sstevel@tonic-gate /* allocate buffer for the alts partition map (sector size) */
1290Sstevel@tonic-gate /* buffers include the disk image bit map */
1300Sstevel@tonic-gate /* and the incore transformed char map */
1310Sstevel@tonic-gate
1320Sstevel@tonic-gate if ((ap->ap_memmapp = (uchar_t *)malloc(part->p_size)) == NULL) {
1330Sstevel@tonic-gate (void) fprintf(stderr,
1340Sstevel@tonic-gate "Unable to malloc incore alternate partition map.\n");
1350Sstevel@tonic-gate return (51);
1360Sstevel@tonic-gate }
1370Sstevel@tonic-gate ap->ap_tblp->alts_map_len = (part->p_size + 8 - 1) / 8;
1380Sstevel@tonic-gate ap->ap_map_secsiz = byte_to_secsiz(ap->ap_tblp->alts_map_len,
1390Sstevel@tonic-gate NBPSCTR);
1400Sstevel@tonic-gate ap->ap_map_sectot = ap->ap_map_secsiz / NBPSCTR;
1410Sstevel@tonic-gate if ((ap->ap_mapp = (uchar_t *)malloc(ap->ap_map_secsiz)) == NULL) {
1420Sstevel@tonic-gate (void) fprintf(stderr,
1430Sstevel@tonic-gate "Unable to malloc alternate partition map.\n");
1440Sstevel@tonic-gate return (52);
1450Sstevel@tonic-gate }
1460Sstevel@tonic-gate /* clear the buffers to zero */
1470Sstevel@tonic-gate (void) memset(ap->ap_memmapp, 0, part->p_size);
1480Sstevel@tonic-gate (void) memset(ap->ap_mapp, 0, ap->ap_map_secsiz);
1490Sstevel@tonic-gate ap->part = *part; /* struct copy */
1500Sstevel@tonic-gate
1510Sstevel@tonic-gate /*
1520Sstevel@tonic-gate * if add alternate partition flag is set, then install the partition
1530Sstevel@tonic-gate * otherwise read the alts partition info from disk
1540Sstevel@tonic-gate * if failed, then assume the first installation
1550Sstevel@tonic-gate */
1560Sstevel@tonic-gate if (ap->ap_flag & ALTS_ADDPART)
1570Sstevel@tonic-gate {
1580Sstevel@tonic-gate (void) fprintf(stderr,
1590Sstevel@tonic-gate "WARNING: Manually initializing alternate table.\n");
1600Sstevel@tonic-gate (void) init_altsctr();
1610Sstevel@tonic-gate } else {
1620Sstevel@tonic-gate if (get_altsctr() == SUCCESS)
1630Sstevel@tonic-gate (void) chk_badsec();
1640Sstevel@tonic-gate else
1650Sstevel@tonic-gate (void) init_altsctr();
1660Sstevel@tonic-gate }
1670Sstevel@tonic-gate }
1680Sstevel@tonic-gate return (SUCCESS);
1690Sstevel@tonic-gate }
1700Sstevel@tonic-gate
1710Sstevel@tonic-gate
1720Sstevel@tonic-gate /*
1730Sstevel@tonic-gate * checking duplicate bad sectors or bad sectors in ALTSCTR partition
1740Sstevel@tonic-gate */
1750Sstevel@tonic-gate static int
chk_badsec()1760Sstevel@tonic-gate chk_badsec()
1770Sstevel@tonic-gate {
178*7563SPrasad.Singamsetty@Sun.COM blkaddr_t badsec;
179*7563SPrasad.Singamsetty@Sun.COM blkaddr_t altsp_srtsec = ap->part.p_start;
180*7563SPrasad.Singamsetty@Sun.COM blkaddr_t altsp_endsec = ap->part.p_start + ap->part.p_size - 1;
1810Sstevel@tonic-gate int cnt;
1820Sstevel@tonic-gate int status;
1830Sstevel@tonic-gate
1840Sstevel@tonic-gate for (cnt = 0; cnt < ap->ap_gbadcnt; cnt++) {
1850Sstevel@tonic-gate badsec = (ap->ap_gbadp)[cnt].bad_start;
1860Sstevel@tonic-gate
1870Sstevel@tonic-gate /* if bad sector is within the ATLSCTR partition */
1880Sstevel@tonic-gate if ((badsec >= altsp_srtsec) && (badsec <= altsp_endsec)) {
1890Sstevel@tonic-gate if ((ap->ap_memmapp)[badsec - altsp_srtsec] != ALTS_BAD) {
1900Sstevel@tonic-gate if ((badsec >= altsp_srtsec) && (badsec <= (altsp_srtsec +
1910Sstevel@tonic-gate ap->ap_tbl_secsiz / NBPSCTR - 1))) {
1920Sstevel@tonic-gate (void) fprintf(stderr,
1930Sstevel@tonic-gate "Alternate partition information table is bad.\n");
1940Sstevel@tonic-gate return (53);
1950Sstevel@tonic-gate }
1960Sstevel@tonic-gate if ((badsec >= altsp_srtsec+ap->ap_tblp->alts_map_base) &&
1970Sstevel@tonic-gate (badsec <= (altsp_srtsec + ap->ap_tblp->alts_map_base +
1980Sstevel@tonic-gate ap->ap_map_sectot - 1))) {
1990Sstevel@tonic-gate (void) fprintf(stderr,
2000Sstevel@tonic-gate "Alternate partition map is bad.\n");
2010Sstevel@tonic-gate return (54);
2020Sstevel@tonic-gate }
2030Sstevel@tonic-gate if ((badsec >= altsp_srtsec+ap->ap_tblp->alts_ent_base) &&
2040Sstevel@tonic-gate (badsec <= (altsp_srtsec + ap->ap_tblp->alts_ent_base +
2050Sstevel@tonic-gate ap->ap_ent_secsiz / NBPSCTR - 1))) {
2060Sstevel@tonic-gate (void) fprintf(stderr,
2070Sstevel@tonic-gate "Alternate partition entry table is bad.\n");
2080Sstevel@tonic-gate return (55);
2090Sstevel@tonic-gate }
2100Sstevel@tonic-gate (ap->ap_memmapp)[badsec - altsp_srtsec] = ALTS_BAD;
211*7563SPrasad.Singamsetty@Sun.COM (ap->ap_gbadp)[cnt].bad_start = (uint32_t)ALTS_ENT_EMPTY;
2120Sstevel@tonic-gate } else {
2130Sstevel@tonic-gate status = chk_bad_altsctr(badsec);
214*7563SPrasad.Singamsetty@Sun.COM (ap->ap_gbadp)[cnt].bad_start = (uint32_t)ALTS_ENT_EMPTY;
2150Sstevel@tonic-gate }
2160Sstevel@tonic-gate } else {
2170Sstevel@tonic-gate /*
2180Sstevel@tonic-gate * binary search for bad sector in the alts entry table
2190Sstevel@tonic-gate */
2200Sstevel@tonic-gate status = ent_bsearch(ap->ap_entp, ap->ap_tblp->alts_ent_used,
2210Sstevel@tonic-gate &((ap->ap_gbadp)[cnt]));
2220Sstevel@tonic-gate /*
2230Sstevel@tonic-gate * if the bad sector had already been remapped(found in alts_entry)
2240Sstevel@tonic-gate * then ignore the bad sector
2250Sstevel@tonic-gate */
2260Sstevel@tonic-gate if (status != -1) {
227*7563SPrasad.Singamsetty@Sun.COM (ap->ap_gbadp)[cnt].bad_start = (uint32_t)ALTS_ENT_EMPTY;
2280Sstevel@tonic-gate }
2290Sstevel@tonic-gate }
2300Sstevel@tonic-gate }
2310Sstevel@tonic-gate return (SUCCESS);
2320Sstevel@tonic-gate }
2330Sstevel@tonic-gate
2340Sstevel@tonic-gate /*
2350Sstevel@tonic-gate * initialize the alternate partition tables
2360Sstevel@tonic-gate */
2370Sstevel@tonic-gate static int
init_altsctr()2380Sstevel@tonic-gate init_altsctr()
2390Sstevel@tonic-gate {
240*7563SPrasad.Singamsetty@Sun.COM blkaddr_t badsec;
241*7563SPrasad.Singamsetty@Sun.COM blkaddr_t altsp_srtsec = ap->part.p_start;
242*7563SPrasad.Singamsetty@Sun.COM blkaddr_t altsp_endsec = ap->part.p_start + ap->part.p_size - 1;
2430Sstevel@tonic-gate int cnt;
2440Sstevel@tonic-gate
2450Sstevel@tonic-gate ap->ap_entp = NULL;
2460Sstevel@tonic-gate ap->ap_ent_secsiz = 0;
2470Sstevel@tonic-gate ap->ap_tblp->alts_sanity = ALTS_SANITY;
2480Sstevel@tonic-gate ap->ap_tblp->alts_version = ALTS_VERSION1;
2490Sstevel@tonic-gate ap->ap_tblp->alts_map_len = (ap->part.p_size + 8 - 1) / 8;
2500Sstevel@tonic-gate ap->ap_tblp->alts_ent_used = 0;
2510Sstevel@tonic-gate ap->ap_tblp->alts_ent_base = 0;
2520Sstevel@tonic-gate ap->ap_tblp->alts_ent_end = 0;
2530Sstevel@tonic-gate ap->ap_tblp->alts_resv_base = ap->part.p_size - 1;
2540Sstevel@tonic-gate for (cnt = 0; cnt < 5; cnt++)
2550Sstevel@tonic-gate ap->ap_tblp->alts_pad[cnt] = 0;
2560Sstevel@tonic-gate
2570Sstevel@tonic-gate for (cnt = 0; cnt < ap->ap_gbadcnt; cnt++) {
2580Sstevel@tonic-gate badsec = (ap->ap_gbadp)[cnt].bad_start;
2590Sstevel@tonic-gate if ((badsec >= altsp_srtsec) && (badsec <= altsp_endsec)) {
2600Sstevel@tonic-gate if (badsec == altsp_srtsec) {
2610Sstevel@tonic-gate (void) fprintf(stderr,
2620Sstevel@tonic-gate "First sector of alternate partition is bad.\n");
2630Sstevel@tonic-gate return (56);
2640Sstevel@tonic-gate }
2650Sstevel@tonic-gate (ap->ap_memmapp)[badsec - altsp_srtsec] = ALTS_BAD;
266*7563SPrasad.Singamsetty@Sun.COM (ap->ap_gbadp)[cnt].bad_start = (uint32_t)ALTS_ENT_EMPTY;
2670Sstevel@tonic-gate }
2680Sstevel@tonic-gate }
2690Sstevel@tonic-gate
2700Sstevel@tonic-gate /* allocate the alts_map on disk skipping possible bad sectors */
2710Sstevel@tonic-gate ap->ap_tblp->alts_map_base =
2720Sstevel@tonic-gate altsmap_alloc(ap->ap_tbl_secsiz / NBPSCTR,
2730Sstevel@tonic-gate ap->part.p_size, ap->ap_map_sectot, ALTS_MAP_UP);
2740Sstevel@tonic-gate if (ap->ap_tblp->alts_map_base == NULL) {
2750Sstevel@tonic-gate perror("Unable to allocate alternate map on disk: ");
2760Sstevel@tonic-gate return (57);
2770Sstevel@tonic-gate }
2780Sstevel@tonic-gate (void) wr_altsctr();
2790Sstevel@tonic-gate
2800Sstevel@tonic-gate return (SUCCESS);
2810Sstevel@tonic-gate }
2820Sstevel@tonic-gate
2830Sstevel@tonic-gate
2840Sstevel@tonic-gate /*
2850Sstevel@tonic-gate * read the alternate partition tables from disk
2860Sstevel@tonic-gate */
2870Sstevel@tonic-gate static int
get_altsctr()2880Sstevel@tonic-gate get_altsctr()
2890Sstevel@tonic-gate {
2900Sstevel@tonic-gate int mystatus = FAILURE;
2910Sstevel@tonic-gate int status = 0;
2920Sstevel@tonic-gate
2930Sstevel@tonic-gate /* get alts partition table info */
2940Sstevel@tonic-gate
2950Sstevel@tonic-gate status = ata_rdwr(DIR_READ, cur_file, altsec_offset,
2960Sstevel@tonic-gate ap->ap_tbl_secsiz / UBSIZE, (char *)ap->ap_tblp,
2970Sstevel@tonic-gate 0, NULL);
2980Sstevel@tonic-gate if (status == FAILURE) {
2990Sstevel@tonic-gate perror("Unable to read alternate sector partition: ");
3000Sstevel@tonic-gate return (58);
3010Sstevel@tonic-gate }
3020Sstevel@tonic-gate if (ap->ap_tblp->alts_sanity != ALTS_SANITY)
3030Sstevel@tonic-gate return (mystatus);
3040Sstevel@tonic-gate
3050Sstevel@tonic-gate /* get the alts map */
3060Sstevel@tonic-gate status = ata_rdwr(DIR_READ, cur_file,
3070Sstevel@tonic-gate (ap->ap_tblp->alts_map_base) + altsec_offset,
3080Sstevel@tonic-gate ap->ap_map_secsiz / UBSIZE, (char *)ap->ap_mapp, 0, NULL);
3090Sstevel@tonic-gate if (status == FAILURE) {
3100Sstevel@tonic-gate perror("Unable to read alternate sector partition map: ");
3110Sstevel@tonic-gate return (59);
3120Sstevel@tonic-gate }
3130Sstevel@tonic-gate
3140Sstevel@tonic-gate /* transform the disk image bit-map to incore char map */
3150Sstevel@tonic-gate expand_map();
3160Sstevel@tonic-gate
3170Sstevel@tonic-gate if (ap->ap_tblp->alts_ent_used == 0) {
3180Sstevel@tonic-gate ap->ap_entp = NULL;
3190Sstevel@tonic-gate ap->ap_ent_secsiz = 0;
3200Sstevel@tonic-gate } else {
3210Sstevel@tonic-gate ap->ap_ent_secsiz = byte_to_secsiz(
3220Sstevel@tonic-gate (ap->ap_tblp->alts_ent_used*ALTS_ENT_SIZE), NBPSCTR);
3230Sstevel@tonic-gate if ((ap->ap_entp =
3240Sstevel@tonic-gate (struct alts_ent *)malloc(ap->ap_ent_secsiz)) == NULL) {
3250Sstevel@tonic-gate (void) fprintf(stderr,
3260Sstevel@tonic-gate "Unable to malloc alternate sector entry table.\n");
3270Sstevel@tonic-gate return (60);
3280Sstevel@tonic-gate }
3290Sstevel@tonic-gate
3300Sstevel@tonic-gate status = ata_rdwr(DIR_READ, cur_file,
3310Sstevel@tonic-gate (ap->ap_tblp->alts_ent_base) + altsec_offset,
3320Sstevel@tonic-gate ap->ap_ent_secsiz / UBSIZE, (char *)ap->ap_entp,
3330Sstevel@tonic-gate 0, NULL);
3340Sstevel@tonic-gate if (status == FAILURE) {
3350Sstevel@tonic-gate perror("Unable to read alternate sector entry table: ");
3360Sstevel@tonic-gate return (61);
3370Sstevel@tonic-gate }
3380Sstevel@tonic-gate }
3390Sstevel@tonic-gate
3400Sstevel@tonic-gate return (SUCCESS);
3410Sstevel@tonic-gate }
3420Sstevel@tonic-gate
3430Sstevel@tonic-gate
3440Sstevel@tonic-gate /*
3450Sstevel@tonic-gate * update the new alternate partition tables on disk
3460Sstevel@tonic-gate */
3470Sstevel@tonic-gate int
wr_altsctr()3480Sstevel@tonic-gate wr_altsctr()
3490Sstevel@tonic-gate {
3500Sstevel@tonic-gate int status;
3510Sstevel@tonic-gate
3520Sstevel@tonic-gate if (ap->ap_tblp == NULL)
3530Sstevel@tonic-gate return (0);
3540Sstevel@tonic-gate status = ata_rdwr(DIR_WRITE, cur_file, altsec_offset,
3550Sstevel@tonic-gate ap->ap_tbl_secsiz / UBSIZE, (char *)ap->ap_tblp, 0, NULL);
3560Sstevel@tonic-gate if (status) {
3570Sstevel@tonic-gate (void) printf("ata_rdwr status = %d need = %d\n",
3580Sstevel@tonic-gate status, ap->ap_tbl_secsiz / 512);
3590Sstevel@tonic-gate perror("Unable to write with ata_rdwr the alt sector part: ");
3600Sstevel@tonic-gate return (62);
3610Sstevel@tonic-gate }
3620Sstevel@tonic-gate
3630Sstevel@tonic-gate if (ata_rdwr(DIR_WRITE, cur_file, (ap->ap_tblp->alts_map_base) +
3640Sstevel@tonic-gate altsec_offset, ap->ap_map_secsiz / UBSIZE,
3650Sstevel@tonic-gate (char *)ap->ap_mapp, 0, NULL) == FAILURE) {
3660Sstevel@tonic-gate perror("Unable to write alternate sector partition map: ");
3670Sstevel@tonic-gate return (63);
3680Sstevel@tonic-gate }
3690Sstevel@tonic-gate
3700Sstevel@tonic-gate if (ap->ap_tblp->alts_ent_used != 0) {
3710Sstevel@tonic-gate if (ata_rdwr(DIR_WRITE, cur_file,
3720Sstevel@tonic-gate (ap->ap_tblp->alts_ent_base)+ altsec_offset,
3730Sstevel@tonic-gate ap->ap_ent_secsiz / UBSIZE,
3740Sstevel@tonic-gate (char *)ap->ap_entp, 0, NULL) == FAILURE) {
3750Sstevel@tonic-gate perror("Unable to write alternate sector entry table: ");
3760Sstevel@tonic-gate return (64);
3770Sstevel@tonic-gate }
3780Sstevel@tonic-gate }
3790Sstevel@tonic-gate return (0);
3800Sstevel@tonic-gate }
3810Sstevel@tonic-gate
3820Sstevel@tonic-gate
3830Sstevel@tonic-gate /*
3840Sstevel@tonic-gate * get a list of bad sector
3850Sstevel@tonic-gate */
3860Sstevel@tonic-gate static void
get_badsec()3870Sstevel@tonic-gate get_badsec()
3880Sstevel@tonic-gate {
3890Sstevel@tonic-gate int cnt;
3900Sstevel@tonic-gate struct badsec_lst *blc_p;
391*7563SPrasad.Singamsetty@Sun.COM blkaddr_t curbad;
392*7563SPrasad.Singamsetty@Sun.COM blkaddr_t maxsec = cur_dtype->dtype_nhead *
3930Sstevel@tonic-gate cur_dtype->dtype_ncyl *
3940Sstevel@tonic-gate cur_dtype->dtype_nsect;
3950Sstevel@tonic-gate struct alts_ent *growbadp;
3960Sstevel@tonic-gate int i;
3970Sstevel@tonic-gate
3980Sstevel@tonic-gate cnt = count_badsec();
3990Sstevel@tonic-gate if (!cnt) {
4000Sstevel@tonic-gate ap->ap_gbadp = NULL;
4010Sstevel@tonic-gate ap->ap_gbadcnt = 0;
4020Sstevel@tonic-gate } else {
4030Sstevel@tonic-gate ap->ap_gbadp = malloc(cnt*ALTS_ENT_SIZE);
4040Sstevel@tonic-gate if (ap->ap_gbadp == NULL) {
4050Sstevel@tonic-gate err_print("get_badsec: unable to malloc %d bytes\n",
4060Sstevel@tonic-gate cnt*ALTS_ENT_SIZE);
4070Sstevel@tonic-gate fullabort();
4080Sstevel@tonic-gate }
4090Sstevel@tonic-gate (void) memset(ap->ap_gbadp, 0, cnt*ALTS_ENT_SIZE);
4100Sstevel@tonic-gate
4110Sstevel@tonic-gate for (growbadp = ap->ap_gbadp, cnt = 0, blc_p = badsl_chain;
4120Sstevel@tonic-gate blc_p; blc_p = blc_p->bl_nxt) {
4130Sstevel@tonic-gate for (i = 0; i < blc_p->bl_cnt; i++) {
4140Sstevel@tonic-gate curbad = blc_p->bl_sec[i];
415*7563SPrasad.Singamsetty@Sun.COM if (curbad < (blkaddr_t)cur_dtype->dtype_nsect) {
4160Sstevel@tonic-gate (void) fprintf(stderr,
4170Sstevel@tonic-gate "Ignoring bad sector %ld which is in first track of the drive.\n", curbad);
4180Sstevel@tonic-gate continue;
4190Sstevel@tonic-gate }
4200Sstevel@tonic-gate if (curbad >= maxsec) {
4210Sstevel@tonic-gate (void) fprintf(stderr,
4220Sstevel@tonic-gate "Ignoring bad sector %ld which is past the end of the drive.\n", curbad);
4230Sstevel@tonic-gate continue;
4240Sstevel@tonic-gate }
4250Sstevel@tonic-gate growbadp[cnt].bad_start = curbad;
4260Sstevel@tonic-gate growbadp[cnt].bad_end = curbad;
4270Sstevel@tonic-gate cnt++;
4280Sstevel@tonic-gate }
4290Sstevel@tonic-gate }
4300Sstevel@tonic-gate }
4310Sstevel@tonic-gate ap->ap_gbadcnt = cnt;
4320Sstevel@tonic-gate }
4330Sstevel@tonic-gate
4340Sstevel@tonic-gate /*
4350Sstevel@tonic-gate * count number of bad sector on list
4360Sstevel@tonic-gate * merging the bad sector list from surface analysis and the
4370Sstevel@tonic-gate * one given through the command line
4380Sstevel@tonic-gate */
4390Sstevel@tonic-gate static int
count_badsec()4400Sstevel@tonic-gate count_badsec()
4410Sstevel@tonic-gate {
4420Sstevel@tonic-gate
4430Sstevel@tonic-gate struct badsec_lst *blc_p;
4440Sstevel@tonic-gate
4450Sstevel@tonic-gate if (!badsl_chain)
4460Sstevel@tonic-gate badsl_chain = gbadsl_chain;
4470Sstevel@tonic-gate else {
4480Sstevel@tonic-gate for (blc_p = badsl_chain; blc_p->bl_nxt; blc_p = blc_p->bl_nxt)
4490Sstevel@tonic-gate ;
4500Sstevel@tonic-gate blc_p->bl_nxt = gbadsl_chain;
4510Sstevel@tonic-gate }
4520Sstevel@tonic-gate
4530Sstevel@tonic-gate badsl_chain_cnt += gbadsl_chain_cnt;
4540Sstevel@tonic-gate return (badsl_chain_cnt);
4550Sstevel@tonic-gate }
4560Sstevel@tonic-gate
4570Sstevel@tonic-gate
4580Sstevel@tonic-gate /*
4590Sstevel@tonic-gate * generate alternate entry table by merging the existing and
4600Sstevel@tonic-gate * the new entry list.
4610Sstevel@tonic-gate */
4620Sstevel@tonic-gate static int
gen_alts_ent()4630Sstevel@tonic-gate gen_alts_ent() {
464*7563SPrasad.Singamsetty@Sun.COM uint_t ent_used;
4650Sstevel@tonic-gate struct alts_ent *entp;
4660Sstevel@tonic-gate
4670Sstevel@tonic-gate if (ap->ap_gbadcnt == 0)
4680Sstevel@tonic-gate return (0);
4690Sstevel@tonic-gate
4700Sstevel@tonic-gate ent_used = ap->ap_tblp->alts_ent_used + ap->ap_gbadcnt;
4710Sstevel@tonic-gate ap->ap_ent_secsiz = byte_to_secsiz(ent_used*ALTS_ENT_SIZE, NBPSCTR);
4720Sstevel@tonic-gate entp = malloc(ap->ap_ent_secsiz);
4730Sstevel@tonic-gate if (entp == NULL) {
4740Sstevel@tonic-gate err_print("get_alts_ent: unable to malloc %d bytes\n",
4750Sstevel@tonic-gate ap->ap_ent_secsiz);
4760Sstevel@tonic-gate fullabort();
4770Sstevel@tonic-gate }
4780Sstevel@tonic-gate
4790Sstevel@tonic-gate ent_used = ent_merge(entp, ap->ap_entp, ap->ap_tblp->alts_ent_used,
4800Sstevel@tonic-gate ap->ap_gbadp, ap->ap_gbadcnt);
4810Sstevel@tonic-gate if (ap->ap_entp)
4820Sstevel@tonic-gate free(ap->ap_entp);
4830Sstevel@tonic-gate if (ap->ap_gbadp)
4840Sstevel@tonic-gate free(ap->ap_gbadp);
4850Sstevel@tonic-gate ap->ap_entp = entp;
4860Sstevel@tonic-gate ap->ap_ent_secsiz = byte_to_secsiz(ent_used*ALTS_ENT_SIZE, NBPSCTR);
4870Sstevel@tonic-gate ap->ap_tblp->alts_ent_used = ent_used;
4880Sstevel@tonic-gate ap->ap_gbadp = NULL;
4890Sstevel@tonic-gate ap->ap_gbadcnt = 0;
4900Sstevel@tonic-gate
4910Sstevel@tonic-gate /* assign alternate sectors to the bad sectors */
4920Sstevel@tonic-gate (void) assign_altsctr();
4930Sstevel@tonic-gate
4940Sstevel@tonic-gate /* allocate the alts_entry on disk skipping possible bad sectors */
4950Sstevel@tonic-gate ap->ap_tblp->alts_ent_base =
496*7563SPrasad.Singamsetty@Sun.COM altsmap_alloc((blkaddr_t)ap->ap_tblp->alts_map_base +
497*7563SPrasad.Singamsetty@Sun.COM ap->ap_map_sectot, (blkaddr_t)ap->part.p_size,
4980Sstevel@tonic-gate ap->ap_ent_secsiz / NBPSCTR, ALTS_MAP_UP);
4990Sstevel@tonic-gate if (ap->ap_tblp->alts_ent_base == NULL) {
5000Sstevel@tonic-gate perror("Unable to allocate alternate entry table on disk: ");
5010Sstevel@tonic-gate return (65);
5020Sstevel@tonic-gate }
5030Sstevel@tonic-gate
5040Sstevel@tonic-gate ap->ap_tblp->alts_ent_end = ap->ap_tblp->alts_ent_base +
5050Sstevel@tonic-gate (ap->ap_ent_secsiz / NBPSCTR) - 1;
5060Sstevel@tonic-gate return (0);
5070Sstevel@tonic-gate }
5080Sstevel@tonic-gate
5090Sstevel@tonic-gate
5100Sstevel@tonic-gate /*
5110Sstevel@tonic-gate * assign alternate sectors for bad sector mapping
5120Sstevel@tonic-gate */
5130Sstevel@tonic-gate static int
assign_altsctr()5140Sstevel@tonic-gate assign_altsctr()
5150Sstevel@tonic-gate {
516*7563SPrasad.Singamsetty@Sun.COM uint_t i;
517*7563SPrasad.Singamsetty@Sun.COM uint_t j;
518*7563SPrasad.Singamsetty@Sun.COM blkaddr_t alts_ind;
519*7563SPrasad.Singamsetty@Sun.COM uint_t cluster;
5200Sstevel@tonic-gate
5210Sstevel@tonic-gate for (i = 0; i < ap->ap_tblp->alts_ent_used; i++) {
522*7563SPrasad.Singamsetty@Sun.COM if ((ap->ap_entp)[i].bad_start == (uint32_t)ALTS_ENT_EMPTY)
5230Sstevel@tonic-gate continue;
5240Sstevel@tonic-gate if ((ap->ap_entp)[i].good_start != 0)
5250Sstevel@tonic-gate continue;
5260Sstevel@tonic-gate cluster = (ap->ap_entp)[i].bad_end-(ap->ap_entp)[i].bad_start +1;
5270Sstevel@tonic-gate alts_ind =
5280Sstevel@tonic-gate altsmap_alloc(ap->part.p_size-1, ap->ap_tblp->alts_map_base +
5290Sstevel@tonic-gate ap->ap_map_sectot - 1, cluster, ALTS_MAP_DOWN);
5300Sstevel@tonic-gate if (alts_ind == NULL) {
5310Sstevel@tonic-gate (void) fprintf(stderr,
532786Slclee "Unable to allocate alternates for bad starting sector %u.\n",
5330Sstevel@tonic-gate (ap->ap_entp)[i].bad_start);
5340Sstevel@tonic-gate return (65);
5350Sstevel@tonic-gate }
5360Sstevel@tonic-gate alts_ind = alts_ind - cluster + 1;
5370Sstevel@tonic-gate (ap->ap_entp)[i].good_start = alts_ind +ap->part.p_start;
5380Sstevel@tonic-gate for (j = 0; j < cluster; j++) {
5390Sstevel@tonic-gate (ap->ap_memmapp)[alts_ind+j] = ALTS_BAD;
5400Sstevel@tonic-gate }
5410Sstevel@tonic-gate
5420Sstevel@tonic-gate }
5430Sstevel@tonic-gate return (SUCCESS);
5440Sstevel@tonic-gate }
5450Sstevel@tonic-gate
5460Sstevel@tonic-gate /*
5470Sstevel@tonic-gate * transform the disk image alts bit map to incore char map
5480Sstevel@tonic-gate */
5490Sstevel@tonic-gate static void
expand_map()5500Sstevel@tonic-gate expand_map()
5510Sstevel@tonic-gate {
5520Sstevel@tonic-gate int i;
5530Sstevel@tonic-gate
5540Sstevel@tonic-gate for (i = 0; i < ap->part.p_size; i++) {
5550Sstevel@tonic-gate (ap->ap_memmapp)[i] = altsmap_getbit(i);
5560Sstevel@tonic-gate }
5570Sstevel@tonic-gate }
5580Sstevel@tonic-gate
5590Sstevel@tonic-gate /*
5600Sstevel@tonic-gate * transform the incore alts char map to the disk image bit map
5610Sstevel@tonic-gate */
5620Sstevel@tonic-gate static void
compress_map()5630Sstevel@tonic-gate compress_map()
5640Sstevel@tonic-gate {
5650Sstevel@tonic-gate
5660Sstevel@tonic-gate int i;
5670Sstevel@tonic-gate int bytesz;
5680Sstevel@tonic-gate char mask = 0;
5690Sstevel@tonic-gate int maplen = 0;
5700Sstevel@tonic-gate
5710Sstevel@tonic-gate for (i = 0, bytesz = 7; i < ap->part.p_size; i++) {
5720Sstevel@tonic-gate mask |= ((ap->ap_memmapp)[i] << bytesz--);
5730Sstevel@tonic-gate if (bytesz < 0) {
5740Sstevel@tonic-gate (ap->ap_mapp)[maplen++] = mask;
5750Sstevel@tonic-gate bytesz = 7;
5760Sstevel@tonic-gate mask = 0;
5770Sstevel@tonic-gate }
5780Sstevel@tonic-gate }
5790Sstevel@tonic-gate /*
5800Sstevel@tonic-gate * if partition size != multiple number of bytes
5810Sstevel@tonic-gate * then record the last partial byte
5820Sstevel@tonic-gate */
5830Sstevel@tonic-gate if (bytesz != 7)
5840Sstevel@tonic-gate (ap->ap_mapp)[maplen] = mask;
5850Sstevel@tonic-gate
5860Sstevel@tonic-gate }
5870Sstevel@tonic-gate
5880Sstevel@tonic-gate /*
5890Sstevel@tonic-gate * given a bad sector number, search in the alts bit map
5900Sstevel@tonic-gate * and identify the sector as good or bad
5910Sstevel@tonic-gate */
5920Sstevel@tonic-gate static int
altsmap_getbit(badsec)5930Sstevel@tonic-gate altsmap_getbit(badsec)
594*7563SPrasad.Singamsetty@Sun.COM blkaddr_t badsec;
5950Sstevel@tonic-gate {
596*7563SPrasad.Singamsetty@Sun.COM uint_t slot = badsec / 8;
597*7563SPrasad.Singamsetty@Sun.COM uint_t field = badsec % 8;
5980Sstevel@tonic-gate uchar_t mask;
5990Sstevel@tonic-gate
6000Sstevel@tonic-gate mask = ALTS_BAD<<7;
6010Sstevel@tonic-gate mask >>= field;
6020Sstevel@tonic-gate if ((ap->ap_mapp)[slot] & mask)
6030Sstevel@tonic-gate return (ALTS_BAD);
6040Sstevel@tonic-gate return (ALTS_GOOD);
6050Sstevel@tonic-gate }
6060Sstevel@tonic-gate
6070Sstevel@tonic-gate
6080Sstevel@tonic-gate /*
6090Sstevel@tonic-gate * allocate a range of sectors from the alternate partition
6100Sstevel@tonic-gate */
611*7563SPrasad.Singamsetty@Sun.COM static blkaddr_t
altsmap_alloc(srt_ind,end_ind,cnt,dir)6120Sstevel@tonic-gate altsmap_alloc(srt_ind, end_ind, cnt, dir)
613*7563SPrasad.Singamsetty@Sun.COM blkaddr_t srt_ind;
614*7563SPrasad.Singamsetty@Sun.COM blkaddr_t end_ind;
6150Sstevel@tonic-gate int cnt;
6160Sstevel@tonic-gate int dir;
6170Sstevel@tonic-gate {
618*7563SPrasad.Singamsetty@Sun.COM blkaddr_t i;
619*7563SPrasad.Singamsetty@Sun.COM blkaddr_t total;
620*7563SPrasad.Singamsetty@Sun.COM blkaddr_t first_ind;
6210Sstevel@tonic-gate
6220Sstevel@tonic-gate for (i = srt_ind, first_ind = srt_ind, total = 0;
6230Sstevel@tonic-gate i != end_ind; i += dir) {
6240Sstevel@tonic-gate if ((ap->ap_memmapp)[i] == ALTS_BAD) {
6250Sstevel@tonic-gate total = 0;
6260Sstevel@tonic-gate first_ind = i + dir;
6270Sstevel@tonic-gate continue;
6280Sstevel@tonic-gate }
6290Sstevel@tonic-gate total++;
6300Sstevel@tonic-gate if (total == cnt)
6310Sstevel@tonic-gate return (first_ind);
6320Sstevel@tonic-gate
6330Sstevel@tonic-gate }
6340Sstevel@tonic-gate return (NULL);
6350Sstevel@tonic-gate }
6360Sstevel@tonic-gate
6370Sstevel@tonic-gate
6380Sstevel@tonic-gate
6390Sstevel@tonic-gate /*
6400Sstevel@tonic-gate * bubble sort the entry table into ascending order
6410Sstevel@tonic-gate */
6420Sstevel@tonic-gate static void
ent_sort(buf,cnt)6430Sstevel@tonic-gate ent_sort(buf, cnt)
6440Sstevel@tonic-gate struct alts_ent buf[];
6450Sstevel@tonic-gate int cnt;
6460Sstevel@tonic-gate {
6470Sstevel@tonic-gate struct alts_ent temp;
6480Sstevel@tonic-gate int flag;
6490Sstevel@tonic-gate int i, j;
6500Sstevel@tonic-gate
6510Sstevel@tonic-gate for (i = 0; i < cnt-1; i++) {
6520Sstevel@tonic-gate temp = buf[cnt-1];
6530Sstevel@tonic-gate flag = 1;
6540Sstevel@tonic-gate
6550Sstevel@tonic-gate for (j = cnt-1; j > i; j--) {
6560Sstevel@tonic-gate if (buf[j-1].bad_start < temp.bad_start) {
6570Sstevel@tonic-gate buf[j] = temp;
6580Sstevel@tonic-gate temp = buf[j-1];
6590Sstevel@tonic-gate } else {
6600Sstevel@tonic-gate buf[j] = buf[j-1];
6610Sstevel@tonic-gate flag = 0;
6620Sstevel@tonic-gate }
6630Sstevel@tonic-gate }
6640Sstevel@tonic-gate buf[i] = temp;
6650Sstevel@tonic-gate if (flag) break;
6660Sstevel@tonic-gate }
6670Sstevel@tonic-gate
6680Sstevel@tonic-gate }
6690Sstevel@tonic-gate
6700Sstevel@tonic-gate
6710Sstevel@tonic-gate /*
6720Sstevel@tonic-gate * compress all the contiguous bad sectors into a single entry
6730Sstevel@tonic-gate * in the entry table. The entry table must be sorted into ascending
6740Sstevel@tonic-gate * before the compression.
6750Sstevel@tonic-gate */
6760Sstevel@tonic-gate static void
ent_compress(buf,cnt)6770Sstevel@tonic-gate ent_compress(buf, cnt)
6780Sstevel@tonic-gate struct alts_ent buf[];
6790Sstevel@tonic-gate int cnt;
6800Sstevel@tonic-gate {
6810Sstevel@tonic-gate int keyp;
6820Sstevel@tonic-gate int movp;
6830Sstevel@tonic-gate int i;
6840Sstevel@tonic-gate
6850Sstevel@tonic-gate for (i = 0; i < cnt; i++) {
686*7563SPrasad.Singamsetty@Sun.COM if (buf[i].bad_start == (uint32_t)ALTS_ENT_EMPTY)
6870Sstevel@tonic-gate continue;
6880Sstevel@tonic-gate for (keyp = i, movp = i+1; movp < cnt; movp++) {
689*7563SPrasad.Singamsetty@Sun.COM if (buf[movp].bad_start == (uint32_t)ALTS_ENT_EMPTY)
6900Sstevel@tonic-gate continue;
6910Sstevel@tonic-gate if (buf[keyp].bad_end+1 != buf[movp].bad_start)
6920Sstevel@tonic-gate break;
6930Sstevel@tonic-gate buf[keyp].bad_end++;
694*7563SPrasad.Singamsetty@Sun.COM buf[movp].bad_start = (uint32_t)ALTS_ENT_EMPTY;
6950Sstevel@tonic-gate }
6960Sstevel@tonic-gate if (movp == cnt) break;
6970Sstevel@tonic-gate }
6980Sstevel@tonic-gate }
6990Sstevel@tonic-gate
7000Sstevel@tonic-gate
7010Sstevel@tonic-gate /*
7020Sstevel@tonic-gate * merging two entry tables into a single table. In addition,
7030Sstevel@tonic-gate * all empty slots in the entry table will be removed.
7040Sstevel@tonic-gate */
7050Sstevel@tonic-gate static int
ent_merge(buf,list1,lcnt1,list2,lcnt2)7060Sstevel@tonic-gate ent_merge(buf, list1, lcnt1, list2, lcnt2)
7070Sstevel@tonic-gate struct alts_ent buf[];
7080Sstevel@tonic-gate struct alts_ent list1[];
7090Sstevel@tonic-gate int lcnt1;
7100Sstevel@tonic-gate struct alts_ent list2[];
7110Sstevel@tonic-gate int lcnt2;
7120Sstevel@tonic-gate {
7130Sstevel@tonic-gate int i;
7140Sstevel@tonic-gate int j1, j2;
7150Sstevel@tonic-gate
7160Sstevel@tonic-gate for (i = 0, j1 = 0, j2 = 0; j1 < lcnt1 && j2 < lcnt2; ) {
717*7563SPrasad.Singamsetty@Sun.COM if (list1[j1].bad_start == (uint32_t)ALTS_ENT_EMPTY) {
7180Sstevel@tonic-gate j1++;
7190Sstevel@tonic-gate continue;
7200Sstevel@tonic-gate }
721*7563SPrasad.Singamsetty@Sun.COM if (list2[j2].bad_start == (uint32_t)ALTS_ENT_EMPTY) {
7220Sstevel@tonic-gate j2++;
7230Sstevel@tonic-gate continue;
7240Sstevel@tonic-gate }
7250Sstevel@tonic-gate if (list1[j1].bad_start < list2[j2].bad_start)
7260Sstevel@tonic-gate buf[i++] = list1[j1++];
7270Sstevel@tonic-gate else
7280Sstevel@tonic-gate buf[i++] = list2[j2++];
7290Sstevel@tonic-gate }
7300Sstevel@tonic-gate for (; j1 < lcnt1; j1++) {
731*7563SPrasad.Singamsetty@Sun.COM if (list1[j1].bad_start == (uint32_t)ALTS_ENT_EMPTY)
7320Sstevel@tonic-gate continue;
7330Sstevel@tonic-gate buf[i++] = list1[j1];
7340Sstevel@tonic-gate }
7350Sstevel@tonic-gate for (; j2 < lcnt2; j2++) {
736*7563SPrasad.Singamsetty@Sun.COM if (list2[j2].bad_start == (uint32_t)ALTS_ENT_EMPTY)
7370Sstevel@tonic-gate continue;
7380Sstevel@tonic-gate buf[i++] = list2[j2];
7390Sstevel@tonic-gate }
7400Sstevel@tonic-gate return (i);
7410Sstevel@tonic-gate }
7420Sstevel@tonic-gate
7430Sstevel@tonic-gate
7440Sstevel@tonic-gate /*
7450Sstevel@tonic-gate * binary search for bad sector in the alternate entry table
7460Sstevel@tonic-gate */
7470Sstevel@tonic-gate static int
ent_bsearch(buf,cnt,key)7480Sstevel@tonic-gate ent_bsearch(buf, cnt, key)
7490Sstevel@tonic-gate struct alts_ent buf[];
7500Sstevel@tonic-gate int cnt;
7510Sstevel@tonic-gate struct alts_ent *key;
7520Sstevel@tonic-gate {
7530Sstevel@tonic-gate int i;
7540Sstevel@tonic-gate int ind;
7550Sstevel@tonic-gate int interval;
7560Sstevel@tonic-gate int mystatus = -1;
7570Sstevel@tonic-gate
7580Sstevel@tonic-gate if (!cnt)
7590Sstevel@tonic-gate return (mystatus);
7600Sstevel@tonic-gate
7610Sstevel@tonic-gate for (i = 1; i <= cnt; i <<= 1)
7620Sstevel@tonic-gate ind = i;
7630Sstevel@tonic-gate
7640Sstevel@tonic-gate for (interval = ind; interval; ) {
7650Sstevel@tonic-gate if ((key->bad_start >= buf[ind-1].bad_start) &&
7660Sstevel@tonic-gate (key->bad_start <= buf[ind-1].bad_end)) {
7670Sstevel@tonic-gate return (mystatus = ind-1);
7680Sstevel@tonic-gate } else {
7690Sstevel@tonic-gate interval >>= 1;
7700Sstevel@tonic-gate if (!interval) break;
7710Sstevel@tonic-gate if (key->bad_start < buf[ind-1].bad_start) {
7720Sstevel@tonic-gate ind = ind - interval;
7730Sstevel@tonic-gate } else {
7740Sstevel@tonic-gate /* if key is larger than the last element then break */
7750Sstevel@tonic-gate if (ind == cnt) break;
7760Sstevel@tonic-gate if ((ind+interval) <= cnt)
7770Sstevel@tonic-gate ind += interval;
7780Sstevel@tonic-gate }
7790Sstevel@tonic-gate }
7800Sstevel@tonic-gate }
7810Sstevel@tonic-gate return (mystatus);
7820Sstevel@tonic-gate }
7830Sstevel@tonic-gate
7840Sstevel@tonic-gate /*
7850Sstevel@tonic-gate * check for bad sector in assigned alternate sectors
7860Sstevel@tonic-gate */
7870Sstevel@tonic-gate static int
chk_bad_altsctr(badsec)7880Sstevel@tonic-gate chk_bad_altsctr(badsec)
789*7563SPrasad.Singamsetty@Sun.COM blkaddr_t badsec;
7900Sstevel@tonic-gate {
7910Sstevel@tonic-gate int i;
792*7563SPrasad.Singamsetty@Sun.COM blkaddr_t numsec;
7930Sstevel@tonic-gate int cnt = ap->ap_tblp->alts_ent_used;
7940Sstevel@tonic-gate /*
7950Sstevel@tonic-gate * daddr_t intv[3];
7960Sstevel@tonic-gate */
7970Sstevel@tonic-gate
7980Sstevel@tonic-gate for (i = 0; i < cnt; i++) {
7990Sstevel@tonic-gate numsec = (ap->ap_entp)[i].bad_end - (ap->ap_entp)[i].bad_start;
8000Sstevel@tonic-gate if ((badsec >= (ap->ap_entp)[i].good_start) &&
8010Sstevel@tonic-gate (badsec <= ((ap->ap_entp)[i].good_start + numsec))) {
8020Sstevel@tonic-gate (void) fprintf(stderr,
8030Sstevel@tonic-gate "Bad sector %ld is an assigned alternate sector.\n", badsec);
8040Sstevel@tonic-gate return (66);
8050Sstevel@tonic-gate /*
8060Sstevel@tonic-gate * if (!numsec) {
8070Sstevel@tonic-gate * (ap->ap_entp)[i].good_start = 0;
8080Sstevel@tonic-gate * return (FAILURE);
8090Sstevel@tonic-gate * }
8100Sstevel@tonic-gate * intv[0] = badsec - (ap->ap_entp)[i].good_start;
8110Sstevel@tonic-gate * intv[1] = 1;
8120Sstevel@tonic-gate * intv[2] = (ap->ap_entp)[i].good_start + numsec - badsec;
8130Sstevel@tonic-gate */
8140Sstevel@tonic-gate }
8150Sstevel@tonic-gate }
8160Sstevel@tonic-gate /* the bad sector has already been identified as bad */
8170Sstevel@tonic-gate return (SUCCESS);
8180Sstevel@tonic-gate
8190Sstevel@tonic-gate }
820