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 *
auto_efi_sense(int fd,struct efi_info * label)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
efi_ioctl(int fd,int cmd,dk_efi_t * dk_ioc)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 *
find_ctlr_type(ushort_t 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 *
find_ctlr_info(struct dk_cinfo * dkinfo,ushort_t type)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 *
find_disk_info(struct dk_cinfo * dkinfo,ushort_t type)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
auto_label_init(struct dk_label * label)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 *
new_direct_disk_type(int fd,char * disk_name,struct dk_label * label)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 *
auto_direct_get_geom_label(int fd,struct dk_label * label)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 *
auto_sense(int fd,int can_prompt,struct dk_label * label)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 *
generic_disk_sense(int fd,int can_prompt,struct dk_label * label,struct scsi_inquiry * inquiry,struct scsi_capacity_16 * capacity,char * disk_name)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
use_existing_disk_type(int fd,int can_prompt,struct dk_label * label,struct scsi_inquiry * inquiry,struct disk_type * disk_type,struct scsi_capacity_16 * capacity)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
build_default_partition(struct dk_label * label,int ctrl_type)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