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 5698107ecSlh195018 * Common Development and Distribution License (the "License"). 6698107ecSlh195018 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 221662a2f2SGary Mills * Copyright (c) 2011 Gary Mills 231662a2f2SGary Mills * 24b63e7ecbSAbhinandan Ekande * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 257c478bd9Sstevel@tonic-gate * Use is subject to license terms. 26f1bf0656SHans Rosenfeld * Copyright 2015 Nexenta Systems, Inc. All rights reserved. 27*2f15e7adSIgor Kozhukhov * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com> 287c478bd9Sstevel@tonic-gate */ 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate /* 317c478bd9Sstevel@tonic-gate * This file contains functions to implement automatic configuration 327c478bd9Sstevel@tonic-gate * of scsi disks. 337c478bd9Sstevel@tonic-gate */ 347c478bd9Sstevel@tonic-gate #include "global.h" 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate #include <fcntl.h> 377c478bd9Sstevel@tonic-gate #include <stdlib.h> 387c478bd9Sstevel@tonic-gate #include <string.h> 397c478bd9Sstevel@tonic-gate #include <strings.h> 407c478bd9Sstevel@tonic-gate #include <stdlib.h> 417c478bd9Sstevel@tonic-gate #include <ctype.h> 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate #include "misc.h" 447c478bd9Sstevel@tonic-gate #include "param.h" 457c478bd9Sstevel@tonic-gate #include "ctlr_scsi.h" 467c478bd9Sstevel@tonic-gate #include "auto_sense.h" 477c478bd9Sstevel@tonic-gate #include "partition.h" 487c478bd9Sstevel@tonic-gate #include "label.h" 497c478bd9Sstevel@tonic-gate #include "startup.h" 507c478bd9Sstevel@tonic-gate #include "analyze.h" 517c478bd9Sstevel@tonic-gate #include "io.h" 527c478bd9Sstevel@tonic-gate #include "hardware_structs.h" 537c478bd9Sstevel@tonic-gate #include "menu_fdisk.h" 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate #define DISK_NAME_MAX 256 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate extern int nctypes; 597c478bd9Sstevel@tonic-gate extern struct ctlr_type ctlr_types[]; 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate /* 637c478bd9Sstevel@tonic-gate * Marker for free hog partition 647c478bd9Sstevel@tonic-gate */ 657c478bd9Sstevel@tonic-gate #define HOG (-1) 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate /* 707c478bd9Sstevel@tonic-gate * Default partition tables 717c478bd9Sstevel@tonic-gate * 727c478bd9Sstevel@tonic-gate * Disk capacity root swap usr 737c478bd9Sstevel@tonic-gate * ------------- ---- ---- --- 747c478bd9Sstevel@tonic-gate * 0mb to 64mb 0 0 remainder 757c478bd9Sstevel@tonic-gate * 64mb to 180mb 16mb 16mb remainder 767c478bd9Sstevel@tonic-gate * 180mb to 280mb 16mb 32mb remainder 777c478bd9Sstevel@tonic-gate * 280mb to 380mb 24mb 32mb remainder 787c478bd9Sstevel@tonic-gate * 380mb to 600mb 32mb 32mb remainder 797c478bd9Sstevel@tonic-gate * 600mb to 1gb 32mb 64mb remainder 807c478bd9Sstevel@tonic-gate * 1gb to 2gb 64mb 128mb remainder 817c478bd9Sstevel@tonic-gate * 2gb on up 128mb 128mb remainder 827c478bd9Sstevel@tonic-gate */ 837c478bd9Sstevel@tonic-gate struct part_table { 847c478bd9Sstevel@tonic-gate int partitions[NDKMAP]; 857c478bd9Sstevel@tonic-gate }; 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate static struct part_table part_table_64mb = { 887c478bd9Sstevel@tonic-gate { 0, 0, 0, 0, 0, 0, HOG, 0} 897c478bd9Sstevel@tonic-gate }; 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate static struct part_table part_table_180mb = { 927c478bd9Sstevel@tonic-gate { 16, 16, 0, 0, 0, 0, HOG, 0} 937c478bd9Sstevel@tonic-gate }; 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate static struct part_table part_table_280mb = { 967c478bd9Sstevel@tonic-gate { 16, 32, 0, 0, 0, 0, HOG, 0} 977c478bd9Sstevel@tonic-gate }; 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate static struct part_table part_table_380mb = { 1007c478bd9Sstevel@tonic-gate { 24, 32, 0, 0, 0, 0, HOG, 0} 1017c478bd9Sstevel@tonic-gate }; 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate static struct part_table part_table_600mb = { 1047c478bd9Sstevel@tonic-gate { 32, 32, 0, 0, 0, 0, HOG, 0} 1057c478bd9Sstevel@tonic-gate }; 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate static struct part_table part_table_1gb = { 1087c478bd9Sstevel@tonic-gate { 32, 64, 0, 0, 0, 0, HOG, 0} 1097c478bd9Sstevel@tonic-gate }; 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate static struct part_table part_table_2gb = { 1127c478bd9Sstevel@tonic-gate { 64, 128, 0, 0, 0, 0, HOG, 0} 1137c478bd9Sstevel@tonic-gate }; 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate static struct part_table part_table_infinity = { 1167c478bd9Sstevel@tonic-gate { 128, 128, 0, 0, 0, 0, HOG, 0} 1177c478bd9Sstevel@tonic-gate }; 1187c478bd9Sstevel@tonic-gate 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate static struct default_partitions { 121342440ecSPrasad Singamsetty diskaddr_t min_capacity; 122342440ecSPrasad Singamsetty diskaddr_t max_capacity; 1237c478bd9Sstevel@tonic-gate struct part_table *part_table; 1247c478bd9Sstevel@tonic-gate } default_partitions[] = { 1257c478bd9Sstevel@tonic-gate { 0, 64, &part_table_64mb }, /* 0 to 64 mb */ 1267c478bd9Sstevel@tonic-gate { 64, 180, &part_table_180mb }, /* 64 to 180 mb */ 1277c478bd9Sstevel@tonic-gate { 180, 280, &part_table_280mb }, /* 180 to 280 mb */ 1287c478bd9Sstevel@tonic-gate { 280, 380, &part_table_380mb }, /* 280 to 380 mb */ 1297c478bd9Sstevel@tonic-gate { 380, 600, &part_table_600mb }, /* 380 to 600 mb */ 1307c478bd9Sstevel@tonic-gate { 600, 1024, &part_table_1gb }, /* 600 to 1 gb */ 1317c478bd9Sstevel@tonic-gate { 1024, 2048, &part_table_2gb }, /* 1 to 2 gb */ 1327c478bd9Sstevel@tonic-gate { 2048, INFINITY, &part_table_infinity }, /* 2 gb on up */ 1337c478bd9Sstevel@tonic-gate }; 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate #define DEFAULT_PARTITION_TABLE_SIZE \ 1367c478bd9Sstevel@tonic-gate (sizeof (default_partitions) / sizeof (struct default_partitions)) 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate /* 1397c478bd9Sstevel@tonic-gate * msgs for check() 1407c478bd9Sstevel@tonic-gate */ 1417c478bd9Sstevel@tonic-gate #define FORMAT_MSG "Auto configuration via format.dat" 1427c478bd9Sstevel@tonic-gate #define GENERIC_MSG "Auto configuration via generic SCSI-2" 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate /* 1457c478bd9Sstevel@tonic-gate * Disks on symbios(Hardwire raid controller) return a fixed number 1467c478bd9Sstevel@tonic-gate * of heads(64)/cylinders(64) and adjust the cylinders depending 1477c478bd9Sstevel@tonic-gate * capacity of the configured lun. 1487c478bd9Sstevel@tonic-gate * In such a case we get number of physical cylinders < 3 which 1497c478bd9Sstevel@tonic-gate * is the minimum required by solaris(2 reserved + 1 data cylinders). 1507c478bd9Sstevel@tonic-gate * Hence try to adjust the cylinders by reducing the "nsect/nhead". 1517c478bd9Sstevel@tonic-gate * 1527c478bd9Sstevel@tonic-gate */ 1537c478bd9Sstevel@tonic-gate /* 1547c478bd9Sstevel@tonic-gate * assuming a minimum of 32 block cylinders. 1557c478bd9Sstevel@tonic-gate */ 1567c478bd9Sstevel@tonic-gate #define MINIMUM_NO_HEADS 2 1577c478bd9Sstevel@tonic-gate #define MINIMUM_NO_SECTORS 16 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate #define MINIMUM_NO_CYLINDERS 128 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8) 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate /* These are 16-bit fields */ 1647c478bd9Sstevel@tonic-gate #define MAXIMUM_NO_HEADS 65535 1657c478bd9Sstevel@tonic-gate #define MAXIMUM_NO_SECTORS 65535 1667c478bd9Sstevel@tonic-gate #define MAXIMUM_NO_CYLINDERS 65535 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate #endif /* defined(_SUNOS_VTOC_8) */ 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate /* 1717c478bd9Sstevel@tonic-gate * minimum number of cylinders required by Solaris. 1727c478bd9Sstevel@tonic-gate */ 1737c478bd9Sstevel@tonic-gate #define SUN_MIN_CYL 3 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate 1767c478bd9Sstevel@tonic-gate 1777c478bd9Sstevel@tonic-gate /* 1787c478bd9Sstevel@tonic-gate * ANSI prototypes for local static functions 1797c478bd9Sstevel@tonic-gate */ 1807c478bd9Sstevel@tonic-gate static struct disk_type *generic_disk_sense( 1817c478bd9Sstevel@tonic-gate int fd, 1827c478bd9Sstevel@tonic-gate int can_prompt, 1837c478bd9Sstevel@tonic-gate struct dk_label *label, 1847c478bd9Sstevel@tonic-gate struct scsi_inquiry *inquiry, 1857c478bd9Sstevel@tonic-gate struct scsi_capacity_16 *capacity, 1867c478bd9Sstevel@tonic-gate char *disk_name); 1877c478bd9Sstevel@tonic-gate static int use_existing_disk_type( 1887c478bd9Sstevel@tonic-gate int fd, 1897c478bd9Sstevel@tonic-gate int can_prompt, 1907c478bd9Sstevel@tonic-gate struct dk_label *label, 1917c478bd9Sstevel@tonic-gate struct scsi_inquiry *inquiry, 1927c478bd9Sstevel@tonic-gate struct disk_type *disk_type, 1937c478bd9Sstevel@tonic-gate struct scsi_capacity_16 *capacity); 1947c478bd9Sstevel@tonic-gate int build_default_partition(struct dk_label *label, 1957c478bd9Sstevel@tonic-gate int ctrl_type); 1967c478bd9Sstevel@tonic-gate static struct disk_type *find_scsi_disk_type( 1977c478bd9Sstevel@tonic-gate char *disk_name, 1987c478bd9Sstevel@tonic-gate struct dk_label *label); 1997c478bd9Sstevel@tonic-gate static struct disk_type *find_scsi_disk_by_name( 2007c478bd9Sstevel@tonic-gate char *disk_name); 2017c478bd9Sstevel@tonic-gate static struct ctlr_type *find_scsi_ctlr_type(void); 2027c478bd9Sstevel@tonic-gate static struct ctlr_info *find_scsi_ctlr_info( 2037c478bd9Sstevel@tonic-gate struct dk_cinfo *dkinfo); 2047c478bd9Sstevel@tonic-gate static struct disk_type *new_scsi_disk_type( 2057c478bd9Sstevel@tonic-gate int fd, 2067c478bd9Sstevel@tonic-gate char *disk_name, 2077c478bd9Sstevel@tonic-gate struct dk_label *label); 2087c478bd9Sstevel@tonic-gate static struct disk_info *find_scsi_disk_info( 2097c478bd9Sstevel@tonic-gate struct dk_cinfo *dkinfo); 2103ccda647Slclee 2113ccda647Slclee static struct disk_type *new_direct_disk_type(int fd, char *disk_name, 2123ccda647Slclee struct dk_label *label); 2133ccda647Slclee 2143ccda647Slclee static int efi_ioctl(int fd, int cmd, dk_efi_t *dk_ioc); 2153ccda647Slclee static int auto_label_init(struct dk_label *label); 216*2f15e7adSIgor Kozhukhov static struct ctlr_type *find_ctlr_type(ushort_t); 217*2f15e7adSIgor Kozhukhov static struct ctlr_info *find_ctlr_info(struct dk_cinfo *, ushort_t); 218*2f15e7adSIgor Kozhukhov static struct disk_info *find_disk_info(struct dk_cinfo *, ushort_t); 2193ccda647Slclee 2207c478bd9Sstevel@tonic-gate static char *get_sun_disk_name( 2217c478bd9Sstevel@tonic-gate char *disk_name, 2227c478bd9Sstevel@tonic-gate struct scsi_inquiry *inquiry); 2237c478bd9Sstevel@tonic-gate static char *strcopy( 2247c478bd9Sstevel@tonic-gate char *dst, 2257c478bd9Sstevel@tonic-gate char *src, 2267c478bd9Sstevel@tonic-gate int n); 227342440ecSPrasad Singamsetty static int adjust_disk_geometry(diskaddr_t capacity, uint_t *cyl, 228342440ecSPrasad Singamsetty uint_t *nsect, uint_t *nhead); 229342440ecSPrasad Singamsetty static void compute_chs_values(diskaddr_t total_capacity, 230342440ecSPrasad Singamsetty diskaddr_t usable_capacity, uint_t *pcylp, 231342440ecSPrasad Singamsetty uint_t *nheadp, uint_t *nsectp); 2327c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8) 233342440ecSPrasad Singamsetty static diskaddr_t square_box( 234342440ecSPrasad Singamsetty diskaddr_t capacity, 235342440ecSPrasad Singamsetty uint_t *dim1, uint_t lim1, 236342440ecSPrasad Singamsetty uint_t *dim2, uint_t lim2, 237342440ecSPrasad Singamsetty uint_t *dim3, uint_t lim3); 2387c478bd9Sstevel@tonic-gate #endif /* defined(_SUNOS_VTOC_8) */ 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate 2417c478bd9Sstevel@tonic-gate /* 2427c478bd9Sstevel@tonic-gate * We need to get information necessary to construct a *new* efi 2437c478bd9Sstevel@tonic-gate * label type 2447c478bd9Sstevel@tonic-gate */ 2457c478bd9Sstevel@tonic-gate struct disk_type * 2467c478bd9Sstevel@tonic-gate auto_efi_sense(int fd, struct efi_info *label) 2477c478bd9Sstevel@tonic-gate { 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate struct dk_gpt *vtoc; 2507c478bd9Sstevel@tonic-gate int i; 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate struct disk_type *disk, *dp; 2537c478bd9Sstevel@tonic-gate struct disk_info *disk_info; 2547c478bd9Sstevel@tonic-gate struct ctlr_info *ctlr; 2557c478bd9Sstevel@tonic-gate struct dk_cinfo dkinfo; 2567c478bd9Sstevel@tonic-gate struct partition_info *part; 2577c478bd9Sstevel@tonic-gate 258f1bf0656SHans Rosenfeld if (ioctl(fd, DKIOCINFO, &dkinfo) == -1) { 259f1bf0656SHans Rosenfeld if (option_msg && diag_msg) { 260f1bf0656SHans Rosenfeld err_print("DKIOCINFO failed\n"); 261f1bf0656SHans Rosenfeld } 262f1bf0656SHans Rosenfeld return (NULL); 263f1bf0656SHans Rosenfeld } 264*2f15e7adSIgor Kozhukhov if ((cur_ctype != NULL) && (cur_ctype->ctype_ctype == DKC_DIRECT || 265*2f15e7adSIgor Kozhukhov cur_ctype->ctype_ctype == DKC_VBD || 266*2f15e7adSIgor Kozhukhov cur_ctype->ctype_ctype == DKC_BLKDEV)) { 267*2f15e7adSIgor Kozhukhov ctlr = find_ctlr_info(&dkinfo, cur_ctype->ctype_ctype); 268*2f15e7adSIgor Kozhukhov disk_info = find_disk_info(&dkinfo, cur_ctype->ctype_ctype); 269f1bf0656SHans Rosenfeld } else { 270f1bf0656SHans Rosenfeld ctlr = find_scsi_ctlr_info(&dkinfo); 271f1bf0656SHans Rosenfeld disk_info = find_scsi_disk_info(&dkinfo); 272f1bf0656SHans Rosenfeld } 273f1bf0656SHans Rosenfeld 2747c478bd9Sstevel@tonic-gate /* 2757c478bd9Sstevel@tonic-gate * get vendor, product, revision and capacity info. 2767c478bd9Sstevel@tonic-gate */ 277f1bf0656SHans Rosenfeld if (get_disk_info(fd, label, disk_info) == -1) { 2787c478bd9Sstevel@tonic-gate return ((struct disk_type *)NULL); 2797c478bd9Sstevel@tonic-gate } 2807c478bd9Sstevel@tonic-gate /* 2817c478bd9Sstevel@tonic-gate * Now build the default partition table 2827c478bd9Sstevel@tonic-gate */ 2837c478bd9Sstevel@tonic-gate if (efi_alloc_and_init(fd, EFI_NUMPAR, &vtoc) != 0) { 2847c478bd9Sstevel@tonic-gate err_print("efi_alloc_and_init failed. \n"); 2857c478bd9Sstevel@tonic-gate return ((struct disk_type *)NULL); 2867c478bd9Sstevel@tonic-gate } 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate label->e_parts = vtoc; 2897c478bd9Sstevel@tonic-gate 2901cce8a3fSyl194034 /* 2911cce8a3fSyl194034 * Create a whole hog EFI partition table: 2921cce8a3fSyl194034 * S0 takes the whole disk except the primary EFI label, 2931cce8a3fSyl194034 * backup EFI label, and the reserved partition. 2941cce8a3fSyl194034 */ 2951cce8a3fSyl194034 vtoc->efi_parts[0].p_tag = V_USR; 2961cce8a3fSyl194034 vtoc->efi_parts[0].p_start = vtoc->efi_first_u_lba; 2971cce8a3fSyl194034 vtoc->efi_parts[0].p_size = vtoc->efi_last_u_lba - vtoc->efi_first_u_lba 2981cce8a3fSyl194034 - EFI_MIN_RESV_SIZE + 1; 2991cce8a3fSyl194034 3001cce8a3fSyl194034 /* 3011cce8a3fSyl194034 * S1-S6 are unassigned slices. 3021cce8a3fSyl194034 */ 3031cce8a3fSyl194034 for (i = 1; i < vtoc->efi_nparts - 2; i ++) { 3041cce8a3fSyl194034 vtoc->efi_parts[i].p_tag = V_UNASSIGNED; 3057c478bd9Sstevel@tonic-gate vtoc->efi_parts[i].p_start = 0; 3067c478bd9Sstevel@tonic-gate vtoc->efi_parts[i].p_size = 0; 3077c478bd9Sstevel@tonic-gate } 3081cce8a3fSyl194034 3097c478bd9Sstevel@tonic-gate /* 3101cce8a3fSyl194034 * The reserved slice 3117c478bd9Sstevel@tonic-gate */ 3121cce8a3fSyl194034 vtoc->efi_parts[vtoc->efi_nparts - 1].p_tag = V_RESERVED; 3131cce8a3fSyl194034 vtoc->efi_parts[vtoc->efi_nparts - 1].p_start = 3141cce8a3fSyl194034 vtoc->efi_last_u_lba - EFI_MIN_RESV_SIZE + 1; 3151cce8a3fSyl194034 vtoc->efi_parts[vtoc->efi_nparts - 1].p_size = EFI_MIN_RESV_SIZE; 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate /* 3187c478bd9Sstevel@tonic-gate * Now stick all of it into the disk_type struct 3197c478bd9Sstevel@tonic-gate */ 3207c478bd9Sstevel@tonic-gate 321698107ecSlh195018 disk = (struct disk_type *)zalloc(sizeof (struct disk_type)); 3227c478bd9Sstevel@tonic-gate assert(disk_info->disk_ctlr == ctlr); 3237c478bd9Sstevel@tonic-gate dp = ctlr->ctlr_ctype->ctype_dlist; 3247c478bd9Sstevel@tonic-gate if (dp == NULL) { 3257c478bd9Sstevel@tonic-gate ctlr->ctlr_ctype->ctype_dlist = dp; 3267c478bd9Sstevel@tonic-gate } else { 3277c478bd9Sstevel@tonic-gate while (dp->dtype_next != NULL) { 3287c478bd9Sstevel@tonic-gate dp = dp->dtype_next; 3297c478bd9Sstevel@tonic-gate } 3307c478bd9Sstevel@tonic-gate dp->dtype_next = disk; 3317c478bd9Sstevel@tonic-gate } 3327c478bd9Sstevel@tonic-gate disk->dtype_next = NULL; 3337c478bd9Sstevel@tonic-gate 334f1bf0656SHans Rosenfeld disk->vendor = strdup(label->vendor); 335f1bf0656SHans Rosenfeld disk->product = strdup(label->product); 336f1bf0656SHans Rosenfeld disk->revision = strdup(label->revision); 337f1bf0656SHans Rosenfeld 338f1bf0656SHans Rosenfeld if (disk->vendor == NULL || 339f1bf0656SHans Rosenfeld disk->product == NULL || 340f1bf0656SHans Rosenfeld disk->revision == NULL) { 341f1bf0656SHans Rosenfeld free(disk->vendor); 342f1bf0656SHans Rosenfeld free(disk->product); 343f1bf0656SHans Rosenfeld free(disk->revision); 344f1bf0656SHans Rosenfeld free(disk); 345f1bf0656SHans Rosenfeld return (NULL); 346f1bf0656SHans Rosenfeld } 347f1bf0656SHans Rosenfeld 3487c478bd9Sstevel@tonic-gate disk->capacity = label->capacity; 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate part = (struct partition_info *) 3517c478bd9Sstevel@tonic-gate zalloc(sizeof (struct partition_info)); 3527c478bd9Sstevel@tonic-gate disk->dtype_plist = part; 3537c478bd9Sstevel@tonic-gate 3547c478bd9Sstevel@tonic-gate part->pinfo_name = alloc_string("default"); 3557c478bd9Sstevel@tonic-gate part->pinfo_next = NULL; 3567c478bd9Sstevel@tonic-gate part->etoc = vtoc; 3577c478bd9Sstevel@tonic-gate 3587c478bd9Sstevel@tonic-gate bzero(disk_info->v_volume, LEN_DKL_VVOL); 3597c478bd9Sstevel@tonic-gate disk_info->disk_parts = part; 3607c478bd9Sstevel@tonic-gate return (disk); 3617c478bd9Sstevel@tonic-gate } 3627c478bd9Sstevel@tonic-gate 3633ccda647Slclee static int 3643ccda647Slclee efi_ioctl(int fd, int cmd, dk_efi_t *dk_ioc) 3653ccda647Slclee { 3663ccda647Slclee void *data = dk_ioc->dki_data; 3673ccda647Slclee int error; 3683ccda647Slclee 3693ccda647Slclee dk_ioc->dki_data_64 = (uint64_t)(uintptr_t)data; 3703ccda647Slclee error = ioctl(fd, cmd, (void *)dk_ioc); 3713ccda647Slclee dk_ioc->dki_data = data; 3723ccda647Slclee 3733ccda647Slclee return (error); 3743ccda647Slclee } 3753ccda647Slclee 376698107ecSlh195018 static struct ctlr_type * 377*2f15e7adSIgor Kozhukhov find_ctlr_type(ushort_t type) 378698107ecSlh195018 { 379698107ecSlh195018 struct mctlr_list *mlp; 380698107ecSlh195018 381*2f15e7adSIgor Kozhukhov assert(type == DKC_DIRECT || 382*2f15e7adSIgor Kozhukhov type == DKC_VBD || 383*2f15e7adSIgor Kozhukhov type == DKC_BLKDEV); 384*2f15e7adSIgor Kozhukhov 385698107ecSlh195018 mlp = controlp; 386698107ecSlh195018 387698107ecSlh195018 while (mlp != NULL) { 388*2f15e7adSIgor Kozhukhov if (mlp->ctlr_type->ctype_ctype == type) { 389698107ecSlh195018 return (mlp->ctlr_type); 390698107ecSlh195018 } 391698107ecSlh195018 mlp = mlp->next; 392698107ecSlh195018 } 393698107ecSlh195018 394*2f15e7adSIgor Kozhukhov impossible("no DIRECT/VBD/BLKDEV controller type"); 395f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 396f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China return ((struct ctlr_type *)NULL); 397f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China } 398f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 3993ccda647Slclee static struct ctlr_info * 400*2f15e7adSIgor Kozhukhov find_ctlr_info(struct dk_cinfo *dkinfo, ushort_t type) 4013ccda647Slclee { 4023ccda647Slclee struct ctlr_info *ctlr; 4033ccda647Slclee 404*2f15e7adSIgor Kozhukhov assert(type == DKC_DIRECT || 405*2f15e7adSIgor Kozhukhov type == DKC_VBD || 406*2f15e7adSIgor Kozhukhov type == DKC_BLKDEV); 4073ccda647Slclee 4083ccda647Slclee for (ctlr = ctlr_list; ctlr != NULL; ctlr = ctlr->ctlr_next) { 4093ccda647Slclee if (ctlr->ctlr_addr == dkinfo->dki_addr && 4103ccda647Slclee ctlr->ctlr_space == dkinfo->dki_space && 411*2f15e7adSIgor Kozhukhov ctlr->ctlr_ctype->ctype_ctype == dkinfo->dki_ctype) { 4123ccda647Slclee return (ctlr); 4133ccda647Slclee } 4143ccda647Slclee } 4153ccda647Slclee 416*2f15e7adSIgor Kozhukhov impossible("no DIRECT/VBD/BLKDEV controller info"); 4173ccda647Slclee /*NOTREACHED*/ 418*2f15e7adSIgor Kozhukhov return ((struct ctlr_info *)NULL); 419f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China } 420f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 4213ccda647Slclee static struct disk_info * 422*2f15e7adSIgor Kozhukhov find_disk_info(struct dk_cinfo *dkinfo, ushort_t type) 4233ccda647Slclee { 4243ccda647Slclee struct disk_info *disk; 4253ccda647Slclee struct dk_cinfo *dp; 4263ccda647Slclee 427*2f15e7adSIgor Kozhukhov assert(type == DKC_DIRECT || 428*2f15e7adSIgor Kozhukhov type == DKC_VBD || 429*2f15e7adSIgor Kozhukhov type == DKC_BLKDEV); 430*2f15e7adSIgor Kozhukhov 4313ccda647Slclee for (disk = disk_list; disk != NULL; disk = disk->disk_next) { 4323ccda647Slclee dp = &disk->disk_dkinfo; 4333ccda647Slclee if (dp->dki_ctype == dkinfo->dki_ctype && 4343ccda647Slclee dp->dki_cnum == dkinfo->dki_cnum && 4353ccda647Slclee dp->dki_unit == dkinfo->dki_unit && 4363ccda647Slclee strcmp(dp->dki_dname, dkinfo->dki_dname) == 0) { 4373ccda647Slclee return (disk); 4383ccda647Slclee } 4393ccda647Slclee } 4403ccda647Slclee 441*2f15e7adSIgor Kozhukhov impossible("No DIRECT/VBD/BLKDEV disk info instance\n"); 4423ccda647Slclee /*NOTREACHED*/ 443*2f15e7adSIgor Kozhukhov return ((struct disk_info *)NULL); 444f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China } 445f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 4463ccda647Slclee /* 4473ccda647Slclee * To convert EFI to SMI labels, we need to get label geometry. 4483ccda647Slclee * Unfortunately at this time there is no good way to do so. 4493ccda647Slclee * DKIOCGGEOM will fail if disk is EFI labeled. So we hack around 4503ccda647Slclee * it and clear EFI label, do a DKIOCGGEOM and put the EFI label 4513ccda647Slclee * back on disk. 4523ccda647Slclee * This routine gets the label geometry and initializes the label 4533ccda647Slclee * It uses cur_file as opened device. 4543ccda647Slclee * returns 0 if succeeds or -1 if failed. 4553ccda647Slclee */ 4563ccda647Slclee static int 4573ccda647Slclee auto_label_init(struct dk_label *label) 4583ccda647Slclee { 4593ccda647Slclee dk_efi_t dk_ioc; 4603ccda647Slclee dk_efi_t dk_ioc_back; 4613ccda647Slclee efi_gpt_t *data = NULL; 4623ccda647Slclee efi_gpt_t *databack = NULL; 4633ccda647Slclee struct dk_geom disk_geom; 4643ccda647Slclee struct dk_minfo disk_info; 4653ccda647Slclee efi_gpt_t *backsigp; 4663ccda647Slclee int fd = cur_file; 4673ccda647Slclee int rval = -1; 4683ccda647Slclee int efisize = EFI_LABEL_SIZE * 2; 4693ccda647Slclee int success = 0; 4703ccda647Slclee uint64_t sig; 4713ccda647Slclee uint64_t backsig; 4723ccda647Slclee 4733ccda647Slclee if ((data = calloc(efisize, 1)) == NULL) { 4743ccda647Slclee err_print("auto_label_init: calloc failed\n"); 4753ccda647Slclee goto auto_label_init_out; 4763ccda647Slclee } 4773ccda647Slclee 4783ccda647Slclee dk_ioc.dki_data = data; 4793ccda647Slclee dk_ioc.dki_lba = 1; 4803ccda647Slclee dk_ioc.dki_length = efisize; 4813ccda647Slclee 4823ccda647Slclee if (efi_ioctl(fd, DKIOCGETEFI, &dk_ioc) != 0) { 4833ccda647Slclee err_print("auto_label_init: GETEFI failed\n"); 4843ccda647Slclee goto auto_label_init_out; 4853ccda647Slclee } 4863ccda647Slclee 4873ccda647Slclee if ((databack = calloc(efisize, 1)) == NULL) { 4883ccda647Slclee err_print("auto_label_init calloc2 failed"); 4893ccda647Slclee goto auto_label_init_out; 4903ccda647Slclee } 4913ccda647Slclee 4923ccda647Slclee /* get the LBA size and capacity */ 4933ccda647Slclee if (ioctl(fd, DKIOCGMEDIAINFO, (caddr_t)&disk_info) == -1) { 4943ccda647Slclee err_print("auto_label_init: dkiocgmediainfo failed\n"); 4953ccda647Slclee goto auto_label_init_out; 4963ccda647Slclee } 4973ccda647Slclee 4983ccda647Slclee if (disk_info.dki_lbsize == 0) { 4993ccda647Slclee if (option_msg && diag_msg) { 5003ccda647Slclee err_print("auto_lbal_init: assuming 512 byte" 5013ccda647Slclee "block size"); 5023ccda647Slclee } 5033ccda647Slclee disk_info.dki_lbsize = DEV_BSIZE; 5043ccda647Slclee } 5053ccda647Slclee 5063ccda647Slclee dk_ioc_back.dki_data = databack; 5073ccda647Slclee 5083ccda647Slclee /* 5093ccda647Slclee * back up efi label goes to capacity - 1, we are reading an extra block 5103ccda647Slclee * before the back up label. 5113ccda647Slclee */ 5123ccda647Slclee dk_ioc_back.dki_lba = disk_info.dki_capacity - 1 - 1; 5133ccda647Slclee dk_ioc_back.dki_length = efisize; 5143ccda647Slclee 5153ccda647Slclee if (efi_ioctl(fd, DKIOCGETEFI, &dk_ioc_back) != 0) { 5163ccda647Slclee err_print("auto_label_init: GETEFI backup failed\n"); 5173ccda647Slclee goto auto_label_init_out; 5183ccda647Slclee } 5193ccda647Slclee 5203ccda647Slclee sig = dk_ioc.dki_data->efi_gpt_Signature; 5213ccda647Slclee dk_ioc.dki_data->efi_gpt_Signature = 0x0; 5223ccda647Slclee 5233ccda647Slclee enter_critical(); 5243ccda647Slclee 5253ccda647Slclee if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc) == -1) { 5263ccda647Slclee err_print("auto_label_init: SETEFI failed\n"); 5273ccda647Slclee exit_critical(); 5283ccda647Slclee goto auto_label_init_out; 5293ccda647Slclee } 5303ccda647Slclee 53165908c77Syu, larry liu - Sun Microsystems - Beijing China backsigp = (efi_gpt_t *)((uintptr_t)dk_ioc_back.dki_data + cur_blksz); 5323ccda647Slclee 5333ccda647Slclee backsig = backsigp->efi_gpt_Signature; 5343ccda647Slclee 5353ccda647Slclee backsigp->efi_gpt_Signature = 0; 5363ccda647Slclee 5373ccda647Slclee if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc_back) == -1) { 5383ccda647Slclee err_print("auto_label_init: SETEFI backup failed\n"); 5393ccda647Slclee } 5403ccda647Slclee 5413ccda647Slclee if (ioctl(cur_file, DKIOCGGEOM, &disk_geom) != 0) 5423ccda647Slclee err_print("auto_label_init: GGEOM failed\n"); 5433ccda647Slclee else 5443ccda647Slclee success = 1; 5453ccda647Slclee 5463ccda647Slclee dk_ioc.dki_data->efi_gpt_Signature = sig; 5473ccda647Slclee backsigp->efi_gpt_Signature = backsig; 5483ccda647Slclee 5493ccda647Slclee if (efi_ioctl(cur_file, DKIOCSETEFI, &dk_ioc_back) == -1) { 5503ccda647Slclee err_print("auto_label_init: SETEFI revert backup failed\n"); 5513ccda647Slclee success = 0; 5523ccda647Slclee } 5533ccda647Slclee 5543ccda647Slclee if (efi_ioctl(cur_file, DKIOCSETEFI, &dk_ioc) == -1) { 5553ccda647Slclee err_print("auto_label_init: SETEFI revert failed\n"); 5563ccda647Slclee success = 0; 5573ccda647Slclee } 5583ccda647Slclee 5593ccda647Slclee exit_critical(); 5603ccda647Slclee 5613ccda647Slclee if (success == 0) 5623ccda647Slclee goto auto_label_init_out; 5633ccda647Slclee 5643ccda647Slclee ncyl = disk_geom.dkg_ncyl; 5653ccda647Slclee acyl = disk_geom.dkg_acyl; 5663ccda647Slclee nhead = disk_geom.dkg_nhead; 5673ccda647Slclee nsect = disk_geom.dkg_nsect; 5683ccda647Slclee pcyl = ncyl + acyl; 5693ccda647Slclee 5703ccda647Slclee label->dkl_pcyl = pcyl; 5713ccda647Slclee label->dkl_ncyl = ncyl; 5723ccda647Slclee label->dkl_acyl = acyl; 5733ccda647Slclee label->dkl_nhead = nhead; 5743ccda647Slclee label->dkl_nsect = nsect; 5753ccda647Slclee label->dkl_apc = 0; 5763ccda647Slclee label->dkl_intrlv = 1; 5773ccda647Slclee label->dkl_rpm = disk_geom.dkg_rpm; 5783ccda647Slclee 5793ccda647Slclee label->dkl_magic = DKL_MAGIC; 5803ccda647Slclee 5813ccda647Slclee (void) snprintf(label->dkl_asciilabel, sizeof (label->dkl_asciilabel), 582342440ecSPrasad Singamsetty "%s cyl %u alt %u hd %u sec %u", 5833ccda647Slclee "DEFAULT", ncyl, acyl, nhead, nsect); 5843ccda647Slclee 5853ccda647Slclee rval = 0; 5863ccda647Slclee #if defined(_FIRMWARE_NEEDS_FDISK) 5873ccda647Slclee (void) auto_solaris_part(label); 5883ccda647Slclee ncyl = label->dkl_ncyl; 5893ccda647Slclee 5903ccda647Slclee #endif /* defined(_FIRMWARE_NEEDS_FDISK) */ 5913ccda647Slclee 5923ccda647Slclee if (!build_default_partition(label, DKC_DIRECT)) { 5933ccda647Slclee rval = -1; 5943ccda647Slclee } 5953ccda647Slclee 5963ccda647Slclee (void) checksum(label, CK_MAKESUM); 5973ccda647Slclee 5983ccda647Slclee 5993ccda647Slclee auto_label_init_out: 6003ccda647Slclee if (data) 6013ccda647Slclee free(data); 6023ccda647Slclee if (databack) 6033ccda647Slclee free(databack); 6043ccda647Slclee 6053ccda647Slclee return (rval); 6063ccda647Slclee } 6073ccda647Slclee 6083ccda647Slclee static struct disk_type * 6093ccda647Slclee new_direct_disk_type( 6103ccda647Slclee int fd, 6113ccda647Slclee char *disk_name, 6123ccda647Slclee struct dk_label *label) 6133ccda647Slclee { 6143ccda647Slclee struct disk_type *dp; 6153ccda647Slclee struct disk_type *disk; 6163ccda647Slclee struct ctlr_info *ctlr; 6173ccda647Slclee struct dk_cinfo dkinfo; 6183ccda647Slclee struct partition_info *part = NULL; 6193ccda647Slclee struct partition_info *pt; 6203ccda647Slclee struct disk_info *disk_info; 6213ccda647Slclee int i; 6223ccda647Slclee 6233ccda647Slclee /* 6243ccda647Slclee * Get the disk controller info for this disk 6253ccda647Slclee */ 6263ccda647Slclee if (ioctl(fd, DKIOCINFO, &dkinfo) == -1) { 6273ccda647Slclee if (option_msg && diag_msg) { 6283ccda647Slclee err_print("DKIOCINFO failed\n"); 6293ccda647Slclee } 6303ccda647Slclee return (NULL); 6313ccda647Slclee } 6323ccda647Slclee 6333ccda647Slclee /* 6343ccda647Slclee * Find the ctlr_info for this disk. 6353ccda647Slclee */ 636*2f15e7adSIgor Kozhukhov ctlr = find_ctlr_info(&dkinfo, dkinfo.dki_ctype); 6373ccda647Slclee 6383ccda647Slclee /* 6393ccda647Slclee * Allocate a new disk type for the direct controller. 6403ccda647Slclee */ 6413ccda647Slclee disk = (struct disk_type *)zalloc(sizeof (struct disk_type)); 6423ccda647Slclee 6433ccda647Slclee /* 6443ccda647Slclee * Find the disk_info instance for this disk. 6453ccda647Slclee */ 646*2f15e7adSIgor Kozhukhov disk_info = find_disk_info(&dkinfo, dkinfo.dki_ctype); 6473ccda647Slclee 6483ccda647Slclee /* 6493ccda647Slclee * The controller and the disk should match. 6503ccda647Slclee */ 6513ccda647Slclee assert(disk_info->disk_ctlr == ctlr); 6523ccda647Slclee 6533ccda647Slclee /* 6543ccda647Slclee * Link the disk into the list of disks 6553ccda647Slclee */ 6563ccda647Slclee dp = ctlr->ctlr_ctype->ctype_dlist; 6573ccda647Slclee if (dp == NULL) { 6583ccda647Slclee ctlr->ctlr_ctype->ctype_dlist = dp; 6593ccda647Slclee } else { 6603ccda647Slclee while (dp->dtype_next != NULL) { 6613ccda647Slclee dp = dp->dtype_next; 6623ccda647Slclee } 6633ccda647Slclee dp->dtype_next = disk; 6643ccda647Slclee } 6653ccda647Slclee disk->dtype_next = NULL; 6663ccda647Slclee 6673ccda647Slclee /* 6683ccda647Slclee * Allocate and initialize the disk name. 6693ccda647Slclee */ 6703ccda647Slclee disk->dtype_asciilabel = alloc_string(disk_name); 6713ccda647Slclee 6723ccda647Slclee /* 6733ccda647Slclee * Initialize disk geometry info 6743ccda647Slclee */ 6753ccda647Slclee disk->dtype_pcyl = label->dkl_pcyl; 6763ccda647Slclee disk->dtype_ncyl = label->dkl_ncyl; 6773ccda647Slclee disk->dtype_acyl = label->dkl_acyl; 6783ccda647Slclee disk->dtype_nhead = label->dkl_nhead; 6793ccda647Slclee disk->dtype_nsect = label->dkl_nsect; 6803ccda647Slclee disk->dtype_rpm = label->dkl_rpm; 6813ccda647Slclee 6823ccda647Slclee part = (struct partition_info *) 6833ccda647Slclee zalloc(sizeof (struct partition_info)); 6843ccda647Slclee pt = disk->dtype_plist; 6853ccda647Slclee if (pt == NULL) { 6863ccda647Slclee disk->dtype_plist = part; 6873ccda647Slclee } else { 6883ccda647Slclee while (pt->pinfo_next != NULL) { 6893ccda647Slclee pt = pt->pinfo_next; 6903ccda647Slclee } 6913ccda647Slclee pt->pinfo_next = part; 6923ccda647Slclee } 6933ccda647Slclee 6943ccda647Slclee part->pinfo_next = NULL; 6953ccda647Slclee 6963ccda647Slclee /* 6973ccda647Slclee * Set up the partition name 6983ccda647Slclee */ 6993ccda647Slclee part->pinfo_name = alloc_string("default"); 7003ccda647Slclee 7013ccda647Slclee /* 7023ccda647Slclee * Fill in the partition info from the label 7033ccda647Slclee */ 7043ccda647Slclee for (i = 0; i < NDKMAP; i++) { 7053ccda647Slclee 7063ccda647Slclee #if defined(_SUNOS_VTOC_8) 7073ccda647Slclee part->pinfo_map[i] = label->dkl_map[i]; 7083ccda647Slclee 7093ccda647Slclee #elif defined(_SUNOS_VTOC_16) 7103ccda647Slclee part->pinfo_map[i].dkl_cylno = 7113ccda647Slclee label->dkl_vtoc.v_part[i].p_start / 712342440ecSPrasad Singamsetty ((blkaddr_t)(disk->dtype_nhead * 7133ccda647Slclee disk->dtype_nsect - apc)); 7143ccda647Slclee part->pinfo_map[i].dkl_nblk = 7153ccda647Slclee label->dkl_vtoc.v_part[i].p_size; 7163ccda647Slclee #else 7173ccda647Slclee #error No VTOC format defined. 7183ccda647Slclee #endif /* defined(_SUNOS_VTOC_8) */ 7193ccda647Slclee } 7203ccda647Slclee 7213ccda647Slclee /* 7223ccda647Slclee * Use the VTOC if valid, or install a default 7233ccda647Slclee */ 7243ccda647Slclee if (label->dkl_vtoc.v_version == V_VERSION) { 7253ccda647Slclee (void) memcpy(disk_info->v_volume, label->dkl_vtoc.v_volume, 7263ccda647Slclee LEN_DKL_VVOL); 7273ccda647Slclee part->vtoc = label->dkl_vtoc; 7283ccda647Slclee } else { 7293ccda647Slclee (void) memset(disk_info->v_volume, 0, LEN_DKL_VVOL); 7303ccda647Slclee set_vtoc_defaults(part); 7313ccda647Slclee } 7323ccda647Slclee 7333ccda647Slclee /* 7343ccda647Slclee * Link the disk to the partition map 7353ccda647Slclee */ 7363ccda647Slclee disk_info->disk_parts = part; 7373ccda647Slclee 7383ccda647Slclee return (disk); 7393ccda647Slclee } 7403ccda647Slclee 7413ccda647Slclee /* 7423ccda647Slclee * Get a disk type that has label info. This is used to convert 7433ccda647Slclee * EFI label to SMI label 7443ccda647Slclee */ 7453ccda647Slclee struct disk_type * 7463ccda647Slclee auto_direct_get_geom_label(int fd, struct dk_label *label) 7473ccda647Slclee { 7483ccda647Slclee struct disk_type *disk_type; 7493ccda647Slclee 7503ccda647Slclee if (auto_label_init(label) != 0) { 7513ccda647Slclee err_print("auto_direct_get_geom_label: failed to get label" 7523ccda647Slclee "geometry"); 7533ccda647Slclee return (NULL); 7543ccda647Slclee } else { 7553ccda647Slclee disk_type = new_direct_disk_type(fd, "DEFAULT", label); 7563ccda647Slclee return (disk_type); 7573ccda647Slclee } 7583ccda647Slclee } 7593ccda647Slclee 7607c478bd9Sstevel@tonic-gate /* 7617c478bd9Sstevel@tonic-gate * Auto-sense a scsi disk configuration, ie get the information 7627c478bd9Sstevel@tonic-gate * necessary to construct a label. We have two different 7637c478bd9Sstevel@tonic-gate * ways to auto-sense a scsi disk: 7647c478bd9Sstevel@tonic-gate * - format.dat override, via inquiry name 7657c478bd9Sstevel@tonic-gate * - generic scsi, via standard mode sense and inquiry 7667c478bd9Sstevel@tonic-gate * Depending on how and when we are called, and/or 7677c478bd9Sstevel@tonic-gate * change geometry and reformat. 7687c478bd9Sstevel@tonic-gate */ 7697c478bd9Sstevel@tonic-gate struct disk_type * 7707c478bd9Sstevel@tonic-gate auto_sense( 7717c478bd9Sstevel@tonic-gate int fd, 7727c478bd9Sstevel@tonic-gate int can_prompt, 7737c478bd9Sstevel@tonic-gate struct dk_label *label) 7747c478bd9Sstevel@tonic-gate { 7757c478bd9Sstevel@tonic-gate struct scsi_inquiry inquiry; 7767c478bd9Sstevel@tonic-gate struct scsi_capacity_16 capacity; 7777c478bd9Sstevel@tonic-gate struct disk_type *disk_type; 7787c478bd9Sstevel@tonic-gate char disk_name[DISK_NAME_MAX]; 7797c478bd9Sstevel@tonic-gate int force_format_dat = 0; 7807c478bd9Sstevel@tonic-gate int force_generic = 0; 7817c478bd9Sstevel@tonic-gate u_ioparam_t ioparam; 7827c478bd9Sstevel@tonic-gate int deflt; 7834ee50ec3Sbo zhou - Sun Microsystems - Beijing China char *buf; 7847c478bd9Sstevel@tonic-gate 7857c478bd9Sstevel@tonic-gate /* 7867c478bd9Sstevel@tonic-gate * First, if expert mode, find out if the user 7877c478bd9Sstevel@tonic-gate * wants to override any of the standard methods. 7887c478bd9Sstevel@tonic-gate */ 7897c478bd9Sstevel@tonic-gate if (can_prompt && expert_mode) { 7907c478bd9Sstevel@tonic-gate deflt = 1; 7917c478bd9Sstevel@tonic-gate ioparam.io_charlist = confirm_list; 7927c478bd9Sstevel@tonic-gate if (input(FIO_MSTR, FORMAT_MSG, '?', &ioparam, 7937c478bd9Sstevel@tonic-gate &deflt, DATA_INPUT) == 0) { 7947c478bd9Sstevel@tonic-gate force_format_dat = 1; 7957c478bd9Sstevel@tonic-gate } else if (input(FIO_MSTR, GENERIC_MSG, '?', &ioparam, 7967c478bd9Sstevel@tonic-gate &deflt, DATA_INPUT) == 0) { 7977c478bd9Sstevel@tonic-gate force_generic = 1; 7987c478bd9Sstevel@tonic-gate } 7997c478bd9Sstevel@tonic-gate } 8007c478bd9Sstevel@tonic-gate 8017c478bd9Sstevel@tonic-gate /* 8027c478bd9Sstevel@tonic-gate * Get the Inquiry data. If this fails, there's 8037c478bd9Sstevel@tonic-gate * no hope for this disk, so give up. 8047c478bd9Sstevel@tonic-gate */ 8057c478bd9Sstevel@tonic-gate if (uscsi_inquiry(fd, (char *)&inquiry, sizeof (inquiry))) { 8067c478bd9Sstevel@tonic-gate return ((struct disk_type *)NULL); 8077c478bd9Sstevel@tonic-gate } 8087c478bd9Sstevel@tonic-gate if (option_msg && diag_msg) { 8097c478bd9Sstevel@tonic-gate err_print("Product id: "); 8107c478bd9Sstevel@tonic-gate print_buf(inquiry.inq_pid, sizeof (inquiry.inq_pid)); 8117c478bd9Sstevel@tonic-gate err_print("\n"); 8127c478bd9Sstevel@tonic-gate } 8137c478bd9Sstevel@tonic-gate 8147c478bd9Sstevel@tonic-gate /* 8157c478bd9Sstevel@tonic-gate * Get the Read Capacity 8167c478bd9Sstevel@tonic-gate */ 8177c478bd9Sstevel@tonic-gate if (uscsi_read_capacity(fd, &capacity)) { 8187c478bd9Sstevel@tonic-gate return ((struct disk_type *)NULL); 8197c478bd9Sstevel@tonic-gate } 8200972747aSyl194034 8210972747aSyl194034 /* 8220972747aSyl194034 * If the reported capacity is set to zero, then the disk 8230972747aSyl194034 * is not usable. If the reported capacity is set to all 8240972747aSyl194034 * 0xf's, then this disk is too large. These could only 8250972747aSyl194034 * happen with a device that supports LBAs larger than 64 8260972747aSyl194034 * bits which are not defined by any current T10 standards 8270972747aSyl194034 * or by error responding from target. 8280972747aSyl194034 */ 8290972747aSyl194034 if ((capacity.sc_capacity == 0) || 8300972747aSyl194034 (capacity.sc_capacity == UINT_MAX64)) { 8310972747aSyl194034 if (option_msg && diag_msg) { 8320972747aSyl194034 err_print("Invalid capacity\n"); 8330972747aSyl194034 } 8340972747aSyl194034 return ((struct disk_type *)NULL); 8350972747aSyl194034 } 8367c478bd9Sstevel@tonic-gate if (option_msg && diag_msg) { 8377c478bd9Sstevel@tonic-gate err_print("blocks: %llu (0x%llx)\n", 8387c478bd9Sstevel@tonic-gate capacity.sc_capacity, capacity.sc_capacity); 8397c478bd9Sstevel@tonic-gate err_print("blksize: %u\n", capacity.sc_lbasize); 8407c478bd9Sstevel@tonic-gate } 8417c478bd9Sstevel@tonic-gate 8427c478bd9Sstevel@tonic-gate /* 8437c478bd9Sstevel@tonic-gate * Extract the disk name for the format.dat override 8447c478bd9Sstevel@tonic-gate */ 8457c478bd9Sstevel@tonic-gate (void) get_sun_disk_name(disk_name, &inquiry); 8467c478bd9Sstevel@tonic-gate if (option_msg && diag_msg) { 8477c478bd9Sstevel@tonic-gate err_print("disk name: `%s`\n", disk_name); 8487c478bd9Sstevel@tonic-gate } 8497c478bd9Sstevel@tonic-gate 8504ee50ec3Sbo zhou - Sun Microsystems - Beijing China buf = zalloc(cur_blksz); 8514ee50ec3Sbo zhou - Sun Microsystems - Beijing China if (scsi_rdwr(DIR_READ, fd, (diskaddr_t)0, 1, (caddr_t)buf, 8524ee50ec3Sbo zhou - Sun Microsystems - Beijing China F_SILENT, NULL)) { 8534ee50ec3Sbo zhou - Sun Microsystems - Beijing China free(buf); 854b63e7ecbSAbhinandan Ekande return ((struct disk_type *)NULL); 8554ee50ec3Sbo zhou - Sun Microsystems - Beijing China } 8564ee50ec3Sbo zhou - Sun Microsystems - Beijing China free(buf); 857b63e7ecbSAbhinandan Ekande 8587c478bd9Sstevel@tonic-gate /* 8597c478bd9Sstevel@tonic-gate * Figure out which method we use for auto sense. 8607c478bd9Sstevel@tonic-gate * If a particular method fails, we fall back to 8617c478bd9Sstevel@tonic-gate * the next possibility. 8627c478bd9Sstevel@tonic-gate */ 8637c478bd9Sstevel@tonic-gate 8647c478bd9Sstevel@tonic-gate if (force_generic) { 8657c478bd9Sstevel@tonic-gate return (generic_disk_sense(fd, can_prompt, label, 8667c478bd9Sstevel@tonic-gate &inquiry, &capacity, disk_name)); 8677c478bd9Sstevel@tonic-gate } 8687c478bd9Sstevel@tonic-gate 8697c478bd9Sstevel@tonic-gate /* 8707c478bd9Sstevel@tonic-gate * Try for an existing format.dat first 8717c478bd9Sstevel@tonic-gate */ 8727c478bd9Sstevel@tonic-gate if ((disk_type = find_scsi_disk_by_name(disk_name)) != NULL) { 8737c478bd9Sstevel@tonic-gate if (use_existing_disk_type(fd, can_prompt, label, 8747c478bd9Sstevel@tonic-gate &inquiry, disk_type, &capacity)) { 8757c478bd9Sstevel@tonic-gate return (disk_type); 8767c478bd9Sstevel@tonic-gate } 8777c478bd9Sstevel@tonic-gate if (force_format_dat) { 8787c478bd9Sstevel@tonic-gate return (NULL); 8797c478bd9Sstevel@tonic-gate } 8807c478bd9Sstevel@tonic-gate } 8817c478bd9Sstevel@tonic-gate 8827c478bd9Sstevel@tonic-gate /* 8837c478bd9Sstevel@tonic-gate * Otherwise, try using generic SCSI-2 sense and inquiry. 8847c478bd9Sstevel@tonic-gate */ 8857c478bd9Sstevel@tonic-gate 8867c478bd9Sstevel@tonic-gate return (generic_disk_sense(fd, can_prompt, label, 8877c478bd9Sstevel@tonic-gate &inquiry, &capacity, disk_name)); 8887c478bd9Sstevel@tonic-gate } 8897c478bd9Sstevel@tonic-gate 8907c478bd9Sstevel@tonic-gate 8917c478bd9Sstevel@tonic-gate 8927c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 8937c478bd9Sstevel@tonic-gate static struct disk_type * 8947c478bd9Sstevel@tonic-gate generic_disk_sense( 8957c478bd9Sstevel@tonic-gate int fd, 8967c478bd9Sstevel@tonic-gate int can_prompt, 8977c478bd9Sstevel@tonic-gate struct dk_label *label, 8987c478bd9Sstevel@tonic-gate struct scsi_inquiry *inquiry, 8997c478bd9Sstevel@tonic-gate struct scsi_capacity_16 *capacity, 9007c478bd9Sstevel@tonic-gate char *disk_name) 9017c478bd9Sstevel@tonic-gate { 9027c478bd9Sstevel@tonic-gate struct disk_type *disk; 903bc067c09Sqd208687 int setdefault = 0; 904342440ecSPrasad Singamsetty uint_t pcyl = 0; 905342440ecSPrasad Singamsetty uint_t ncyl = 0; 906342440ecSPrasad Singamsetty uint_t acyl = 0; 907342440ecSPrasad Singamsetty uint_t nhead = 0; 908342440ecSPrasad Singamsetty uint_t nsect = 0; 909bc067c09Sqd208687 int rpm = 0; 910342440ecSPrasad Singamsetty diskaddr_t nblocks = 0; 911342440ecSPrasad Singamsetty diskaddr_t tblocks = 0; 9127c478bd9Sstevel@tonic-gate union { 9137c478bd9Sstevel@tonic-gate struct mode_format page3; 9147c478bd9Sstevel@tonic-gate uchar_t buf3[MAX_MODE_SENSE_SIZE]; 9157c478bd9Sstevel@tonic-gate } u_page3; 9167c478bd9Sstevel@tonic-gate union { 9177c478bd9Sstevel@tonic-gate struct mode_geometry page4; 9187c478bd9Sstevel@tonic-gate uchar_t buf4[MAX_MODE_SENSE_SIZE]; 9197c478bd9Sstevel@tonic-gate } u_page4; 9207c478bd9Sstevel@tonic-gate struct mode_format *page3 = &u_page3.page3; 9217c478bd9Sstevel@tonic-gate struct mode_geometry *page4 = &u_page4.page4; 9227c478bd9Sstevel@tonic-gate struct scsi_ms_header header; 9237c478bd9Sstevel@tonic-gate 9247c478bd9Sstevel@tonic-gate /* 9257c478bd9Sstevel@tonic-gate * If the name of this disk appears to be "SUN", use it, 9267c478bd9Sstevel@tonic-gate * otherwise construct a name out of the generic 9277c478bd9Sstevel@tonic-gate * Inquiry info. If it turns out that we already 9287c478bd9Sstevel@tonic-gate * have a SUN disk type of this name that differs 9297c478bd9Sstevel@tonic-gate * in geometry, we will revert to the generic name 9307c478bd9Sstevel@tonic-gate * anyway. 9317c478bd9Sstevel@tonic-gate */ 9327c478bd9Sstevel@tonic-gate if (memcmp(disk_name, "SUN", strlen("SUN")) != 0) { 9337c478bd9Sstevel@tonic-gate (void) get_generic_disk_name(disk_name, inquiry); 9347c478bd9Sstevel@tonic-gate } 9357c478bd9Sstevel@tonic-gate 9367c478bd9Sstevel@tonic-gate /* 937bc067c09Sqd208687 * Get the number of blocks from Read Capacity data. Note that 938bc067c09Sqd208687 * the logical block address range from 0 to capacity->sc_capacity. 939342440ecSPrasad Singamsetty * Limit the size to 2 TB (UINT32_MAX) to use with SMI labels. 940bc067c09Sqd208687 */ 941342440ecSPrasad Singamsetty tblocks = (capacity->sc_capacity + 1); 942342440ecSPrasad Singamsetty if (tblocks > UINT32_MAX) 943342440ecSPrasad Singamsetty nblocks = UINT32_MAX; 944342440ecSPrasad Singamsetty else 945342440ecSPrasad Singamsetty nblocks = tblocks; 946bc067c09Sqd208687 947bc067c09Sqd208687 /* 9487c478bd9Sstevel@tonic-gate * Get current Page 3 - Format Parameters page 9497c478bd9Sstevel@tonic-gate */ 9507c478bd9Sstevel@tonic-gate if (uscsi_mode_sense(fd, DAD_MODE_FORMAT, MODE_SENSE_PC_CURRENT, 9517c478bd9Sstevel@tonic-gate (caddr_t)&u_page3, MAX_MODE_SENSE_SIZE, &header)) { 952bc067c09Sqd208687 setdefault = 1; 9537c478bd9Sstevel@tonic-gate } 9547c478bd9Sstevel@tonic-gate 9557c478bd9Sstevel@tonic-gate /* 9567c478bd9Sstevel@tonic-gate * Get current Page 4 - Drive Geometry page 9577c478bd9Sstevel@tonic-gate */ 9587c478bd9Sstevel@tonic-gate if (uscsi_mode_sense(fd, DAD_MODE_GEOMETRY, MODE_SENSE_PC_CURRENT, 9597c478bd9Sstevel@tonic-gate (caddr_t)&u_page4, MAX_MODE_SENSE_SIZE, &header)) { 960bc067c09Sqd208687 setdefault = 1; 9617c478bd9Sstevel@tonic-gate } 9627c478bd9Sstevel@tonic-gate 963bc067c09Sqd208687 if (setdefault != 1) { 964bc067c09Sqd208687 /* The inquiry of mode page 3 & page 4 are successful */ 9657c478bd9Sstevel@tonic-gate /* 9667c478bd9Sstevel@tonic-gate * Correct for byte order if necessary 9677c478bd9Sstevel@tonic-gate */ 9687c478bd9Sstevel@tonic-gate page4->rpm = BE_16(page4->rpm); 9697c478bd9Sstevel@tonic-gate page4->step_rate = BE_16(page4->step_rate); 9707c478bd9Sstevel@tonic-gate page3->tracks_per_zone = BE_16(page3->tracks_per_zone); 9717c478bd9Sstevel@tonic-gate page3->alt_sect_zone = BE_16(page3->alt_sect_zone); 9727c478bd9Sstevel@tonic-gate page3->alt_tracks_zone = BE_16(page3->alt_tracks_zone); 9737c478bd9Sstevel@tonic-gate page3->alt_tracks_vol = BE_16(page3->alt_tracks_vol); 9747c478bd9Sstevel@tonic-gate page3->sect_track = BE_16(page3->sect_track); 9757c478bd9Sstevel@tonic-gate page3->data_bytes_sect = BE_16(page3->data_bytes_sect); 9767c478bd9Sstevel@tonic-gate page3->interleave = BE_16(page3->interleave); 9777c478bd9Sstevel@tonic-gate page3->track_skew = BE_16(page3->track_skew); 9787c478bd9Sstevel@tonic-gate page3->cylinder_skew = BE_16(page3->cylinder_skew); 9797c478bd9Sstevel@tonic-gate 9807c478bd9Sstevel@tonic-gate 9817c478bd9Sstevel@tonic-gate /* 9827c478bd9Sstevel@tonic-gate * Construct a new label out of the sense data, 9837c478bd9Sstevel@tonic-gate * Inquiry and Capacity. 984342440ecSPrasad Singamsetty * 985342440ecSPrasad Singamsetty * If the disk capacity is > 1TB then simply compute 986342440ecSPrasad Singamsetty * the CHS values based on the total disk capacity and 987342440ecSPrasad Singamsetty * not use the values from mode-sense data. 9887c478bd9Sstevel@tonic-gate */ 989342440ecSPrasad Singamsetty if (tblocks > INT32_MAX) { 990342440ecSPrasad Singamsetty compute_chs_values(tblocks, nblocks, &pcyl, &nhead, 991342440ecSPrasad Singamsetty &nsect); 992342440ecSPrasad Singamsetty } else { 99356507910Sqd208687 pcyl = (page4->cyl_ub << 16) + (page4->cyl_mb << 8) + 99456507910Sqd208687 page4->cyl_lb; 9957c478bd9Sstevel@tonic-gate nhead = page4->heads; 9967c478bd9Sstevel@tonic-gate nsect = page3->sect_track; 997342440ecSPrasad Singamsetty } 998342440ecSPrasad Singamsetty 9997c478bd9Sstevel@tonic-gate rpm = page4->rpm; 10007c478bd9Sstevel@tonic-gate 10017c478bd9Sstevel@tonic-gate /* 10027c478bd9Sstevel@tonic-gate * If the number of physical cylinders reported is less 10037c478bd9Sstevel@tonic-gate * the SUN_MIN_CYL(3) then try to adjust the geometry so that 10047c478bd9Sstevel@tonic-gate * we have atleast SUN_MIN_CYL cylinders. 10057c478bd9Sstevel@tonic-gate */ 10067c478bd9Sstevel@tonic-gate if (pcyl < SUN_MIN_CYL) { 1007342440ecSPrasad Singamsetty if (nhead == 0 || nsect == 0) { 1008bc067c09Sqd208687 setdefault = 1; 100956507910Sqd208687 } else if (adjust_disk_geometry( 1010342440ecSPrasad Singamsetty (diskaddr_t)(capacity->sc_capacity + 1), 10117c478bd9Sstevel@tonic-gate &pcyl, &nhead, &nsect)) { 1012bc067c09Sqd208687 setdefault = 1; 1013bc067c09Sqd208687 } 1014bc067c09Sqd208687 } 1015bc067c09Sqd208687 } 1016bc067c09Sqd208687 101765908c77Syu, larry liu - Sun Microsystems - Beijing China /* 101865908c77Syu, larry liu - Sun Microsystems - Beijing China * Mode sense page 3 and page 4 are obsolete in SCSI-3. For 101965908c77Syu, larry liu - Sun Microsystems - Beijing China * newly developed large sector size disk, we will not rely on 102065908c77Syu, larry liu - Sun Microsystems - Beijing China * those two pages but compute geometry directly. 102165908c77Syu, larry liu - Sun Microsystems - Beijing China */ 102265908c77Syu, larry liu - Sun Microsystems - Beijing China if ((setdefault == 1) || (capacity->sc_lbasize != DEV_BSIZE)) { 1023bc067c09Sqd208687 /* 1024bc067c09Sqd208687 * If the number of cylinders or the number of heads reported 1025bc067c09Sqd208687 * is zero, we think the inquiry of page 3 and page 4 failed. 1026bc067c09Sqd208687 * We will set the geometry infomation by ourselves. 1027bc067c09Sqd208687 */ 1028342440ecSPrasad Singamsetty compute_chs_values(tblocks, nblocks, &pcyl, &nhead, &nsect); 10297c478bd9Sstevel@tonic-gate } 10307c478bd9Sstevel@tonic-gate 10317c478bd9Sstevel@tonic-gate /* 10327c478bd9Sstevel@tonic-gate * The sd driver reserves 2 cylinders the backup disk label and 10337c478bd9Sstevel@tonic-gate * the deviceid. Set the number of data cylinders to pcyl-acyl. 10347c478bd9Sstevel@tonic-gate */ 10357c478bd9Sstevel@tonic-gate acyl = DK_ACYL; 10367c478bd9Sstevel@tonic-gate ncyl = pcyl - acyl; 10377c478bd9Sstevel@tonic-gate 10387c478bd9Sstevel@tonic-gate if (option_msg && diag_msg) { 10397c478bd9Sstevel@tonic-gate err_print("Geometry:\n"); 1040342440ecSPrasad Singamsetty err_print(" pcyl: %u\n", pcyl); 1041342440ecSPrasad Singamsetty err_print(" ncyl: %u\n", ncyl); 1042342440ecSPrasad Singamsetty err_print(" heads: %u\n", nhead); 1043342440ecSPrasad Singamsetty err_print(" nsects: %u\n", nsect); 1044342440ecSPrasad Singamsetty err_print(" acyl: %u\n", acyl); 10457c478bd9Sstevel@tonic-gate 10467c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_16) 1047342440ecSPrasad Singamsetty err_print(" bcyl: %u\n", bcyl); 10487c478bd9Sstevel@tonic-gate #endif /* defined(_SUNOS_VTOC_16) */ 10497c478bd9Sstevel@tonic-gate 10507c478bd9Sstevel@tonic-gate err_print(" rpm: %d\n", rpm); 1051342440ecSPrasad Singamsetty err_print(" nblocks: %llu\n", nblocks); 10527c478bd9Sstevel@tonic-gate } 10537c478bd9Sstevel@tonic-gate 10547c478bd9Sstevel@tonic-gate /* 1055bc067c09Sqd208687 * Some drives do not support page4 or report 0 for page4->rpm, 1056bc067c09Sqd208687 * adjust it to AVG_RPM, 3600. 10577c478bd9Sstevel@tonic-gate */ 10587c478bd9Sstevel@tonic-gate if (rpm < MIN_RPM || rpm > MAX_RPM) { 1059b63e7ecbSAbhinandan Ekande if (option_msg && diag_msg) 1060bc067c09Sqd208687 err_print("The current rpm value %d is invalid," 10617c478bd9Sstevel@tonic-gate " adjusting it to %d\n", rpm, AVG_RPM); 10627c478bd9Sstevel@tonic-gate rpm = AVG_RPM; 10637c478bd9Sstevel@tonic-gate } 10647c478bd9Sstevel@tonic-gate 10657c478bd9Sstevel@tonic-gate /* 10667c478bd9Sstevel@tonic-gate * Some drives report 0 for nsect (page 3, byte 10 and 11) if they 10677c478bd9Sstevel@tonic-gate * have variable number of sectors per track. So adjust nsect. 10687c478bd9Sstevel@tonic-gate * Also the value is defined as vendor specific, hence check if 10697c478bd9Sstevel@tonic-gate * it is in a tolerable range. The values (32 and 4 below) are 10707c478bd9Sstevel@tonic-gate * chosen so that this change below does not generate a different 10717c478bd9Sstevel@tonic-gate * geometry for currently supported sun disks. 10727c478bd9Sstevel@tonic-gate */ 1073342440ecSPrasad Singamsetty if ((nsect == 0) || 1074342440ecSPrasad Singamsetty ((diskaddr_t)pcyl * nhead * nsect) < (nblocks - nblocks/32) || 1075342440ecSPrasad Singamsetty ((diskaddr_t)pcyl * nhead * nsect) > (nblocks + nblocks/4)) { 1076342440ecSPrasad Singamsetty if (nblocks > (pcyl * nhead)) { 1077342440ecSPrasad Singamsetty err_print("Mode sense page(3) reports nsect value" 1078342440ecSPrasad Singamsetty " as %d, adjusting it to %llu\n", 1079342440ecSPrasad Singamsetty nsect, nblocks / (pcyl * nhead)); 10807c478bd9Sstevel@tonic-gate nsect = nblocks / (pcyl * nhead); 1081342440ecSPrasad Singamsetty } else { 1082342440ecSPrasad Singamsetty /* convert capacity to nsect * nhead * pcyl */ 1083342440ecSPrasad Singamsetty err_print("\nWARNING: Disk geometry is based on " 1084342440ecSPrasad Singamsetty "capacity data.\n\n"); 1085342440ecSPrasad Singamsetty compute_chs_values(tblocks, nblocks, &pcyl, &nhead, 1086342440ecSPrasad Singamsetty &nsect); 1087342440ecSPrasad Singamsetty ncyl = pcyl - acyl; 1088342440ecSPrasad Singamsetty if (option_msg && diag_msg) { 1089342440ecSPrasad Singamsetty err_print("Geometry:(after adjustment)\n"); 1090342440ecSPrasad Singamsetty err_print(" pcyl: %u\n", pcyl); 1091342440ecSPrasad Singamsetty err_print(" ncyl: %u\n", ncyl); 1092342440ecSPrasad Singamsetty err_print(" heads: %u\n", nhead); 1093342440ecSPrasad Singamsetty err_print(" nsects: %u\n", nsect); 1094342440ecSPrasad Singamsetty err_print(" acyl: %u\n", acyl); 1095342440ecSPrasad Singamsetty 1096342440ecSPrasad Singamsetty #if defined(_SUNOS_VTOC_16) 1097342440ecSPrasad Singamsetty err_print(" bcyl: %u\n", bcyl); 1098342440ecSPrasad Singamsetty #endif 1099342440ecSPrasad Singamsetty 1100342440ecSPrasad Singamsetty err_print(" rpm: %d\n", rpm); 1101342440ecSPrasad Singamsetty err_print(" nblocks: %llu\n", nblocks); 1102342440ecSPrasad Singamsetty } 1103342440ecSPrasad Singamsetty } 11047c478bd9Sstevel@tonic-gate } 11057c478bd9Sstevel@tonic-gate 11067c478bd9Sstevel@tonic-gate /* 11077c478bd9Sstevel@tonic-gate * Some drives report their physical geometry such that 11087c478bd9Sstevel@tonic-gate * it is greater than the actual capacity. Adjust the 11097c478bd9Sstevel@tonic-gate * geometry to allow for this, so we don't run off 11107c478bd9Sstevel@tonic-gate * the end of the disk. 11117c478bd9Sstevel@tonic-gate */ 1112342440ecSPrasad Singamsetty if (((diskaddr_t)pcyl * nhead * nsect) > nblocks) { 1113342440ecSPrasad Singamsetty uint_t p = pcyl; 11147c478bd9Sstevel@tonic-gate if (option_msg && diag_msg) { 1115342440ecSPrasad Singamsetty err_print("Computed capacity (%llu) exceeds actual " 1116342440ecSPrasad Singamsetty "disk capacity (%llu)\n", 1117342440ecSPrasad Singamsetty (diskaddr_t)pcyl * nhead * nsect, nblocks); 11187c478bd9Sstevel@tonic-gate } 11197c478bd9Sstevel@tonic-gate do { 11207c478bd9Sstevel@tonic-gate pcyl--; 1121342440ecSPrasad Singamsetty } while (((diskaddr_t)pcyl * nhead * nsect) > nblocks); 11227c478bd9Sstevel@tonic-gate 11237c478bd9Sstevel@tonic-gate if (can_prompt && expert_mode && !option_f) { 11247c478bd9Sstevel@tonic-gate /* 11257c478bd9Sstevel@tonic-gate * Try to adjust nsect instead of pcyl to see if we 11267c478bd9Sstevel@tonic-gate * can optimize. For compatability reasons do this 11277c478bd9Sstevel@tonic-gate * only in expert mode (refer to bug 1144812). 11287c478bd9Sstevel@tonic-gate */ 1129342440ecSPrasad Singamsetty uint_t n = nsect; 11307c478bd9Sstevel@tonic-gate do { 11317c478bd9Sstevel@tonic-gate n--; 1132342440ecSPrasad Singamsetty } while (((diskaddr_t)p * nhead * n) > nblocks); 1133342440ecSPrasad Singamsetty if (((diskaddr_t)p * nhead * n) > 1134342440ecSPrasad Singamsetty ((diskaddr_t)pcyl * nhead * nsect)) { 11357c478bd9Sstevel@tonic-gate u_ioparam_t ioparam; 11367c478bd9Sstevel@tonic-gate int deflt = 1; 11377c478bd9Sstevel@tonic-gate /* 11387c478bd9Sstevel@tonic-gate * Ask the user for a choice here. 11397c478bd9Sstevel@tonic-gate */ 11407c478bd9Sstevel@tonic-gate ioparam.io_bounds.lower = 1; 11417c478bd9Sstevel@tonic-gate ioparam.io_bounds.upper = 2; 1142342440ecSPrasad Singamsetty err_print("1. Capacity = %llu, with pcyl = %u " 1143342440ecSPrasad Singamsetty "nhead = %u nsect = %u\n", 1144342440ecSPrasad Singamsetty ((diskaddr_t)pcyl * nhead * nsect), 11457c478bd9Sstevel@tonic-gate pcyl, nhead, nsect); 1146342440ecSPrasad Singamsetty err_print("2. Capacity = %llu, with pcyl = %u " 1147342440ecSPrasad Singamsetty "nhead = %u nsect = %u\n", 1148342440ecSPrasad Singamsetty ((diskaddr_t)p * nhead * n), 11497c478bd9Sstevel@tonic-gate p, nhead, n); 11507c478bd9Sstevel@tonic-gate if (input(FIO_INT, "Select one of the above " 11517c478bd9Sstevel@tonic-gate "choices ", ':', &ioparam, 11527c478bd9Sstevel@tonic-gate &deflt, DATA_INPUT) == 2) { 11537c478bd9Sstevel@tonic-gate pcyl = p; 11547c478bd9Sstevel@tonic-gate nsect = n; 11557c478bd9Sstevel@tonic-gate } 11567c478bd9Sstevel@tonic-gate } 11577c478bd9Sstevel@tonic-gate } 11587c478bd9Sstevel@tonic-gate } 11597c478bd9Sstevel@tonic-gate 11607c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8) 11617c478bd9Sstevel@tonic-gate /* 11627c478bd9Sstevel@tonic-gate * Finally, we need to make sure we don't overflow any of the 11637c478bd9Sstevel@tonic-gate * fields in our disk label. To do this we need to `square 11647c478bd9Sstevel@tonic-gate * the box' so to speak. We will lose bits here. 11657c478bd9Sstevel@tonic-gate */ 11667c478bd9Sstevel@tonic-gate 11677c478bd9Sstevel@tonic-gate if ((pcyl > MAXIMUM_NO_CYLINDERS && 11687c478bd9Sstevel@tonic-gate ((nsect > MAXIMUM_NO_SECTORS) || 11697c478bd9Sstevel@tonic-gate (nhead > MAXIMUM_NO_HEADS))) || 11707c478bd9Sstevel@tonic-gate ((nsect > MAXIMUM_NO_SECTORS) && 11717c478bd9Sstevel@tonic-gate (nhead > MAXIMUM_NO_HEADS))) { 11727c478bd9Sstevel@tonic-gate err_print("This disk is too big to label. " 11737c478bd9Sstevel@tonic-gate " You will lose some blocks.\n"); 11747c478bd9Sstevel@tonic-gate } 11757c478bd9Sstevel@tonic-gate if ((pcyl > MAXIMUM_NO_CYLINDERS) || 11767c478bd9Sstevel@tonic-gate (nsect > MAXIMUM_NO_SECTORS) || 11777c478bd9Sstevel@tonic-gate (nhead > MAXIMUM_NO_HEADS)) { 11787c478bd9Sstevel@tonic-gate u_ioparam_t ioparam; 11797c478bd9Sstevel@tonic-gate int order; 11807c478bd9Sstevel@tonic-gate char msg[256]; 11817c478bd9Sstevel@tonic-gate 1182d2a20373Sbz211116 order = ((pcyl > nhead)<<2) | 1183d2a20373Sbz211116 ((pcyl > nsect)<<1) | 11847c478bd9Sstevel@tonic-gate (nhead > nsect); 11857c478bd9Sstevel@tonic-gate switch (order) { 1186d2a20373Sbz211116 case 0x7: /* pcyl > nhead > nsect */ 11877c478bd9Sstevel@tonic-gate nblocks = 11887c478bd9Sstevel@tonic-gate square_box(nblocks, 11897c478bd9Sstevel@tonic-gate &pcyl, MAXIMUM_NO_CYLINDERS, 11907c478bd9Sstevel@tonic-gate &nhead, MAXIMUM_NO_HEADS, 11917c478bd9Sstevel@tonic-gate &nsect, MAXIMUM_NO_SECTORS); 11927c478bd9Sstevel@tonic-gate break; 1193d2a20373Sbz211116 case 0x6: /* pcyl > nsect > nhead */ 11947c478bd9Sstevel@tonic-gate nblocks = 11957c478bd9Sstevel@tonic-gate square_box(nblocks, 11967c478bd9Sstevel@tonic-gate &pcyl, MAXIMUM_NO_CYLINDERS, 11977c478bd9Sstevel@tonic-gate &nsect, MAXIMUM_NO_SECTORS, 11987c478bd9Sstevel@tonic-gate &nhead, MAXIMUM_NO_HEADS); 11997c478bd9Sstevel@tonic-gate break; 1200d2a20373Sbz211116 case 0x4: /* nsect > pcyl > nhead */ 12017c478bd9Sstevel@tonic-gate nblocks = 12027c478bd9Sstevel@tonic-gate square_box(nblocks, 12037c478bd9Sstevel@tonic-gate &nsect, MAXIMUM_NO_SECTORS, 12047c478bd9Sstevel@tonic-gate &pcyl, MAXIMUM_NO_CYLINDERS, 12057c478bd9Sstevel@tonic-gate &nhead, MAXIMUM_NO_HEADS); 12067c478bd9Sstevel@tonic-gate break; 1207d2a20373Sbz211116 case 0x0: /* nsect > nhead > pcyl */ 12087c478bd9Sstevel@tonic-gate nblocks = 12097c478bd9Sstevel@tonic-gate square_box(nblocks, 12107c478bd9Sstevel@tonic-gate &nsect, MAXIMUM_NO_SECTORS, 12117c478bd9Sstevel@tonic-gate &nhead, MAXIMUM_NO_HEADS, 12127c478bd9Sstevel@tonic-gate &pcyl, MAXIMUM_NO_CYLINDERS); 12137c478bd9Sstevel@tonic-gate break; 1214d2a20373Sbz211116 case 0x3: /* nhead > pcyl > nsect */ 12157c478bd9Sstevel@tonic-gate nblocks = 12167c478bd9Sstevel@tonic-gate square_box(nblocks, 12177c478bd9Sstevel@tonic-gate &nhead, MAXIMUM_NO_HEADS, 12187c478bd9Sstevel@tonic-gate &pcyl, MAXIMUM_NO_CYLINDERS, 12197c478bd9Sstevel@tonic-gate &nsect, MAXIMUM_NO_SECTORS); 12207c478bd9Sstevel@tonic-gate break; 1221d2a20373Sbz211116 case 0x1: /* nhead > nsect > pcyl */ 12227c478bd9Sstevel@tonic-gate nblocks = 12237c478bd9Sstevel@tonic-gate square_box(nblocks, 12247c478bd9Sstevel@tonic-gate &nhead, MAXIMUM_NO_HEADS, 12257c478bd9Sstevel@tonic-gate &nsect, MAXIMUM_NO_SECTORS, 12267c478bd9Sstevel@tonic-gate &pcyl, MAXIMUM_NO_CYLINDERS); 12277c478bd9Sstevel@tonic-gate break; 12287c478bd9Sstevel@tonic-gate default: 12297c478bd9Sstevel@tonic-gate /* How did we get here? */ 12307c478bd9Sstevel@tonic-gate impossible("label overflow adjustment"); 12317c478bd9Sstevel@tonic-gate 12327c478bd9Sstevel@tonic-gate /* Do something useful */ 12337c478bd9Sstevel@tonic-gate nblocks = 12347c478bd9Sstevel@tonic-gate square_box(nblocks, 12357c478bd9Sstevel@tonic-gate &nhead, MAXIMUM_NO_HEADS, 12367c478bd9Sstevel@tonic-gate &nsect, MAXIMUM_NO_SECTORS, 12377c478bd9Sstevel@tonic-gate &pcyl, MAXIMUM_NO_CYLINDERS); 12387c478bd9Sstevel@tonic-gate break; 12397c478bd9Sstevel@tonic-gate } 12407c478bd9Sstevel@tonic-gate if (option_msg && diag_msg && 12417c478bd9Sstevel@tonic-gate (capacity->sc_capacity + 1 != nblocks)) { 12427c478bd9Sstevel@tonic-gate err_print("After adjusting geometry you lost" 1243342440ecSPrasad Singamsetty " %llu of %llu blocks.\n", 12447c478bd9Sstevel@tonic-gate (capacity->sc_capacity + 1 - nblocks), 12457c478bd9Sstevel@tonic-gate capacity->sc_capacity + 1); 12467c478bd9Sstevel@tonic-gate } 12477c478bd9Sstevel@tonic-gate while (can_prompt && expert_mode && !option_f) { 12487c478bd9Sstevel@tonic-gate int deflt = 1; 12497c478bd9Sstevel@tonic-gate 12507c478bd9Sstevel@tonic-gate /* 12517c478bd9Sstevel@tonic-gate * Allow user to modify this by hand if desired. 12527c478bd9Sstevel@tonic-gate */ 12537c478bd9Sstevel@tonic-gate (void) sprintf(msg, 1254342440ecSPrasad Singamsetty "\nGeometry: %u heads, %u sectors %u cylinders" 1255342440ecSPrasad Singamsetty " result in %llu out of %llu blocks.\n" 12567c478bd9Sstevel@tonic-gate "Do you want to modify the device geometry", 12577c478bd9Sstevel@tonic-gate nhead, nsect, pcyl, 1258342440ecSPrasad Singamsetty nblocks, capacity->sc_capacity + 1); 12597c478bd9Sstevel@tonic-gate 12607c478bd9Sstevel@tonic-gate ioparam.io_charlist = confirm_list; 12617c478bd9Sstevel@tonic-gate if (input(FIO_MSTR, msg, '?', &ioparam, 12627c478bd9Sstevel@tonic-gate &deflt, DATA_INPUT) != 0) 12637c478bd9Sstevel@tonic-gate break; 12647c478bd9Sstevel@tonic-gate 12657c478bd9Sstevel@tonic-gate ioparam.io_bounds.lower = MINIMUM_NO_HEADS; 12667c478bd9Sstevel@tonic-gate ioparam.io_bounds.upper = MAXIMUM_NO_HEADS; 12677c478bd9Sstevel@tonic-gate nhead = input(FIO_INT, "Number of heads", ':', 1268342440ecSPrasad Singamsetty &ioparam, (int *)&nhead, DATA_INPUT); 12697c478bd9Sstevel@tonic-gate ioparam.io_bounds.lower = MINIMUM_NO_SECTORS; 12707c478bd9Sstevel@tonic-gate ioparam.io_bounds.upper = MAXIMUM_NO_SECTORS; 12717c478bd9Sstevel@tonic-gate nsect = input(FIO_INT, 12727c478bd9Sstevel@tonic-gate "Number of sectors per track", 1273342440ecSPrasad Singamsetty ':', &ioparam, (int *)&nsect, DATA_INPUT); 12747c478bd9Sstevel@tonic-gate ioparam.io_bounds.lower = SUN_MIN_CYL; 12757c478bd9Sstevel@tonic-gate ioparam.io_bounds.upper = MAXIMUM_NO_CYLINDERS; 12767c478bd9Sstevel@tonic-gate pcyl = input(FIO_INT, "Number of cylinders", 1277342440ecSPrasad Singamsetty ':', &ioparam, (int *)&pcyl, DATA_INPUT); 1278342440ecSPrasad Singamsetty nblocks = (diskaddr_t)nhead * nsect * pcyl; 12797c478bd9Sstevel@tonic-gate if (nblocks > capacity->sc_capacity + 1) { 1280342440ecSPrasad Singamsetty err_print("Warning: %llu blocks exceeds " 1281342440ecSPrasad Singamsetty "disk capacity of %llu blocks\n", 12827c478bd9Sstevel@tonic-gate nblocks, 12837c478bd9Sstevel@tonic-gate capacity->sc_capacity + 1); 12847c478bd9Sstevel@tonic-gate } 12857c478bd9Sstevel@tonic-gate } 12867c478bd9Sstevel@tonic-gate } 12877c478bd9Sstevel@tonic-gate #endif /* defined(_SUNOS_VTOC_8) */ 12887c478bd9Sstevel@tonic-gate 12897c478bd9Sstevel@tonic-gate ncyl = pcyl - acyl; 12907c478bd9Sstevel@tonic-gate 12917c478bd9Sstevel@tonic-gate if (option_msg && diag_msg) { 12927c478bd9Sstevel@tonic-gate err_print("\nGeometry after adjusting for capacity:\n"); 1293342440ecSPrasad Singamsetty err_print(" pcyl: %u\n", pcyl); 1294342440ecSPrasad Singamsetty err_print(" ncyl: %u\n", ncyl); 1295342440ecSPrasad Singamsetty err_print(" heads: %u\n", nhead); 1296342440ecSPrasad Singamsetty err_print(" nsects: %u\n", nsect); 1297342440ecSPrasad Singamsetty err_print(" acyl: %u\n", acyl); 12987c478bd9Sstevel@tonic-gate err_print(" rpm: %d\n", rpm); 12997c478bd9Sstevel@tonic-gate } 13007c478bd9Sstevel@tonic-gate 13017c478bd9Sstevel@tonic-gate (void) memset((char *)label, 0, sizeof (struct dk_label)); 13027c478bd9Sstevel@tonic-gate 13037c478bd9Sstevel@tonic-gate label->dkl_magic = DKL_MAGIC; 13047c478bd9Sstevel@tonic-gate 13057c478bd9Sstevel@tonic-gate (void) snprintf(label->dkl_asciilabel, sizeof (label->dkl_asciilabel), 1306342440ecSPrasad Singamsetty "%s cyl %u alt %u hd %u sec %u", 13077c478bd9Sstevel@tonic-gate disk_name, ncyl, acyl, nhead, nsect); 13087c478bd9Sstevel@tonic-gate 13097c478bd9Sstevel@tonic-gate label->dkl_pcyl = pcyl; 13107c478bd9Sstevel@tonic-gate label->dkl_ncyl = ncyl; 13117c478bd9Sstevel@tonic-gate label->dkl_acyl = acyl; 13127c478bd9Sstevel@tonic-gate label->dkl_nhead = nhead; 13137c478bd9Sstevel@tonic-gate label->dkl_nsect = nsect; 13147c478bd9Sstevel@tonic-gate label->dkl_apc = 0; 13157c478bd9Sstevel@tonic-gate label->dkl_intrlv = 1; 13167c478bd9Sstevel@tonic-gate label->dkl_rpm = rpm; 13177c478bd9Sstevel@tonic-gate 13187c478bd9Sstevel@tonic-gate #if defined(_FIRMWARE_NEEDS_FDISK) 1319342440ecSPrasad Singamsetty if (auto_solaris_part(label) == -1) 1320342440ecSPrasad Singamsetty goto err; 13217c478bd9Sstevel@tonic-gate ncyl = label->dkl_ncyl; 13227c478bd9Sstevel@tonic-gate #endif /* defined(_FIRMWARE_NEEDS_FDISK) */ 13237c478bd9Sstevel@tonic-gate 13247c478bd9Sstevel@tonic-gate 13257c478bd9Sstevel@tonic-gate if (!build_default_partition(label, DKC_SCSI_CCS)) { 13267c478bd9Sstevel@tonic-gate goto err; 13277c478bd9Sstevel@tonic-gate } 13287c478bd9Sstevel@tonic-gate 13297c478bd9Sstevel@tonic-gate (void) checksum(label, CK_MAKESUM); 13307c478bd9Sstevel@tonic-gate 13317c478bd9Sstevel@tonic-gate /* 13327c478bd9Sstevel@tonic-gate * Find an existing disk type defined for this disk. 13337c478bd9Sstevel@tonic-gate * For this to work, both the name and geometry must 13347c478bd9Sstevel@tonic-gate * match. If there is no such type, but there already 13357c478bd9Sstevel@tonic-gate * is a disk defined with that name, but with a different 13367c478bd9Sstevel@tonic-gate * geometry, construct a new generic disk name out of 13377c478bd9Sstevel@tonic-gate * the inquiry information. Whatever name we're 13387c478bd9Sstevel@tonic-gate * finally using, if there's no such disk type defined, 13397c478bd9Sstevel@tonic-gate * build a new disk definition. 13407c478bd9Sstevel@tonic-gate */ 13417c478bd9Sstevel@tonic-gate if ((disk = find_scsi_disk_type(disk_name, label)) == NULL) { 13427c478bd9Sstevel@tonic-gate if (find_scsi_disk_by_name(disk_name) != NULL) { 13437c478bd9Sstevel@tonic-gate char old_name[DISK_NAME_MAX]; 13447c478bd9Sstevel@tonic-gate (void) strcpy(old_name, disk_name); 13457c478bd9Sstevel@tonic-gate (void) get_generic_disk_name(disk_name, 13467c478bd9Sstevel@tonic-gate inquiry); 13477c478bd9Sstevel@tonic-gate if (option_msg && diag_msg) { 13487c478bd9Sstevel@tonic-gate err_print( 13497c478bd9Sstevel@tonic-gate "Changing disk type name from '%s' to '%s'\n", old_name, disk_name); 13507c478bd9Sstevel@tonic-gate } 13517c478bd9Sstevel@tonic-gate (void) snprintf(label->dkl_asciilabel, 13527c478bd9Sstevel@tonic-gate sizeof (label->dkl_asciilabel), 1353342440ecSPrasad Singamsetty "%s cyl %u alt %u hd %u sec %u", 13547c478bd9Sstevel@tonic-gate disk_name, ncyl, acyl, nhead, nsect); 13557c478bd9Sstevel@tonic-gate (void) checksum(label, CK_MAKESUM); 13567c478bd9Sstevel@tonic-gate disk = find_scsi_disk_type(disk_name, label); 13577c478bd9Sstevel@tonic-gate } 13587c478bd9Sstevel@tonic-gate if (disk == NULL) { 13597c478bd9Sstevel@tonic-gate disk = new_scsi_disk_type(fd, disk_name, label); 13607c478bd9Sstevel@tonic-gate if (disk == NULL) 13617c478bd9Sstevel@tonic-gate goto err; 13627c478bd9Sstevel@tonic-gate } 13637c478bd9Sstevel@tonic-gate } 13647c478bd9Sstevel@tonic-gate 13657c478bd9Sstevel@tonic-gate return (disk); 13667c478bd9Sstevel@tonic-gate 13677c478bd9Sstevel@tonic-gate err: 13687c478bd9Sstevel@tonic-gate if (option_msg && diag_msg) { 13697c478bd9Sstevel@tonic-gate err_print( 13707c478bd9Sstevel@tonic-gate "Configuration via generic SCSI-2 information failed\n"); 13717c478bd9Sstevel@tonic-gate } 13727c478bd9Sstevel@tonic-gate return (NULL); 13737c478bd9Sstevel@tonic-gate } 13747c478bd9Sstevel@tonic-gate 13757c478bd9Sstevel@tonic-gate 13767c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 13777c478bd9Sstevel@tonic-gate static int 13787c478bd9Sstevel@tonic-gate use_existing_disk_type( 13797c478bd9Sstevel@tonic-gate int fd, 13807c478bd9Sstevel@tonic-gate int can_prompt, 13817c478bd9Sstevel@tonic-gate struct dk_label *label, 13827c478bd9Sstevel@tonic-gate struct scsi_inquiry *inquiry, 13837c478bd9Sstevel@tonic-gate struct disk_type *disk_type, 13847c478bd9Sstevel@tonic-gate struct scsi_capacity_16 *capacity) 13857c478bd9Sstevel@tonic-gate { 13867c478bd9Sstevel@tonic-gate int pcyl; 13877c478bd9Sstevel@tonic-gate int acyl; 13887c478bd9Sstevel@tonic-gate int nhead; 13897c478bd9Sstevel@tonic-gate int nsect; 13907c478bd9Sstevel@tonic-gate int rpm; 13917c478bd9Sstevel@tonic-gate 13927c478bd9Sstevel@tonic-gate /* 13937c478bd9Sstevel@tonic-gate * Construct a new label out of the format.dat 13947c478bd9Sstevel@tonic-gate */ 13957c478bd9Sstevel@tonic-gate pcyl = disk_type->dtype_pcyl; 13967c478bd9Sstevel@tonic-gate acyl = disk_type->dtype_acyl; 13977c478bd9Sstevel@tonic-gate ncyl = disk_type->dtype_ncyl; 13987c478bd9Sstevel@tonic-gate nhead = disk_type->dtype_nhead; 13997c478bd9Sstevel@tonic-gate nsect = disk_type->dtype_nsect; 14007c478bd9Sstevel@tonic-gate rpm = disk_type->dtype_rpm; 14017c478bd9Sstevel@tonic-gate 14027c478bd9Sstevel@tonic-gate if (option_msg && diag_msg) { 14037c478bd9Sstevel@tonic-gate err_print("Format.dat geometry:\n"); 1404342440ecSPrasad Singamsetty err_print(" pcyl: %u\n", pcyl); 1405342440ecSPrasad Singamsetty err_print(" heads: %u\n", nhead); 1406342440ecSPrasad Singamsetty err_print(" nsects: %u\n", nsect); 1407342440ecSPrasad Singamsetty err_print(" acyl: %u\n", acyl); 14087c478bd9Sstevel@tonic-gate err_print(" rpm: %d\n", rpm); 14097c478bd9Sstevel@tonic-gate } 14107c478bd9Sstevel@tonic-gate 14117c478bd9Sstevel@tonic-gate (void) memset((char *)label, 0, sizeof (struct dk_label)); 14127c478bd9Sstevel@tonic-gate 14137c478bd9Sstevel@tonic-gate label->dkl_magic = DKL_MAGIC; 14147c478bd9Sstevel@tonic-gate 14157c478bd9Sstevel@tonic-gate (void) snprintf(label->dkl_asciilabel, sizeof (label->dkl_asciilabel), 1416342440ecSPrasad Singamsetty "%s cyl %u alt %u hd %u sec %u", 14177c478bd9Sstevel@tonic-gate disk_type->dtype_asciilabel, 14187c478bd9Sstevel@tonic-gate ncyl, acyl, nhead, nsect); 14197c478bd9Sstevel@tonic-gate 14207c478bd9Sstevel@tonic-gate label->dkl_pcyl = pcyl; 14217c478bd9Sstevel@tonic-gate label->dkl_ncyl = ncyl; 14227c478bd9Sstevel@tonic-gate label->dkl_acyl = acyl; 14237c478bd9Sstevel@tonic-gate label->dkl_nhead = nhead; 14247c478bd9Sstevel@tonic-gate label->dkl_nsect = nsect; 14257c478bd9Sstevel@tonic-gate label->dkl_apc = 0; 14267c478bd9Sstevel@tonic-gate label->dkl_intrlv = 1; 14277c478bd9Sstevel@tonic-gate label->dkl_rpm = rpm; 14287c478bd9Sstevel@tonic-gate 14297c478bd9Sstevel@tonic-gate if (!build_default_partition(label, DKC_SCSI_CCS)) { 14307c478bd9Sstevel@tonic-gate goto err; 14317c478bd9Sstevel@tonic-gate } 14327c478bd9Sstevel@tonic-gate 14337c478bd9Sstevel@tonic-gate (void) checksum(label, CK_MAKESUM); 14347c478bd9Sstevel@tonic-gate return (1); 14357c478bd9Sstevel@tonic-gate 14367c478bd9Sstevel@tonic-gate err: 14377c478bd9Sstevel@tonic-gate if (option_msg && diag_msg) { 14387c478bd9Sstevel@tonic-gate err_print( 14397c478bd9Sstevel@tonic-gate "Configuration via format.dat geometry failed\n"); 14407c478bd9Sstevel@tonic-gate } 14417c478bd9Sstevel@tonic-gate return (0); 14427c478bd9Sstevel@tonic-gate } 14437c478bd9Sstevel@tonic-gate 14447c478bd9Sstevel@tonic-gate int 14457c478bd9Sstevel@tonic-gate build_default_partition( 14467c478bd9Sstevel@tonic-gate struct dk_label *label, 14477c478bd9Sstevel@tonic-gate int ctrl_type) 14487c478bd9Sstevel@tonic-gate { 14497c478bd9Sstevel@tonic-gate int i; 14507c478bd9Sstevel@tonic-gate int ncyls[NDKMAP]; 1451342440ecSPrasad Singamsetty diskaddr_t nblks; 14527c478bd9Sstevel@tonic-gate int cyl; 14537c478bd9Sstevel@tonic-gate struct dk_vtoc *vtoc; 14547c478bd9Sstevel@tonic-gate struct part_table *pt; 14557c478bd9Sstevel@tonic-gate struct default_partitions *dpt; 1456342440ecSPrasad Singamsetty diskaddr_t capacity; 14577c478bd9Sstevel@tonic-gate int freecyls; 14587c478bd9Sstevel@tonic-gate int blks_per_cyl; 14597c478bd9Sstevel@tonic-gate int ncyl; 14607c478bd9Sstevel@tonic-gate 14617c478bd9Sstevel@tonic-gate #ifdef lint 14627c478bd9Sstevel@tonic-gate ctrl_type = ctrl_type; 14637c478bd9Sstevel@tonic-gate #endif 14647c478bd9Sstevel@tonic-gate 14657c478bd9Sstevel@tonic-gate /* 14667c478bd9Sstevel@tonic-gate * Install a default vtoc 14677c478bd9Sstevel@tonic-gate */ 14687c478bd9Sstevel@tonic-gate vtoc = &label->dkl_vtoc; 14697c478bd9Sstevel@tonic-gate vtoc->v_version = V_VERSION; 14707c478bd9Sstevel@tonic-gate vtoc->v_nparts = NDKMAP; 14717c478bd9Sstevel@tonic-gate vtoc->v_sanity = VTOC_SANE; 14727c478bd9Sstevel@tonic-gate 14737c478bd9Sstevel@tonic-gate for (i = 0; i < NDKMAP; i++) { 14747c478bd9Sstevel@tonic-gate vtoc->v_part[i].p_tag = default_vtoc_map[i].p_tag; 14757c478bd9Sstevel@tonic-gate vtoc->v_part[i].p_flag = default_vtoc_map[i].p_flag; 14767c478bd9Sstevel@tonic-gate } 14777c478bd9Sstevel@tonic-gate 14787c478bd9Sstevel@tonic-gate /* 14797c478bd9Sstevel@tonic-gate * Find a partition that matches this disk. Capacity 14807c478bd9Sstevel@tonic-gate * is in integral number of megabytes. 14817c478bd9Sstevel@tonic-gate */ 1482342440ecSPrasad Singamsetty capacity = ((diskaddr_t)(label->dkl_ncyl) * label->dkl_nhead * 148382bff436Sbo zhou - Sun Microsystems - Beijing China label->dkl_nsect) / (diskaddr_t)((1024 * 1024) / cur_blksz); 14847c478bd9Sstevel@tonic-gate dpt = default_partitions; 14857c478bd9Sstevel@tonic-gate for (i = 0; i < DEFAULT_PARTITION_TABLE_SIZE; i++, dpt++) { 14867c478bd9Sstevel@tonic-gate if (capacity >= dpt->min_capacity && 14877c478bd9Sstevel@tonic-gate capacity < dpt->max_capacity) { 14887c478bd9Sstevel@tonic-gate break; 14897c478bd9Sstevel@tonic-gate } 14907c478bd9Sstevel@tonic-gate } 14917c478bd9Sstevel@tonic-gate if (i == DEFAULT_PARTITION_TABLE_SIZE) { 14927c478bd9Sstevel@tonic-gate if (option_msg && diag_msg) { 1493342440ecSPrasad Singamsetty err_print("No matching default partition (%llu)\n", 14947c478bd9Sstevel@tonic-gate capacity); 14957c478bd9Sstevel@tonic-gate } 14967c478bd9Sstevel@tonic-gate return (0); 14977c478bd9Sstevel@tonic-gate } 14987c478bd9Sstevel@tonic-gate pt = dpt->part_table; 14997c478bd9Sstevel@tonic-gate 15007c478bd9Sstevel@tonic-gate /* 15017c478bd9Sstevel@tonic-gate * Go through default partition table, finding fixed 15027c478bd9Sstevel@tonic-gate * sized entries. 15037c478bd9Sstevel@tonic-gate */ 15047c478bd9Sstevel@tonic-gate freecyls = label->dkl_ncyl; 15057c478bd9Sstevel@tonic-gate blks_per_cyl = label->dkl_nhead * label->dkl_nsect; 15067c478bd9Sstevel@tonic-gate for (i = 0; i < NDKMAP; i++) { 15077c478bd9Sstevel@tonic-gate if (pt->partitions[i] == HOG || pt->partitions[i] == 0) { 15087c478bd9Sstevel@tonic-gate ncyls[i] = 0; 15097c478bd9Sstevel@tonic-gate } else { 15107c478bd9Sstevel@tonic-gate /* 15117c478bd9Sstevel@tonic-gate * Calculate number of cylinders necessary 15127c478bd9Sstevel@tonic-gate * for specified size, rounding up to 15137c478bd9Sstevel@tonic-gate * the next greatest integral number of 15147c478bd9Sstevel@tonic-gate * cylinders. Always give what they 15157c478bd9Sstevel@tonic-gate * asked or more, never less. 15167c478bd9Sstevel@tonic-gate */ 151765908c77Syu, larry liu - Sun Microsystems - Beijing China nblks = pt->partitions[i] * ((1024*1024)/cur_blksz); 15187c478bd9Sstevel@tonic-gate nblks += (blks_per_cyl - 1); 15197c478bd9Sstevel@tonic-gate ncyls[i] = nblks / blks_per_cyl; 15207c478bd9Sstevel@tonic-gate freecyls -= ncyls[i]; 15217c478bd9Sstevel@tonic-gate } 15227c478bd9Sstevel@tonic-gate } 15237c478bd9Sstevel@tonic-gate 15247c478bd9Sstevel@tonic-gate if (freecyls < 0) { 15257c478bd9Sstevel@tonic-gate if (option_msg && diag_msg) { 15267c478bd9Sstevel@tonic-gate for (i = 0; i < NDKMAP; i++) { 15277c478bd9Sstevel@tonic-gate if (ncyls[i] == 0) 15287c478bd9Sstevel@tonic-gate continue; 1529342440ecSPrasad Singamsetty err_print("Partition %d: %u cyls\n", 15307c478bd9Sstevel@tonic-gate i, ncyls[i]); 15317c478bd9Sstevel@tonic-gate } 15327c478bd9Sstevel@tonic-gate err_print("Free cylinders exhausted (%d)\n", 15337c478bd9Sstevel@tonic-gate freecyls); 15347c478bd9Sstevel@tonic-gate } 15357c478bd9Sstevel@tonic-gate return (0); 15367c478bd9Sstevel@tonic-gate } 15377c478bd9Sstevel@tonic-gate #if defined(i386) 15387c478bd9Sstevel@tonic-gate /* 15397c478bd9Sstevel@tonic-gate * Set the default boot partition to 1 cylinder 15407c478bd9Sstevel@tonic-gate */ 15417c478bd9Sstevel@tonic-gate ncyls[8] = 1; 15427c478bd9Sstevel@tonic-gate freecyls -= 1; 15437c478bd9Sstevel@tonic-gate 15447c478bd9Sstevel@tonic-gate /* 15457c478bd9Sstevel@tonic-gate * If current disk type is not a SCSI disk, 15467c478bd9Sstevel@tonic-gate * set the default alternates partition to 2 cylinders 15477c478bd9Sstevel@tonic-gate */ 15487c478bd9Sstevel@tonic-gate if (ctrl_type != DKC_SCSI_CCS) { 15497c478bd9Sstevel@tonic-gate ncyls[9] = 2; 15507c478bd9Sstevel@tonic-gate freecyls -= 2; 15517c478bd9Sstevel@tonic-gate } 15527c478bd9Sstevel@tonic-gate #endif /* defined(i386) */ 15537c478bd9Sstevel@tonic-gate 15547c478bd9Sstevel@tonic-gate /* 15557c478bd9Sstevel@tonic-gate * Set the free hog partition to whatever space remains. 15567c478bd9Sstevel@tonic-gate * It's an error to have more than one HOG partition, 15577c478bd9Sstevel@tonic-gate * but we don't verify that here. 15587c478bd9Sstevel@tonic-gate */ 15597c478bd9Sstevel@tonic-gate for (i = 0; i < NDKMAP; i++) { 15607c478bd9Sstevel@tonic-gate if (pt->partitions[i] == HOG) { 15617c478bd9Sstevel@tonic-gate assert(ncyls[i] == 0); 15627c478bd9Sstevel@tonic-gate ncyls[i] = freecyls; 15637c478bd9Sstevel@tonic-gate break; 15647c478bd9Sstevel@tonic-gate } 15657c478bd9Sstevel@tonic-gate } 15667c478bd9Sstevel@tonic-gate 15677c478bd9Sstevel@tonic-gate /* 15687c478bd9Sstevel@tonic-gate * Error checking 15697c478bd9Sstevel@tonic-gate */ 15707c478bd9Sstevel@tonic-gate ncyl = 0; 15717c478bd9Sstevel@tonic-gate for (i = 0; i < NDKMAP; i++) { 15727c478bd9Sstevel@tonic-gate ncyl += ncyls[i]; 15737c478bd9Sstevel@tonic-gate } 15747c478bd9Sstevel@tonic-gate assert(ncyl == (label->dkl_ncyl)); 15757c478bd9Sstevel@tonic-gate 15767c478bd9Sstevel@tonic-gate /* 15777c478bd9Sstevel@tonic-gate * Finally, install the partition in the label. 15787c478bd9Sstevel@tonic-gate */ 15797c478bd9Sstevel@tonic-gate cyl = 0; 15807c478bd9Sstevel@tonic-gate 15817c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_16) 15827c478bd9Sstevel@tonic-gate for (i = NDKMAP/2; i < NDKMAP; i++) { 15837c478bd9Sstevel@tonic-gate if (i == 2 || ncyls[i] == 0) 15847c478bd9Sstevel@tonic-gate continue; 15857c478bd9Sstevel@tonic-gate label->dkl_vtoc.v_part[i].p_start = cyl * blks_per_cyl; 15867c478bd9Sstevel@tonic-gate label->dkl_vtoc.v_part[i].p_size = ncyls[i] * blks_per_cyl; 15877c478bd9Sstevel@tonic-gate cyl += ncyls[i]; 15887c478bd9Sstevel@tonic-gate } 15897c478bd9Sstevel@tonic-gate for (i = 0; i < NDKMAP/2; i++) { 15907c478bd9Sstevel@tonic-gate 15917c478bd9Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_8) 15927c478bd9Sstevel@tonic-gate for (i = 0; i < NDKMAP; i++) { 15937c478bd9Sstevel@tonic-gate 15947c478bd9Sstevel@tonic-gate #else 15957c478bd9Sstevel@tonic-gate #error No VTOC format defined. 15967c478bd9Sstevel@tonic-gate #endif /* defined(_SUNOS_VTOC_16) */ 15977c478bd9Sstevel@tonic-gate 15983ccda647Slclee if (i == 2 || ncyls[i] == 0) { 15993ccda647Slclee #if defined(_SUNOS_VTOC_8) 16003ccda647Slclee if (i != 2) { 16013ccda647Slclee label->dkl_map[i].dkl_cylno = 0; 16023ccda647Slclee label->dkl_map[i].dkl_nblk = 0; 16033ccda647Slclee } 16043ccda647Slclee #endif 16057c478bd9Sstevel@tonic-gate continue; 16063ccda647Slclee } 16077c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8) 16087c478bd9Sstevel@tonic-gate label->dkl_map[i].dkl_cylno = cyl; 16097c478bd9Sstevel@tonic-gate label->dkl_map[i].dkl_nblk = ncyls[i] * blks_per_cyl; 16107c478bd9Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16) 16117c478bd9Sstevel@tonic-gate label->dkl_vtoc.v_part[i].p_start = cyl * blks_per_cyl; 16127c478bd9Sstevel@tonic-gate label->dkl_vtoc.v_part[i].p_size = ncyls[i] * blks_per_cyl; 16137c478bd9Sstevel@tonic-gate 16147c478bd9Sstevel@tonic-gate #else 16157c478bd9Sstevel@tonic-gate #error No VTOC format defined. 16167c478bd9Sstevel@tonic-gate #endif /* defined(_SUNOS_VTOC_8) */ 16177c478bd9Sstevel@tonic-gate 16187c478bd9Sstevel@tonic-gate cyl += ncyls[i]; 16197c478bd9Sstevel@tonic-gate } 16207c478bd9Sstevel@tonic-gate 16217c478bd9Sstevel@tonic-gate /* 16227c478bd9Sstevel@tonic-gate * Set the whole disk partition 16237c478bd9Sstevel@tonic-gate */ 16247c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8) 16257c478bd9Sstevel@tonic-gate label->dkl_map[2].dkl_cylno = 0; 16267c478bd9Sstevel@tonic-gate label->dkl_map[2].dkl_nblk = 16277c478bd9Sstevel@tonic-gate label->dkl_ncyl * label->dkl_nhead * label->dkl_nsect; 16287c478bd9Sstevel@tonic-gate 16297c478bd9Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16) 16307c478bd9Sstevel@tonic-gate label->dkl_vtoc.v_part[2].p_start = 0; 16317c478bd9Sstevel@tonic-gate label->dkl_vtoc.v_part[2].p_size = 16327c478bd9Sstevel@tonic-gate (label->dkl_ncyl + label->dkl_acyl) * label->dkl_nhead * 16337c478bd9Sstevel@tonic-gate label->dkl_nsect; 16347c478bd9Sstevel@tonic-gate #else 16357c478bd9Sstevel@tonic-gate #error No VTOC format defined. 16367c478bd9Sstevel@tonic-gate #endif /* defined(_SUNOS_VTOC_8) */ 16377c478bd9Sstevel@tonic-gate 16387c478bd9Sstevel@tonic-gate 16397c478bd9Sstevel@tonic-gate if (option_msg && diag_msg) { 16407c478bd9Sstevel@tonic-gate float scaled; 16417c478bd9Sstevel@tonic-gate err_print("\n"); 16427c478bd9Sstevel@tonic-gate for (i = 0; i < NDKMAP; i++) { 16437c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8) 16447c478bd9Sstevel@tonic-gate if (label->dkl_map[i].dkl_nblk == 0) 16457c478bd9Sstevel@tonic-gate 16467c478bd9Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16) 16477c478bd9Sstevel@tonic-gate if (label->dkl_vtoc.v_part[i].p_size == 0) 16487c478bd9Sstevel@tonic-gate 16497c478bd9Sstevel@tonic-gate #else 16507c478bd9Sstevel@tonic-gate #error No VTOC format defined. 16517c478bd9Sstevel@tonic-gate #endif /* defined(_SUNOS_VTOC_8) */ 16527c478bd9Sstevel@tonic-gate 16537c478bd9Sstevel@tonic-gate continue; 16547c478bd9Sstevel@tonic-gate err_print("Partition %d: ", i); 16557c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8) 16567c478bd9Sstevel@tonic-gate scaled = bn2mb(label->dkl_map[i].dkl_nblk); 16577c478bd9Sstevel@tonic-gate 16587c478bd9Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16) 16597c478bd9Sstevel@tonic-gate 16607c478bd9Sstevel@tonic-gate scaled = bn2mb(label->dkl_vtoc.v_part[i].p_size); 16617c478bd9Sstevel@tonic-gate #else 16627c478bd9Sstevel@tonic-gate #error No VTOC format defined. 16637c478bd9Sstevel@tonic-gate #endif /* defined(_SUNOS_VTOC_8) */ 16647c478bd9Sstevel@tonic-gate 16657c478bd9Sstevel@tonic-gate if (scaled > 1024.0) { 16667c478bd9Sstevel@tonic-gate err_print("%6.2fGB ", scaled/1024.0); 16677c478bd9Sstevel@tonic-gate } else { 16687c478bd9Sstevel@tonic-gate err_print("%6.2fMB ", scaled); 16697c478bd9Sstevel@tonic-gate } 16707c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8) 167165908c77Syu, larry liu - Sun Microsystems - Beijing China err_print(" %6d cylinders\n", 16727c478bd9Sstevel@tonic-gate label->dkl_map[i].dkl_nblk/blks_per_cyl); 16737c478bd9Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16) 167465908c77Syu, larry liu - Sun Microsystems - Beijing China err_print(" %6d cylinders\n", 16757c478bd9Sstevel@tonic-gate label->dkl_vtoc.v_part[i].p_size/blks_per_cyl); 16767c478bd9Sstevel@tonic-gate #else 16777c478bd9Sstevel@tonic-gate #error No VTOC format defined. 16787c478bd9Sstevel@tonic-gate #endif /* defined(_SUNOS_VTOC_8) */ 16797c478bd9Sstevel@tonic-gate 16807c478bd9Sstevel@tonic-gate } 16817c478bd9Sstevel@tonic-gate err_print("\n"); 16827c478bd9Sstevel@tonic-gate } 16837c478bd9Sstevel@tonic-gate 16847c478bd9Sstevel@tonic-gate return (1); 16857c478bd9Sstevel@tonic-gate } 16867c478bd9Sstevel@tonic-gate 16877c478bd9Sstevel@tonic-gate 16887c478bd9Sstevel@tonic-gate 16897c478bd9Sstevel@tonic-gate /* 16907c478bd9Sstevel@tonic-gate * Find an existing scsi disk definition by this name, 16917c478bd9Sstevel@tonic-gate * if possible. 16927c478bd9Sstevel@tonic-gate */ 16937c478bd9Sstevel@tonic-gate static struct disk_type * 16947c478bd9Sstevel@tonic-gate find_scsi_disk_type( 16957c478bd9Sstevel@tonic-gate char *disk_name, 16967c478bd9Sstevel@tonic-gate struct dk_label *label) 16977c478bd9Sstevel@tonic-gate { 16987c478bd9Sstevel@tonic-gate struct ctlr_type *ctlr; 16997c478bd9Sstevel@tonic-gate struct disk_type *dp; 17007c478bd9Sstevel@tonic-gate 17017c478bd9Sstevel@tonic-gate ctlr = find_scsi_ctlr_type(); 17027c478bd9Sstevel@tonic-gate for (dp = ctlr->ctype_dlist; dp != NULL; dp = dp->dtype_next) { 17037c478bd9Sstevel@tonic-gate if (dp->dtype_asciilabel) { 17047c478bd9Sstevel@tonic-gate if ((strcmp(dp->dtype_asciilabel, disk_name) == 0) && 17057c478bd9Sstevel@tonic-gate dp->dtype_pcyl == label->dkl_pcyl && 17067c478bd9Sstevel@tonic-gate dp->dtype_ncyl == label->dkl_ncyl && 17077c478bd9Sstevel@tonic-gate dp->dtype_acyl == label->dkl_acyl && 17087c478bd9Sstevel@tonic-gate dp->dtype_nhead == label->dkl_nhead && 17097c478bd9Sstevel@tonic-gate dp->dtype_nsect == label->dkl_nsect) { 17107c478bd9Sstevel@tonic-gate return (dp); 17117c478bd9Sstevel@tonic-gate } 17127c478bd9Sstevel@tonic-gate } 17137c478bd9Sstevel@tonic-gate } 17147c478bd9Sstevel@tonic-gate 17157c478bd9Sstevel@tonic-gate return ((struct disk_type *)NULL); 17167c478bd9Sstevel@tonic-gate } 17177c478bd9Sstevel@tonic-gate 17187c478bd9Sstevel@tonic-gate 17197c478bd9Sstevel@tonic-gate /* 17207c478bd9Sstevel@tonic-gate * Find an existing scsi disk definition by this name, 17217c478bd9Sstevel@tonic-gate * if possible. 17227c478bd9Sstevel@tonic-gate */ 17237c478bd9Sstevel@tonic-gate static struct disk_type * 17247c478bd9Sstevel@tonic-gate find_scsi_disk_by_name( 17257c478bd9Sstevel@tonic-gate char *disk_name) 17267c478bd9Sstevel@tonic-gate { 17277c478bd9Sstevel@tonic-gate struct ctlr_type *ctlr; 17287c478bd9Sstevel@tonic-gate struct disk_type *dp; 17297c478bd9Sstevel@tonic-gate 17307c478bd9Sstevel@tonic-gate ctlr = find_scsi_ctlr_type(); 17317c478bd9Sstevel@tonic-gate for (dp = ctlr->ctype_dlist; dp != NULL; dp = dp->dtype_next) { 17327c478bd9Sstevel@tonic-gate if (dp->dtype_asciilabel) { 17337c478bd9Sstevel@tonic-gate if ((strcmp(dp->dtype_asciilabel, disk_name) == 0)) { 17347c478bd9Sstevel@tonic-gate return (dp); 17357c478bd9Sstevel@tonic-gate } 17367c478bd9Sstevel@tonic-gate } 17377c478bd9Sstevel@tonic-gate } 17387c478bd9Sstevel@tonic-gate 17397c478bd9Sstevel@tonic-gate return ((struct disk_type *)NULL); 17407c478bd9Sstevel@tonic-gate } 17417c478bd9Sstevel@tonic-gate 17427c478bd9Sstevel@tonic-gate 17437c478bd9Sstevel@tonic-gate /* 17447c478bd9Sstevel@tonic-gate * Return a pointer to the ctlr_type structure for SCSI 17457c478bd9Sstevel@tonic-gate * disks. This list is built into the program, so there's 17467c478bd9Sstevel@tonic-gate * no chance of not being able to find it, unless someone 17477c478bd9Sstevel@tonic-gate * totally mangles the code. 17487c478bd9Sstevel@tonic-gate */ 17497c478bd9Sstevel@tonic-gate static struct ctlr_type * 17507c478bd9Sstevel@tonic-gate find_scsi_ctlr_type() 17517c478bd9Sstevel@tonic-gate { 17527c478bd9Sstevel@tonic-gate struct mctlr_list *mlp; 17537c478bd9Sstevel@tonic-gate 17547c478bd9Sstevel@tonic-gate mlp = controlp; 17557c478bd9Sstevel@tonic-gate 17567c478bd9Sstevel@tonic-gate while (mlp != NULL) { 1757f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China if (mlp->ctlr_type->ctype_ctype == DKC_SCSI_CCS) { 17587c478bd9Sstevel@tonic-gate return (mlp->ctlr_type); 17597c478bd9Sstevel@tonic-gate } 17607c478bd9Sstevel@tonic-gate mlp = mlp->next; 17617c478bd9Sstevel@tonic-gate } 17627c478bd9Sstevel@tonic-gate 17637c478bd9Sstevel@tonic-gate impossible("no SCSI controller type"); 1764052b6e8aSbg159949 1765052b6e8aSbg159949 return ((struct ctlr_type *)NULL); 17667c478bd9Sstevel@tonic-gate } 17677c478bd9Sstevel@tonic-gate 17687c478bd9Sstevel@tonic-gate 17697c478bd9Sstevel@tonic-gate 17707c478bd9Sstevel@tonic-gate /* 17717c478bd9Sstevel@tonic-gate * Return a pointer to the scsi ctlr_info structure. This 17727c478bd9Sstevel@tonic-gate * structure is allocated the first time format sees a 17737c478bd9Sstevel@tonic-gate * disk on this controller, so it must be present. 17747c478bd9Sstevel@tonic-gate */ 17757c478bd9Sstevel@tonic-gate static struct ctlr_info * 17767c478bd9Sstevel@tonic-gate find_scsi_ctlr_info( 17777c478bd9Sstevel@tonic-gate struct dk_cinfo *dkinfo) 17787c478bd9Sstevel@tonic-gate { 17797c478bd9Sstevel@tonic-gate struct ctlr_info *ctlr; 17807c478bd9Sstevel@tonic-gate 1781f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China if (dkinfo->dki_ctype != DKC_SCSI_CCS) { 17827c478bd9Sstevel@tonic-gate return (NULL); 17837c478bd9Sstevel@tonic-gate } 17847c478bd9Sstevel@tonic-gate 17857c478bd9Sstevel@tonic-gate for (ctlr = ctlr_list; ctlr != NULL; ctlr = ctlr->ctlr_next) { 17867c478bd9Sstevel@tonic-gate if (ctlr->ctlr_addr == dkinfo->dki_addr && 17877c478bd9Sstevel@tonic-gate ctlr->ctlr_space == dkinfo->dki_space && 1788f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China ctlr->ctlr_ctype->ctype_ctype == DKC_SCSI_CCS) { 17897c478bd9Sstevel@tonic-gate return (ctlr); 17907c478bd9Sstevel@tonic-gate } 17917c478bd9Sstevel@tonic-gate } 17927c478bd9Sstevel@tonic-gate 17937c478bd9Sstevel@tonic-gate impossible("no SCSI controller info"); 1794052b6e8aSbg159949 1795052b6e8aSbg159949 return ((struct ctlr_info *)NULL); 17967c478bd9Sstevel@tonic-gate } 17977c478bd9Sstevel@tonic-gate 17987c478bd9Sstevel@tonic-gate 17997c478bd9Sstevel@tonic-gate 18007c478bd9Sstevel@tonic-gate static struct disk_type * 18017c478bd9Sstevel@tonic-gate new_scsi_disk_type( 18027c478bd9Sstevel@tonic-gate int fd, 18037c478bd9Sstevel@tonic-gate char *disk_name, 18047c478bd9Sstevel@tonic-gate struct dk_label *label) 18057c478bd9Sstevel@tonic-gate { 18067c478bd9Sstevel@tonic-gate struct disk_type *dp; 18077c478bd9Sstevel@tonic-gate struct disk_type *disk; 18087c478bd9Sstevel@tonic-gate struct ctlr_info *ctlr; 18097c478bd9Sstevel@tonic-gate struct dk_cinfo dkinfo; 18107c478bd9Sstevel@tonic-gate struct partition_info *part; 18117c478bd9Sstevel@tonic-gate struct partition_info *pt; 18127c478bd9Sstevel@tonic-gate struct disk_info *disk_info; 18137c478bd9Sstevel@tonic-gate int i; 18147c478bd9Sstevel@tonic-gate 18157c478bd9Sstevel@tonic-gate /* 18167c478bd9Sstevel@tonic-gate * Get the disk controller info for this disk 18177c478bd9Sstevel@tonic-gate */ 18187c478bd9Sstevel@tonic-gate if (ioctl(fd, DKIOCINFO, &dkinfo) == -1) { 18197c478bd9Sstevel@tonic-gate if (option_msg && diag_msg) { 18207c478bd9Sstevel@tonic-gate err_print("DKIOCINFO failed\n"); 18217c478bd9Sstevel@tonic-gate } 18227c478bd9Sstevel@tonic-gate return (NULL); 18237c478bd9Sstevel@tonic-gate } 18247c478bd9Sstevel@tonic-gate 18257c478bd9Sstevel@tonic-gate /* 18267c478bd9Sstevel@tonic-gate * Find the ctlr_info for this disk. 18277c478bd9Sstevel@tonic-gate */ 18287c478bd9Sstevel@tonic-gate ctlr = find_scsi_ctlr_info(&dkinfo); 18297c478bd9Sstevel@tonic-gate 18307c478bd9Sstevel@tonic-gate /* 18317c478bd9Sstevel@tonic-gate * Allocate a new disk type for the SCSI controller. 18327c478bd9Sstevel@tonic-gate */ 18337c478bd9Sstevel@tonic-gate disk = (struct disk_type *)zalloc(sizeof (struct disk_type)); 18347c478bd9Sstevel@tonic-gate 18357c478bd9Sstevel@tonic-gate /* 18367c478bd9Sstevel@tonic-gate * Find the disk_info instance for this disk. 18377c478bd9Sstevel@tonic-gate */ 18387c478bd9Sstevel@tonic-gate disk_info = find_scsi_disk_info(&dkinfo); 18397c478bd9Sstevel@tonic-gate 18407c478bd9Sstevel@tonic-gate /* 18417c478bd9Sstevel@tonic-gate * The controller and the disk should match. 18427c478bd9Sstevel@tonic-gate */ 18437c478bd9Sstevel@tonic-gate assert(disk_info->disk_ctlr == ctlr); 18447c478bd9Sstevel@tonic-gate 18457c478bd9Sstevel@tonic-gate /* 18467c478bd9Sstevel@tonic-gate * Link the disk into the list of disks 18477c478bd9Sstevel@tonic-gate */ 18487c478bd9Sstevel@tonic-gate dp = ctlr->ctlr_ctype->ctype_dlist; 18497c478bd9Sstevel@tonic-gate if (dp == NULL) { 1850342440ecSPrasad Singamsetty ctlr->ctlr_ctype->ctype_dlist = disk; 18517c478bd9Sstevel@tonic-gate } else { 18527c478bd9Sstevel@tonic-gate while (dp->dtype_next != NULL) { 18537c478bd9Sstevel@tonic-gate dp = dp->dtype_next; 18547c478bd9Sstevel@tonic-gate } 18557c478bd9Sstevel@tonic-gate dp->dtype_next = disk; 18567c478bd9Sstevel@tonic-gate } 18577c478bd9Sstevel@tonic-gate disk->dtype_next = NULL; 18587c478bd9Sstevel@tonic-gate 18597c478bd9Sstevel@tonic-gate /* 18607c478bd9Sstevel@tonic-gate * Allocate and initialize the disk name. 18617c478bd9Sstevel@tonic-gate */ 18627c478bd9Sstevel@tonic-gate disk->dtype_asciilabel = alloc_string(disk_name); 18637c478bd9Sstevel@tonic-gate 18647c478bd9Sstevel@tonic-gate /* 18657c478bd9Sstevel@tonic-gate * Initialize disk geometry info 18667c478bd9Sstevel@tonic-gate */ 18677c478bd9Sstevel@tonic-gate disk->dtype_pcyl = label->dkl_pcyl; 18687c478bd9Sstevel@tonic-gate disk->dtype_ncyl = label->dkl_ncyl; 18697c478bd9Sstevel@tonic-gate disk->dtype_acyl = label->dkl_acyl; 18707c478bd9Sstevel@tonic-gate disk->dtype_nhead = label->dkl_nhead; 18717c478bd9Sstevel@tonic-gate disk->dtype_nsect = label->dkl_nsect; 18727c478bd9Sstevel@tonic-gate disk->dtype_rpm = label->dkl_rpm; 18737c478bd9Sstevel@tonic-gate 18747c478bd9Sstevel@tonic-gate /* 18757c478bd9Sstevel@tonic-gate * Attempt to match the partition map in the label 18767c478bd9Sstevel@tonic-gate * with a know partition for this disk type. 18777c478bd9Sstevel@tonic-gate */ 18787c478bd9Sstevel@tonic-gate for (part = disk->dtype_plist; part; part = part->pinfo_next) { 18797c478bd9Sstevel@tonic-gate if (parts_match(label, part)) { 18807c478bd9Sstevel@tonic-gate break; 18817c478bd9Sstevel@tonic-gate } 18827c478bd9Sstevel@tonic-gate } 18837c478bd9Sstevel@tonic-gate 18847c478bd9Sstevel@tonic-gate /* 18857c478bd9Sstevel@tonic-gate * If no match was made, we need to create a partition 18867c478bd9Sstevel@tonic-gate * map for this disk. 18877c478bd9Sstevel@tonic-gate */ 18887c478bd9Sstevel@tonic-gate if (part == NULL) { 18897c478bd9Sstevel@tonic-gate part = (struct partition_info *) 18907c478bd9Sstevel@tonic-gate zalloc(sizeof (struct partition_info)); 18917c478bd9Sstevel@tonic-gate pt = disk->dtype_plist; 18927c478bd9Sstevel@tonic-gate if (pt == NULL) { 18937c478bd9Sstevel@tonic-gate disk->dtype_plist = part; 18947c478bd9Sstevel@tonic-gate } else { 18957c478bd9Sstevel@tonic-gate while (pt->pinfo_next != NULL) { 18967c478bd9Sstevel@tonic-gate pt = pt->pinfo_next; 18977c478bd9Sstevel@tonic-gate } 18987c478bd9Sstevel@tonic-gate pt->pinfo_next = part; 18997c478bd9Sstevel@tonic-gate } 19007c478bd9Sstevel@tonic-gate part->pinfo_next = NULL; 19017c478bd9Sstevel@tonic-gate 19027c478bd9Sstevel@tonic-gate /* 19037c478bd9Sstevel@tonic-gate * Set up the partition name 19047c478bd9Sstevel@tonic-gate */ 19057c478bd9Sstevel@tonic-gate part->pinfo_name = alloc_string("default"); 19067c478bd9Sstevel@tonic-gate 19077c478bd9Sstevel@tonic-gate /* 19087c478bd9Sstevel@tonic-gate * Fill in the partition info from the label 19097c478bd9Sstevel@tonic-gate */ 19107c478bd9Sstevel@tonic-gate for (i = 0; i < NDKMAP; i++) { 19117c478bd9Sstevel@tonic-gate 19127c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8) 19137c478bd9Sstevel@tonic-gate part->pinfo_map[i] = label->dkl_map[i]; 19147c478bd9Sstevel@tonic-gate 19157c478bd9Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16) 19167c478bd9Sstevel@tonic-gate part->pinfo_map[i].dkl_cylno = 19177c478bd9Sstevel@tonic-gate label->dkl_vtoc.v_part[i].p_start / 1918342440ecSPrasad Singamsetty ((blkaddr32_t)(disk->dtype_nhead * 19197c478bd9Sstevel@tonic-gate disk->dtype_nsect - apc)); 19207c478bd9Sstevel@tonic-gate part->pinfo_map[i].dkl_nblk = 19217c478bd9Sstevel@tonic-gate label->dkl_vtoc.v_part[i].p_size; 19227c478bd9Sstevel@tonic-gate #else 19237c478bd9Sstevel@tonic-gate #error No VTOC format defined. 19247c478bd9Sstevel@tonic-gate #endif /* defined(_SUNOS_VTOC_8) */ 19257c478bd9Sstevel@tonic-gate 19267c478bd9Sstevel@tonic-gate } 19277c478bd9Sstevel@tonic-gate } 19287c478bd9Sstevel@tonic-gate 19297c478bd9Sstevel@tonic-gate 19307c478bd9Sstevel@tonic-gate /* 19317c478bd9Sstevel@tonic-gate * Use the VTOC if valid, or install a default 19327c478bd9Sstevel@tonic-gate */ 19337c478bd9Sstevel@tonic-gate if (label->dkl_vtoc.v_version == V_VERSION) { 19347c478bd9Sstevel@tonic-gate (void) memcpy(disk_info->v_volume, label->dkl_vtoc.v_volume, 19357c478bd9Sstevel@tonic-gate LEN_DKL_VVOL); 19367c478bd9Sstevel@tonic-gate part->vtoc = label->dkl_vtoc; 19377c478bd9Sstevel@tonic-gate } else { 19387c478bd9Sstevel@tonic-gate (void) memset(disk_info->v_volume, 0, LEN_DKL_VVOL); 19397c478bd9Sstevel@tonic-gate set_vtoc_defaults(part); 19407c478bd9Sstevel@tonic-gate } 19417c478bd9Sstevel@tonic-gate 19427c478bd9Sstevel@tonic-gate /* 19437c478bd9Sstevel@tonic-gate * Link the disk to the partition map 19447c478bd9Sstevel@tonic-gate */ 19457c478bd9Sstevel@tonic-gate disk_info->disk_parts = part; 19467c478bd9Sstevel@tonic-gate 19477c478bd9Sstevel@tonic-gate return (disk); 19487c478bd9Sstevel@tonic-gate } 19497c478bd9Sstevel@tonic-gate 19507c478bd9Sstevel@tonic-gate 1951698107ecSlh195018 /* 1952698107ecSlh195018 * Delete a disk type from disk type list. 1953698107ecSlh195018 */ 1954698107ecSlh195018 int 1955*2f15e7adSIgor Kozhukhov delete_disk_type(struct disk_type *disk_type) 1956698107ecSlh195018 { 1957698107ecSlh195018 struct ctlr_type *ctlr; 1958698107ecSlh195018 struct disk_type *dp, *disk; 1959698107ecSlh195018 1960*2f15e7adSIgor Kozhukhov if (cur_ctype->ctype_ctype == DKC_DIRECT || 1961*2f15e7adSIgor Kozhukhov cur_ctype->ctype_ctype == DKC_VBD || 1962*2f15e7adSIgor Kozhukhov cur_ctype->ctype_ctype == DKC_BLKDEV) 1963*2f15e7adSIgor Kozhukhov ctlr = find_ctlr_type(cur_ctype->ctype_ctype); 1964698107ecSlh195018 else 1965698107ecSlh195018 ctlr = find_scsi_ctlr_type(); 1966698107ecSlh195018 if (ctlr == NULL || ctlr->ctype_dlist == NULL) { 1967698107ecSlh195018 return (-1); 1968698107ecSlh195018 } 1969698107ecSlh195018 1970698107ecSlh195018 disk = ctlr->ctype_dlist; 1971698107ecSlh195018 if (disk == disk_type) { 1972698107ecSlh195018 ctlr->ctype_dlist = disk->dtype_next; 1973698107ecSlh195018 if (cur_label == L_TYPE_EFI) 1974698107ecSlh195018 free(disk->dtype_plist->etoc); 1975698107ecSlh195018 free(disk->dtype_plist); 1976f1bf0656SHans Rosenfeld free(disk->vendor); 1977f1bf0656SHans Rosenfeld free(disk->product); 1978f1bf0656SHans Rosenfeld free(disk->revision); 1979698107ecSlh195018 free(disk); 1980698107ecSlh195018 return (0); 1981698107ecSlh195018 } else { 1982698107ecSlh195018 for (dp = disk->dtype_next; dp != NULL; 1983698107ecSlh195018 disk = disk->dtype_next, dp = dp->dtype_next) { 1984698107ecSlh195018 if (dp == disk_type) { 1985698107ecSlh195018 disk->dtype_next = dp->dtype_next; 1986698107ecSlh195018 if (cur_label == L_TYPE_EFI) 1987698107ecSlh195018 free(dp->dtype_plist->etoc); 1988698107ecSlh195018 free(dp->dtype_plist); 1989f1bf0656SHans Rosenfeld free(dp->vendor); 1990f1bf0656SHans Rosenfeld free(dp->product); 1991f1bf0656SHans Rosenfeld free(dp->revision); 1992698107ecSlh195018 free(dp); 1993698107ecSlh195018 return (0); 1994698107ecSlh195018 } 1995698107ecSlh195018 } 1996698107ecSlh195018 return (-1); 1997698107ecSlh195018 } 1998698107ecSlh195018 } 1999698107ecSlh195018 2000698107ecSlh195018 20017c478bd9Sstevel@tonic-gate static struct disk_info * 20027c478bd9Sstevel@tonic-gate find_scsi_disk_info( 20037c478bd9Sstevel@tonic-gate struct dk_cinfo *dkinfo) 20047c478bd9Sstevel@tonic-gate { 20057c478bd9Sstevel@tonic-gate struct disk_info *disk; 20067c478bd9Sstevel@tonic-gate struct dk_cinfo *dp; 20077c478bd9Sstevel@tonic-gate 20087c478bd9Sstevel@tonic-gate for (disk = disk_list; disk != NULL; disk = disk->disk_next) { 2009f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China assert(dkinfo->dki_ctype == DKC_SCSI_CCS); 20107c478bd9Sstevel@tonic-gate dp = &disk->disk_dkinfo; 20117c478bd9Sstevel@tonic-gate if (dp->dki_ctype == dkinfo->dki_ctype && 20127c478bd9Sstevel@tonic-gate dp->dki_cnum == dkinfo->dki_cnum && 20137c478bd9Sstevel@tonic-gate dp->dki_unit == dkinfo->dki_unit && 20147c478bd9Sstevel@tonic-gate strcmp(dp->dki_dname, dkinfo->dki_dname) == 0) { 20157c478bd9Sstevel@tonic-gate return (disk); 20167c478bd9Sstevel@tonic-gate } 20177c478bd9Sstevel@tonic-gate } 20187c478bd9Sstevel@tonic-gate 20197c478bd9Sstevel@tonic-gate impossible("No SCSI disk info instance\n"); 2020052b6e8aSbg159949 2021052b6e8aSbg159949 return ((struct disk_info *)NULL); 20227c478bd9Sstevel@tonic-gate } 20237c478bd9Sstevel@tonic-gate 20247c478bd9Sstevel@tonic-gate 20257c478bd9Sstevel@tonic-gate static char * 20267c478bd9Sstevel@tonic-gate get_sun_disk_name( 20277c478bd9Sstevel@tonic-gate char *disk_name, 20287c478bd9Sstevel@tonic-gate struct scsi_inquiry *inquiry) 20297c478bd9Sstevel@tonic-gate { 20307c478bd9Sstevel@tonic-gate /* 20317c478bd9Sstevel@tonic-gate * Extract the sun name of the disk 20327c478bd9Sstevel@tonic-gate */ 20337c478bd9Sstevel@tonic-gate (void) memset(disk_name, 0, DISK_NAME_MAX); 20347c478bd9Sstevel@tonic-gate (void) memcpy(disk_name, (char *)&inquiry->inq_pid[9], 7); 20357c478bd9Sstevel@tonic-gate 20367c478bd9Sstevel@tonic-gate return (disk_name); 20377c478bd9Sstevel@tonic-gate } 20387c478bd9Sstevel@tonic-gate 20397c478bd9Sstevel@tonic-gate 20401662a2f2SGary Mills char * 20417c478bd9Sstevel@tonic-gate get_generic_disk_name( 20427c478bd9Sstevel@tonic-gate char *disk_name, 20437c478bd9Sstevel@tonic-gate struct scsi_inquiry *inquiry) 20447c478bd9Sstevel@tonic-gate { 20457c478bd9Sstevel@tonic-gate char *p; 20467c478bd9Sstevel@tonic-gate 20477c478bd9Sstevel@tonic-gate (void) memset(disk_name, 0, DISK_NAME_MAX); 20487c478bd9Sstevel@tonic-gate p = strcopy(disk_name, inquiry->inq_vid, 20497c478bd9Sstevel@tonic-gate sizeof (inquiry->inq_vid)); 20507c478bd9Sstevel@tonic-gate *p++ = '-'; 20517c478bd9Sstevel@tonic-gate p = strcopy(p, inquiry->inq_pid, sizeof (inquiry->inq_pid)); 20527c478bd9Sstevel@tonic-gate *p++ = '-'; 20537c478bd9Sstevel@tonic-gate p = strcopy(p, inquiry->inq_revision, 20547c478bd9Sstevel@tonic-gate sizeof (inquiry->inq_revision)); 20557c478bd9Sstevel@tonic-gate 20567c478bd9Sstevel@tonic-gate return (disk_name); 20577c478bd9Sstevel@tonic-gate } 20587c478bd9Sstevel@tonic-gate 20597c478bd9Sstevel@tonic-gate /* 20607c478bd9Sstevel@tonic-gate * Copy a string of characters from src to dst, for at 20617c478bd9Sstevel@tonic-gate * most n bytes. Strip all leading and trailing spaces, 20627c478bd9Sstevel@tonic-gate * and stop if there are any non-printable characters. 20637c478bd9Sstevel@tonic-gate * Return ptr to the next character to be filled. 20647c478bd9Sstevel@tonic-gate */ 20657c478bd9Sstevel@tonic-gate static char * 20667c478bd9Sstevel@tonic-gate strcopy( 20677c478bd9Sstevel@tonic-gate char *dst, 20687c478bd9Sstevel@tonic-gate char *src, 20697c478bd9Sstevel@tonic-gate int n) 20707c478bd9Sstevel@tonic-gate { 20717c478bd9Sstevel@tonic-gate int i; 20727c478bd9Sstevel@tonic-gate 20737c478bd9Sstevel@tonic-gate while (*src == ' ' && n > 0) { 20747c478bd9Sstevel@tonic-gate src++; 20757c478bd9Sstevel@tonic-gate n--; 20767c478bd9Sstevel@tonic-gate } 20777c478bd9Sstevel@tonic-gate 20787c478bd9Sstevel@tonic-gate for (i = 0; n-- > 0 && isascii(*src) && isprint(*src); src++) { 20797c478bd9Sstevel@tonic-gate if (*src == ' ') { 20807c478bd9Sstevel@tonic-gate i++; 20817c478bd9Sstevel@tonic-gate } else { 20827c478bd9Sstevel@tonic-gate while (i-- > 0) 20837c478bd9Sstevel@tonic-gate *dst++ = ' '; 20847c478bd9Sstevel@tonic-gate *dst++ = *src; 20857c478bd9Sstevel@tonic-gate } 20867c478bd9Sstevel@tonic-gate } 20877c478bd9Sstevel@tonic-gate 20887c478bd9Sstevel@tonic-gate *dst = 0; 20897c478bd9Sstevel@tonic-gate return (dst); 20907c478bd9Sstevel@tonic-gate } 20917c478bd9Sstevel@tonic-gate 20927c478bd9Sstevel@tonic-gate /* 20937c478bd9Sstevel@tonic-gate * adjust disk geometry. 20947c478bd9Sstevel@tonic-gate * This is used when disk reports a disk geometry page having 20957c478bd9Sstevel@tonic-gate * no of physical cylinders is < 3 which is the minimum required 20967c478bd9Sstevel@tonic-gate * by Solaris (2 for storing labels and at least one as a data 20977c478bd9Sstevel@tonic-gate * cylinder ) 20987c478bd9Sstevel@tonic-gate */ 20997c478bd9Sstevel@tonic-gate int 2100342440ecSPrasad Singamsetty adjust_disk_geometry(diskaddr_t capacity, uint_t *cyl, uint_t *nhead, 2101342440ecSPrasad Singamsetty uint_t *nsect) 21027c478bd9Sstevel@tonic-gate { 2103342440ecSPrasad Singamsetty uint_t lcyl = *cyl; 2104342440ecSPrasad Singamsetty uint_t lnhead = *nhead; 2105342440ecSPrasad Singamsetty uint_t lnsect = *nsect; 21067c478bd9Sstevel@tonic-gate 21077c478bd9Sstevel@tonic-gate assert(lcyl < SUN_MIN_CYL); 21087c478bd9Sstevel@tonic-gate 21097c478bd9Sstevel@tonic-gate /* 21107c478bd9Sstevel@tonic-gate * reduce nsect by 2 for each iteration and re-calculate 21117c478bd9Sstevel@tonic-gate * the number of cylinders. 21127c478bd9Sstevel@tonic-gate */ 21137c478bd9Sstevel@tonic-gate while (lnsect > MINIMUM_NO_SECTORS && 21147c478bd9Sstevel@tonic-gate lcyl < MINIMUM_NO_CYLINDERS) { 21157c478bd9Sstevel@tonic-gate /* 21167c478bd9Sstevel@tonic-gate * make sure that we do not go below MINIMUM_NO_SECTORS. 21177c478bd9Sstevel@tonic-gate */ 21187c478bd9Sstevel@tonic-gate lnsect = max(MINIMUM_NO_SECTORS, lnsect / 2); 21197c478bd9Sstevel@tonic-gate lcyl = (capacity) / (lnhead * lnsect); 21207c478bd9Sstevel@tonic-gate } 21217c478bd9Sstevel@tonic-gate /* 21227c478bd9Sstevel@tonic-gate * If the geometry still does not satisfy 21237c478bd9Sstevel@tonic-gate * MINIMUM_NO_CYLINDERS then try to reduce the 21247c478bd9Sstevel@tonic-gate * no of heads. 21257c478bd9Sstevel@tonic-gate */ 21267c478bd9Sstevel@tonic-gate while (lnhead > MINIMUM_NO_HEADS && 2127bc067c09Sqd208687 lcyl < MINIMUM_NO_CYLINDERS) { 21287c478bd9Sstevel@tonic-gate lnhead = max(MINIMUM_NO_HEADS, lnhead / 2); 21297c478bd9Sstevel@tonic-gate lcyl = (capacity) / (lnhead * lnsect); 21307c478bd9Sstevel@tonic-gate } 21317c478bd9Sstevel@tonic-gate /* 21327c478bd9Sstevel@tonic-gate * now we should have atleast SUN_MIN_CYL cylinders. 21337c478bd9Sstevel@tonic-gate * If we still do not get SUN_MIN_CYL with MINIMUM_NO_HEADS 21347c478bd9Sstevel@tonic-gate * and MINIMUM_NO_HEADS then return error. 21357c478bd9Sstevel@tonic-gate */ 21367c478bd9Sstevel@tonic-gate if (lcyl < SUN_MIN_CYL) 21377c478bd9Sstevel@tonic-gate return (1); 21387c478bd9Sstevel@tonic-gate else { 21397c478bd9Sstevel@tonic-gate *cyl = lcyl; 21407c478bd9Sstevel@tonic-gate *nhead = lnhead; 21417c478bd9Sstevel@tonic-gate *nsect = lnsect; 21427c478bd9Sstevel@tonic-gate return (0); 21437c478bd9Sstevel@tonic-gate } 21447c478bd9Sstevel@tonic-gate } 21457c478bd9Sstevel@tonic-gate 21467c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8) 21477c478bd9Sstevel@tonic-gate /* 21487c478bd9Sstevel@tonic-gate * Reduce the size of one dimention below a specified 21497c478bd9Sstevel@tonic-gate * limit with a minimum loss of volume. Dimenstions are 21507c478bd9Sstevel@tonic-gate * assumed to be passed in form the largest value (the one 21517c478bd9Sstevel@tonic-gate * that needs to be reduced) to the smallest value. The 21527c478bd9Sstevel@tonic-gate * values will be twiddled until they are all less than or 21537c478bd9Sstevel@tonic-gate * equal to their limit. Returns the number in the new geometry. 21547c478bd9Sstevel@tonic-gate */ 2155342440ecSPrasad Singamsetty static diskaddr_t 21567c478bd9Sstevel@tonic-gate square_box( 2157342440ecSPrasad Singamsetty diskaddr_t capacity, 2158342440ecSPrasad Singamsetty uint_t *dim1, uint_t lim1, 2159342440ecSPrasad Singamsetty uint_t *dim2, uint_t lim2, 2160342440ecSPrasad Singamsetty uint_t *dim3, uint_t lim3) 21617c478bd9Sstevel@tonic-gate { 2162342440ecSPrasad Singamsetty uint_t i; 21637c478bd9Sstevel@tonic-gate 21647c478bd9Sstevel@tonic-gate /* 21657c478bd9Sstevel@tonic-gate * Although the routine should work with any ordering of 21667c478bd9Sstevel@tonic-gate * parameters, it's most efficient if they are passed in 21677c478bd9Sstevel@tonic-gate * in decreasing magnitude. 21687c478bd9Sstevel@tonic-gate */ 21697c478bd9Sstevel@tonic-gate assert(*dim1 >= *dim2); 21707c478bd9Sstevel@tonic-gate assert(*dim2 >= *dim3); 21717c478bd9Sstevel@tonic-gate 21727c478bd9Sstevel@tonic-gate /* 21737c478bd9Sstevel@tonic-gate * This is done in a very arbitrary manner. We could try to 21747c478bd9Sstevel@tonic-gate * find better values but I can't come up with a method that 21757c478bd9Sstevel@tonic-gate * would run in a reasonable amount of time. That could take 21767c478bd9Sstevel@tonic-gate * approximately 65535 * 65535 iterations of a dozen flops each 21777c478bd9Sstevel@tonic-gate * or well over 4G flops. 21787c478bd9Sstevel@tonic-gate * 21797c478bd9Sstevel@tonic-gate * First: 21807c478bd9Sstevel@tonic-gate * 21817c478bd9Sstevel@tonic-gate * Let's see how far we can go with bitshifts w/o losing 21827c478bd9Sstevel@tonic-gate * any blocks. 21837c478bd9Sstevel@tonic-gate */ 21847c478bd9Sstevel@tonic-gate 218565908c77Syu, larry liu - Sun Microsystems - Beijing China for (i = 0; (((*dim1)>>i)&1) == 0 && ((*dim1)>>i) > lim1; i++) 218665908c77Syu, larry liu - Sun Microsystems - Beijing China ; 21877c478bd9Sstevel@tonic-gate if (i) { 21887c478bd9Sstevel@tonic-gate *dim1 = ((*dim1)>>i); 21897c478bd9Sstevel@tonic-gate *dim3 = ((*dim3)<<i); 21907c478bd9Sstevel@tonic-gate } 21917c478bd9Sstevel@tonic-gate 21927c478bd9Sstevel@tonic-gate if (((*dim1) > lim1) || ((*dim2) > lim2) || ((*dim3) > lim3)) { 21937c478bd9Sstevel@tonic-gate double d[4]; 21947c478bd9Sstevel@tonic-gate 21957c478bd9Sstevel@tonic-gate /* 21967c478bd9Sstevel@tonic-gate * Second: 21977c478bd9Sstevel@tonic-gate * 21987c478bd9Sstevel@tonic-gate * Set the highest value at its limit then calculate errors, 21997c478bd9Sstevel@tonic-gate * adjusting the 2nd highest value (we get better resolution 22007c478bd9Sstevel@tonic-gate * that way). 22017c478bd9Sstevel@tonic-gate */ 22027c478bd9Sstevel@tonic-gate d[1] = lim1; 22037c478bd9Sstevel@tonic-gate d[3] = *dim3; 22047c478bd9Sstevel@tonic-gate d[2] = (double)capacity/(d[1]*d[3]); 22057c478bd9Sstevel@tonic-gate 22067c478bd9Sstevel@tonic-gate /* 22077c478bd9Sstevel@tonic-gate * If we overflowed the middle term, set it to its limit and 22087c478bd9Sstevel@tonic-gate * chose a new low term. 22097c478bd9Sstevel@tonic-gate */ 22107c478bd9Sstevel@tonic-gate if (d[2] > lim2) { 22117c478bd9Sstevel@tonic-gate d[2] = lim2; 22127c478bd9Sstevel@tonic-gate d[3] = (double)capacity/(d[1]*d[2]); 22137c478bd9Sstevel@tonic-gate } 22147c478bd9Sstevel@tonic-gate /* 22157c478bd9Sstevel@tonic-gate * Convert to integers. 22167c478bd9Sstevel@tonic-gate */ 22177c478bd9Sstevel@tonic-gate *dim1 = (int)d[1]; 22187c478bd9Sstevel@tonic-gate *dim2 = (int)d[2]; 22197c478bd9Sstevel@tonic-gate *dim3 = (int)d[3]; 22207c478bd9Sstevel@tonic-gate } 22217c478bd9Sstevel@tonic-gate /* 22227c478bd9Sstevel@tonic-gate * Fixup any other possible problems. 22237c478bd9Sstevel@tonic-gate * If this happens, we need a new disklabel format. 22247c478bd9Sstevel@tonic-gate */ 22257c478bd9Sstevel@tonic-gate if (*dim1 > lim1) *dim1 = lim1; 22267c478bd9Sstevel@tonic-gate if (*dim2 > lim2) *dim2 = lim2; 22277c478bd9Sstevel@tonic-gate if (*dim3 > lim3) *dim3 = lim3; 22287c478bd9Sstevel@tonic-gate return (*dim1 * *dim2 * *dim3); 22297c478bd9Sstevel@tonic-gate } 22307c478bd9Sstevel@tonic-gate #endif /* defined(_SUNOS_VTOC_8) */ 2231342440ecSPrasad Singamsetty 2232342440ecSPrasad Singamsetty /* 2233342440ecSPrasad Singamsetty * Calculate CHS values based on the capacity data. 2234342440ecSPrasad Singamsetty * 2235342440ecSPrasad Singamsetty * NOTE: This function is same as cmlb_convert_geomerty() function in 2236342440ecSPrasad Singamsetty * cmlb kernel module. 2237342440ecSPrasad Singamsetty */ 2238342440ecSPrasad Singamsetty static void 2239342440ecSPrasad Singamsetty compute_chs_values(diskaddr_t total_capacity, diskaddr_t usable_capacity, 2240342440ecSPrasad Singamsetty uint_t *pcylp, uint_t *nheadp, uint_t *nsectp) 2241342440ecSPrasad Singamsetty { 2242342440ecSPrasad Singamsetty 2243342440ecSPrasad Singamsetty /* Unlabeled SCSI floppy device */ 2244c31fac72SShidokht Yadegari if (total_capacity < 160) { 2245c31fac72SShidokht Yadegari /* Less than 80K */ 2246c31fac72SShidokht Yadegari *nheadp = 1; 2247c31fac72SShidokht Yadegari *pcylp = total_capacity; 2248c31fac72SShidokht Yadegari *nsectp = 1; 2249c31fac72SShidokht Yadegari return; 2250c31fac72SShidokht Yadegari } else if (total_capacity <= 0x1000) { 2251342440ecSPrasad Singamsetty *nheadp = 2; 2252342440ecSPrasad Singamsetty *pcylp = 80; 2253342440ecSPrasad Singamsetty *nsectp = total_capacity / (80 * 2); 2254342440ecSPrasad Singamsetty return; 2255342440ecSPrasad Singamsetty } 2256342440ecSPrasad Singamsetty 2257342440ecSPrasad Singamsetty /* 2258342440ecSPrasad Singamsetty * For all devices we calculate cylinders using the heads and sectors 2259342440ecSPrasad Singamsetty * we assign based on capacity of the device. The algorithm is 2260342440ecSPrasad Singamsetty * designed to be compatible with the way other operating systems 2261342440ecSPrasad Singamsetty * lay out fdisk tables for X86 and to insure that the cylinders never 2262342440ecSPrasad Singamsetty * exceed 65535 to prevent problems with X86 ioctls that report 2263342440ecSPrasad Singamsetty * geometry. 2264342440ecSPrasad Singamsetty * For some smaller disk sizes we report geometry that matches those 2265342440ecSPrasad Singamsetty * used by X86 BIOS usage. For larger disks, we use SPT that are 2266342440ecSPrasad Singamsetty * multiples of 63, since other OSes that are not limited to 16-bits 2267342440ecSPrasad Singamsetty * for cylinders stop at 63 SPT we make do by using multiples of 63 SPT. 2268342440ecSPrasad Singamsetty * 2269342440ecSPrasad Singamsetty * The following table (in order) illustrates some end result 2270342440ecSPrasad Singamsetty * calculations: 2271342440ecSPrasad Singamsetty * 2272342440ecSPrasad Singamsetty * Maximum number of blocks nhead nsect 2273342440ecSPrasad Singamsetty * 2274342440ecSPrasad Singamsetty * 2097152 (1GB) 64 32 2275342440ecSPrasad Singamsetty * 16777216 (8GB) 128 32 2276342440ecSPrasad Singamsetty * 1052819775 (502.02GB) 255 63 2277342440ecSPrasad Singamsetty * 2105639550 (0.98TB) 255 126 2278342440ecSPrasad Singamsetty * 3158459325 (1.47TB) 255 189 2279342440ecSPrasad Singamsetty * 4211279100 (1.96TB) 255 252 2280342440ecSPrasad Singamsetty * 5264098875 (2.45TB) 255 315 2281342440ecSPrasad Singamsetty * ... 2282342440ecSPrasad Singamsetty */ 2283342440ecSPrasad Singamsetty 2284342440ecSPrasad Singamsetty if (total_capacity <= 0x200000) { 2285342440ecSPrasad Singamsetty *nheadp = 64; 2286342440ecSPrasad Singamsetty *nsectp = 32; 2287342440ecSPrasad Singamsetty } else if (total_capacity <= 0x01000000) { 2288342440ecSPrasad Singamsetty *nheadp = 128; 2289342440ecSPrasad Singamsetty *nsectp = 32; 2290342440ecSPrasad Singamsetty } else { 2291342440ecSPrasad Singamsetty *nheadp = 255; 2292342440ecSPrasad Singamsetty 2293342440ecSPrasad Singamsetty /* make nsect be smallest multiple of 63 */ 2294342440ecSPrasad Singamsetty *nsectp = ((total_capacity + 2295342440ecSPrasad Singamsetty (UINT16_MAX * 255 * 63) - 1) / 2296342440ecSPrasad Singamsetty (UINT16_MAX * 255 * 63)) * 63; 2297342440ecSPrasad Singamsetty 2298342440ecSPrasad Singamsetty if (*nsectp == 0) 2299342440ecSPrasad Singamsetty *nsectp = (UINT16_MAX / 63) * 63; 2300342440ecSPrasad Singamsetty } 2301342440ecSPrasad Singamsetty 2302342440ecSPrasad Singamsetty if (usable_capacity < total_capacity) 2303342440ecSPrasad Singamsetty *pcylp = usable_capacity / ((*nheadp) * (*nsectp)); 2304342440ecSPrasad Singamsetty else 2305342440ecSPrasad Singamsetty *pcylp = total_capacity / ((*nheadp) * (*nsectp)); 2306342440ecSPrasad Singamsetty } 2307