xref: /onnv-gate/usr/src/cmd/format/auto_sense.c (revision 11904:0553a8f29c9d)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51524Slh195018  * Common Development and Distribution License (the "License").
61524Slh195018  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
2211533SAbhinandan.Ekande@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate  * This file contains functions to implement automatic configuration
280Sstevel@tonic-gate  * of scsi disks.
290Sstevel@tonic-gate  */
300Sstevel@tonic-gate #include "global.h"
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #include <fcntl.h>
330Sstevel@tonic-gate #include <stdlib.h>
340Sstevel@tonic-gate #include <string.h>
350Sstevel@tonic-gate #include <strings.h>
360Sstevel@tonic-gate #include <stdlib.h>
370Sstevel@tonic-gate #include <ctype.h>
380Sstevel@tonic-gate 
390Sstevel@tonic-gate #include "misc.h"
400Sstevel@tonic-gate #include "param.h"
410Sstevel@tonic-gate #include "ctlr_scsi.h"
420Sstevel@tonic-gate #include "auto_sense.h"
430Sstevel@tonic-gate #include "partition.h"
440Sstevel@tonic-gate #include "label.h"
450Sstevel@tonic-gate #include "startup.h"
460Sstevel@tonic-gate #include "analyze.h"
470Sstevel@tonic-gate #include "io.h"
480Sstevel@tonic-gate #include "hardware_structs.h"
490Sstevel@tonic-gate #include "menu_fdisk.h"
500Sstevel@tonic-gate 
510Sstevel@tonic-gate 
520Sstevel@tonic-gate #define	DISK_NAME_MAX		256
530Sstevel@tonic-gate 
540Sstevel@tonic-gate extern	int			nctypes;
550Sstevel@tonic-gate extern	struct	ctlr_type	ctlr_types[];
560Sstevel@tonic-gate 
570Sstevel@tonic-gate 
580Sstevel@tonic-gate /*
590Sstevel@tonic-gate  * Marker for free hog partition
600Sstevel@tonic-gate  */
610Sstevel@tonic-gate #define	HOG		(-1)
620Sstevel@tonic-gate 
630Sstevel@tonic-gate 
640Sstevel@tonic-gate 
650Sstevel@tonic-gate /*
660Sstevel@tonic-gate  * Default partition tables
670Sstevel@tonic-gate  *
680Sstevel@tonic-gate  *	Disk capacity		root	swap	usr
690Sstevel@tonic-gate  *	-------------		----	----	---
700Sstevel@tonic-gate  *	0mb to 64mb		0	0	remainder
710Sstevel@tonic-gate  *	64mb to 180mb		16mb	16mb	remainder
720Sstevel@tonic-gate  *	180mb to 280mb		16mb	32mb	remainder
730Sstevel@tonic-gate  *	280mb to 380mb		24mb	32mb	remainder
740Sstevel@tonic-gate  *	380mb to 600mb		32mb	32mb	remainder
750Sstevel@tonic-gate  *	600mb to 1gb		32mb	64mb	remainder
760Sstevel@tonic-gate  *	1gb to 2gb		64mb	128mb	remainder
770Sstevel@tonic-gate  *	2gb on up		128mb	128mb	remainder
780Sstevel@tonic-gate  */
790Sstevel@tonic-gate struct part_table {
800Sstevel@tonic-gate 	int	partitions[NDKMAP];
810Sstevel@tonic-gate };
820Sstevel@tonic-gate 
830Sstevel@tonic-gate static struct part_table part_table_64mb = {
840Sstevel@tonic-gate 	{ 0,	0,	0,	0,	0,	0,	HOG,	0}
850Sstevel@tonic-gate };
860Sstevel@tonic-gate 
870Sstevel@tonic-gate static struct part_table part_table_180mb = {
880Sstevel@tonic-gate 	{ 16,	16,	0,	0,	0,	0,	HOG,	0}
890Sstevel@tonic-gate };
900Sstevel@tonic-gate 
910Sstevel@tonic-gate static struct part_table part_table_280mb = {
920Sstevel@tonic-gate 	{ 16,	32,	0,	0,	0,	0,	HOG,	0}
930Sstevel@tonic-gate };
940Sstevel@tonic-gate 
950Sstevel@tonic-gate static struct part_table part_table_380mb = {
960Sstevel@tonic-gate 	{ 24,	32,	0,	0,	0,	0,	HOG,	0}
970Sstevel@tonic-gate };
980Sstevel@tonic-gate 
990Sstevel@tonic-gate static struct part_table part_table_600mb = {
1000Sstevel@tonic-gate 	{ 32,	32,	0,	0,	0,	0,	HOG,	0}
1010Sstevel@tonic-gate };
1020Sstevel@tonic-gate 
1030Sstevel@tonic-gate static struct part_table part_table_1gb = {
1040Sstevel@tonic-gate 	{ 32,	64,	0,	0,	0,	0,	HOG,	0}
1050Sstevel@tonic-gate };
1060Sstevel@tonic-gate 
1070Sstevel@tonic-gate static struct part_table part_table_2gb = {
1080Sstevel@tonic-gate 	{ 64,	128,	0,	0,	0,	0,	HOG,	0}
1090Sstevel@tonic-gate };
1100Sstevel@tonic-gate 
1110Sstevel@tonic-gate static struct part_table part_table_infinity = {
1120Sstevel@tonic-gate 	{ 128,	128,	0,	0,	0,	0,	HOG,	0}
1130Sstevel@tonic-gate };
1140Sstevel@tonic-gate 
1150Sstevel@tonic-gate 
1160Sstevel@tonic-gate static struct default_partitions {
1177563SPrasad.Singamsetty@Sun.COM 	diskaddr_t		min_capacity;
1187563SPrasad.Singamsetty@Sun.COM 	diskaddr_t		max_capacity;
1190Sstevel@tonic-gate 	struct part_table	*part_table;
1200Sstevel@tonic-gate } default_partitions[] = {
1210Sstevel@tonic-gate 	{ 0,	64,		&part_table_64mb },	/* 0 to 64 mb */
1220Sstevel@tonic-gate 	{ 64,	180,		&part_table_180mb },	/* 64 to 180 mb */
1230Sstevel@tonic-gate 	{ 180,	280,		&part_table_280mb },	/* 180 to 280 mb */
1240Sstevel@tonic-gate 	{ 280,	380,		&part_table_380mb },	/* 280 to 380 mb */
1250Sstevel@tonic-gate 	{ 380,	600,		&part_table_600mb },	/* 380 to 600 mb */
1260Sstevel@tonic-gate 	{ 600,	1024,		&part_table_1gb },	/* 600 to 1 gb */
1270Sstevel@tonic-gate 	{ 1024,	2048,		&part_table_2gb },	/* 1 to 2 gb */
1280Sstevel@tonic-gate 	{ 2048,	INFINITY,	&part_table_infinity },	/* 2 gb on up */
1290Sstevel@tonic-gate };
1300Sstevel@tonic-gate 
1310Sstevel@tonic-gate #define	DEFAULT_PARTITION_TABLE_SIZE	\
1320Sstevel@tonic-gate 	(sizeof (default_partitions) / sizeof (struct default_partitions))
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate /*
1350Sstevel@tonic-gate  * msgs for check()
1360Sstevel@tonic-gate  */
1370Sstevel@tonic-gate #define	FORMAT_MSG	"Auto configuration via format.dat"
1380Sstevel@tonic-gate #define	GENERIC_MSG	"Auto configuration via generic SCSI-2"
1390Sstevel@tonic-gate 
1400Sstevel@tonic-gate /*
1410Sstevel@tonic-gate  * Disks on symbios(Hardwire raid controller) return a fixed number
1420Sstevel@tonic-gate  * of heads(64)/cylinders(64) and adjust the cylinders depending
1430Sstevel@tonic-gate  * capacity of the configured lun.
1440Sstevel@tonic-gate  * In such a case we get number of physical cylinders < 3 which
1450Sstevel@tonic-gate  * is the minimum required by solaris(2 reserved + 1 data cylinders).
1460Sstevel@tonic-gate  * Hence try to adjust the cylinders by reducing the "nsect/nhead".
1470Sstevel@tonic-gate  *
1480Sstevel@tonic-gate  */
1490Sstevel@tonic-gate /*
1500Sstevel@tonic-gate  * assuming a minimum of 32 block cylinders.
1510Sstevel@tonic-gate  */
1520Sstevel@tonic-gate #define	MINIMUM_NO_HEADS	2
1530Sstevel@tonic-gate #define	MINIMUM_NO_SECTORS	16
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate #define	MINIMUM_NO_CYLINDERS	128
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate /* These are 16-bit fields */
1600Sstevel@tonic-gate #define	MAXIMUM_NO_HEADS	65535
1610Sstevel@tonic-gate #define	MAXIMUM_NO_SECTORS	65535
1620Sstevel@tonic-gate #define	MAXIMUM_NO_CYLINDERS	65535
1630Sstevel@tonic-gate 
1640Sstevel@tonic-gate #endif	/* defined(_SUNOS_VTOC_8) */
1650Sstevel@tonic-gate 
1660Sstevel@tonic-gate /*
1670Sstevel@tonic-gate  * minimum number of cylinders required by Solaris.
1680Sstevel@tonic-gate  */
1690Sstevel@tonic-gate #define	SUN_MIN_CYL		3
1700Sstevel@tonic-gate 
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate /*
1740Sstevel@tonic-gate  * ANSI prototypes for local static functions
1750Sstevel@tonic-gate  */
1760Sstevel@tonic-gate static struct disk_type	*generic_disk_sense(
1770Sstevel@tonic-gate 				int		fd,
1780Sstevel@tonic-gate 				int		can_prompt,
1790Sstevel@tonic-gate 				struct dk_label	*label,
1800Sstevel@tonic-gate 				struct scsi_inquiry *inquiry,
1810Sstevel@tonic-gate 				struct scsi_capacity_16 *capacity,
1820Sstevel@tonic-gate 				char		*disk_name);
1830Sstevel@tonic-gate static int		use_existing_disk_type(
1840Sstevel@tonic-gate 				int		fd,
1850Sstevel@tonic-gate 				int		can_prompt,
1860Sstevel@tonic-gate 				struct dk_label	*label,
1870Sstevel@tonic-gate 				struct scsi_inquiry *inquiry,
1880Sstevel@tonic-gate 				struct disk_type *disk_type,
1890Sstevel@tonic-gate 				struct scsi_capacity_16 *capacity);
1900Sstevel@tonic-gate int			build_default_partition(struct dk_label *label,
1910Sstevel@tonic-gate 				int ctrl_type);
1920Sstevel@tonic-gate static struct disk_type	*find_scsi_disk_type(
1930Sstevel@tonic-gate 				char		*disk_name,
1940Sstevel@tonic-gate 				struct dk_label	*label);
1950Sstevel@tonic-gate static struct disk_type	*find_scsi_disk_by_name(
1960Sstevel@tonic-gate 				char		*disk_name);
1970Sstevel@tonic-gate static struct ctlr_type	*find_scsi_ctlr_type(void);
1980Sstevel@tonic-gate static struct ctlr_info	*find_scsi_ctlr_info(
1990Sstevel@tonic-gate 				struct dk_cinfo	*dkinfo);
2000Sstevel@tonic-gate static struct disk_type	*new_scsi_disk_type(
2010Sstevel@tonic-gate 				int		fd,
2020Sstevel@tonic-gate 				char		*disk_name,
2030Sstevel@tonic-gate 				struct dk_label	*label);
2040Sstevel@tonic-gate static struct disk_info	*find_scsi_disk_info(
2050Sstevel@tonic-gate 				struct dk_cinfo	*dkinfo);
206786Slclee 
207786Slclee static struct disk_type *new_direct_disk_type(int fd, char *disk_name,
208786Slclee     struct dk_label *label);
209786Slclee 
210786Slclee static struct disk_info *find_direct_disk_info(struct dk_cinfo *dkinfo);
211786Slclee static int efi_ioctl(int fd, int cmd, dk_efi_t *dk_ioc);
212786Slclee static int auto_label_init(struct dk_label *label);
2131524Slh195018 static struct ctlr_type *find_direct_ctlr_type(void);
214786Slclee static struct ctlr_info *find_direct_ctlr_info(struct dk_cinfo	*dkinfo);
215786Slclee static  struct disk_info *find_direct_disk_info(struct dk_cinfo *dkinfo);
2169547SBo.Zhou@Sun.COM static struct ctlr_type *find_vbd_ctlr_type(void);
2179547SBo.Zhou@Sun.COM static struct ctlr_info *find_vbd_ctlr_info(struct dk_cinfo *dkinfo);
2189547SBo.Zhou@Sun.COM static struct disk_info *find_vbd_disk_info(struct dk_cinfo *dkinfo);
219786Slclee 
2200Sstevel@tonic-gate static char		*get_sun_disk_name(
2210Sstevel@tonic-gate 				char		*disk_name,
2220Sstevel@tonic-gate 				struct scsi_inquiry *inquiry);
2230Sstevel@tonic-gate static char		*get_generic_disk_name(
2240Sstevel@tonic-gate 				char		*disk_name,
2250Sstevel@tonic-gate 				struct scsi_inquiry *inquiry);
2260Sstevel@tonic-gate static char		*strcopy(
2270Sstevel@tonic-gate 				char	*dst,
2280Sstevel@tonic-gate 				char	*src,
2290Sstevel@tonic-gate 				int	n);
2307563SPrasad.Singamsetty@Sun.COM static	int		adjust_disk_geometry(diskaddr_t capacity, uint_t *cyl,
2317563SPrasad.Singamsetty@Sun.COM 				uint_t *nsect, uint_t *nhead);
2327563SPrasad.Singamsetty@Sun.COM static void 		compute_chs_values(diskaddr_t total_capacity,
2337563SPrasad.Singamsetty@Sun.COM 				diskaddr_t usable_capacity, uint_t *pcylp,
2347563SPrasad.Singamsetty@Sun.COM 				uint_t *nheadp, uint_t *nsectp);
2350Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
2367563SPrasad.Singamsetty@Sun.COM static diskaddr_t square_box(
2377563SPrasad.Singamsetty@Sun.COM 			diskaddr_t capacity,
2387563SPrasad.Singamsetty@Sun.COM 			uint_t *dim1, uint_t lim1,
2397563SPrasad.Singamsetty@Sun.COM 			uint_t *dim2, uint_t lim2,
2407563SPrasad.Singamsetty@Sun.COM 			uint_t *dim3, uint_t lim3);
2410Sstevel@tonic-gate #endif	/* defined(_SUNOS_VTOC_8) */
2420Sstevel@tonic-gate 
2430Sstevel@tonic-gate 
2440Sstevel@tonic-gate /*
2450Sstevel@tonic-gate  * We need to get information necessary to construct a *new* efi
2460Sstevel@tonic-gate  * label type
2470Sstevel@tonic-gate  */
2480Sstevel@tonic-gate struct disk_type *
auto_efi_sense(int fd,struct efi_info * label)2490Sstevel@tonic-gate auto_efi_sense(int fd, struct efi_info *label)
2500Sstevel@tonic-gate {
2510Sstevel@tonic-gate 
2520Sstevel@tonic-gate 	struct dk_gpt	*vtoc;
2530Sstevel@tonic-gate 	int		i;
2540Sstevel@tonic-gate 
2550Sstevel@tonic-gate 	struct disk_type *disk, *dp;
2560Sstevel@tonic-gate 	struct disk_info *disk_info;
2570Sstevel@tonic-gate 	struct ctlr_info *ctlr;
2580Sstevel@tonic-gate 	struct dk_cinfo dkinfo;
2590Sstevel@tonic-gate 	struct partition_info *part;
2600Sstevel@tonic-gate 
2610Sstevel@tonic-gate 	/*
2620Sstevel@tonic-gate 	 * get vendor, product, revision and capacity info.
2630Sstevel@tonic-gate 	 */
2640Sstevel@tonic-gate 	if (get_disk_info(fd, label) == -1) {
2650Sstevel@tonic-gate 		return ((struct disk_type *)NULL);
2660Sstevel@tonic-gate 	}
2670Sstevel@tonic-gate 	/*
2680Sstevel@tonic-gate 	 * Now build the default partition table
2690Sstevel@tonic-gate 	 */
2700Sstevel@tonic-gate 	if (efi_alloc_and_init(fd, EFI_NUMPAR, &vtoc) != 0) {
2710Sstevel@tonic-gate 		err_print("efi_alloc_and_init failed. \n");
2720Sstevel@tonic-gate 		return ((struct disk_type *)NULL);
2730Sstevel@tonic-gate 	}
2740Sstevel@tonic-gate 
2750Sstevel@tonic-gate 	label->e_parts = vtoc;
2760Sstevel@tonic-gate 
2774304Syl194034 	/*
2784304Syl194034 	 * Create a whole hog EFI partition table:
2794304Syl194034 	 * S0 takes the whole disk except the primary EFI label,
2804304Syl194034 	 * backup EFI label, and the reserved partition.
2814304Syl194034 	 */
2824304Syl194034 	vtoc->efi_parts[0].p_tag = V_USR;
2834304Syl194034 	vtoc->efi_parts[0].p_start = vtoc->efi_first_u_lba;
2844304Syl194034 	vtoc->efi_parts[0].p_size = vtoc->efi_last_u_lba - vtoc->efi_first_u_lba
2854304Syl194034 	    - EFI_MIN_RESV_SIZE + 1;
2864304Syl194034 
2874304Syl194034 	/*
2884304Syl194034 	 * S1-S6 are unassigned slices.
2894304Syl194034 	 */
2904304Syl194034 	for (i = 1; i < vtoc->efi_nparts - 2; i ++) {
2914304Syl194034 		vtoc->efi_parts[i].p_tag = V_UNASSIGNED;
2920Sstevel@tonic-gate 		vtoc->efi_parts[i].p_start = 0;
2930Sstevel@tonic-gate 		vtoc->efi_parts[i].p_size = 0;
2940Sstevel@tonic-gate 	}
2950Sstevel@tonic-gate 
2964304Syl194034 	/*
2974304Syl194034 	 * The reserved slice
2984304Syl194034 	 */
2994304Syl194034 	vtoc->efi_parts[vtoc->efi_nparts - 1].p_tag = V_RESERVED;
3004304Syl194034 	vtoc->efi_parts[vtoc->efi_nparts - 1].p_start =
3014304Syl194034 	    vtoc->efi_last_u_lba - EFI_MIN_RESV_SIZE + 1;
3024304Syl194034 	vtoc->efi_parts[vtoc->efi_nparts - 1].p_size = EFI_MIN_RESV_SIZE;
3030Sstevel@tonic-gate 
3040Sstevel@tonic-gate 	/*
3050Sstevel@tonic-gate 	 * Now stick all of it into the disk_type struct
3060Sstevel@tonic-gate 	 */
3070Sstevel@tonic-gate 
3080Sstevel@tonic-gate 	if (ioctl(fd, DKIOCINFO, &dkinfo) == -1) {
3099889SLarry.Liu@Sun.COM 		if (option_msg && diag_msg) {
3109889SLarry.Liu@Sun.COM 			err_print("DKIOCINFO failed\n");
3119889SLarry.Liu@Sun.COM 		}
3129889SLarry.Liu@Sun.COM 		return (NULL);
3130Sstevel@tonic-gate 	}
3141564Slh195018 	if ((cur_ctype != NULL) && (cur_ctype->ctype_ctype == DKC_DIRECT)) {
3151524Slh195018 		ctlr = find_direct_ctlr_info(&dkinfo);
3161524Slh195018 		disk_info = find_direct_disk_info(&dkinfo);
3179547SBo.Zhou@Sun.COM 	} else if ((cur_ctype != NULL) && (cur_ctype->ctype_ctype == DKC_VBD)) {
3189547SBo.Zhou@Sun.COM 		ctlr = find_vbd_ctlr_info(&dkinfo);
3199547SBo.Zhou@Sun.COM 		disk_info = find_vbd_disk_info(&dkinfo);
3201524Slh195018 	} else {
3211524Slh195018 		ctlr = find_scsi_ctlr_info(&dkinfo);
3221524Slh195018 		disk_info = find_scsi_disk_info(&dkinfo);
3231524Slh195018 	}
3240Sstevel@tonic-gate 	disk = (struct disk_type *)zalloc(sizeof (struct disk_type));
3250Sstevel@tonic-gate 	assert(disk_info->disk_ctlr == ctlr);
3260Sstevel@tonic-gate 	dp = ctlr->ctlr_ctype->ctype_dlist;
3270Sstevel@tonic-gate 	if (dp == NULL) {
3280Sstevel@tonic-gate 		ctlr->ctlr_ctype->ctype_dlist = dp;
3290Sstevel@tonic-gate 	} else {
3300Sstevel@tonic-gate 		while (dp->dtype_next != NULL) {
3310Sstevel@tonic-gate 			dp = dp->dtype_next;
3320Sstevel@tonic-gate 		}
3330Sstevel@tonic-gate 		dp->dtype_next = disk;
3340Sstevel@tonic-gate 	}
3350Sstevel@tonic-gate 	disk->dtype_next = NULL;
3360Sstevel@tonic-gate 
3370Sstevel@tonic-gate 	(void) strlcpy(disk->vendor, label->vendor,
3389889SLarry.Liu@Sun.COM 	    sizeof (disk->vendor));
3390Sstevel@tonic-gate 	(void) strlcpy(disk->product, label->product,
3409889SLarry.Liu@Sun.COM 	    sizeof (disk->product));
3410Sstevel@tonic-gate 	(void) strlcpy(disk->revision, label->revision,
3429889SLarry.Liu@Sun.COM 	    sizeof (disk->revision));
3430Sstevel@tonic-gate 	disk->capacity = label->capacity;
3440Sstevel@tonic-gate 
3450Sstevel@tonic-gate 	part = (struct partition_info *)
3460Sstevel@tonic-gate 	    zalloc(sizeof (struct partition_info));
3470Sstevel@tonic-gate 	disk->dtype_plist = part;
3480Sstevel@tonic-gate 
3490Sstevel@tonic-gate 	part->pinfo_name = alloc_string("default");
3500Sstevel@tonic-gate 	part->pinfo_next = NULL;
3510Sstevel@tonic-gate 	part->etoc = vtoc;
3520Sstevel@tonic-gate 
3530Sstevel@tonic-gate 	bzero(disk_info->v_volume, LEN_DKL_VVOL);
3540Sstevel@tonic-gate 	disk_info->disk_parts = part;
3550Sstevel@tonic-gate 	return (disk);
3560Sstevel@tonic-gate }
3570Sstevel@tonic-gate 
358786Slclee static int
efi_ioctl(int fd,int cmd,dk_efi_t * dk_ioc)359786Slclee efi_ioctl(int fd, int cmd, dk_efi_t *dk_ioc)
360786Slclee {
361786Slclee 	void *data = dk_ioc->dki_data;
362786Slclee 	int error;
363786Slclee 
364786Slclee 	dk_ioc->dki_data_64 = (uint64_t)(uintptr_t)data;
365786Slclee 	error = ioctl(fd, cmd, (void *)dk_ioc);
366786Slclee 	dk_ioc->dki_data = data;
367786Slclee 
368786Slclee 	return (error);
369786Slclee }
370786Slclee 
3711524Slh195018 static struct ctlr_type *
find_direct_ctlr_type()3721524Slh195018 find_direct_ctlr_type()
3731524Slh195018 {
3741524Slh195018 	struct	mctlr_list	*mlp;
3751524Slh195018 
3761524Slh195018 	mlp = controlp;
3771524Slh195018 
3781524Slh195018 	while (mlp != NULL) {
3791524Slh195018 		if (mlp->ctlr_type->ctype_ctype == DKC_DIRECT) {
3801524Slh195018 			return (mlp->ctlr_type);
3811524Slh195018 		}
3821524Slh195018 		mlp = mlp->next;
3831524Slh195018 	}
3841524Slh195018 
3851524Slh195018 	impossible("no DIRECT controller type");
3861524Slh195018 
3871524Slh195018 	return ((struct ctlr_type *)NULL);
3881524Slh195018 }
3891524Slh195018 
3909547SBo.Zhou@Sun.COM static struct ctlr_type *
find_vbd_ctlr_type()3919547SBo.Zhou@Sun.COM find_vbd_ctlr_type()
3929547SBo.Zhou@Sun.COM {
3939547SBo.Zhou@Sun.COM 	struct	mctlr_list	*mlp;
3949547SBo.Zhou@Sun.COM 
3959547SBo.Zhou@Sun.COM 	mlp = controlp;
3969547SBo.Zhou@Sun.COM 
3979547SBo.Zhou@Sun.COM 	while (mlp != NULL) {
3989547SBo.Zhou@Sun.COM 		if (mlp->ctlr_type->ctype_ctype == DKC_VBD) {
3999547SBo.Zhou@Sun.COM 			return (mlp->ctlr_type);
4009547SBo.Zhou@Sun.COM 		}
4019547SBo.Zhou@Sun.COM 		mlp = mlp->next;
4029547SBo.Zhou@Sun.COM 	}
4039547SBo.Zhou@Sun.COM 
4049547SBo.Zhou@Sun.COM 	impossible("no VBD controller type");
4059547SBo.Zhou@Sun.COM 
4069547SBo.Zhou@Sun.COM 	return ((struct ctlr_type *)NULL);
4079547SBo.Zhou@Sun.COM }
4089547SBo.Zhou@Sun.COM 
409786Slclee static struct ctlr_info *
find_direct_ctlr_info(struct dk_cinfo * dkinfo)410786Slclee find_direct_ctlr_info(
411786Slclee 	struct dk_cinfo		*dkinfo)
412786Slclee {
413786Slclee 	struct ctlr_info	*ctlr;
414786Slclee 
415786Slclee 	if (dkinfo->dki_ctype != DKC_DIRECT)
416786Slclee 		return (NULL);
417786Slclee 
418786Slclee 	for (ctlr = ctlr_list; ctlr != NULL; ctlr = ctlr->ctlr_next) {
419786Slclee 		if (ctlr->ctlr_addr == dkinfo->dki_addr &&
420786Slclee 		    ctlr->ctlr_space == dkinfo->dki_space &&
421786Slclee 		    ctlr->ctlr_ctype->ctype_ctype == DKC_DIRECT) {
422786Slclee 			return (ctlr);
423786Slclee 		}
424786Slclee 	}
425786Slclee 
426786Slclee 	impossible("no DIRECT controller info");
427786Slclee 	/*NOTREACHED*/
428786Slclee }
429786Slclee 
4309547SBo.Zhou@Sun.COM static struct ctlr_info *
find_vbd_ctlr_info(struct dk_cinfo * dkinfo)4319547SBo.Zhou@Sun.COM find_vbd_ctlr_info(
4329547SBo.Zhou@Sun.COM 	struct dk_cinfo		*dkinfo)
4339547SBo.Zhou@Sun.COM {
4349547SBo.Zhou@Sun.COM 	struct ctlr_info	*ctlr;
4359547SBo.Zhou@Sun.COM 
4369547SBo.Zhou@Sun.COM 	if (dkinfo->dki_ctype != DKC_VBD)
4379547SBo.Zhou@Sun.COM 		return (NULL);
4389547SBo.Zhou@Sun.COM 
4399547SBo.Zhou@Sun.COM 	for (ctlr = ctlr_list; ctlr != NULL; ctlr = ctlr->ctlr_next) {
4409547SBo.Zhou@Sun.COM 		if (ctlr->ctlr_addr == dkinfo->dki_addr &&
4419547SBo.Zhou@Sun.COM 		    ctlr->ctlr_space == dkinfo->dki_space &&
4429547SBo.Zhou@Sun.COM 		    ctlr->ctlr_ctype->ctype_ctype == DKC_VBD) {
4439547SBo.Zhou@Sun.COM 			return (ctlr);
4449547SBo.Zhou@Sun.COM 		}
4459547SBo.Zhou@Sun.COM 	}
4469547SBo.Zhou@Sun.COM 
4479547SBo.Zhou@Sun.COM 	impossible("no VBD controller info");
4489547SBo.Zhou@Sun.COM 	/*NOTREACHED*/
4499547SBo.Zhou@Sun.COM }
4509547SBo.Zhou@Sun.COM 
451786Slclee static  struct disk_info *
find_direct_disk_info(struct dk_cinfo * dkinfo)452786Slclee find_direct_disk_info(
453786Slclee 	struct dk_cinfo		*dkinfo)
454786Slclee {
455786Slclee 	struct disk_info	*disk;
456786Slclee 	struct dk_cinfo		*dp;
457786Slclee 
458786Slclee 	for (disk = disk_list; disk != NULL; disk = disk->disk_next) {
459786Slclee 		assert(dkinfo->dki_ctype == DKC_DIRECT);
460786Slclee 		dp = &disk->disk_dkinfo;
461786Slclee 		if (dp->dki_ctype == dkinfo->dki_ctype &&
462786Slclee 		    dp->dki_cnum == dkinfo->dki_cnum &&
463786Slclee 		    dp->dki_unit == dkinfo->dki_unit &&
464786Slclee 		    strcmp(dp->dki_dname, dkinfo->dki_dname) == 0) {
465786Slclee 			return (disk);
466786Slclee 		}
467786Slclee 	}
468786Slclee 
469786Slclee 	impossible("No DIRECT disk info instance\n");
470786Slclee 	/*NOTREACHED*/
471786Slclee }
472786Slclee 
4739547SBo.Zhou@Sun.COM static  struct disk_info *
find_vbd_disk_info(struct dk_cinfo * dkinfo)4749547SBo.Zhou@Sun.COM find_vbd_disk_info(
4759547SBo.Zhou@Sun.COM 	struct dk_cinfo		*dkinfo)
4769547SBo.Zhou@Sun.COM {
4779547SBo.Zhou@Sun.COM 	struct disk_info	*disk;
4789547SBo.Zhou@Sun.COM 	struct dk_cinfo		*dp;
4799547SBo.Zhou@Sun.COM 
4809547SBo.Zhou@Sun.COM 	for (disk = disk_list; disk != NULL; disk = disk->disk_next) {
4819547SBo.Zhou@Sun.COM 		assert(dkinfo->dki_ctype == DKC_VBD);
4829547SBo.Zhou@Sun.COM 		dp = &disk->disk_dkinfo;
4839547SBo.Zhou@Sun.COM 		if (dp->dki_ctype == dkinfo->dki_ctype &&
4849547SBo.Zhou@Sun.COM 		    dp->dki_cnum == dkinfo->dki_cnum &&
4859547SBo.Zhou@Sun.COM 		    dp->dki_unit == dkinfo->dki_unit &&
4869547SBo.Zhou@Sun.COM 		    strcmp(dp->dki_dname, dkinfo->dki_dname) == 0) {
4879547SBo.Zhou@Sun.COM 			return (disk);
4889547SBo.Zhou@Sun.COM 		}
4899547SBo.Zhou@Sun.COM 	}
4909547SBo.Zhou@Sun.COM 
4919547SBo.Zhou@Sun.COM 	impossible("No VBD disk info instance\n");
4929547SBo.Zhou@Sun.COM 	/*NOTREACHED*/
4939547SBo.Zhou@Sun.COM }
4949547SBo.Zhou@Sun.COM 
495786Slclee /*
496786Slclee  * To convert EFI to SMI labels, we need to get label geometry.
497786Slclee  * Unfortunately at this time there is no good way to do so.
498786Slclee  * DKIOCGGEOM will fail if disk is EFI labeled. So we hack around
499786Slclee  * it and clear EFI label, do a DKIOCGGEOM and put the EFI label
500786Slclee  * back on disk.
501786Slclee  * This routine gets the label geometry and initializes the label
502786Slclee  * It uses cur_file as opened device.
503786Slclee  * returns 0 if succeeds or -1 if failed.
504786Slclee  */
505786Slclee static int
auto_label_init(struct dk_label * label)506786Slclee auto_label_init(struct dk_label *label)
507786Slclee {
508786Slclee 	dk_efi_t	dk_ioc;
509786Slclee 	dk_efi_t	dk_ioc_back;
510786Slclee 	efi_gpt_t	*data = NULL;
511786Slclee 	efi_gpt_t	*databack = NULL;
512786Slclee 	struct dk_geom	disk_geom;
513786Slclee 	struct dk_minfo	disk_info;
514786Slclee 	efi_gpt_t 	*backsigp;
515786Slclee 	int		fd = cur_file;
516786Slclee 	int		rval = -1;
517786Slclee 	int		efisize = EFI_LABEL_SIZE * 2;
518786Slclee 	int		success = 0;
519786Slclee 	uint64_t	sig;
520786Slclee 	uint64_t	backsig;
521786Slclee 
522786Slclee 	if ((data = calloc(efisize, 1)) == NULL) {
523786Slclee 		err_print("auto_label_init: calloc failed\n");
524786Slclee 		goto auto_label_init_out;
525786Slclee 	}
526786Slclee 
527786Slclee 	dk_ioc.dki_data = data;
528786Slclee 	dk_ioc.dki_lba = 1;
529786Slclee 	dk_ioc.dki_length = efisize;
530786Slclee 
531786Slclee 	if (efi_ioctl(fd, DKIOCGETEFI, &dk_ioc) != 0) {
532786Slclee 		err_print("auto_label_init: GETEFI failed\n");
533786Slclee 		goto auto_label_init_out;
534786Slclee 	}
535786Slclee 
536786Slclee 	if ((databack = calloc(efisize, 1)) == NULL) {
537786Slclee 		err_print("auto_label_init calloc2 failed");
538786Slclee 		goto auto_label_init_out;
539786Slclee 	}
540786Slclee 
541786Slclee 	/* get the LBA size and capacity */
542786Slclee 	if (ioctl(fd, DKIOCGMEDIAINFO, (caddr_t)&disk_info) == -1) {
543786Slclee 		err_print("auto_label_init: dkiocgmediainfo failed\n");
544786Slclee 		goto auto_label_init_out;
545786Slclee 	}
546786Slclee 
547786Slclee 	if (disk_info.dki_lbsize == 0) {
548786Slclee 		if (option_msg && diag_msg) {
549786Slclee 			err_print("auto_lbal_init: assuming 512 byte"
550786Slclee 			    "block size");
551786Slclee 		}
552786Slclee 		disk_info.dki_lbsize = DEV_BSIZE;
553786Slclee 	}
554786Slclee 
555786Slclee 	dk_ioc_back.dki_data = databack;
556786Slclee 
557786Slclee 	/*
558786Slclee 	 * back up efi label goes to capacity - 1, we are reading an extra block
559786Slclee 	 * before the back up label.
560786Slclee 	 */
561786Slclee 	dk_ioc_back.dki_lba = disk_info.dki_capacity - 1 - 1;
562786Slclee 	dk_ioc_back.dki_length = efisize;
563786Slclee 
564786Slclee 	if (efi_ioctl(fd, DKIOCGETEFI, &dk_ioc_back) != 0) {
565786Slclee 		err_print("auto_label_init: GETEFI backup failed\n");
566786Slclee 		goto auto_label_init_out;
567786Slclee 	}
568786Slclee 
569786Slclee 	sig = dk_ioc.dki_data->efi_gpt_Signature;
570786Slclee 	dk_ioc.dki_data->efi_gpt_Signature = 0x0;
571786Slclee 
572786Slclee 	enter_critical();
573786Slclee 
574786Slclee 	if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc) == -1) {
575786Slclee 		err_print("auto_label_init: SETEFI failed\n");
576786Slclee 		exit_critical();
577786Slclee 		goto auto_label_init_out;
578786Slclee 	}
579786Slclee 
5809889SLarry.Liu@Sun.COM 	backsigp = (efi_gpt_t *)((uintptr_t)dk_ioc_back.dki_data + cur_blksz);
581786Slclee 
582786Slclee 	backsig = backsigp->efi_gpt_Signature;
583786Slclee 
584786Slclee 	backsigp->efi_gpt_Signature = 0;
585786Slclee 
586786Slclee 	if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc_back) == -1) {
587786Slclee 		err_print("auto_label_init: SETEFI backup failed\n");
588786Slclee 	}
589786Slclee 
590786Slclee 	if (ioctl(cur_file, DKIOCGGEOM, &disk_geom) != 0)
591786Slclee 		err_print("auto_label_init: GGEOM failed\n");
592786Slclee 	else
593786Slclee 		success = 1;
594786Slclee 
595786Slclee 	dk_ioc.dki_data->efi_gpt_Signature = sig;
596786Slclee 	backsigp->efi_gpt_Signature = backsig;
597786Slclee 
598786Slclee 	if (efi_ioctl(cur_file, DKIOCSETEFI, &dk_ioc_back) == -1) {
599786Slclee 		err_print("auto_label_init: SETEFI revert backup failed\n");
600786Slclee 		success = 0;
601786Slclee 	}
602786Slclee 
603786Slclee 	if (efi_ioctl(cur_file, DKIOCSETEFI, &dk_ioc) == -1) {
604786Slclee 		err_print("auto_label_init: SETEFI revert failed\n");
605786Slclee 		success = 0;
606786Slclee 	}
607786Slclee 
608786Slclee 	exit_critical();
609786Slclee 
610786Slclee 	if (success == 0)
611786Slclee 		goto auto_label_init_out;
612786Slclee 
613786Slclee 	ncyl = disk_geom.dkg_ncyl;
614786Slclee 	acyl = disk_geom.dkg_acyl;
615786Slclee 	nhead =  disk_geom.dkg_nhead;
616786Slclee 	nsect = disk_geom.dkg_nsect;
617786Slclee 	pcyl = ncyl + acyl;
618786Slclee 
619786Slclee 	label->dkl_pcyl = pcyl;
620786Slclee 	label->dkl_ncyl = ncyl;
621786Slclee 	label->dkl_acyl = acyl;
622786Slclee 	label->dkl_nhead = nhead;
623786Slclee 	label->dkl_nsect = nsect;
624786Slclee 	label->dkl_apc = 0;
625786Slclee 	label->dkl_intrlv = 1;
626786Slclee 	label->dkl_rpm = disk_geom.dkg_rpm;
627786Slclee 
628786Slclee 	label->dkl_magic = DKL_MAGIC;
629786Slclee 
630786Slclee 	(void) snprintf(label->dkl_asciilabel, sizeof (label->dkl_asciilabel),
6317563SPrasad.Singamsetty@Sun.COM 	    "%s cyl %u alt %u hd %u sec %u",
632786Slclee 	    "DEFAULT", ncyl, acyl, nhead, nsect);
633786Slclee 
634786Slclee 	rval = 0;
635786Slclee #if defined(_FIRMWARE_NEEDS_FDISK)
636786Slclee 	(void) auto_solaris_part(label);
637786Slclee 	ncyl = label->dkl_ncyl;
638786Slclee 
639786Slclee #endif	/* defined(_FIRMWARE_NEEDS_FDISK) */
640786Slclee 
641786Slclee 	if (!build_default_partition(label, DKC_DIRECT)) {
642786Slclee 		rval = -1;
643786Slclee 	}
644786Slclee 
645786Slclee 	(void) checksum(label, CK_MAKESUM);
646786Slclee 
647786Slclee 
648786Slclee auto_label_init_out:
649786Slclee 	if (data)
650786Slclee 		free(data);
651786Slclee 	if (databack)
652786Slclee 		free(databack);
653786Slclee 
654786Slclee 	return (rval);
655786Slclee }
656786Slclee 
657786Slclee static struct disk_type *
new_direct_disk_type(int fd,char * disk_name,struct dk_label * label)658786Slclee new_direct_disk_type(
659786Slclee 	int		fd,
660786Slclee 	char		*disk_name,
661786Slclee 	struct dk_label	*label)
662786Slclee {
663786Slclee 	struct disk_type	*dp;
664786Slclee 	struct disk_type	*disk;
665786Slclee 	struct ctlr_info	*ctlr;
666786Slclee 	struct dk_cinfo		dkinfo;
667786Slclee 	struct partition_info	*part = NULL;
668786Slclee 	struct partition_info	*pt;
669786Slclee 	struct disk_info	*disk_info;
670786Slclee 	int			i;
671786Slclee 
672786Slclee 	/*
673786Slclee 	 * Get the disk controller info for this disk
674786Slclee 	 */
675786Slclee 	if (ioctl(fd, DKIOCINFO, &dkinfo) == -1) {
676786Slclee 		if (option_msg && diag_msg) {
677786Slclee 			err_print("DKIOCINFO failed\n");
678786Slclee 		}
679786Slclee 		return (NULL);
680786Slclee 	}
681786Slclee 
682786Slclee 	/*
683786Slclee 	 * Find the ctlr_info for this disk.
684786Slclee 	 */
685786Slclee 	ctlr = find_direct_ctlr_info(&dkinfo);
686786Slclee 
687786Slclee 	/*
688786Slclee 	 * Allocate a new disk type for the direct controller.
689786Slclee 	 */
690786Slclee 	disk = (struct disk_type *)zalloc(sizeof (struct disk_type));
691786Slclee 
692786Slclee 	/*
693786Slclee 	 * Find the disk_info instance for this disk.
694786Slclee 	 */
695786Slclee 	disk_info = find_direct_disk_info(&dkinfo);
696786Slclee 
697786Slclee 	/*
698786Slclee 	 * The controller and the disk should match.
699786Slclee 	 */
700786Slclee 	assert(disk_info->disk_ctlr == ctlr);
701786Slclee 
702786Slclee 	/*
703786Slclee 	 * Link the disk into the list of disks
704786Slclee 	 */
705786Slclee 	dp = ctlr->ctlr_ctype->ctype_dlist;
706786Slclee 	if (dp == NULL) {
707786Slclee 		ctlr->ctlr_ctype->ctype_dlist = dp;
708786Slclee 	} else {
709786Slclee 		while (dp->dtype_next != NULL) {
710786Slclee 			dp = dp->dtype_next;
711786Slclee 		}
712786Slclee 		dp->dtype_next = disk;
713786Slclee 	}
714786Slclee 	disk->dtype_next = NULL;
715786Slclee 
716786Slclee 	/*
717786Slclee 	 * Allocate and initialize the disk name.
718786Slclee 	 */
719786Slclee 	disk->dtype_asciilabel = alloc_string(disk_name);
720786Slclee 
721786Slclee 	/*
722786Slclee 	 * Initialize disk geometry info
723786Slclee 	 */
724786Slclee 	disk->dtype_pcyl = label->dkl_pcyl;
725786Slclee 	disk->dtype_ncyl = label->dkl_ncyl;
726786Slclee 	disk->dtype_acyl = label->dkl_acyl;
727786Slclee 	disk->dtype_nhead = label->dkl_nhead;
728786Slclee 	disk->dtype_nsect = label->dkl_nsect;
729786Slclee 	disk->dtype_rpm = label->dkl_rpm;
730786Slclee 
731786Slclee 	part = (struct partition_info *)
7329889SLarry.Liu@Sun.COM 	    zalloc(sizeof (struct partition_info));
733786Slclee 	pt = disk->dtype_plist;
734786Slclee 	if (pt == NULL) {
735786Slclee 		disk->dtype_plist = part;
736786Slclee 	} else {
737786Slclee 		while (pt->pinfo_next != NULL) {
738786Slclee 			pt = pt->pinfo_next;
739786Slclee 		}
740786Slclee 		pt->pinfo_next = part;
741786Slclee 	}
742786Slclee 
743786Slclee 	part->pinfo_next = NULL;
744786Slclee 
745786Slclee 	/*
746786Slclee 	 * Set up the partition name
747786Slclee 	 */
748786Slclee 	part->pinfo_name = alloc_string("default");
749786Slclee 
750786Slclee 	/*
751786Slclee 	 * Fill in the partition info from the label
752786Slclee 	 */
753786Slclee 	for (i = 0; i < NDKMAP; i++) {
754786Slclee 
755786Slclee #if defined(_SUNOS_VTOC_8)
756786Slclee 		part->pinfo_map[i] = label->dkl_map[i];
757786Slclee 
758786Slclee #elif defined(_SUNOS_VTOC_16)
759786Slclee 		part->pinfo_map[i].dkl_cylno =
7609889SLarry.Liu@Sun.COM 		    label->dkl_vtoc.v_part[i].p_start /
7619889SLarry.Liu@Sun.COM 		    ((blkaddr_t)(disk->dtype_nhead *
7629889SLarry.Liu@Sun.COM 		    disk->dtype_nsect - apc));
763786Slclee 		part->pinfo_map[i].dkl_nblk =
7649889SLarry.Liu@Sun.COM 		    label->dkl_vtoc.v_part[i].p_size;
765786Slclee #else
766786Slclee #error No VTOC format defined.
767786Slclee #endif				/* defined(_SUNOS_VTOC_8) */
768786Slclee 	}
769786Slclee 
770786Slclee 	/*
771786Slclee 	 * Use the VTOC if valid, or install a default
772786Slclee 	 */
773786Slclee 	if (label->dkl_vtoc.v_version == V_VERSION) {
774786Slclee 		(void) memcpy(disk_info->v_volume, label->dkl_vtoc.v_volume,
7759889SLarry.Liu@Sun.COM 		    LEN_DKL_VVOL);
776786Slclee 		part->vtoc = label->dkl_vtoc;
777786Slclee 	} else {
778786Slclee 		(void) memset(disk_info->v_volume, 0, LEN_DKL_VVOL);
779786Slclee 		set_vtoc_defaults(part);
780786Slclee 	}
781786Slclee 
782786Slclee 	/*
783786Slclee 	 * Link the disk to the partition map
784786Slclee 	 */
785786Slclee 	disk_info->disk_parts = part;
786786Slclee 
787786Slclee 	return (disk);
788786Slclee }
789786Slclee 
790786Slclee /*
791786Slclee  * Get a disk type that has label info. This is used to convert
792786Slclee  * EFI label to SMI label
793786Slclee  */
794786Slclee struct disk_type *
auto_direct_get_geom_label(int fd,struct dk_label * label)795786Slclee auto_direct_get_geom_label(int fd, struct dk_label *label)
796786Slclee {
797786Slclee 	struct disk_type		*disk_type;
798786Slclee 
799786Slclee 	if (auto_label_init(label) != 0) {
800786Slclee 		err_print("auto_direct_get_geom_label: failed to get label"
801786Slclee 		    "geometry");
802786Slclee 		return (NULL);
803786Slclee 	} else {
804786Slclee 		disk_type = new_direct_disk_type(fd, "DEFAULT", label);
805786Slclee 		return (disk_type);
806786Slclee 	}
807786Slclee }
808786Slclee 
8090Sstevel@tonic-gate /*
8100Sstevel@tonic-gate  * Auto-sense a scsi disk configuration, ie get the information
8110Sstevel@tonic-gate  * necessary to construct a label.  We have two different
8120Sstevel@tonic-gate  * ways to auto-sense a scsi disk:
8130Sstevel@tonic-gate  *	- format.dat override, via inquiry name
8140Sstevel@tonic-gate  *	- generic scsi, via standard mode sense and inquiry
8150Sstevel@tonic-gate  * Depending on how and when we are called, and/or
8160Sstevel@tonic-gate  * change geometry and reformat.
8170Sstevel@tonic-gate  */
8180Sstevel@tonic-gate struct disk_type *
auto_sense(int fd,int can_prompt,struct dk_label * label)8190Sstevel@tonic-gate auto_sense(
8200Sstevel@tonic-gate 	int		fd,
8210Sstevel@tonic-gate 	int		can_prompt,
8220Sstevel@tonic-gate 	struct dk_label	*label)
8230Sstevel@tonic-gate {
8240Sstevel@tonic-gate 	struct scsi_inquiry		inquiry;
8250Sstevel@tonic-gate 	struct scsi_capacity_16		capacity;
8260Sstevel@tonic-gate 	struct disk_type		*disk_type;
8270Sstevel@tonic-gate 	char				disk_name[DISK_NAME_MAX];
8280Sstevel@tonic-gate 	int				force_format_dat = 0;
8290Sstevel@tonic-gate 	int				force_generic = 0;
8300Sstevel@tonic-gate 	u_ioparam_t			ioparam;
8310Sstevel@tonic-gate 	int				deflt;
832*11904SBo.Zhou@Sun.COM 	char				*buf;
8330Sstevel@tonic-gate 
8340Sstevel@tonic-gate 	/*
8350Sstevel@tonic-gate 	 * First, if expert mode, find out if the user
8360Sstevel@tonic-gate 	 * wants to override any of the standard methods.
8370Sstevel@tonic-gate 	 */
8380Sstevel@tonic-gate 	if (can_prompt && expert_mode) {
8390Sstevel@tonic-gate 		deflt = 1;
8400Sstevel@tonic-gate 		ioparam.io_charlist = confirm_list;
8410Sstevel@tonic-gate 		if (input(FIO_MSTR, FORMAT_MSG, '?', &ioparam,
8429889SLarry.Liu@Sun.COM 		    &deflt, DATA_INPUT) == 0) {
8430Sstevel@tonic-gate 			force_format_dat = 1;
8440Sstevel@tonic-gate 		} else if (input(FIO_MSTR, GENERIC_MSG, '?', &ioparam,
8459889SLarry.Liu@Sun.COM 		    &deflt, DATA_INPUT) == 0) {
8460Sstevel@tonic-gate 			force_generic = 1;
8470Sstevel@tonic-gate 		}
8480Sstevel@tonic-gate 	}
8490Sstevel@tonic-gate 
8500Sstevel@tonic-gate 	/*
8510Sstevel@tonic-gate 	 * Get the Inquiry data.  If this fails, there's
8520Sstevel@tonic-gate 	 * no hope for this disk, so give up.
8530Sstevel@tonic-gate 	 */
8540Sstevel@tonic-gate 	if (uscsi_inquiry(fd, (char *)&inquiry, sizeof (inquiry))) {
8550Sstevel@tonic-gate 		return ((struct disk_type *)NULL);
8560Sstevel@tonic-gate 	}
8570Sstevel@tonic-gate 	if (option_msg && diag_msg) {
8580Sstevel@tonic-gate 		err_print("Product id: ");
8590Sstevel@tonic-gate 		print_buf(inquiry.inq_pid, sizeof (inquiry.inq_pid));
8600Sstevel@tonic-gate 		err_print("\n");
8610Sstevel@tonic-gate 	}
8620Sstevel@tonic-gate 
8630Sstevel@tonic-gate 	/*
8640Sstevel@tonic-gate 	 * Get the Read Capacity
8650Sstevel@tonic-gate 	 */
8660Sstevel@tonic-gate 	if (uscsi_read_capacity(fd, &capacity)) {
8670Sstevel@tonic-gate 		return ((struct disk_type *)NULL);
8680Sstevel@tonic-gate 	}
8692094Syl194034 
8702094Syl194034 	/*
8712094Syl194034 	 * If the reported capacity is set to zero, then the disk
8722094Syl194034 	 * is not usable. If the reported capacity is set to all
8732094Syl194034 	 * 0xf's, then this disk is too large.  These could only
8742094Syl194034 	 * happen with a device that supports LBAs larger than 64
8752094Syl194034 	 * bits which are not defined by any current T10 standards
8762094Syl194034 	 * or by error responding from target.
8772094Syl194034 	 */
8782094Syl194034 	if ((capacity.sc_capacity == 0) ||
8792094Syl194034 	    (capacity.sc_capacity == UINT_MAX64)) {
8802094Syl194034 		if (option_msg && diag_msg) {
8812094Syl194034 			err_print("Invalid capacity\n");
8822094Syl194034 		}
8832094Syl194034 		return ((struct disk_type *)NULL);
8842094Syl194034 	}
8850Sstevel@tonic-gate 	if (option_msg && diag_msg) {
8860Sstevel@tonic-gate 		err_print("blocks:  %llu (0x%llx)\n",
8879889SLarry.Liu@Sun.COM 		    capacity.sc_capacity, capacity.sc_capacity);
8880Sstevel@tonic-gate 		err_print("blksize: %u\n", capacity.sc_lbasize);
8890Sstevel@tonic-gate 	}
8900Sstevel@tonic-gate 
8910Sstevel@tonic-gate 	/*
8920Sstevel@tonic-gate 	 * Extract the disk name for the format.dat override
8930Sstevel@tonic-gate 	 */
8940Sstevel@tonic-gate 	(void) get_sun_disk_name(disk_name, &inquiry);
8950Sstevel@tonic-gate 	if (option_msg && diag_msg) {
8960Sstevel@tonic-gate 		err_print("disk name:  `%s`\n", disk_name);
8970Sstevel@tonic-gate 	}
8980Sstevel@tonic-gate 
899*11904SBo.Zhou@Sun.COM 	buf = zalloc(cur_blksz);
900*11904SBo.Zhou@Sun.COM 	if (scsi_rdwr(DIR_READ, fd, (diskaddr_t)0, 1, (caddr_t)buf,
901*11904SBo.Zhou@Sun.COM 	    F_SILENT, NULL)) {
902*11904SBo.Zhou@Sun.COM 		free(buf);
90311533SAbhinandan.Ekande@Sun.COM 		return ((struct disk_type *)NULL);
904*11904SBo.Zhou@Sun.COM 	}
905*11904SBo.Zhou@Sun.COM 	free(buf);
90611533SAbhinandan.Ekande@Sun.COM 
9070Sstevel@tonic-gate 	/*
9080Sstevel@tonic-gate 	 * Figure out which method we use for auto sense.
9090Sstevel@tonic-gate 	 * If a particular method fails, we fall back to
9100Sstevel@tonic-gate 	 * the next possibility.
9110Sstevel@tonic-gate 	 */
9120Sstevel@tonic-gate 
9130Sstevel@tonic-gate 	if (force_generic) {
9140Sstevel@tonic-gate 		return (generic_disk_sense(fd, can_prompt, label,
9159889SLarry.Liu@Sun.COM 		    &inquiry, &capacity, disk_name));
9160Sstevel@tonic-gate 	}
9170Sstevel@tonic-gate 
9180Sstevel@tonic-gate 	/*
9190Sstevel@tonic-gate 	 * Try for an existing format.dat first
9200Sstevel@tonic-gate 	 */
9210Sstevel@tonic-gate 	if ((disk_type = find_scsi_disk_by_name(disk_name)) != NULL) {
9220Sstevel@tonic-gate 		if (use_existing_disk_type(fd, can_prompt, label,
9239889SLarry.Liu@Sun.COM 		    &inquiry, disk_type, &capacity)) {
9240Sstevel@tonic-gate 			return (disk_type);
9250Sstevel@tonic-gate 		}
9260Sstevel@tonic-gate 		if (force_format_dat) {
9270Sstevel@tonic-gate 			return (NULL);
9280Sstevel@tonic-gate 		}
9290Sstevel@tonic-gate 	}
9300Sstevel@tonic-gate 
9310Sstevel@tonic-gate 	/*
9320Sstevel@tonic-gate 	 * Otherwise, try using generic SCSI-2 sense and inquiry.
9330Sstevel@tonic-gate 	 */
9340Sstevel@tonic-gate 
9350Sstevel@tonic-gate 	return (generic_disk_sense(fd, can_prompt, label,
9369889SLarry.Liu@Sun.COM 	    &inquiry, &capacity, disk_name));
9370Sstevel@tonic-gate }
9380Sstevel@tonic-gate 
9390Sstevel@tonic-gate 
9400Sstevel@tonic-gate 
9410Sstevel@tonic-gate /*ARGSUSED*/
9420Sstevel@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)9430Sstevel@tonic-gate generic_disk_sense(
9440Sstevel@tonic-gate 	int			fd,
9450Sstevel@tonic-gate 	int			can_prompt,
9460Sstevel@tonic-gate 	struct dk_label		*label,
9470Sstevel@tonic-gate 	struct scsi_inquiry	*inquiry,
9480Sstevel@tonic-gate 	struct scsi_capacity_16	*capacity,
9490Sstevel@tonic-gate 	char			*disk_name)
9500Sstevel@tonic-gate {
9510Sstevel@tonic-gate 	struct disk_type		*disk;
9525786Sqd208687 	int				setdefault = 0;
9537563SPrasad.Singamsetty@Sun.COM 	uint_t				pcyl = 0;
9547563SPrasad.Singamsetty@Sun.COM 	uint_t				ncyl = 0;
9557563SPrasad.Singamsetty@Sun.COM 	uint_t				acyl = 0;
9567563SPrasad.Singamsetty@Sun.COM 	uint_t				nhead = 0;
9577563SPrasad.Singamsetty@Sun.COM 	uint_t				nsect = 0;
9585786Sqd208687 	int				rpm = 0;
9597563SPrasad.Singamsetty@Sun.COM 	diskaddr_t			nblocks = 0;
9607563SPrasad.Singamsetty@Sun.COM 	diskaddr_t			tblocks = 0;
9610Sstevel@tonic-gate 	union {
9620Sstevel@tonic-gate 		struct mode_format	page3;
9630Sstevel@tonic-gate 		uchar_t			buf3[MAX_MODE_SENSE_SIZE];
9640Sstevel@tonic-gate 	} u_page3;
9650Sstevel@tonic-gate 	union {
9660Sstevel@tonic-gate 		struct mode_geometry	page4;
9670Sstevel@tonic-gate 		uchar_t			buf4[MAX_MODE_SENSE_SIZE];
9680Sstevel@tonic-gate 	} u_page4;
9690Sstevel@tonic-gate 	struct mode_format		*page3 = &u_page3.page3;
9700Sstevel@tonic-gate 	struct mode_geometry		*page4 = &u_page4.page4;
9710Sstevel@tonic-gate 	struct scsi_ms_header		header;
9720Sstevel@tonic-gate 
9730Sstevel@tonic-gate 	/*
9740Sstevel@tonic-gate 	 * If the name of this disk appears to be "SUN", use it,
9750Sstevel@tonic-gate 	 * otherwise construct a name out of the generic
9760Sstevel@tonic-gate 	 * Inquiry info.  If it turns out that we already
9770Sstevel@tonic-gate 	 * have a SUN disk type of this name that differs
9780Sstevel@tonic-gate 	 * in geometry, we will revert to the generic name
9790Sstevel@tonic-gate 	 * anyway.
9800Sstevel@tonic-gate 	 */
9810Sstevel@tonic-gate 	if (memcmp(disk_name, "SUN", strlen("SUN")) != 0) {
9820Sstevel@tonic-gate 		(void) get_generic_disk_name(disk_name, inquiry);
9830Sstevel@tonic-gate 	}
9840Sstevel@tonic-gate 
9850Sstevel@tonic-gate 	/*
9865786Sqd208687 	 * Get the number of blocks from Read Capacity data. Note that
9875786Sqd208687 	 * the logical block address range from 0 to capacity->sc_capacity.
9887563SPrasad.Singamsetty@Sun.COM 	 * Limit the size to 2 TB (UINT32_MAX) to use with SMI labels.
9895786Sqd208687 	 */
9907563SPrasad.Singamsetty@Sun.COM 	tblocks = (capacity->sc_capacity + 1);
9917563SPrasad.Singamsetty@Sun.COM 	if (tblocks > UINT32_MAX)
9927563SPrasad.Singamsetty@Sun.COM 		nblocks = UINT32_MAX;
9937563SPrasad.Singamsetty@Sun.COM 	else
9947563SPrasad.Singamsetty@Sun.COM 		nblocks = tblocks;
9955786Sqd208687 
9965786Sqd208687 	/*
9970Sstevel@tonic-gate 	 * Get current Page 3 - Format Parameters page
9980Sstevel@tonic-gate 	 */
9990Sstevel@tonic-gate 	if (uscsi_mode_sense(fd, DAD_MODE_FORMAT, MODE_SENSE_PC_CURRENT,
10009889SLarry.Liu@Sun.COM 	    (caddr_t)&u_page3, MAX_MODE_SENSE_SIZE, &header)) {
10015786Sqd208687 		setdefault = 1;
10020Sstevel@tonic-gate 	}
10030Sstevel@tonic-gate 
10040Sstevel@tonic-gate 	/*
10050Sstevel@tonic-gate 	 * Get current Page 4 - Drive Geometry page
10060Sstevel@tonic-gate 	 */
10070Sstevel@tonic-gate 	if (uscsi_mode_sense(fd, DAD_MODE_GEOMETRY, MODE_SENSE_PC_CURRENT,
10089889SLarry.Liu@Sun.COM 	    (caddr_t)&u_page4, MAX_MODE_SENSE_SIZE, &header)) {
10095786Sqd208687 		setdefault = 1;
10100Sstevel@tonic-gate 	}
10110Sstevel@tonic-gate 
10125786Sqd208687 	if (setdefault != 1) {
10135786Sqd208687 		/* The inquiry of mode page 3 & page 4 are successful */
10145786Sqd208687 		/*
10155786Sqd208687 		 * Correct for byte order if necessary
10165786Sqd208687 		 */
10175786Sqd208687 		page4->rpm = BE_16(page4->rpm);
10185786Sqd208687 		page4->step_rate = BE_16(page4->step_rate);
10195786Sqd208687 		page3->tracks_per_zone = BE_16(page3->tracks_per_zone);
10205786Sqd208687 		page3->alt_sect_zone = BE_16(page3->alt_sect_zone);
10215786Sqd208687 		page3->alt_tracks_zone = BE_16(page3->alt_tracks_zone);
10225786Sqd208687 		page3->alt_tracks_vol = BE_16(page3->alt_tracks_vol);
10235786Sqd208687 		page3->sect_track = BE_16(page3->sect_track);
10245786Sqd208687 		page3->data_bytes_sect = BE_16(page3->data_bytes_sect);
10255786Sqd208687 		page3->interleave = BE_16(page3->interleave);
10265786Sqd208687 		page3->track_skew = BE_16(page3->track_skew);
10275786Sqd208687 		page3->cylinder_skew = BE_16(page3->cylinder_skew);
10280Sstevel@tonic-gate 
10290Sstevel@tonic-gate 
10305786Sqd208687 		/*
10315786Sqd208687 		 * Construct a new label out of the sense data,
10325786Sqd208687 		 * Inquiry and Capacity.
10337563SPrasad.Singamsetty@Sun.COM 		 *
10347563SPrasad.Singamsetty@Sun.COM 		 * If the disk capacity is > 1TB then simply compute
10357563SPrasad.Singamsetty@Sun.COM 		 * the CHS values based on the total disk capacity and
10367563SPrasad.Singamsetty@Sun.COM 		 * not use the values from mode-sense data.
10375786Sqd208687 		 */
10387563SPrasad.Singamsetty@Sun.COM 		if (tblocks > INT32_MAX) {
10397563SPrasad.Singamsetty@Sun.COM 			compute_chs_values(tblocks, nblocks, &pcyl, &nhead,
10407563SPrasad.Singamsetty@Sun.COM 			    &nsect);
10417563SPrasad.Singamsetty@Sun.COM 		} else {
10427563SPrasad.Singamsetty@Sun.COM 			pcyl = (page4->cyl_ub << 16) + (page4->cyl_mb << 8) +
10439889SLarry.Liu@Sun.COM 			    page4->cyl_lb;
10447563SPrasad.Singamsetty@Sun.COM 			nhead = page4->heads;
10457563SPrasad.Singamsetty@Sun.COM 			nsect = page3->sect_track;
10467563SPrasad.Singamsetty@Sun.COM 		}
10477563SPrasad.Singamsetty@Sun.COM 
10485786Sqd208687 		rpm = page4->rpm;
10495786Sqd208687 
10505786Sqd208687 		/*
10515786Sqd208687 		 * If the number of physical cylinders reported is less
10525786Sqd208687 		 * the SUN_MIN_CYL(3) then try to adjust the geometry so that
10535786Sqd208687 		 * we have atleast SUN_MIN_CYL cylinders.
10545786Sqd208687 		 */
10555786Sqd208687 		if (pcyl < SUN_MIN_CYL) {
10567563SPrasad.Singamsetty@Sun.COM 			if (nhead == 0 || nsect == 0) {
10575786Sqd208687 				setdefault = 1;
10585790Sqd208687 			} else if (adjust_disk_geometry(
10597563SPrasad.Singamsetty@Sun.COM 			    (diskaddr_t)(capacity->sc_capacity + 1),
10605786Sqd208687 			    &pcyl, &nhead, &nsect)) {
10615786Sqd208687 				setdefault = 1;
10625786Sqd208687 			}
10635786Sqd208687 		}
10645786Sqd208687 	}
10650Sstevel@tonic-gate 
10669889SLarry.Liu@Sun.COM 	/*
10679889SLarry.Liu@Sun.COM 	 * Mode sense page 3 and page 4 are obsolete in SCSI-3. For
10689889SLarry.Liu@Sun.COM 	 * newly developed large sector size disk, we will not rely on
10699889SLarry.Liu@Sun.COM 	 * those two pages but compute geometry directly.
10709889SLarry.Liu@Sun.COM 	 */
10719889SLarry.Liu@Sun.COM 	if ((setdefault == 1) || (capacity->sc_lbasize != DEV_BSIZE)) {
10725786Sqd208687 		/*
10735786Sqd208687 		 * If the number of cylinders or the number of heads reported
10745786Sqd208687 		 * is zero, we think the inquiry of page 3 and page 4 failed.
10755786Sqd208687 		 * We will set the geometry infomation by ourselves.
10765786Sqd208687 		 */
10777563SPrasad.Singamsetty@Sun.COM 		compute_chs_values(tblocks, nblocks, &pcyl, &nhead, &nsect);
10780Sstevel@tonic-gate 	}
10790Sstevel@tonic-gate 
10800Sstevel@tonic-gate 	/*
10810Sstevel@tonic-gate 	 * The sd driver reserves 2 cylinders the backup disk label and
10820Sstevel@tonic-gate 	 * the deviceid.  Set the number of data cylinders to pcyl-acyl.
10830Sstevel@tonic-gate 	 */
10840Sstevel@tonic-gate 	acyl = DK_ACYL;
10850Sstevel@tonic-gate 	ncyl = pcyl - acyl;
10860Sstevel@tonic-gate 
10870Sstevel@tonic-gate 	if (option_msg && diag_msg) {
10880Sstevel@tonic-gate 		err_print("Geometry:\n");
10897563SPrasad.Singamsetty@Sun.COM 		err_print("    pcyl:    %u\n", pcyl);
10907563SPrasad.Singamsetty@Sun.COM 		err_print("    ncyl:    %u\n", ncyl);
10917563SPrasad.Singamsetty@Sun.COM 		err_print("    heads:   %u\n", nhead);
10927563SPrasad.Singamsetty@Sun.COM 		err_print("    nsects:  %u\n", nsect);
10937563SPrasad.Singamsetty@Sun.COM 		err_print("    acyl:    %u\n", acyl);
10940Sstevel@tonic-gate 
10950Sstevel@tonic-gate #if defined(_SUNOS_VTOC_16)
10967563SPrasad.Singamsetty@Sun.COM 		err_print("    bcyl:    %u\n", bcyl);
10970Sstevel@tonic-gate #endif			/* defined(_SUNOS_VTOC_16) */
10980Sstevel@tonic-gate 
10990Sstevel@tonic-gate 		err_print("    rpm:     %d\n", rpm);
11007563SPrasad.Singamsetty@Sun.COM 		err_print("    nblocks:     %llu\n", nblocks);
11010Sstevel@tonic-gate 	}
11020Sstevel@tonic-gate 
11030Sstevel@tonic-gate 	/*
11045786Sqd208687 	 * Some drives do not support page4 or report 0 for page4->rpm,
11055786Sqd208687 	 * adjust it to AVG_RPM, 3600.
11060Sstevel@tonic-gate 	 */
11070Sstevel@tonic-gate 	if (rpm < MIN_RPM || rpm > MAX_RPM) {
110811533SAbhinandan.Ekande@Sun.COM 		if (option_msg && diag_msg)
110911533SAbhinandan.Ekande@Sun.COM 			err_print("The current rpm value %d is invalid,"
111011533SAbhinandan.Ekande@Sun.COM 			    " adjusting it to %d\n", rpm, AVG_RPM);
11110Sstevel@tonic-gate 		rpm = AVG_RPM;
11120Sstevel@tonic-gate 	}
11130Sstevel@tonic-gate 
11140Sstevel@tonic-gate 	/*
11150Sstevel@tonic-gate 	 * Some drives report 0 for nsect (page 3, byte 10 and 11) if they
11160Sstevel@tonic-gate 	 * have variable number of sectors per track. So adjust nsect.
11170Sstevel@tonic-gate 	 * Also the value is defined as vendor specific, hence check if
11180Sstevel@tonic-gate 	 * it is in a tolerable range. The values (32 and 4 below) are
11190Sstevel@tonic-gate 	 * chosen so that this change below does not generate a different
11200Sstevel@tonic-gate 	 * geometry for currently supported sun disks.
11210Sstevel@tonic-gate 	 */
11227563SPrasad.Singamsetty@Sun.COM 	if ((nsect == 0) ||
11237563SPrasad.Singamsetty@Sun.COM 	    ((diskaddr_t)pcyl * nhead * nsect) < (nblocks - nblocks/32) ||
11247563SPrasad.Singamsetty@Sun.COM 	    ((diskaddr_t)pcyl * nhead * nsect) > (nblocks + nblocks/4)) {
11257563SPrasad.Singamsetty@Sun.COM 		if (nblocks > (pcyl * nhead)) {
11267563SPrasad.Singamsetty@Sun.COM 			err_print("Mode sense page(3) reports nsect value"
11277563SPrasad.Singamsetty@Sun.COM 			    " as %d, adjusting it to %llu\n",
11287563SPrasad.Singamsetty@Sun.COM 			    nsect, nblocks / (pcyl * nhead));
11297563SPrasad.Singamsetty@Sun.COM 			nsect = nblocks / (pcyl * nhead);
11307563SPrasad.Singamsetty@Sun.COM 		} else {
11317563SPrasad.Singamsetty@Sun.COM 			/* convert capacity to nsect * nhead * pcyl */
11327563SPrasad.Singamsetty@Sun.COM 			err_print("\nWARNING: Disk geometry is based on "
11337563SPrasad.Singamsetty@Sun.COM 			    "capacity data.\n\n");
11347563SPrasad.Singamsetty@Sun.COM 			compute_chs_values(tblocks, nblocks, &pcyl, &nhead,
11357563SPrasad.Singamsetty@Sun.COM 			    &nsect);
11367563SPrasad.Singamsetty@Sun.COM 			ncyl = pcyl - acyl;
11377563SPrasad.Singamsetty@Sun.COM 			if (option_msg && diag_msg) {
11387563SPrasad.Singamsetty@Sun.COM 				err_print("Geometry:(after adjustment)\n");
11397563SPrasad.Singamsetty@Sun.COM 				err_print("    pcyl:    %u\n", pcyl);
11407563SPrasad.Singamsetty@Sun.COM 				err_print("    ncyl:    %u\n", ncyl);
11417563SPrasad.Singamsetty@Sun.COM 				err_print("    heads:   %u\n", nhead);
11427563SPrasad.Singamsetty@Sun.COM 				err_print("    nsects:  %u\n", nsect);
11437563SPrasad.Singamsetty@Sun.COM 				err_print("    acyl:    %u\n", acyl);
11447563SPrasad.Singamsetty@Sun.COM 
11457563SPrasad.Singamsetty@Sun.COM #if defined(_SUNOS_VTOC_16)
11467563SPrasad.Singamsetty@Sun.COM 				err_print("    bcyl:    %u\n", bcyl);
11477563SPrasad.Singamsetty@Sun.COM #endif
11487563SPrasad.Singamsetty@Sun.COM 
11497563SPrasad.Singamsetty@Sun.COM 				err_print("    rpm:     %d\n", rpm);
11507563SPrasad.Singamsetty@Sun.COM 				err_print("    nblocks:     %llu\n", nblocks);
11517563SPrasad.Singamsetty@Sun.COM 			}
11527563SPrasad.Singamsetty@Sun.COM 		}
11530Sstevel@tonic-gate 	}
11540Sstevel@tonic-gate 
11550Sstevel@tonic-gate 	/*
11560Sstevel@tonic-gate 	 * Some drives report their physical geometry such that
11570Sstevel@tonic-gate 	 * it is greater than the actual capacity.  Adjust the
11580Sstevel@tonic-gate 	 * geometry to allow for this, so we don't run off
11590Sstevel@tonic-gate 	 * the end of the disk.
11600Sstevel@tonic-gate 	 */
11617563SPrasad.Singamsetty@Sun.COM 	if (((diskaddr_t)pcyl * nhead * nsect) > nblocks) {
11627563SPrasad.Singamsetty@Sun.COM 		uint_t	p = pcyl;
11630Sstevel@tonic-gate 		if (option_msg && diag_msg) {
11647563SPrasad.Singamsetty@Sun.COM 			err_print("Computed capacity (%llu) exceeds actual "
11657563SPrasad.Singamsetty@Sun.COM 			    "disk capacity (%llu)\n",
11667563SPrasad.Singamsetty@Sun.COM 			    (diskaddr_t)pcyl * nhead * nsect, nblocks);
11670Sstevel@tonic-gate 		}
11680Sstevel@tonic-gate 		do {
11690Sstevel@tonic-gate 			pcyl--;
11707563SPrasad.Singamsetty@Sun.COM 		} while (((diskaddr_t)pcyl * nhead * nsect) > nblocks);
11710Sstevel@tonic-gate 
11720Sstevel@tonic-gate 		if (can_prompt && expert_mode && !option_f) {
11730Sstevel@tonic-gate 			/*
11740Sstevel@tonic-gate 			 * Try to adjust nsect instead of pcyl to see if we
11750Sstevel@tonic-gate 			 * can optimize. For compatability reasons do this
11760Sstevel@tonic-gate 			 * only in expert mode (refer to bug 1144812).
11770Sstevel@tonic-gate 			 */
11787563SPrasad.Singamsetty@Sun.COM 			uint_t	n = nsect;
11790Sstevel@tonic-gate 			do {
11800Sstevel@tonic-gate 				n--;
11817563SPrasad.Singamsetty@Sun.COM 			} while (((diskaddr_t)p * nhead * n) > nblocks);
11827563SPrasad.Singamsetty@Sun.COM 			if (((diskaddr_t)p * nhead * n) >
11837563SPrasad.Singamsetty@Sun.COM 			    ((diskaddr_t)pcyl * nhead * nsect)) {
11840Sstevel@tonic-gate 				u_ioparam_t	ioparam;
11850Sstevel@tonic-gate 				int		deflt = 1;
11860Sstevel@tonic-gate 				/*
11870Sstevel@tonic-gate 				 * Ask the user for a choice here.
11880Sstevel@tonic-gate 				 */
11890Sstevel@tonic-gate 				ioparam.io_bounds.lower = 1;
11900Sstevel@tonic-gate 				ioparam.io_bounds.upper = 2;
11917563SPrasad.Singamsetty@Sun.COM 				err_print("1. Capacity = %llu, with pcyl = %u "
11927563SPrasad.Singamsetty@Sun.COM 				    "nhead = %u nsect = %u\n",
11937563SPrasad.Singamsetty@Sun.COM 				    ((diskaddr_t)pcyl * nhead * nsect),
11947563SPrasad.Singamsetty@Sun.COM 				    pcyl, nhead, nsect);
11957563SPrasad.Singamsetty@Sun.COM 				err_print("2. Capacity = %llu, with pcyl = %u "
11967563SPrasad.Singamsetty@Sun.COM 				    "nhead = %u nsect = %u\n",
11977563SPrasad.Singamsetty@Sun.COM 				    ((diskaddr_t)p * nhead * n),
11987563SPrasad.Singamsetty@Sun.COM 				    p, nhead, n);
11990Sstevel@tonic-gate 				if (input(FIO_INT, "Select one of the above "
12000Sstevel@tonic-gate 				    "choices ", ':', &ioparam,
12019889SLarry.Liu@Sun.COM 				    &deflt, DATA_INPUT) == 2) {
12020Sstevel@tonic-gate 					pcyl = p;
12030Sstevel@tonic-gate 					nsect = n;
12040Sstevel@tonic-gate 				}
12050Sstevel@tonic-gate 			}
12060Sstevel@tonic-gate 		}
12070Sstevel@tonic-gate 	}
12080Sstevel@tonic-gate 
12090Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
12100Sstevel@tonic-gate 	/*
12110Sstevel@tonic-gate 	 * Finally, we need to make sure we don't overflow any of the
12120Sstevel@tonic-gate 	 * fields in our disk label.  To do this we need to `square
12130Sstevel@tonic-gate 	 * the box' so to speak.  We will lose bits here.
12140Sstevel@tonic-gate 	 */
12150Sstevel@tonic-gate 
12160Sstevel@tonic-gate 	if ((pcyl > MAXIMUM_NO_CYLINDERS &&
12179889SLarry.Liu@Sun.COM 	    ((nsect > MAXIMUM_NO_SECTORS) ||
12189889SLarry.Liu@Sun.COM 	    (nhead > MAXIMUM_NO_HEADS))) ||
12199889SLarry.Liu@Sun.COM 	    ((nsect > MAXIMUM_NO_SECTORS) &&
12209889SLarry.Liu@Sun.COM 	    (nhead > MAXIMUM_NO_HEADS))) {
12210Sstevel@tonic-gate 		err_print("This disk is too big to label. "
12229889SLarry.Liu@Sun.COM 		    " You will lose some blocks.\n");
12230Sstevel@tonic-gate 	}
12240Sstevel@tonic-gate 	if ((pcyl > MAXIMUM_NO_CYLINDERS) ||
12259889SLarry.Liu@Sun.COM 	    (nsect > MAXIMUM_NO_SECTORS) ||
12269889SLarry.Liu@Sun.COM 	    (nhead > MAXIMUM_NO_HEADS)) {
12270Sstevel@tonic-gate 		u_ioparam_t	ioparam;
12280Sstevel@tonic-gate 		int		order;
12290Sstevel@tonic-gate 		char		msg[256];
12300Sstevel@tonic-gate 
12316382Sbz211116 		order = ((pcyl > nhead)<<2) |
12326382Sbz211116 		    ((pcyl > nsect)<<1) |
12336382Sbz211116 		    (nhead > nsect);
12340Sstevel@tonic-gate 		switch (order) {
12356382Sbz211116 		case 0x7: /* pcyl > nhead > nsect */
12360Sstevel@tonic-gate 			nblocks =
12379889SLarry.Liu@Sun.COM 			    square_box(nblocks,
12389889SLarry.Liu@Sun.COM 			    &pcyl, MAXIMUM_NO_CYLINDERS,
12399889SLarry.Liu@Sun.COM 			    &nhead, MAXIMUM_NO_HEADS,
12409889SLarry.Liu@Sun.COM 			    &nsect, MAXIMUM_NO_SECTORS);
12410Sstevel@tonic-gate 			break;
12426382Sbz211116 		case 0x6: /* pcyl > nsect > nhead */
12430Sstevel@tonic-gate 			nblocks =
12449889SLarry.Liu@Sun.COM 			    square_box(nblocks,
12459889SLarry.Liu@Sun.COM 			    &pcyl, MAXIMUM_NO_CYLINDERS,
12469889SLarry.Liu@Sun.COM 			    &nsect, MAXIMUM_NO_SECTORS,
12479889SLarry.Liu@Sun.COM 			    &nhead, MAXIMUM_NO_HEADS);
12480Sstevel@tonic-gate 			break;
12496382Sbz211116 		case 0x4: /* nsect > pcyl > nhead */
12500Sstevel@tonic-gate 			nblocks =
12519889SLarry.Liu@Sun.COM 			    square_box(nblocks,
12529889SLarry.Liu@Sun.COM 			    &nsect, MAXIMUM_NO_SECTORS,
12539889SLarry.Liu@Sun.COM 			    &pcyl, MAXIMUM_NO_CYLINDERS,
12549889SLarry.Liu@Sun.COM 			    &nhead, MAXIMUM_NO_HEADS);
12550Sstevel@tonic-gate 			break;
12566382Sbz211116 		case 0x0: /* nsect > nhead > pcyl */
12570Sstevel@tonic-gate 			nblocks =
12589889SLarry.Liu@Sun.COM 			    square_box(nblocks,
12599889SLarry.Liu@Sun.COM 			    &nsect, MAXIMUM_NO_SECTORS,
12609889SLarry.Liu@Sun.COM 			    &nhead, MAXIMUM_NO_HEADS,
12619889SLarry.Liu@Sun.COM 			    &pcyl, MAXIMUM_NO_CYLINDERS);
12620Sstevel@tonic-gate 			break;
12636382Sbz211116 		case 0x3: /* nhead > pcyl > nsect */
12640Sstevel@tonic-gate 			nblocks =
12659889SLarry.Liu@Sun.COM 			    square_box(nblocks,
12669889SLarry.Liu@Sun.COM 			    &nhead, MAXIMUM_NO_HEADS,
12679889SLarry.Liu@Sun.COM 			    &pcyl, MAXIMUM_NO_CYLINDERS,
12689889SLarry.Liu@Sun.COM 			    &nsect, MAXIMUM_NO_SECTORS);
12690Sstevel@tonic-gate 			break;
12706382Sbz211116 		case 0x1: /* nhead > nsect > pcyl */
12710Sstevel@tonic-gate 			nblocks =
12729889SLarry.Liu@Sun.COM 			    square_box(nblocks,
12739889SLarry.Liu@Sun.COM 			    &nhead, MAXIMUM_NO_HEADS,
12749889SLarry.Liu@Sun.COM 			    &nsect, MAXIMUM_NO_SECTORS,
12759889SLarry.Liu@Sun.COM 			    &pcyl, MAXIMUM_NO_CYLINDERS);
12760Sstevel@tonic-gate 			break;
12770Sstevel@tonic-gate 		default:
12780Sstevel@tonic-gate 			/* How did we get here? */
12790Sstevel@tonic-gate 			impossible("label overflow adjustment");
12800Sstevel@tonic-gate 
12810Sstevel@tonic-gate 			/* Do something useful */
12820Sstevel@tonic-gate 			nblocks =
12839889SLarry.Liu@Sun.COM 			    square_box(nblocks,
12849889SLarry.Liu@Sun.COM 			    &nhead, MAXIMUM_NO_HEADS,
12859889SLarry.Liu@Sun.COM 			    &nsect, MAXIMUM_NO_SECTORS,
12869889SLarry.Liu@Sun.COM 			    &pcyl, MAXIMUM_NO_CYLINDERS);
12870Sstevel@tonic-gate 			break;
12880Sstevel@tonic-gate 		}
12890Sstevel@tonic-gate 		if (option_msg && diag_msg &&
12900Sstevel@tonic-gate 		    (capacity->sc_capacity + 1 != nblocks)) {
12910Sstevel@tonic-gate 			err_print("After adjusting geometry you lost"
12927563SPrasad.Singamsetty@Sun.COM 			    " %llu of %llu blocks.\n",
12937563SPrasad.Singamsetty@Sun.COM 			    (capacity->sc_capacity + 1 - nblocks),
12947563SPrasad.Singamsetty@Sun.COM 			    capacity->sc_capacity + 1);
12950Sstevel@tonic-gate 		}
12960Sstevel@tonic-gate 		while (can_prompt && expert_mode && !option_f) {
12970Sstevel@tonic-gate 			int				deflt = 1;
12980Sstevel@tonic-gate 
12990Sstevel@tonic-gate 			/*
13000Sstevel@tonic-gate 			 * Allow user to modify this by hand if desired.
13010Sstevel@tonic-gate 			 */
13020Sstevel@tonic-gate 			(void) sprintf(msg,
13037563SPrasad.Singamsetty@Sun.COM 			    "\nGeometry: %u heads, %u sectors %u cylinders"
13047563SPrasad.Singamsetty@Sun.COM 			    " result in %llu out of %llu blocks.\n"
13057563SPrasad.Singamsetty@Sun.COM 			    "Do you want to modify the device geometry",
13067563SPrasad.Singamsetty@Sun.COM 			    nhead, nsect, pcyl,
13077563SPrasad.Singamsetty@Sun.COM 			    nblocks, capacity->sc_capacity + 1);
13080Sstevel@tonic-gate 
13090Sstevel@tonic-gate 			ioparam.io_charlist = confirm_list;
13100Sstevel@tonic-gate 			if (input(FIO_MSTR, msg, '?', &ioparam,
13119889SLarry.Liu@Sun.COM 			    &deflt, DATA_INPUT) != 0)
13120Sstevel@tonic-gate 				break;
13130Sstevel@tonic-gate 
13140Sstevel@tonic-gate 			ioparam.io_bounds.lower = MINIMUM_NO_HEADS;
13150Sstevel@tonic-gate 			ioparam.io_bounds.upper = MAXIMUM_NO_HEADS;
13160Sstevel@tonic-gate 			nhead = input(FIO_INT, "Number of heads", ':',
13177563SPrasad.Singamsetty@Sun.COM 			    &ioparam, (int *)&nhead, DATA_INPUT);
13180Sstevel@tonic-gate 			ioparam.io_bounds.lower = MINIMUM_NO_SECTORS;
13190Sstevel@tonic-gate 			ioparam.io_bounds.upper = MAXIMUM_NO_SECTORS;
13200Sstevel@tonic-gate 			nsect = input(FIO_INT,
13217563SPrasad.Singamsetty@Sun.COM 			    "Number of sectors per track",
13227563SPrasad.Singamsetty@Sun.COM 			    ':', &ioparam, (int *)&nsect, DATA_INPUT);
13230Sstevel@tonic-gate 			ioparam.io_bounds.lower = SUN_MIN_CYL;
13240Sstevel@tonic-gate 			ioparam.io_bounds.upper = MAXIMUM_NO_CYLINDERS;
13250Sstevel@tonic-gate 			pcyl = input(FIO_INT, "Number of cylinders",
13267563SPrasad.Singamsetty@Sun.COM 			    ':', &ioparam, (int *)&pcyl, DATA_INPUT);
13277563SPrasad.Singamsetty@Sun.COM 			nblocks = (diskaddr_t)nhead * nsect * pcyl;
13280Sstevel@tonic-gate 			if (nblocks > capacity->sc_capacity + 1) {
13297563SPrasad.Singamsetty@Sun.COM 				err_print("Warning: %llu blocks exceeds "
13307563SPrasad.Singamsetty@Sun.COM 				    "disk capacity of %llu blocks\n",
13317563SPrasad.Singamsetty@Sun.COM 				    nblocks,
13327563SPrasad.Singamsetty@Sun.COM 				    capacity->sc_capacity + 1);
13330Sstevel@tonic-gate 			}
13340Sstevel@tonic-gate 		}
13350Sstevel@tonic-gate 	}
13360Sstevel@tonic-gate #endif		/* defined(_SUNOS_VTOC_8) */
13370Sstevel@tonic-gate 
13380Sstevel@tonic-gate 	ncyl = pcyl - acyl;
13390Sstevel@tonic-gate 
13400Sstevel@tonic-gate 	if (option_msg && diag_msg) {
13410Sstevel@tonic-gate 		err_print("\nGeometry after adjusting for capacity:\n");
13427563SPrasad.Singamsetty@Sun.COM 		err_print("    pcyl:    %u\n", pcyl);
13437563SPrasad.Singamsetty@Sun.COM 		err_print("    ncyl:    %u\n", ncyl);
13447563SPrasad.Singamsetty@Sun.COM 		err_print("    heads:   %u\n", nhead);
13457563SPrasad.Singamsetty@Sun.COM 		err_print("    nsects:  %u\n", nsect);
13467563SPrasad.Singamsetty@Sun.COM 		err_print("    acyl:    %u\n", acyl);
13470Sstevel@tonic-gate 		err_print("    rpm:     %d\n", rpm);
13480Sstevel@tonic-gate 	}
13490Sstevel@tonic-gate 
13500Sstevel@tonic-gate 	(void) memset((char *)label, 0, sizeof (struct dk_label));
13510Sstevel@tonic-gate 
13520Sstevel@tonic-gate 	label->dkl_magic = DKL_MAGIC;
13530Sstevel@tonic-gate 
13540Sstevel@tonic-gate 	(void) snprintf(label->dkl_asciilabel, sizeof (label->dkl_asciilabel),
13557563SPrasad.Singamsetty@Sun.COM 	    "%s cyl %u alt %u hd %u sec %u",
13567563SPrasad.Singamsetty@Sun.COM 	    disk_name, ncyl, acyl, nhead, nsect);
13570Sstevel@tonic-gate 
13580Sstevel@tonic-gate 	label->dkl_pcyl = pcyl;
13590Sstevel@tonic-gate 	label->dkl_ncyl = ncyl;
13600Sstevel@tonic-gate 	label->dkl_acyl = acyl;
13610Sstevel@tonic-gate 	label->dkl_nhead = nhead;
13620Sstevel@tonic-gate 	label->dkl_nsect = nsect;
13630Sstevel@tonic-gate 	label->dkl_apc = 0;
13640Sstevel@tonic-gate 	label->dkl_intrlv = 1;
13650Sstevel@tonic-gate 	label->dkl_rpm = rpm;
13660Sstevel@tonic-gate 
13670Sstevel@tonic-gate #if defined(_FIRMWARE_NEEDS_FDISK)
13687563SPrasad.Singamsetty@Sun.COM 	if (auto_solaris_part(label) == -1)
13697563SPrasad.Singamsetty@Sun.COM 		goto err;
13700Sstevel@tonic-gate 	ncyl = label->dkl_ncyl;
13710Sstevel@tonic-gate #endif		/* defined(_FIRMWARE_NEEDS_FDISK) */
13720Sstevel@tonic-gate 
13730Sstevel@tonic-gate 
13740Sstevel@tonic-gate 	if (!build_default_partition(label, DKC_SCSI_CCS)) {
13750Sstevel@tonic-gate 		goto err;
13760Sstevel@tonic-gate 	}
13770Sstevel@tonic-gate 
13780Sstevel@tonic-gate 	(void) checksum(label, CK_MAKESUM);
13790Sstevel@tonic-gate 
13800Sstevel@tonic-gate 	/*
13810Sstevel@tonic-gate 	 * Find an existing disk type defined for this disk.
13820Sstevel@tonic-gate 	 * For this to work, both the name and geometry must
13830Sstevel@tonic-gate 	 * match.  If there is no such type, but there already
13840Sstevel@tonic-gate 	 * is a disk defined with that name, but with a different
13850Sstevel@tonic-gate 	 * geometry, construct a new generic disk name out of
13860Sstevel@tonic-gate 	 * the inquiry information.  Whatever name we're
13870Sstevel@tonic-gate 	 * finally using, if there's no such disk type defined,
13880Sstevel@tonic-gate 	 * build a new disk definition.
13890Sstevel@tonic-gate 	 */
13900Sstevel@tonic-gate 	if ((disk = find_scsi_disk_type(disk_name, label)) == NULL) {
13910Sstevel@tonic-gate 		if (find_scsi_disk_by_name(disk_name) != NULL) {
13920Sstevel@tonic-gate 			char	old_name[DISK_NAME_MAX];
13930Sstevel@tonic-gate 			(void) strcpy(old_name, disk_name);
13940Sstevel@tonic-gate 			(void) get_generic_disk_name(disk_name,
13959889SLarry.Liu@Sun.COM 			    inquiry);
13960Sstevel@tonic-gate 			if (option_msg && diag_msg) {
13970Sstevel@tonic-gate 				err_print(
13980Sstevel@tonic-gate "Changing disk type name from '%s' to '%s'\n", old_name, disk_name);
13990Sstevel@tonic-gate 			}
14000Sstevel@tonic-gate 			(void) snprintf(label->dkl_asciilabel,
14017563SPrasad.Singamsetty@Sun.COM 			    sizeof (label->dkl_asciilabel),
14027563SPrasad.Singamsetty@Sun.COM 			    "%s cyl %u alt %u hd %u sec %u",
14037563SPrasad.Singamsetty@Sun.COM 			    disk_name, ncyl, acyl, nhead, nsect);
14040Sstevel@tonic-gate 			(void) checksum(label, CK_MAKESUM);
14050Sstevel@tonic-gate 			disk = find_scsi_disk_type(disk_name, label);
14060Sstevel@tonic-gate 		}
14070Sstevel@tonic-gate 		if (disk == NULL) {
14080Sstevel@tonic-gate 			disk = new_scsi_disk_type(fd, disk_name, label);
14090Sstevel@tonic-gate 			if (disk == NULL)
14100Sstevel@tonic-gate 				goto err;
14110Sstevel@tonic-gate 		}
14120Sstevel@tonic-gate 	}
14130Sstevel@tonic-gate 
14140Sstevel@tonic-gate 	return (disk);
14150Sstevel@tonic-gate 
14160Sstevel@tonic-gate err:
14170Sstevel@tonic-gate 	if (option_msg && diag_msg) {
14180Sstevel@tonic-gate 		err_print(
14190Sstevel@tonic-gate 		"Configuration via generic SCSI-2 information failed\n");
14200Sstevel@tonic-gate 	}
14210Sstevel@tonic-gate 	return (NULL);
14220Sstevel@tonic-gate }
14230Sstevel@tonic-gate 
14240Sstevel@tonic-gate 
14250Sstevel@tonic-gate /*ARGSUSED*/
14260Sstevel@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)14270Sstevel@tonic-gate use_existing_disk_type(
14280Sstevel@tonic-gate 	int			fd,
14290Sstevel@tonic-gate 	int			can_prompt,
14300Sstevel@tonic-gate 	struct dk_label		*label,
14310Sstevel@tonic-gate 	struct scsi_inquiry	*inquiry,
14320Sstevel@tonic-gate 	struct disk_type	*disk_type,
14330Sstevel@tonic-gate 	struct scsi_capacity_16	*capacity)
14340Sstevel@tonic-gate {
14350Sstevel@tonic-gate 	int			pcyl;
14360Sstevel@tonic-gate 	int			acyl;
14370Sstevel@tonic-gate 	int			nhead;
14380Sstevel@tonic-gate 	int			nsect;
14390Sstevel@tonic-gate 	int			rpm;
14400Sstevel@tonic-gate 
14410Sstevel@tonic-gate 	/*
14420Sstevel@tonic-gate 	 * Construct a new label out of the format.dat
14430Sstevel@tonic-gate 	 */
14440Sstevel@tonic-gate 	pcyl = disk_type->dtype_pcyl;
14450Sstevel@tonic-gate 	acyl = disk_type->dtype_acyl;
14460Sstevel@tonic-gate 	ncyl = disk_type->dtype_ncyl;
14470Sstevel@tonic-gate 	nhead = disk_type->dtype_nhead;
14480Sstevel@tonic-gate 	nsect = disk_type->dtype_nsect;
14490Sstevel@tonic-gate 	rpm = disk_type->dtype_rpm;
14500Sstevel@tonic-gate 
14510Sstevel@tonic-gate 	if (option_msg && diag_msg) {
14520Sstevel@tonic-gate 		err_print("Format.dat geometry:\n");
14537563SPrasad.Singamsetty@Sun.COM 		err_print("    pcyl:    %u\n", pcyl);
14547563SPrasad.Singamsetty@Sun.COM 		err_print("    heads:   %u\n", nhead);
14557563SPrasad.Singamsetty@Sun.COM 		err_print("    nsects:  %u\n", nsect);
14567563SPrasad.Singamsetty@Sun.COM 		err_print("    acyl:    %u\n", acyl);
14570Sstevel@tonic-gate 		err_print("    rpm:     %d\n", rpm);
14580Sstevel@tonic-gate 	}
14590Sstevel@tonic-gate 
14600Sstevel@tonic-gate 	(void) memset((char *)label, 0, sizeof (struct dk_label));
14610Sstevel@tonic-gate 
14620Sstevel@tonic-gate 	label->dkl_magic = DKL_MAGIC;
14630Sstevel@tonic-gate 
14640Sstevel@tonic-gate 	(void) snprintf(label->dkl_asciilabel, sizeof (label->dkl_asciilabel),
14657563SPrasad.Singamsetty@Sun.COM 	    "%s cyl %u alt %u hd %u sec %u",
14667563SPrasad.Singamsetty@Sun.COM 	    disk_type->dtype_asciilabel,
14677563SPrasad.Singamsetty@Sun.COM 	    ncyl, acyl, nhead, nsect);
14680Sstevel@tonic-gate 
14690Sstevel@tonic-gate 	label->dkl_pcyl = pcyl;
14700Sstevel@tonic-gate 	label->dkl_ncyl = ncyl;
14710Sstevel@tonic-gate 	label->dkl_acyl = acyl;
14720Sstevel@tonic-gate 	label->dkl_nhead = nhead;
14730Sstevel@tonic-gate 	label->dkl_nsect = nsect;
14740Sstevel@tonic-gate 	label->dkl_apc = 0;
14750Sstevel@tonic-gate 	label->dkl_intrlv = 1;
14760Sstevel@tonic-gate 	label->dkl_rpm = rpm;
14770Sstevel@tonic-gate 
14780Sstevel@tonic-gate 	if (!build_default_partition(label, DKC_SCSI_CCS)) {
14790Sstevel@tonic-gate 		goto err;
14800Sstevel@tonic-gate 	}
14810Sstevel@tonic-gate 
14820Sstevel@tonic-gate 	(void) checksum(label, CK_MAKESUM);
14830Sstevel@tonic-gate 	return (1);
14840Sstevel@tonic-gate 
14850Sstevel@tonic-gate err:
14860Sstevel@tonic-gate 	if (option_msg && diag_msg) {
14870Sstevel@tonic-gate 		err_print(
14889889SLarry.Liu@Sun.COM 		    "Configuration via format.dat geometry failed\n");
14890Sstevel@tonic-gate 	}
14900Sstevel@tonic-gate 	return (0);
14910Sstevel@tonic-gate }
14920Sstevel@tonic-gate 
14930Sstevel@tonic-gate int
build_default_partition(struct dk_label * label,int ctrl_type)14940Sstevel@tonic-gate build_default_partition(
14950Sstevel@tonic-gate 	struct dk_label			*label,
14960Sstevel@tonic-gate 	int				ctrl_type)
14970Sstevel@tonic-gate {
14980Sstevel@tonic-gate 	int				i;
14990Sstevel@tonic-gate 	int				ncyls[NDKMAP];
15007563SPrasad.Singamsetty@Sun.COM 	diskaddr_t			nblks;
15010Sstevel@tonic-gate 	int				cyl;
15020Sstevel@tonic-gate 	struct dk_vtoc			*vtoc;
15030Sstevel@tonic-gate 	struct part_table		*pt;
15040Sstevel@tonic-gate 	struct default_partitions	*dpt;
15057563SPrasad.Singamsetty@Sun.COM 	diskaddr_t			capacity;
15060Sstevel@tonic-gate 	int				freecyls;
15070Sstevel@tonic-gate 	int				blks_per_cyl;
15080Sstevel@tonic-gate 	int				ncyl;
15090Sstevel@tonic-gate 
15100Sstevel@tonic-gate #ifdef lint
15110Sstevel@tonic-gate 	ctrl_type = ctrl_type;
15120Sstevel@tonic-gate #endif
15130Sstevel@tonic-gate 
15140Sstevel@tonic-gate 	/*
15150Sstevel@tonic-gate 	 * Install a default vtoc
15160Sstevel@tonic-gate 	 */
15170Sstevel@tonic-gate 	vtoc = &label->dkl_vtoc;
15180Sstevel@tonic-gate 	vtoc->v_version = V_VERSION;
15190Sstevel@tonic-gate 	vtoc->v_nparts = NDKMAP;
15200Sstevel@tonic-gate 	vtoc->v_sanity = VTOC_SANE;
15210Sstevel@tonic-gate 
15220Sstevel@tonic-gate 	for (i = 0; i < NDKMAP; i++) {
15230Sstevel@tonic-gate 		vtoc->v_part[i].p_tag = default_vtoc_map[i].p_tag;
15240Sstevel@tonic-gate 		vtoc->v_part[i].p_flag = default_vtoc_map[i].p_flag;
15250Sstevel@tonic-gate 	}
15260Sstevel@tonic-gate 
15270Sstevel@tonic-gate 	/*
15280Sstevel@tonic-gate 	 * Find a partition that matches this disk.  Capacity
15290Sstevel@tonic-gate 	 * is in integral number of megabytes.
15300Sstevel@tonic-gate 	 */
15317563SPrasad.Singamsetty@Sun.COM 	capacity = ((diskaddr_t)(label->dkl_ncyl) * label->dkl_nhead *
153211350SBo.Zhou@Sun.COM 	    label->dkl_nsect) / (diskaddr_t)((1024 * 1024) / cur_blksz);
15330Sstevel@tonic-gate 	dpt = default_partitions;
15340Sstevel@tonic-gate 	for (i = 0; i < DEFAULT_PARTITION_TABLE_SIZE; i++, dpt++) {
15350Sstevel@tonic-gate 		if (capacity >= dpt->min_capacity &&
15369889SLarry.Liu@Sun.COM 		    capacity < dpt->max_capacity) {
15370Sstevel@tonic-gate 			break;
15380Sstevel@tonic-gate 		}
15390Sstevel@tonic-gate 	}
15400Sstevel@tonic-gate 	if (i == DEFAULT_PARTITION_TABLE_SIZE) {
15410Sstevel@tonic-gate 		if (option_msg && diag_msg) {
15427563SPrasad.Singamsetty@Sun.COM 			err_print("No matching default partition (%llu)\n",
15437563SPrasad.Singamsetty@Sun.COM 			    capacity);
15440Sstevel@tonic-gate 		}
15450Sstevel@tonic-gate 		return (0);
15460Sstevel@tonic-gate 	}
15470Sstevel@tonic-gate 	pt = dpt->part_table;
15480Sstevel@tonic-gate 
15490Sstevel@tonic-gate 	/*
15500Sstevel@tonic-gate 	 * Go through default partition table, finding fixed
15510Sstevel@tonic-gate 	 * sized entries.
15520Sstevel@tonic-gate 	 */
15530Sstevel@tonic-gate 	freecyls = label->dkl_ncyl;
15540Sstevel@tonic-gate 	blks_per_cyl = label->dkl_nhead * label->dkl_nsect;
15550Sstevel@tonic-gate 	for (i = 0; i < NDKMAP; i++) {
15560Sstevel@tonic-gate 		if (pt->partitions[i] == HOG || pt->partitions[i] == 0) {
15570Sstevel@tonic-gate 			ncyls[i] = 0;
15580Sstevel@tonic-gate 		} else {
15590Sstevel@tonic-gate 			/*
15600Sstevel@tonic-gate 			 * Calculate number of cylinders necessary
15610Sstevel@tonic-gate 			 * for specified size, rounding up to
15620Sstevel@tonic-gate 			 * the next greatest integral number of
15630Sstevel@tonic-gate 			 * cylinders.  Always give what they
15640Sstevel@tonic-gate 			 * asked or more, never less.
15650Sstevel@tonic-gate 			 */
15669889SLarry.Liu@Sun.COM 			nblks = pt->partitions[i] * ((1024*1024)/cur_blksz);
15670Sstevel@tonic-gate 			nblks += (blks_per_cyl - 1);
15680Sstevel@tonic-gate 			ncyls[i] = nblks / blks_per_cyl;
15690Sstevel@tonic-gate 			freecyls -= ncyls[i];
15700Sstevel@tonic-gate 		}
15710Sstevel@tonic-gate 	}
15720Sstevel@tonic-gate 
15730Sstevel@tonic-gate 	if (freecyls < 0) {
15740Sstevel@tonic-gate 		if (option_msg && diag_msg) {
15750Sstevel@tonic-gate 			for (i = 0; i < NDKMAP; i++) {
15760Sstevel@tonic-gate 				if (ncyls[i] == 0)
15770Sstevel@tonic-gate 					continue;
15787563SPrasad.Singamsetty@Sun.COM 				err_print("Partition %d: %u cyls\n",
15797563SPrasad.Singamsetty@Sun.COM 				    i, ncyls[i]);
15800Sstevel@tonic-gate 			}
15810Sstevel@tonic-gate 			err_print("Free cylinders exhausted (%d)\n",
15829889SLarry.Liu@Sun.COM 			    freecyls);
15830Sstevel@tonic-gate 		}
15840Sstevel@tonic-gate 		return (0);
15850Sstevel@tonic-gate 	}
15860Sstevel@tonic-gate #if defined(i386)
15870Sstevel@tonic-gate 	/*
15880Sstevel@tonic-gate 	 * Set the default boot partition to 1 cylinder
15890Sstevel@tonic-gate 	 */
15900Sstevel@tonic-gate 	ncyls[8] = 1;
15910Sstevel@tonic-gate 	freecyls -= 1;
15920Sstevel@tonic-gate 
15930Sstevel@tonic-gate 	/*
15940Sstevel@tonic-gate 	 * If current disk type is not a SCSI disk,
15950Sstevel@tonic-gate 	 * set the default alternates partition to 2 cylinders
15960Sstevel@tonic-gate 	 */
15970Sstevel@tonic-gate 	if (ctrl_type != DKC_SCSI_CCS) {
15980Sstevel@tonic-gate 		ncyls[9] = 2;
15990Sstevel@tonic-gate 		freecyls -= 2;
16000Sstevel@tonic-gate 	}
16010Sstevel@tonic-gate #endif			/* defined(i386) */
16020Sstevel@tonic-gate 
16030Sstevel@tonic-gate 	/*
16040Sstevel@tonic-gate 	 * Set the free hog partition to whatever space remains.
16050Sstevel@tonic-gate 	 * It's an error to have more than one HOG partition,
16060Sstevel@tonic-gate 	 * but we don't verify that here.
16070Sstevel@tonic-gate 	 */
16080Sstevel@tonic-gate 	for (i = 0; i < NDKMAP; i++) {
16090Sstevel@tonic-gate 		if (pt->partitions[i] == HOG) {
16100Sstevel@tonic-gate 			assert(ncyls[i] == 0);
16110Sstevel@tonic-gate 			ncyls[i] = freecyls;
16120Sstevel@tonic-gate 			break;
16130Sstevel@tonic-gate 		}
16140Sstevel@tonic-gate 	}
16150Sstevel@tonic-gate 
16160Sstevel@tonic-gate 	/*
16170Sstevel@tonic-gate 	 * Error checking
16180Sstevel@tonic-gate 	 */
16190Sstevel@tonic-gate 	ncyl = 0;
16200Sstevel@tonic-gate 	for (i = 0; i < NDKMAP; i++) {
16210Sstevel@tonic-gate 		ncyl += ncyls[i];
16220Sstevel@tonic-gate 	}
16230Sstevel@tonic-gate 	assert(ncyl == (label->dkl_ncyl));
16240Sstevel@tonic-gate 
16250Sstevel@tonic-gate 	/*
16260Sstevel@tonic-gate 	 * Finally, install the partition in the label.
16270Sstevel@tonic-gate 	 */
16280Sstevel@tonic-gate 	cyl = 0;
16290Sstevel@tonic-gate 
16300Sstevel@tonic-gate #if defined(_SUNOS_VTOC_16)
16310Sstevel@tonic-gate 	for (i = NDKMAP/2; i < NDKMAP; i++) {
16320Sstevel@tonic-gate 		if (i == 2 || ncyls[i] == 0)
16330Sstevel@tonic-gate 			continue;
16340Sstevel@tonic-gate 		label->dkl_vtoc.v_part[i].p_start = cyl * blks_per_cyl;
16350Sstevel@tonic-gate 		label->dkl_vtoc.v_part[i].p_size = ncyls[i] * blks_per_cyl;
16360Sstevel@tonic-gate 		cyl += ncyls[i];
16370Sstevel@tonic-gate 	}
16380Sstevel@tonic-gate 	for (i = 0; i < NDKMAP/2; i++) {
16390Sstevel@tonic-gate 
16400Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_8)
16410Sstevel@tonic-gate 	for (i = 0; i < NDKMAP; i++) {
16420Sstevel@tonic-gate 
16430Sstevel@tonic-gate #else
16440Sstevel@tonic-gate #error No VTOC format defined.
16450Sstevel@tonic-gate #endif				/* defined(_SUNOS_VTOC_16) */
16460Sstevel@tonic-gate 
1647786Slclee 		if (i == 2 || ncyls[i] == 0) {
1648786Slclee #if defined(_SUNOS_VTOC_8)
1649786Slclee 			if (i != 2) {
1650786Slclee 				label->dkl_map[i].dkl_cylno = 0;
1651786Slclee 				label->dkl_map[i].dkl_nblk = 0;
1652786Slclee 			}
1653786Slclee #endif
16540Sstevel@tonic-gate 			continue;
1655786Slclee 		}
16560Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
16570Sstevel@tonic-gate 		label->dkl_map[i].dkl_cylno = cyl;
16580Sstevel@tonic-gate 		label->dkl_map[i].dkl_nblk = ncyls[i] * blks_per_cyl;
16590Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16)
16600Sstevel@tonic-gate 		label->dkl_vtoc.v_part[i].p_start = cyl * blks_per_cyl;
16610Sstevel@tonic-gate 		label->dkl_vtoc.v_part[i].p_size = ncyls[i] * blks_per_cyl;
16620Sstevel@tonic-gate 
16630Sstevel@tonic-gate #else
16640Sstevel@tonic-gate #error No VTOC format defined.
16650Sstevel@tonic-gate #endif				/* defined(_SUNOS_VTOC_8) */
16660Sstevel@tonic-gate 
16670Sstevel@tonic-gate 		cyl += ncyls[i];
16680Sstevel@tonic-gate 	}
16690Sstevel@tonic-gate 
16700Sstevel@tonic-gate 	/*
16710Sstevel@tonic-gate 	 * Set the whole disk partition
16720Sstevel@tonic-gate 	 */
16730Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
16740Sstevel@tonic-gate 	label->dkl_map[2].dkl_cylno = 0;
16750Sstevel@tonic-gate 	label->dkl_map[2].dkl_nblk =
16769889SLarry.Liu@Sun.COM 	    label->dkl_ncyl * label->dkl_nhead * label->dkl_nsect;
16770Sstevel@tonic-gate 
16780Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16)
16790Sstevel@tonic-gate 	label->dkl_vtoc.v_part[2].p_start = 0;
16800Sstevel@tonic-gate 	label->dkl_vtoc.v_part[2].p_size =
16819889SLarry.Liu@Sun.COM 	    (label->dkl_ncyl + label->dkl_acyl) * label->dkl_nhead *
16829889SLarry.Liu@Sun.COM 	    label->dkl_nsect;
16830Sstevel@tonic-gate #else
16840Sstevel@tonic-gate #error No VTOC format defined.
16850Sstevel@tonic-gate #endif				/* defined(_SUNOS_VTOC_8) */
16860Sstevel@tonic-gate 
16870Sstevel@tonic-gate 
16880Sstevel@tonic-gate 	if (option_msg && diag_msg) {
16890Sstevel@tonic-gate 		float	scaled;
16900Sstevel@tonic-gate 		err_print("\n");
16910Sstevel@tonic-gate 		for (i = 0; i < NDKMAP; i++) {
16920Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
16930Sstevel@tonic-gate 			if (label->dkl_map[i].dkl_nblk == 0)
16940Sstevel@tonic-gate 
16950Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16)
16960Sstevel@tonic-gate 			if (label->dkl_vtoc.v_part[i].p_size == 0)
16970Sstevel@tonic-gate 
16980Sstevel@tonic-gate #else
16990Sstevel@tonic-gate #error No VTOC format defined.
17000Sstevel@tonic-gate #endif				/* defined(_SUNOS_VTOC_8) */
17010Sstevel@tonic-gate 
17020Sstevel@tonic-gate 				continue;
17030Sstevel@tonic-gate 			err_print("Partition %d:   ", i);
17040Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
17050Sstevel@tonic-gate 			scaled = bn2mb(label->dkl_map[i].dkl_nblk);
17060Sstevel@tonic-gate 
17070Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16)
17080Sstevel@tonic-gate 
17090Sstevel@tonic-gate 			scaled = bn2mb(label->dkl_vtoc.v_part[i].p_size);
17100Sstevel@tonic-gate #else
17110Sstevel@tonic-gate #error No VTOC format defined.
17120Sstevel@tonic-gate #endif				/* defined(_SUNOS_VTOC_8) */
17130Sstevel@tonic-gate 
17140Sstevel@tonic-gate 			if (scaled > 1024.0) {
17150Sstevel@tonic-gate 				err_print("%6.2fGB  ", scaled/1024.0);
17160Sstevel@tonic-gate 			} else {
17170Sstevel@tonic-gate 				err_print("%6.2fMB  ", scaled);
17180Sstevel@tonic-gate 			}
17199889SLarry.Liu@Sun.COM #if defined(_SUNOS_VTOC_8)
17200Sstevel@tonic-gate 			err_print(" %6d cylinders\n",
17210Sstevel@tonic-gate 			    label->dkl_map[i].dkl_nblk/blks_per_cyl);
17220Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16)
17239889SLarry.Liu@Sun.COM 			err_print(" %6d cylinders\n",
17240Sstevel@tonic-gate 			    label->dkl_vtoc.v_part[i].p_size/blks_per_cyl);
17250Sstevel@tonic-gate #else
17260Sstevel@tonic-gate #error No VTOC format defined.
17270Sstevel@tonic-gate #endif				/* defined(_SUNOS_VTOC_8) */
17280Sstevel@tonic-gate 
17290Sstevel@tonic-gate 		}
17300Sstevel@tonic-gate 		err_print("\n");
17310Sstevel@tonic-gate 	}
17320Sstevel@tonic-gate 
17330Sstevel@tonic-gate 	return (1);
17340Sstevel@tonic-gate }
17350Sstevel@tonic-gate 
17360Sstevel@tonic-gate 
17370Sstevel@tonic-gate 
17380Sstevel@tonic-gate /*
17390Sstevel@tonic-gate  * Find an existing scsi disk definition by this name,
17400Sstevel@tonic-gate  * if possible.
17410Sstevel@tonic-gate  */
17420Sstevel@tonic-gate static struct disk_type *
17430Sstevel@tonic-gate find_scsi_disk_type(
17440Sstevel@tonic-gate 	char			*disk_name,
17450Sstevel@tonic-gate 	struct dk_label		*label)
17460Sstevel@tonic-gate {
17470Sstevel@tonic-gate 	struct ctlr_type	*ctlr;
17480Sstevel@tonic-gate 	struct disk_type	*dp;
17490Sstevel@tonic-gate 
17500Sstevel@tonic-gate 	ctlr = find_scsi_ctlr_type();
17510Sstevel@tonic-gate 	for (dp = ctlr->ctype_dlist; dp != NULL; dp = dp->dtype_next) {
17529889SLarry.Liu@Sun.COM 		if (dp->dtype_asciilabel) {
17539889SLarry.Liu@Sun.COM 			if ((strcmp(dp->dtype_asciilabel, disk_name) == 0) &&
17549889SLarry.Liu@Sun.COM 			    dp->dtype_pcyl == label->dkl_pcyl &&
17559889SLarry.Liu@Sun.COM 			    dp->dtype_ncyl == label->dkl_ncyl &&
17569889SLarry.Liu@Sun.COM 			    dp->dtype_acyl == label->dkl_acyl &&
17579889SLarry.Liu@Sun.COM 			    dp->dtype_nhead == label->dkl_nhead &&
17589889SLarry.Liu@Sun.COM 			    dp->dtype_nsect == label->dkl_nsect) {
17599889SLarry.Liu@Sun.COM 				return (dp);
17609889SLarry.Liu@Sun.COM 			}
17610Sstevel@tonic-gate 		}
17620Sstevel@tonic-gate 	}
17630Sstevel@tonic-gate 
17640Sstevel@tonic-gate 	return ((struct disk_type *)NULL);
17650Sstevel@tonic-gate }
17660Sstevel@tonic-gate 
17670Sstevel@tonic-gate 
17680Sstevel@tonic-gate /*
17690Sstevel@tonic-gate  * Find an existing scsi disk definition by this name,
17700Sstevel@tonic-gate  * if possible.
17710Sstevel@tonic-gate  */
17720Sstevel@tonic-gate static struct disk_type *
17730Sstevel@tonic-gate find_scsi_disk_by_name(
17740Sstevel@tonic-gate 	char			*disk_name)
17750Sstevel@tonic-gate {
17760Sstevel@tonic-gate 	struct ctlr_type	*ctlr;
17770Sstevel@tonic-gate 	struct disk_type	*dp;
17780Sstevel@tonic-gate 
17790Sstevel@tonic-gate 	ctlr = find_scsi_ctlr_type();
17800Sstevel@tonic-gate 	for (dp = ctlr->ctype_dlist; dp != NULL; dp = dp->dtype_next) {
17819889SLarry.Liu@Sun.COM 		if (dp->dtype_asciilabel) {
17829889SLarry.Liu@Sun.COM 			if ((strcmp(dp->dtype_asciilabel, disk_name) == 0)) {
17839889SLarry.Liu@Sun.COM 				return (dp);
17849889SLarry.Liu@Sun.COM 			}
17850Sstevel@tonic-gate 		}
17860Sstevel@tonic-gate 	}
17870Sstevel@tonic-gate 
17880Sstevel@tonic-gate 	return ((struct disk_type *)NULL);
17890Sstevel@tonic-gate }
17900Sstevel@tonic-gate 
17910Sstevel@tonic-gate 
17920Sstevel@tonic-gate /*
17930Sstevel@tonic-gate  * Return a pointer to the ctlr_type structure for SCSI
17940Sstevel@tonic-gate  * disks.  This list is built into the program, so there's
17950Sstevel@tonic-gate  * no chance of not being able to find it, unless someone
17960Sstevel@tonic-gate  * totally mangles the code.
17970Sstevel@tonic-gate  */
17980Sstevel@tonic-gate static struct ctlr_type *
17990Sstevel@tonic-gate find_scsi_ctlr_type()
18000Sstevel@tonic-gate {
18010Sstevel@tonic-gate 	struct	mctlr_list	*mlp;
18020Sstevel@tonic-gate 
18030Sstevel@tonic-gate 	mlp = controlp;
18040Sstevel@tonic-gate 
18050Sstevel@tonic-gate 	while (mlp != NULL) {
18069547SBo.Zhou@Sun.COM 		if (mlp->ctlr_type->ctype_ctype == DKC_SCSI_CCS) {
18070Sstevel@tonic-gate 			return (mlp->ctlr_type);
18080Sstevel@tonic-gate 		}
18097912SBo.Zhou@Sun.COM 		mlp = mlp->next;
18100Sstevel@tonic-gate 	}
18110Sstevel@tonic-gate 
18120Sstevel@tonic-gate 	impossible("no SCSI controller type");
1813362Sbg159949 
1814362Sbg159949 	return ((struct ctlr_type *)NULL);
18150Sstevel@tonic-gate }
18160Sstevel@tonic-gate 
18170Sstevel@tonic-gate 
18180Sstevel@tonic-gate 
18190Sstevel@tonic-gate /*
18200Sstevel@tonic-gate  * Return a pointer to the scsi ctlr_info structure.  This
18210Sstevel@tonic-gate  * structure is allocated the first time format sees a
18220Sstevel@tonic-gate  * disk on this controller, so it must be present.
18230Sstevel@tonic-gate  */
18240Sstevel@tonic-gate static struct ctlr_info *
18250Sstevel@tonic-gate find_scsi_ctlr_info(
18260Sstevel@tonic-gate 	struct dk_cinfo		*dkinfo)
18270Sstevel@tonic-gate {
18280Sstevel@tonic-gate 	struct ctlr_info	*ctlr;
18290Sstevel@tonic-gate 
18309547SBo.Zhou@Sun.COM 	if (dkinfo->dki_ctype != DKC_SCSI_CCS) {
18310Sstevel@tonic-gate 		return (NULL);
18320Sstevel@tonic-gate 	}
18330Sstevel@tonic-gate 
18340Sstevel@tonic-gate 	for (ctlr = ctlr_list; ctlr != NULL; ctlr = ctlr->ctlr_next) {
18350Sstevel@tonic-gate 		if (ctlr->ctlr_addr == dkinfo->dki_addr &&
18367912SBo.Zhou@Sun.COM 		    ctlr->ctlr_space == dkinfo->dki_space &&
18379547SBo.Zhou@Sun.COM 		    ctlr->ctlr_ctype->ctype_ctype == DKC_SCSI_CCS) {
18380Sstevel@tonic-gate 			return (ctlr);
18390Sstevel@tonic-gate 		}
18400Sstevel@tonic-gate 	}
18410Sstevel@tonic-gate 
18420Sstevel@tonic-gate 	impossible("no SCSI controller info");
1843362Sbg159949 
1844362Sbg159949 	return ((struct ctlr_info *)NULL);
18450Sstevel@tonic-gate }
18460Sstevel@tonic-gate 
18470Sstevel@tonic-gate 
18480Sstevel@tonic-gate 
18490Sstevel@tonic-gate static struct disk_type *
18500Sstevel@tonic-gate new_scsi_disk_type(
18510Sstevel@tonic-gate 	int		fd,
18520Sstevel@tonic-gate 	char		*disk_name,
18530Sstevel@tonic-gate 	struct dk_label	*label)
18540Sstevel@tonic-gate {
18550Sstevel@tonic-gate 	struct disk_type	*dp;
18560Sstevel@tonic-gate 	struct disk_type	*disk;
18570Sstevel@tonic-gate 	struct ctlr_info	*ctlr;
18580Sstevel@tonic-gate 	struct dk_cinfo		dkinfo;
18590Sstevel@tonic-gate 	struct partition_info	*part;
18600Sstevel@tonic-gate 	struct partition_info	*pt;
18610Sstevel@tonic-gate 	struct disk_info	*disk_info;
18620Sstevel@tonic-gate 	int			i;
18630Sstevel@tonic-gate 
18640Sstevel@tonic-gate 	/*
18650Sstevel@tonic-gate 	 * Get the disk controller info for this disk
18660Sstevel@tonic-gate 	 */
18670Sstevel@tonic-gate 	if (ioctl(fd, DKIOCINFO, &dkinfo) == -1) {
18680Sstevel@tonic-gate 		if (option_msg && diag_msg) {
18690Sstevel@tonic-gate 			err_print("DKIOCINFO failed\n");
18700Sstevel@tonic-gate 		}
18710Sstevel@tonic-gate 		return (NULL);
18720Sstevel@tonic-gate 	}
18730Sstevel@tonic-gate 
18740Sstevel@tonic-gate 	/*
18750Sstevel@tonic-gate 	 * Find the ctlr_info for this disk.
18760Sstevel@tonic-gate 	 */
18770Sstevel@tonic-gate 	ctlr = find_scsi_ctlr_info(&dkinfo);
18780Sstevel@tonic-gate 
18790Sstevel@tonic-gate 	/*
18800Sstevel@tonic-gate 	 * Allocate a new disk type for the SCSI controller.
18810Sstevel@tonic-gate 	 */
18820Sstevel@tonic-gate 	disk = (struct disk_type *)zalloc(sizeof (struct disk_type));
18830Sstevel@tonic-gate 
18840Sstevel@tonic-gate 	/*
18850Sstevel@tonic-gate 	 * Find the disk_info instance for this disk.
18860Sstevel@tonic-gate 	 */
18870Sstevel@tonic-gate 	disk_info = find_scsi_disk_info(&dkinfo);
18880Sstevel@tonic-gate 
18890Sstevel@tonic-gate 	/*
18900Sstevel@tonic-gate 	 * The controller and the disk should match.
18910Sstevel@tonic-gate 	 */
18920Sstevel@tonic-gate 	assert(disk_info->disk_ctlr == ctlr);
18930Sstevel@tonic-gate 
18940Sstevel@tonic-gate 	/*
18950Sstevel@tonic-gate 	 * Link the disk into the list of disks
18960Sstevel@tonic-gate 	 */
18970Sstevel@tonic-gate 	dp = ctlr->ctlr_ctype->ctype_dlist;
18980Sstevel@tonic-gate 	if (dp == NULL) {
18997563SPrasad.Singamsetty@Sun.COM 		ctlr->ctlr_ctype->ctype_dlist = disk;
19000Sstevel@tonic-gate 	} else {
19010Sstevel@tonic-gate 		while (dp->dtype_next != NULL) {
19020Sstevel@tonic-gate 			dp = dp->dtype_next;
19030Sstevel@tonic-gate 		}
19040Sstevel@tonic-gate 		dp->dtype_next = disk;
19050Sstevel@tonic-gate 	}
19060Sstevel@tonic-gate 	disk->dtype_next = NULL;
19070Sstevel@tonic-gate 
19080Sstevel@tonic-gate 	/*
19090Sstevel@tonic-gate 	 * Allocate and initialize the disk name.
19100Sstevel@tonic-gate 	 */
19110Sstevel@tonic-gate 	disk->dtype_asciilabel = alloc_string(disk_name);
19120Sstevel@tonic-gate 
19130Sstevel@tonic-gate 	/*
19140Sstevel@tonic-gate 	 * Initialize disk geometry info
19150Sstevel@tonic-gate 	 */
19160Sstevel@tonic-gate 	disk->dtype_pcyl = label->dkl_pcyl;
19170Sstevel@tonic-gate 	disk->dtype_ncyl = label->dkl_ncyl;
19180Sstevel@tonic-gate 	disk->dtype_acyl = label->dkl_acyl;
19190Sstevel@tonic-gate 	disk->dtype_nhead = label->dkl_nhead;
19200Sstevel@tonic-gate 	disk->dtype_nsect = label->dkl_nsect;
19210Sstevel@tonic-gate 	disk->dtype_rpm = label->dkl_rpm;
19220Sstevel@tonic-gate 
19230Sstevel@tonic-gate 	/*
19240Sstevel@tonic-gate 	 * Attempt to match the partition map in the label
19250Sstevel@tonic-gate 	 * with a know partition for this disk type.
19260Sstevel@tonic-gate 	 */
19270Sstevel@tonic-gate 	for (part = disk->dtype_plist; part; part = part->pinfo_next) {
19280Sstevel@tonic-gate 		if (parts_match(label, part)) {
19290Sstevel@tonic-gate 			break;
19300Sstevel@tonic-gate 		}
19310Sstevel@tonic-gate 	}
19320Sstevel@tonic-gate 
19330Sstevel@tonic-gate 	/*
19340Sstevel@tonic-gate 	 * If no match was made, we need to create a partition
19350Sstevel@tonic-gate 	 * map for this disk.
19360Sstevel@tonic-gate 	 */
19370Sstevel@tonic-gate 	if (part == NULL) {
19380Sstevel@tonic-gate 		part = (struct partition_info *)
19399889SLarry.Liu@Sun.COM 		    zalloc(sizeof (struct partition_info));
19400Sstevel@tonic-gate 		pt = disk->dtype_plist;
19410Sstevel@tonic-gate 		if (pt == NULL) {
19420Sstevel@tonic-gate 			disk->dtype_plist = part;
19430Sstevel@tonic-gate 		} else {
19440Sstevel@tonic-gate 			while (pt->pinfo_next != NULL) {
19450Sstevel@tonic-gate 				pt = pt->pinfo_next;
19460Sstevel@tonic-gate 			}
19470Sstevel@tonic-gate 			pt->pinfo_next = part;
19480Sstevel@tonic-gate 		}
19490Sstevel@tonic-gate 		part->pinfo_next = NULL;
19500Sstevel@tonic-gate 
19510Sstevel@tonic-gate 		/*
19520Sstevel@tonic-gate 		 * Set up the partition name
19530Sstevel@tonic-gate 		 */
19540Sstevel@tonic-gate 		part->pinfo_name = alloc_string("default");
19550Sstevel@tonic-gate 
19560Sstevel@tonic-gate 		/*
19570Sstevel@tonic-gate 		 * Fill in the partition info from the label
19580Sstevel@tonic-gate 		 */
19590Sstevel@tonic-gate 		for (i = 0; i < NDKMAP; i++) {
19600Sstevel@tonic-gate 
19610Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
19620Sstevel@tonic-gate 			part->pinfo_map[i] = label->dkl_map[i];
19630Sstevel@tonic-gate 
19640Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16)
19650Sstevel@tonic-gate 			part->pinfo_map[i].dkl_cylno =
19669889SLarry.Liu@Sun.COM 			    label->dkl_vtoc.v_part[i].p_start /
19679889SLarry.Liu@Sun.COM 			    ((blkaddr32_t)(disk->dtype_nhead *
19689889SLarry.Liu@Sun.COM 			    disk->dtype_nsect - apc));
19690Sstevel@tonic-gate 			part->pinfo_map[i].dkl_nblk =
19709889SLarry.Liu@Sun.COM 			    label->dkl_vtoc.v_part[i].p_size;
19710Sstevel@tonic-gate #else
19720Sstevel@tonic-gate #error No VTOC format defined.
19730Sstevel@tonic-gate #endif				/* defined(_SUNOS_VTOC_8) */
19740Sstevel@tonic-gate 
19750Sstevel@tonic-gate 		}
19760Sstevel@tonic-gate 	}
19770Sstevel@tonic-gate 
19780Sstevel@tonic-gate 
19790Sstevel@tonic-gate 	/*
19800Sstevel@tonic-gate 	 * Use the VTOC if valid, or install a default
19810Sstevel@tonic-gate 	 */
19820Sstevel@tonic-gate 	if (label->dkl_vtoc.v_version == V_VERSION) {
19830Sstevel@tonic-gate 		(void) memcpy(disk_info->v_volume, label->dkl_vtoc.v_volume,
19849889SLarry.Liu@Sun.COM 		    LEN_DKL_VVOL);
19850Sstevel@tonic-gate 		part->vtoc = label->dkl_vtoc;
19860Sstevel@tonic-gate 	} else {
19870Sstevel@tonic-gate 		(void) memset(disk_info->v_volume, 0, LEN_DKL_VVOL);
19880Sstevel@tonic-gate 		set_vtoc_defaults(part);
19890Sstevel@tonic-gate 	}
19900Sstevel@tonic-gate 
19910Sstevel@tonic-gate 	/*
19920Sstevel@tonic-gate 	 * Link the disk to the partition map
19930Sstevel@tonic-gate 	 */
19940Sstevel@tonic-gate 	disk_info->disk_parts = part;
19950Sstevel@tonic-gate 
19960Sstevel@tonic-gate 	return (disk);
19970Sstevel@tonic-gate }
19980Sstevel@tonic-gate 
19990Sstevel@tonic-gate 
20001524Slh195018 /*
20011524Slh195018  * Delete a disk type from disk type list.
20021524Slh195018  */
20031524Slh195018 int
20041524Slh195018 delete_disk_type(
20051524Slh195018 		struct disk_type *disk_type)
20061524Slh195018 {
20071524Slh195018 	struct ctlr_type	*ctlr;
20081524Slh195018 	struct disk_type	*dp, *disk;
20091524Slh195018 
20101524Slh195018 	if (cur_ctype->ctype_ctype == DKC_DIRECT)
20111524Slh195018 		ctlr = find_direct_ctlr_type();
20129547SBo.Zhou@Sun.COM 	else if (cur_ctype->ctype_ctype == DKC_VBD)
20139547SBo.Zhou@Sun.COM 		ctlr = find_vbd_ctlr_type();
20141524Slh195018 	else
20151524Slh195018 		ctlr = find_scsi_ctlr_type();
20161524Slh195018 	if (ctlr == NULL || ctlr->ctype_dlist == NULL) {
20171524Slh195018 		return (-1);
20181524Slh195018 	}
20191524Slh195018 
20201524Slh195018 	disk = ctlr->ctype_dlist;
20211524Slh195018 	if (disk == disk_type) {
20221524Slh195018 		ctlr->ctype_dlist = disk->dtype_next;
20231524Slh195018 		if (cur_label == L_TYPE_EFI)
20241524Slh195018 			free(disk->dtype_plist->etoc);
20251524Slh195018 		free(disk->dtype_plist);
20261524Slh195018 		free(disk);
20271524Slh195018 		return (0);
20281524Slh195018 	} else {
20291524Slh195018 		for (dp = disk->dtype_next; dp != NULL;
20301524Slh195018 		    disk = disk->dtype_next, dp = dp->dtype_next) {
20311524Slh195018 			if (dp == disk_type) {
20321524Slh195018 				disk->dtype_next = dp->dtype_next;
20331524Slh195018 				if (cur_label == L_TYPE_EFI)
20341524Slh195018 					free(dp->dtype_plist->etoc);
20351524Slh195018 				free(dp->dtype_plist);
20361524Slh195018 				free(dp);
20371524Slh195018 				return (0);
20381524Slh195018 			}
20391524Slh195018 		}
20401524Slh195018 		return (-1);
20411524Slh195018 	}
20421524Slh195018 }
20431524Slh195018 
20441524Slh195018 
20450Sstevel@tonic-gate static struct disk_info *
20460Sstevel@tonic-gate find_scsi_disk_info(
20470Sstevel@tonic-gate 	struct dk_cinfo		*dkinfo)
20480Sstevel@tonic-gate {
20490Sstevel@tonic-gate 	struct disk_info	*disk;
20500Sstevel@tonic-gate 	struct dk_cinfo		*dp;
20510Sstevel@tonic-gate 
20520Sstevel@tonic-gate 	for (disk = disk_list; disk != NULL; disk = disk->disk_next) {
20539547SBo.Zhou@Sun.COM 		assert(dkinfo->dki_ctype == DKC_SCSI_CCS);
20540Sstevel@tonic-gate 		dp = &disk->disk_dkinfo;
20550Sstevel@tonic-gate 		if (dp->dki_ctype == dkinfo->dki_ctype &&
20569547SBo.Zhou@Sun.COM 		    dp->dki_cnum == dkinfo->dki_cnum &&
20579547SBo.Zhou@Sun.COM 		    dp->dki_unit == dkinfo->dki_unit &&
20589547SBo.Zhou@Sun.COM 		    strcmp(dp->dki_dname, dkinfo->dki_dname) == 0) {
20590Sstevel@tonic-gate 			return (disk);
20600Sstevel@tonic-gate 		}
20610Sstevel@tonic-gate 	}
20620Sstevel@tonic-gate 
20630Sstevel@tonic-gate 	impossible("No SCSI disk info instance\n");
2064362Sbg159949 
2065362Sbg159949 	return ((struct disk_info *)NULL);
20660Sstevel@tonic-gate }
20670Sstevel@tonic-gate 
20680Sstevel@tonic-gate 
20690Sstevel@tonic-gate static char *
20700Sstevel@tonic-gate get_sun_disk_name(
20710Sstevel@tonic-gate 	char			*disk_name,
20720Sstevel@tonic-gate 	struct scsi_inquiry	*inquiry)
20730Sstevel@tonic-gate {
20740Sstevel@tonic-gate 	/*
20750Sstevel@tonic-gate 	 * Extract the sun name of the disk
20760Sstevel@tonic-gate 	 */
20770Sstevel@tonic-gate 	(void) memset(disk_name, 0, DISK_NAME_MAX);
20780Sstevel@tonic-gate 	(void) memcpy(disk_name, (char *)&inquiry->inq_pid[9], 7);
20790Sstevel@tonic-gate 
20800Sstevel@tonic-gate 	return (disk_name);
20810Sstevel@tonic-gate }
20820Sstevel@tonic-gate 
20830Sstevel@tonic-gate 
20840Sstevel@tonic-gate static char *
20850Sstevel@tonic-gate get_generic_disk_name(
20860Sstevel@tonic-gate 	char			*disk_name,
20870Sstevel@tonic-gate 	struct scsi_inquiry	*inquiry)
20880Sstevel@tonic-gate {
20890Sstevel@tonic-gate 	char	*p;
20900Sstevel@tonic-gate 
20910Sstevel@tonic-gate 	(void) memset(disk_name, 0, DISK_NAME_MAX);
20920Sstevel@tonic-gate 	p = strcopy(disk_name, inquiry->inq_vid,
20939889SLarry.Liu@Sun.COM 	    sizeof (inquiry->inq_vid));
20940Sstevel@tonic-gate 	*p++ = '-';
20950Sstevel@tonic-gate 	p = strcopy(p, inquiry->inq_pid, sizeof (inquiry->inq_pid));
20960Sstevel@tonic-gate 	*p++ = '-';
20970Sstevel@tonic-gate 	p = strcopy(p, inquiry->inq_revision,
20989889SLarry.Liu@Sun.COM 	    sizeof (inquiry->inq_revision));
20990Sstevel@tonic-gate 
21000Sstevel@tonic-gate 	return (disk_name);
21010Sstevel@tonic-gate }
21020Sstevel@tonic-gate 
21030Sstevel@tonic-gate /*
21040Sstevel@tonic-gate  * Copy a string of characters from src to dst, for at
21050Sstevel@tonic-gate  * most n bytes.  Strip all leading and trailing spaces,
21060Sstevel@tonic-gate  * and stop if there are any non-printable characters.
21070Sstevel@tonic-gate  * Return ptr to the next character to be filled.
21080Sstevel@tonic-gate  */
21090Sstevel@tonic-gate static char *
21100Sstevel@tonic-gate strcopy(
21110Sstevel@tonic-gate 	char	*dst,
21120Sstevel@tonic-gate 	char	*src,
21130Sstevel@tonic-gate 	int	n)
21140Sstevel@tonic-gate {
21150Sstevel@tonic-gate 	int	i;
21160Sstevel@tonic-gate 
21170Sstevel@tonic-gate 	while (*src == ' ' && n > 0) {
21180Sstevel@tonic-gate 		src++;
21190Sstevel@tonic-gate 		n--;
21200Sstevel@tonic-gate 	}
21210Sstevel@tonic-gate 
21220Sstevel@tonic-gate 	for (i = 0; n-- > 0 && isascii(*src) && isprint(*src); src++) {
21230Sstevel@tonic-gate 		if (*src == ' ') {
21240Sstevel@tonic-gate 			i++;
21250Sstevel@tonic-gate 		} else {
21260Sstevel@tonic-gate 			while (i-- > 0)
21270Sstevel@tonic-gate 				*dst++ = ' ';
21280Sstevel@tonic-gate 			*dst++ = *src;
21290Sstevel@tonic-gate 		}
21300Sstevel@tonic-gate 	}
21310Sstevel@tonic-gate 
21320Sstevel@tonic-gate 	*dst = 0;
21330Sstevel@tonic-gate 	return (dst);
21340Sstevel@tonic-gate }
21350Sstevel@tonic-gate 
21360Sstevel@tonic-gate /*
21370Sstevel@tonic-gate  * adjust disk geometry.
21380Sstevel@tonic-gate  * This is used when disk reports a disk geometry page having
21390Sstevel@tonic-gate  * no of physical cylinders is < 3 which is the minimum required
21400Sstevel@tonic-gate  * by Solaris (2 for storing labels and at least one as a data
21410Sstevel@tonic-gate  * cylinder )
21420Sstevel@tonic-gate  */
21430Sstevel@tonic-gate int
21447563SPrasad.Singamsetty@Sun.COM adjust_disk_geometry(diskaddr_t capacity, uint_t *cyl, uint_t *nhead,
21457563SPrasad.Singamsetty@Sun.COM 	uint_t *nsect)
21460Sstevel@tonic-gate {
21477563SPrasad.Singamsetty@Sun.COM 	uint_t	lcyl = *cyl;
21487563SPrasad.Singamsetty@Sun.COM 	uint_t	lnhead = *nhead;
21497563SPrasad.Singamsetty@Sun.COM 	uint_t	lnsect = *nsect;
21500Sstevel@tonic-gate 
21510Sstevel@tonic-gate 	assert(lcyl < SUN_MIN_CYL);
21520Sstevel@tonic-gate 
21530Sstevel@tonic-gate 	/*
21540Sstevel@tonic-gate 	 * reduce nsect by 2 for each iteration  and re-calculate
21550Sstevel@tonic-gate 	 * the number of cylinders.
21560Sstevel@tonic-gate 	 */
21570Sstevel@tonic-gate 	while (lnsect > MINIMUM_NO_SECTORS &&
21585790Sqd208687 	    lcyl < MINIMUM_NO_CYLINDERS) {
21590Sstevel@tonic-gate 		/*
21600Sstevel@tonic-gate 		 * make sure that we do not go below MINIMUM_NO_SECTORS.
21610Sstevel@tonic-gate 		 */
21620Sstevel@tonic-gate 		lnsect = max(MINIMUM_NO_SECTORS, lnsect / 2);
21630Sstevel@tonic-gate 		lcyl   = (capacity) / (lnhead * lnsect);
21640Sstevel@tonic-gate 	}
21650Sstevel@tonic-gate 	/*
21660Sstevel@tonic-gate 	 * If the geometry still does not satisfy
21670Sstevel@tonic-gate 	 * MINIMUM_NO_CYLINDERS then try to reduce the
21680Sstevel@tonic-gate 	 * no of heads.
21690Sstevel@tonic-gate 	 */
21700Sstevel@tonic-gate 	while (lnhead > MINIMUM_NO_HEADS &&
21715790Sqd208687 	    lcyl < MINIMUM_NO_CYLINDERS) {
21720Sstevel@tonic-gate 		lnhead = max(MINIMUM_NO_HEADS, lnhead / 2);
21730Sstevel@tonic-gate 		lcyl =  (capacity) / (lnhead * lnsect);
21740Sstevel@tonic-gate 	}
21750Sstevel@tonic-gate 	/*
21760Sstevel@tonic-gate 	 * now we should have atleast SUN_MIN_CYL cylinders.
21770Sstevel@tonic-gate 	 * If we still do not get SUN_MIN_CYL with MINIMUM_NO_HEADS
21780Sstevel@tonic-gate 	 * and MINIMUM_NO_HEADS then return error.
21790Sstevel@tonic-gate 	 */
21800Sstevel@tonic-gate 	if (lcyl < SUN_MIN_CYL)
21810Sstevel@tonic-gate 		return (1);
21820Sstevel@tonic-gate 	else {
21830Sstevel@tonic-gate 		*cyl = lcyl;
21840Sstevel@tonic-gate 		*nhead = lnhead;
21850Sstevel@tonic-gate 		*nsect = lnsect;
21860Sstevel@tonic-gate 		return (0);
21870Sstevel@tonic-gate 	}
21880Sstevel@tonic-gate }
21890Sstevel@tonic-gate 
21900Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
21910Sstevel@tonic-gate /*
21920Sstevel@tonic-gate  * Reduce the size of one dimention below a specified
21930Sstevel@tonic-gate  * limit with a minimum loss of volume.  Dimenstions are
21940Sstevel@tonic-gate  * assumed to be passed in form the largest value (the one
21950Sstevel@tonic-gate  * that needs to be reduced) to the smallest value.  The
21960Sstevel@tonic-gate  * values will be twiddled until they are all less than or
21970Sstevel@tonic-gate  * equal to their limit.  Returns the number in the new geometry.
21980Sstevel@tonic-gate  */
21997563SPrasad.Singamsetty@Sun.COM static diskaddr_t
22000Sstevel@tonic-gate square_box(
22017563SPrasad.Singamsetty@Sun.COM 		diskaddr_t capacity,
22027563SPrasad.Singamsetty@Sun.COM 		uint_t *dim1, uint_t lim1,
22037563SPrasad.Singamsetty@Sun.COM 		uint_t *dim2, uint_t lim2,
22047563SPrasad.Singamsetty@Sun.COM 		uint_t *dim3, uint_t lim3)
22050Sstevel@tonic-gate {
22067563SPrasad.Singamsetty@Sun.COM 	uint_t	i;
22070Sstevel@tonic-gate 
22080Sstevel@tonic-gate 	/*
22090Sstevel@tonic-gate 	 * Although the routine should work with any ordering of
22100Sstevel@tonic-gate 	 * parameters, it's most efficient if they are passed in
22110Sstevel@tonic-gate 	 * in decreasing magnitude.
22120Sstevel@tonic-gate 	 */
22130Sstevel@tonic-gate 	assert(*dim1 >= *dim2);
22140Sstevel@tonic-gate 	assert(*dim2 >= *dim3);
22150Sstevel@tonic-gate 
22160Sstevel@tonic-gate 	/*
22170Sstevel@tonic-gate 	 * This is done in a very arbitrary manner.  We could try to
22180Sstevel@tonic-gate 	 * find better values but I can't come up with a method that
22190Sstevel@tonic-gate 	 * would run in a reasonable amount of time.  That could take
22200Sstevel@tonic-gate 	 * approximately 65535 * 65535 iterations of a dozen flops each
22210Sstevel@tonic-gate 	 * or well over 4G flops.
22220Sstevel@tonic-gate 	 *
22230Sstevel@tonic-gate 	 * First:
22240Sstevel@tonic-gate 	 *
22250Sstevel@tonic-gate 	 * Let's see how far we can go with bitshifts w/o losing
22260Sstevel@tonic-gate 	 * any blocks.
22270Sstevel@tonic-gate 	 */
22280Sstevel@tonic-gate 
22299889SLarry.Liu@Sun.COM 	for (i = 0; (((*dim1)>>i)&1) == 0 && ((*dim1)>>i) > lim1; i++)
22309889SLarry.Liu@Sun.COM 		;
22310Sstevel@tonic-gate 	if (i) {
22320Sstevel@tonic-gate 		*dim1 = ((*dim1)>>i);
22330Sstevel@tonic-gate 		*dim3 = ((*dim3)<<i);
22340Sstevel@tonic-gate 	}
22350Sstevel@tonic-gate 
22360Sstevel@tonic-gate 	if (((*dim1) > lim1) || ((*dim2) > lim2) || ((*dim3) > lim3)) {
22370Sstevel@tonic-gate 		double 	d[4];
22380Sstevel@tonic-gate 
22390Sstevel@tonic-gate 		/*
22400Sstevel@tonic-gate 		 * Second:
22410Sstevel@tonic-gate 		 *
22420Sstevel@tonic-gate 		 * Set the highest value at its limit then calculate errors,
22430Sstevel@tonic-gate 		 * adjusting the 2nd highest value (we get better resolution
22440Sstevel@tonic-gate 		 * that way).
22450Sstevel@tonic-gate 		 */
22460Sstevel@tonic-gate 		d[1] = lim1;
22470Sstevel@tonic-gate 		d[3] = *dim3;
22480Sstevel@tonic-gate 		d[2] = (double)capacity/(d[1]*d[3]);
22490Sstevel@tonic-gate 
22500Sstevel@tonic-gate 		/*
22510Sstevel@tonic-gate 		 * If we overflowed the middle term, set it to its limit and
22520Sstevel@tonic-gate 		 * chose a new low term.
22530Sstevel@tonic-gate 		 */
22540Sstevel@tonic-gate 		if (d[2] > lim2) {
22550Sstevel@tonic-gate 			d[2] = lim2;
22560Sstevel@tonic-gate 			d[3] = (double)capacity/(d[1]*d[2]);
22570Sstevel@tonic-gate 		}
22580Sstevel@tonic-gate 		/*
22590Sstevel@tonic-gate 		 * Convert to integers.
22600Sstevel@tonic-gate 		 */
22610Sstevel@tonic-gate 		*dim1 = (int)d[1];
22620Sstevel@tonic-gate 		*dim2 = (int)d[2];
22630Sstevel@tonic-gate 		*dim3 = (int)d[3];
22640Sstevel@tonic-gate 	}
22650Sstevel@tonic-gate 	/*
22660Sstevel@tonic-gate 	 * Fixup any other possible problems.
22670Sstevel@tonic-gate 	 * If this happens, we need a new disklabel format.
22680Sstevel@tonic-gate 	 */
22690Sstevel@tonic-gate 	if (*dim1 > lim1) *dim1 = lim1;
22700Sstevel@tonic-gate 	if (*dim2 > lim2) *dim2 = lim2;
22710Sstevel@tonic-gate 	if (*dim3 > lim3) *dim3 = lim3;
22720Sstevel@tonic-gate 	return (*dim1 * *dim2 * *dim3);
22730Sstevel@tonic-gate }
22740Sstevel@tonic-gate #endif /* defined(_SUNOS_VTOC_8) */
22757563SPrasad.Singamsetty@Sun.COM 
22767563SPrasad.Singamsetty@Sun.COM /*
22777563SPrasad.Singamsetty@Sun.COM  * Calculate CHS values based on the capacity data.
22787563SPrasad.Singamsetty@Sun.COM  *
22797563SPrasad.Singamsetty@Sun.COM  * NOTE: This function is same as cmlb_convert_geomerty() function in
22807563SPrasad.Singamsetty@Sun.COM  * cmlb kernel module.
22817563SPrasad.Singamsetty@Sun.COM  */
22827563SPrasad.Singamsetty@Sun.COM static void
22837563SPrasad.Singamsetty@Sun.COM compute_chs_values(diskaddr_t total_capacity, diskaddr_t usable_capacity,
22847563SPrasad.Singamsetty@Sun.COM 	uint_t *pcylp, uint_t *nheadp, uint_t *nsectp)
22857563SPrasad.Singamsetty@Sun.COM {
22867563SPrasad.Singamsetty@Sun.COM 
22877563SPrasad.Singamsetty@Sun.COM 	/* Unlabeled SCSI floppy device */
228811748SShidokht.Yadegari@Sun.COM 	if (total_capacity < 160) {
228911748SShidokht.Yadegari@Sun.COM 		/* Less than 80K */
229011748SShidokht.Yadegari@Sun.COM 		*nheadp = 1;
229111748SShidokht.Yadegari@Sun.COM 		*pcylp = total_capacity;
229211748SShidokht.Yadegari@Sun.COM 		*nsectp = 1;
229311748SShidokht.Yadegari@Sun.COM 		return;
229411748SShidokht.Yadegari@Sun.COM 	} else if (total_capacity <= 0x1000) {
22957563SPrasad.Singamsetty@Sun.COM 		*nheadp = 2;
22967563SPrasad.Singamsetty@Sun.COM 		*pcylp = 80;
22977563SPrasad.Singamsetty@Sun.COM 		*nsectp = total_capacity / (80 * 2);
22987563SPrasad.Singamsetty@Sun.COM 		return;
22997563SPrasad.Singamsetty@Sun.COM 	}
23007563SPrasad.Singamsetty@Sun.COM 
23017563SPrasad.Singamsetty@Sun.COM 	/*
23027563SPrasad.Singamsetty@Sun.COM 	 * For all devices we calculate cylinders using the heads and sectors
23037563SPrasad.Singamsetty@Sun.COM 	 * we assign based on capacity of the device.  The algorithm is
23047563SPrasad.Singamsetty@Sun.COM 	 * designed to be compatible with the way other operating systems
23057563SPrasad.Singamsetty@Sun.COM 	 * lay out fdisk tables for X86 and to insure that the cylinders never
23067563SPrasad.Singamsetty@Sun.COM 	 * exceed 65535 to prevent problems with X86 ioctls that report
23077563SPrasad.Singamsetty@Sun.COM 	 * geometry.
23087563SPrasad.Singamsetty@Sun.COM 	 * For some smaller disk sizes we report geometry that matches those
23097563SPrasad.Singamsetty@Sun.COM 	 * used by X86 BIOS usage. For larger disks, we use SPT that are
23107563SPrasad.Singamsetty@Sun.COM 	 * multiples of 63, since other OSes that are not limited to 16-bits
23117563SPrasad.Singamsetty@Sun.COM 	 * for cylinders stop at 63 SPT we make do by using multiples of 63 SPT.
23127563SPrasad.Singamsetty@Sun.COM 	 *
23137563SPrasad.Singamsetty@Sun.COM 	 * The following table (in order) illustrates some end result
23147563SPrasad.Singamsetty@Sun.COM 	 * calculations:
23157563SPrasad.Singamsetty@Sun.COM 	 *
23167563SPrasad.Singamsetty@Sun.COM 	 * Maximum number of blocks 		nhead	nsect
23177563SPrasad.Singamsetty@Sun.COM 	 *
23187563SPrasad.Singamsetty@Sun.COM 	 * 2097152 (1GB)			64	32
23197563SPrasad.Singamsetty@Sun.COM 	 * 16777216 (8GB)			128	32
23207563SPrasad.Singamsetty@Sun.COM 	 * 1052819775 (502.02GB)		255  	63
23217563SPrasad.Singamsetty@Sun.COM 	 * 2105639550 (0.98TB)			255	126
23227563SPrasad.Singamsetty@Sun.COM 	 * 3158459325 (1.47TB)			255  	189
23237563SPrasad.Singamsetty@Sun.COM 	 * 4211279100 (1.96TB)			255  	252
23247563SPrasad.Singamsetty@Sun.COM 	 * 5264098875 (2.45TB)			255  	315
23257563SPrasad.Singamsetty@Sun.COM 	 * ...
23267563SPrasad.Singamsetty@Sun.COM 	 */
23277563SPrasad.Singamsetty@Sun.COM 
23287563SPrasad.Singamsetty@Sun.COM 	if (total_capacity <= 0x200000) {
23297563SPrasad.Singamsetty@Sun.COM 		*nheadp = 64;
23307563SPrasad.Singamsetty@Sun.COM 		*nsectp = 32;
23317563SPrasad.Singamsetty@Sun.COM 	} else if (total_capacity <= 0x01000000) {
23327563SPrasad.Singamsetty@Sun.COM 		*nheadp = 128;
23337563SPrasad.Singamsetty@Sun.COM 		*nsectp = 32;
23347563SPrasad.Singamsetty@Sun.COM 	} else {
23357563SPrasad.Singamsetty@Sun.COM 		*nheadp = 255;
23367563SPrasad.Singamsetty@Sun.COM 
23377563SPrasad.Singamsetty@Sun.COM 		/* make nsect be smallest multiple of 63 */
23387563SPrasad.Singamsetty@Sun.COM 		*nsectp = ((total_capacity +
23397563SPrasad.Singamsetty@Sun.COM 		    (UINT16_MAX * 255 * 63) - 1) /
23407563SPrasad.Singamsetty@Sun.COM 		    (UINT16_MAX * 255 * 63)) * 63;
23417563SPrasad.Singamsetty@Sun.COM 
23427563SPrasad.Singamsetty@Sun.COM 		if (*nsectp == 0)
23437563SPrasad.Singamsetty@Sun.COM 			*nsectp = (UINT16_MAX / 63) * 63;
23447563SPrasad.Singamsetty@Sun.COM 	}
23457563SPrasad.Singamsetty@Sun.COM 
23467563SPrasad.Singamsetty@Sun.COM 	if (usable_capacity < total_capacity)
23477563SPrasad.Singamsetty@Sun.COM 		*pcylp = usable_capacity / ((*nheadp) * (*nsectp));
23487563SPrasad.Singamsetty@Sun.COM 	else
23497563SPrasad.Singamsetty@Sun.COM 		*pcylp = total_capacity / ((*nheadp) * (*nsectp));
23507563SPrasad.Singamsetty@Sun.COM }
2351