xref: /illumos-gate/usr/src/cmd/format/auto_sense.c (revision dcc43656)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5698107ecSlh  * Common Development and Distribution License (the "License").
6698107ecSlh  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
221662a2f2SGary Mills  * Copyright (c) 2011 Gary Mills
231662a2f2SGary Mills  *
24b63e7ecbSAbhinandan Ekande  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
257c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
26f1bf0656SHans Rosenfeld  * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
272f15e7adSIgor Kozhukhov  * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
287c478bd9Sstevel@tonic-gate  */
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate /*
317c478bd9Sstevel@tonic-gate  * This file contains functions to implement automatic configuration
327c478bd9Sstevel@tonic-gate  * of scsi disks.
337c478bd9Sstevel@tonic-gate  */
347c478bd9Sstevel@tonic-gate #include "global.h"
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate #include <fcntl.h>
377c478bd9Sstevel@tonic-gate #include <stdlib.h>
387c478bd9Sstevel@tonic-gate #include <string.h>
397c478bd9Sstevel@tonic-gate #include <strings.h>
407c478bd9Sstevel@tonic-gate #include <stdlib.h>
417c478bd9Sstevel@tonic-gate #include <ctype.h>
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate #include "misc.h"
447c478bd9Sstevel@tonic-gate #include "param.h"
457c478bd9Sstevel@tonic-gate #include "ctlr_scsi.h"
467c478bd9Sstevel@tonic-gate #include "auto_sense.h"
477c478bd9Sstevel@tonic-gate #include "partition.h"
487c478bd9Sstevel@tonic-gate #include "label.h"
497c478bd9Sstevel@tonic-gate #include "startup.h"
507c478bd9Sstevel@tonic-gate #include "analyze.h"
517c478bd9Sstevel@tonic-gate #include "io.h"
527c478bd9Sstevel@tonic-gate #include "hardware_structs.h"
537c478bd9Sstevel@tonic-gate #include "menu_fdisk.h"
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate #define	DISK_NAME_MAX		256
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate extern	int			nctypes;
597c478bd9Sstevel@tonic-gate extern	struct	ctlr_type	ctlr_types[];
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate /*
637c478bd9Sstevel@tonic-gate  * Marker for free hog partition
647c478bd9Sstevel@tonic-gate  */
657c478bd9Sstevel@tonic-gate #define	HOG		(-1)
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate /*
707c478bd9Sstevel@tonic-gate  * Default partition tables
717c478bd9Sstevel@tonic-gate  *
727c478bd9Sstevel@tonic-gate  *	Disk capacity		root	swap	usr
737c478bd9Sstevel@tonic-gate  *	-------------		----	----	---
747c478bd9Sstevel@tonic-gate  *	0mb to 64mb		0	0	remainder
757c478bd9Sstevel@tonic-gate  *	64mb to 180mb		16mb	16mb	remainder
767c478bd9Sstevel@tonic-gate  *	180mb to 280mb		16mb	32mb	remainder
777c478bd9Sstevel@tonic-gate  *	280mb to 380mb		24mb	32mb	remainder
787c478bd9Sstevel@tonic-gate  *	380mb to 600mb		32mb	32mb	remainder
797c478bd9Sstevel@tonic-gate  *	600mb to 1gb		32mb	64mb	remainder
807c478bd9Sstevel@tonic-gate  *	1gb to 2gb		64mb	128mb	remainder
817c478bd9Sstevel@tonic-gate  *	2gb on up		128mb	128mb	remainder
827c478bd9Sstevel@tonic-gate  */
837c478bd9Sstevel@tonic-gate struct part_table {
847c478bd9Sstevel@tonic-gate 	int	partitions[NDKMAP];
857c478bd9Sstevel@tonic-gate };
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate static struct part_table part_table_64mb = {
887c478bd9Sstevel@tonic-gate 	{ 0,	0,	0,	0,	0,	0,	HOG,	0}
897c478bd9Sstevel@tonic-gate };
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate static struct part_table part_table_180mb = {
927c478bd9Sstevel@tonic-gate 	{ 16,	16,	0,	0,	0,	0,	HOG,	0}
937c478bd9Sstevel@tonic-gate };
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate static struct part_table part_table_280mb = {
967c478bd9Sstevel@tonic-gate 	{ 16,	32,	0,	0,	0,	0,	HOG,	0}
977c478bd9Sstevel@tonic-gate };
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate static struct part_table part_table_380mb = {
1007c478bd9Sstevel@tonic-gate 	{ 24,	32,	0,	0,	0,	0,	HOG,	0}
1017c478bd9Sstevel@tonic-gate };
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate static struct part_table part_table_600mb = {
1047c478bd9Sstevel@tonic-gate 	{ 32,	32,	0,	0,	0,	0,	HOG,	0}
1057c478bd9Sstevel@tonic-gate };
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate static struct part_table part_table_1gb = {
1087c478bd9Sstevel@tonic-gate 	{ 32,	64,	0,	0,	0,	0,	HOG,	0}
1097c478bd9Sstevel@tonic-gate };
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate static struct part_table part_table_2gb = {
1127c478bd9Sstevel@tonic-gate 	{ 64,	128,	0,	0,	0,	0,	HOG,	0}
1137c478bd9Sstevel@tonic-gate };
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate static struct part_table part_table_infinity = {
1167c478bd9Sstevel@tonic-gate 	{ 128,	128,	0,	0,	0,	0,	HOG,	0}
1177c478bd9Sstevel@tonic-gate };
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate 
1207c478bd9Sstevel@tonic-gate static struct default_partitions {
121342440ecSPrasad Singamsetty 	diskaddr_t		min_capacity;
122342440ecSPrasad Singamsetty 	diskaddr_t		max_capacity;
1237c478bd9Sstevel@tonic-gate 	struct part_table	*part_table;
1247c478bd9Sstevel@tonic-gate } default_partitions[] = {
1257c478bd9Sstevel@tonic-gate 	{ 0,	64,		&part_table_64mb },	/* 0 to 64 mb */
1267c478bd9Sstevel@tonic-gate 	{ 64,	180,		&part_table_180mb },	/* 64 to 180 mb */
1277c478bd9Sstevel@tonic-gate 	{ 180,	280,		&part_table_280mb },	/* 180 to 280 mb */
1287c478bd9Sstevel@tonic-gate 	{ 280,	380,		&part_table_380mb },	/* 280 to 380 mb */
1297c478bd9Sstevel@tonic-gate 	{ 380,	600,		&part_table_600mb },	/* 380 to 600 mb */
1307c478bd9Sstevel@tonic-gate 	{ 600,	1024,		&part_table_1gb },	/* 600 to 1 gb */
1317c478bd9Sstevel@tonic-gate 	{ 1024,	2048,		&part_table_2gb },	/* 1 to 2 gb */
1327c478bd9Sstevel@tonic-gate 	{ 2048,	INFINITY,	&part_table_infinity },	/* 2 gb on up */
1337c478bd9Sstevel@tonic-gate };
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate #define	DEFAULT_PARTITION_TABLE_SIZE	\
1367c478bd9Sstevel@tonic-gate 	(sizeof (default_partitions) / sizeof (struct default_partitions))
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate /*
1397c478bd9Sstevel@tonic-gate  * msgs for check()
1407c478bd9Sstevel@tonic-gate  */
1417c478bd9Sstevel@tonic-gate #define	FORMAT_MSG	"Auto configuration via format.dat"
1427c478bd9Sstevel@tonic-gate #define	GENERIC_MSG	"Auto configuration via generic SCSI-2"
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate /*
1457c478bd9Sstevel@tonic-gate  * Disks on symbios(Hardwire raid controller) return a fixed number
1467c478bd9Sstevel@tonic-gate  * of heads(64)/cylinders(64) and adjust the cylinders depending
1477c478bd9Sstevel@tonic-gate  * capacity of the configured lun.
1487c478bd9Sstevel@tonic-gate  * In such a case we get number of physical cylinders < 3 which
1497c478bd9Sstevel@tonic-gate  * is the minimum required by solaris(2 reserved + 1 data cylinders).
1507c478bd9Sstevel@tonic-gate  * Hence try to adjust the cylinders by reducing the "nsect/nhead".
1517c478bd9Sstevel@tonic-gate  *
1527c478bd9Sstevel@tonic-gate  */
1537c478bd9Sstevel@tonic-gate /*
1547c478bd9Sstevel@tonic-gate  * assuming a minimum of 32 block cylinders.
1557c478bd9Sstevel@tonic-gate  */
1567c478bd9Sstevel@tonic-gate #define	MINIMUM_NO_HEADS	2
1577c478bd9Sstevel@tonic-gate #define	MINIMUM_NO_SECTORS	16
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate #define	MINIMUM_NO_CYLINDERS	128
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate /* These are 16-bit fields */
1647c478bd9Sstevel@tonic-gate #define	MAXIMUM_NO_HEADS	65535
1657c478bd9Sstevel@tonic-gate #define	MAXIMUM_NO_SECTORS	65535
1667c478bd9Sstevel@tonic-gate #define	MAXIMUM_NO_CYLINDERS	65535
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate #endif	/* defined(_SUNOS_VTOC_8) */
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate /*
1717c478bd9Sstevel@tonic-gate  * minimum number of cylinders required by Solaris.
1727c478bd9Sstevel@tonic-gate  */
1737c478bd9Sstevel@tonic-gate #define	SUN_MIN_CYL		3
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate static struct disk_type	*generic_disk_sense(
1767c478bd9Sstevel@tonic-gate 				int		fd,
1777c478bd9Sstevel@tonic-gate 				int		can_prompt,
1787c478bd9Sstevel@tonic-gate 				struct dk_label	*label,
1797c478bd9Sstevel@tonic-gate 				struct scsi_inquiry *inquiry,
1807c478bd9Sstevel@tonic-gate 				struct scsi_capacity_16 *capacity,
1817c478bd9Sstevel@tonic-gate 				char		*disk_name);
1827c478bd9Sstevel@tonic-gate static int		use_existing_disk_type(
1837c478bd9Sstevel@tonic-gate 				int		fd,
1847c478bd9Sstevel@tonic-gate 				int		can_prompt,
1857c478bd9Sstevel@tonic-gate 				struct dk_label	*label,
1867c478bd9Sstevel@tonic-gate 				struct scsi_inquiry *inquiry,
1877c478bd9Sstevel@tonic-gate 				struct disk_type *disk_type,
1887c478bd9Sstevel@tonic-gate 				struct scsi_capacity_16 *capacity);
1897c478bd9Sstevel@tonic-gate int			build_default_partition(struct dk_label *label,
1907c478bd9Sstevel@tonic-gate 				int ctrl_type);
1917c478bd9Sstevel@tonic-gate static struct disk_type	*find_scsi_disk_type(
1927c478bd9Sstevel@tonic-gate 				char		*disk_name,
1937c478bd9Sstevel@tonic-gate 				struct dk_label	*label);
1947c478bd9Sstevel@tonic-gate static struct disk_type	*find_scsi_disk_by_name(
1957c478bd9Sstevel@tonic-gate 				char		*disk_name);
1967c478bd9Sstevel@tonic-gate static struct ctlr_type	*find_scsi_ctlr_type(void);
1977c478bd9Sstevel@tonic-gate static struct ctlr_info	*find_scsi_ctlr_info(
1987c478bd9Sstevel@tonic-gate 				struct dk_cinfo	*dkinfo);
1997c478bd9Sstevel@tonic-gate static struct disk_type	*new_scsi_disk_type(
2007c478bd9Sstevel@tonic-gate 				int		fd,
2017c478bd9Sstevel@tonic-gate 				char		*disk_name,
2027c478bd9Sstevel@tonic-gate 				struct dk_label	*label);
2037c478bd9Sstevel@tonic-gate static struct disk_info	*find_scsi_disk_info(
2047c478bd9Sstevel@tonic-gate 				struct dk_cinfo	*dkinfo);
2053ccda647Slclee 
2063ccda647Slclee static struct disk_type *new_direct_disk_type(int fd, char *disk_name,
2073ccda647Slclee     struct dk_label *label);
2083ccda647Slclee 
2093ccda647Slclee static int efi_ioctl(int fd, int cmd, dk_efi_t *dk_ioc);
2103ccda647Slclee static int auto_label_init(struct dk_label *label);
2112f15e7adSIgor Kozhukhov static struct ctlr_type *find_ctlr_type(ushort_t);
2122f15e7adSIgor Kozhukhov static struct ctlr_info *find_ctlr_info(struct dk_cinfo	*, ushort_t);
2132f15e7adSIgor Kozhukhov static struct disk_info *find_disk_info(struct dk_cinfo *, ushort_t);
2143ccda647Slclee 
2157c478bd9Sstevel@tonic-gate static char		*get_sun_disk_name(
2167c478bd9Sstevel@tonic-gate 				char		*disk_name,
2177c478bd9Sstevel@tonic-gate 				struct scsi_inquiry *inquiry);
2187c478bd9Sstevel@tonic-gate static char		*strcopy(
2197c478bd9Sstevel@tonic-gate 				char	*dst,
2207c478bd9Sstevel@tonic-gate 				char	*src,
2217c478bd9Sstevel@tonic-gate 				int	n);
222342440ecSPrasad Singamsetty static	int		adjust_disk_geometry(diskaddr_t capacity, uint_t *cyl,
223342440ecSPrasad Singamsetty 				uint_t *nsect, uint_t *nhead);
22432a71e42SToomas Soome static void		compute_chs_values(diskaddr_t total_capacity,
225342440ecSPrasad Singamsetty 				diskaddr_t usable_capacity, uint_t *pcylp,
226342440ecSPrasad Singamsetty 				uint_t *nheadp, uint_t *nsectp);
2277c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
228342440ecSPrasad Singamsetty static diskaddr_t square_box(
229342440ecSPrasad Singamsetty 			diskaddr_t capacity,
230342440ecSPrasad Singamsetty 			uint_t *dim1, uint_t lim1,
231342440ecSPrasad Singamsetty 			uint_t *dim2, uint_t lim2,
232342440ecSPrasad Singamsetty 			uint_t *dim3, uint_t lim3);
2337c478bd9Sstevel@tonic-gate #endif	/* defined(_SUNOS_VTOC_8) */
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate /*
2377c478bd9Sstevel@tonic-gate  * We need to get information necessary to construct a *new* efi
2387c478bd9Sstevel@tonic-gate  * label type
2397c478bd9Sstevel@tonic-gate  */
2407c478bd9Sstevel@tonic-gate struct disk_type *
auto_efi_sense(int fd,struct efi_info * label)2417c478bd9Sstevel@tonic-gate auto_efi_sense(int fd, struct efi_info *label)
2427c478bd9Sstevel@tonic-gate {
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate 	struct dk_gpt	*vtoc;
2457c478bd9Sstevel@tonic-gate 	int		i;
2467c478bd9Sstevel@tonic-gate 
2477c478bd9Sstevel@tonic-gate 	struct disk_type *disk, *dp;
2487c478bd9Sstevel@tonic-gate 	struct disk_info *disk_info;
2497c478bd9Sstevel@tonic-gate 	struct ctlr_info *ctlr;
2507c478bd9Sstevel@tonic-gate 	struct dk_cinfo dkinfo;
2517c478bd9Sstevel@tonic-gate 	struct partition_info *part;
25232a71e42SToomas Soome 	uint64_t reserved;
253*dcc43656SToomas Soome 	uint16_t type;
2547c478bd9Sstevel@tonic-gate 
255f1bf0656SHans Rosenfeld 	if (ioctl(fd, DKIOCINFO, &dkinfo) == -1) {
256f1bf0656SHans Rosenfeld 		if (option_msg && diag_msg) {
257f1bf0656SHans Rosenfeld 			err_print("DKIOCINFO failed\n");
258f1bf0656SHans Rosenfeld 		}
259f1bf0656SHans Rosenfeld 		return (NULL);
260f1bf0656SHans Rosenfeld 	}
261*dcc43656SToomas Soome 	if (cur_ctype != NULL)
262*dcc43656SToomas Soome 		type = cur_ctype->ctype_ctype;
263*dcc43656SToomas Soome 	else
264*dcc43656SToomas Soome 		type = dkinfo.dki_ctype;
265*dcc43656SToomas Soome 
266*dcc43656SToomas Soome 	if (type == DKC_DIRECT || type == DKC_VBD || type == DKC_BLKDEV) {
267*dcc43656SToomas Soome 		ctlr = find_ctlr_info(&dkinfo, type);
268*dcc43656SToomas Soome 		disk_info = find_disk_info(&dkinfo, type);
269f1bf0656SHans Rosenfeld 	} else {
270f1bf0656SHans Rosenfeld 		ctlr = find_scsi_ctlr_info(&dkinfo);
271f1bf0656SHans Rosenfeld 		disk_info = find_scsi_disk_info(&dkinfo);
272f1bf0656SHans Rosenfeld 	}
273f1bf0656SHans Rosenfeld 
2747c478bd9Sstevel@tonic-gate 	/*
2757c478bd9Sstevel@tonic-gate 	 * get vendor, product, revision and capacity info.
2767c478bd9Sstevel@tonic-gate 	 */
277f1bf0656SHans Rosenfeld 	if (get_disk_info(fd, label, disk_info) == -1) {
278b12aaafbSToomas Soome 		return (NULL);
2797c478bd9Sstevel@tonic-gate 	}
2807c478bd9Sstevel@tonic-gate 	/*
2817c478bd9Sstevel@tonic-gate 	 * Now build the default partition table
2827c478bd9Sstevel@tonic-gate 	 */
2837c478bd9Sstevel@tonic-gate 	if (efi_alloc_and_init(fd, EFI_NUMPAR, &vtoc) != 0) {
2847c478bd9Sstevel@tonic-gate 		err_print("efi_alloc_and_init failed. \n");
285b12aaafbSToomas Soome 		return (NULL);
2867c478bd9Sstevel@tonic-gate 	}
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate 	label->e_parts = vtoc;
28932a71e42SToomas Soome 	reserved = efi_reserved_sectors(vtoc);
2907c478bd9Sstevel@tonic-gate 
2911cce8a3fSyl 	/*
2921cce8a3fSyl 	 * Create a whole hog EFI partition table:
2931cce8a3fSyl 	 * S0 takes the whole disk except the primary EFI label,
2941cce8a3fSyl 	 * backup EFI label, and the reserved partition.
2951cce8a3fSyl 	 */
2961cce8a3fSyl 	vtoc->efi_parts[0].p_tag = V_USR;
2971cce8a3fSyl 	vtoc->efi_parts[0].p_start = vtoc->efi_first_u_lba;
2981cce8a3fSyl 	vtoc->efi_parts[0].p_size = vtoc->efi_last_u_lba - vtoc->efi_first_u_lba
29932a71e42SToomas Soome 	    - reserved + 1;
3001cce8a3fSyl 
3011cce8a3fSyl 	/*
3021cce8a3fSyl 	 * S1-S6 are unassigned slices.
3031cce8a3fSyl 	 */
3041cce8a3fSyl 	for (i = 1; i < vtoc->efi_nparts - 2; i ++) {
3051cce8a3fSyl 		vtoc->efi_parts[i].p_tag = V_UNASSIGNED;
3067c478bd9Sstevel@tonic-gate 		vtoc->efi_parts[i].p_start = 0;
3077c478bd9Sstevel@tonic-gate 		vtoc->efi_parts[i].p_size = 0;
3087c478bd9Sstevel@tonic-gate 	}
3091cce8a3fSyl 
3107c478bd9Sstevel@tonic-gate 	/*
3111cce8a3fSyl 	 * The reserved slice
3127c478bd9Sstevel@tonic-gate 	 */
3131cce8a3fSyl 	vtoc->efi_parts[vtoc->efi_nparts - 1].p_tag = V_RESERVED;
3141cce8a3fSyl 	vtoc->efi_parts[vtoc->efi_nparts - 1].p_start =
31532a71e42SToomas Soome 	    vtoc->efi_last_u_lba - reserved + 1;
31632a71e42SToomas Soome 	vtoc->efi_parts[vtoc->efi_nparts - 1].p_size = reserved;
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate 	/*
3197c478bd9Sstevel@tonic-gate 	 * Now stick all of it into the disk_type struct
3207c478bd9Sstevel@tonic-gate 	 */
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate 	disk = (struct disk_type *)zalloc(sizeof (struct disk_type));
3237c478bd9Sstevel@tonic-gate 	assert(disk_info->disk_ctlr == ctlr);
3247c478bd9Sstevel@tonic-gate 	dp = ctlr->ctlr_ctype->ctype_dlist;
3257c478bd9Sstevel@tonic-gate 	if (dp == NULL) {
3267c478bd9Sstevel@tonic-gate 		ctlr->ctlr_ctype->ctype_dlist = dp;
3277c478bd9Sstevel@tonic-gate 	} else {
3287c478bd9Sstevel@tonic-gate 		while (dp->dtype_next != NULL) {
3297c478bd9Sstevel@tonic-gate 			dp = dp->dtype_next;
3307c478bd9Sstevel@tonic-gate 		}
3317c478bd9Sstevel@tonic-gate 		dp->dtype_next = disk;
3327c478bd9Sstevel@tonic-gate 	}
3337c478bd9Sstevel@tonic-gate 	disk->dtype_next = NULL;
3347c478bd9Sstevel@tonic-gate 
335f1bf0656SHans Rosenfeld 	disk->vendor = strdup(label->vendor);
336f1bf0656SHans Rosenfeld 	disk->product = strdup(label->product);
337f1bf0656SHans Rosenfeld 	disk->revision = strdup(label->revision);
338f1bf0656SHans Rosenfeld 
339f1bf0656SHans Rosenfeld 	if (disk->vendor == NULL ||
340f1bf0656SHans Rosenfeld 	    disk->product == NULL ||
341f1bf0656SHans Rosenfeld 	    disk->revision == NULL) {
342f1bf0656SHans Rosenfeld 		free(disk->vendor);
343f1bf0656SHans Rosenfeld 		free(disk->product);
344f1bf0656SHans Rosenfeld 		free(disk->revision);
345f1bf0656SHans Rosenfeld 		free(disk);
346f1bf0656SHans Rosenfeld 		return (NULL);
347f1bf0656SHans Rosenfeld 	}
348f1bf0656SHans Rosenfeld 
3497c478bd9Sstevel@tonic-gate 	disk->capacity = label->capacity;
3507c478bd9Sstevel@tonic-gate 
3517c478bd9Sstevel@tonic-gate 	part = (struct partition_info *)
3527c478bd9Sstevel@tonic-gate 	    zalloc(sizeof (struct partition_info));
3537c478bd9Sstevel@tonic-gate 	disk->dtype_plist = part;
3547c478bd9Sstevel@tonic-gate 
3557c478bd9Sstevel@tonic-gate 	part->pinfo_name = alloc_string("default");
3567c478bd9Sstevel@tonic-gate 	part->pinfo_next = NULL;
3577c478bd9Sstevel@tonic-gate 	part->etoc = vtoc;
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate 	bzero(disk_info->v_volume, LEN_DKL_VVOL);
3607c478bd9Sstevel@tonic-gate 	disk_info->disk_parts = part;
3617c478bd9Sstevel@tonic-gate 	return (disk);
3627c478bd9Sstevel@tonic-gate }
3637c478bd9Sstevel@tonic-gate 
3643ccda647Slclee static int
efi_ioctl(int fd,int cmd,dk_efi_t * dk_ioc)3653ccda647Slclee efi_ioctl(int fd, int cmd, dk_efi_t *dk_ioc)
3663ccda647Slclee {
3673ccda647Slclee 	void *data = dk_ioc->dki_data;
3683ccda647Slclee 	int error;
3693ccda647Slclee 
3703ccda647Slclee 	dk_ioc->dki_data_64 = (uint64_t)(uintptr_t)data;
3713ccda647Slclee 	error = ioctl(fd, cmd, (void *)dk_ioc);
3723ccda647Slclee 	dk_ioc->dki_data = data;
3733ccda647Slclee 
3743ccda647Slclee 	return (error);
3753ccda647Slclee }
3763ccda647Slclee 
377698107ecSlh static struct ctlr_type *
find_ctlr_type(ushort_t type)3782f15e7adSIgor Kozhukhov find_ctlr_type(ushort_t type)
379698107ecSlh {
380698107ecSlh 	struct	mctlr_list	*mlp;
381698107ecSlh 
3822f15e7adSIgor Kozhukhov 	assert(type == DKC_DIRECT ||
3832f15e7adSIgor Kozhukhov 	    type == DKC_VBD ||
3842f15e7adSIgor Kozhukhov 	    type == DKC_BLKDEV);
385f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 
386f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 	mlp = controlp;
387f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 
388f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 	while (mlp != NULL) {
3892f15e7adSIgor Kozhukhov 		if (mlp->ctlr_type->ctype_ctype == type) {
390f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 			return (mlp->ctlr_type);
391f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 		}
392f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 		mlp = mlp->next;
393f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 	}
394f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 
3952f15e7adSIgor Kozhukhov 	impossible("no DIRECT/VBD/BLKDEV controller type");
396f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 
397b12aaafbSToomas Soome 	return (NULL);
398f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China }
399f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 
4003ccda647Slclee static struct ctlr_info *
find_ctlr_info(struct dk_cinfo * dkinfo,ushort_t type)4012f15e7adSIgor Kozhukhov find_ctlr_info(struct dk_cinfo *dkinfo, ushort_t type)
4023ccda647Slclee {
4033ccda647Slclee 	struct ctlr_info	*ctlr;
4043ccda647Slclee 
4052f15e7adSIgor Kozhukhov 	assert(type == DKC_DIRECT ||
4062f15e7adSIgor Kozhukhov 	    type == DKC_VBD ||
4072f15e7adSIgor Kozhukhov 	    type == DKC_BLKDEV);
4083ccda647Slclee 
4093ccda647Slclee 	for (ctlr = ctlr_list; ctlr != NULL; ctlr = ctlr->ctlr_next) {
4103ccda647Slclee 		if (ctlr->ctlr_addr == dkinfo->dki_addr &&
4113ccda647Slclee 		    ctlr->ctlr_space == dkinfo->dki_space &&
4122f15e7adSIgor Kozhukhov 		    ctlr->ctlr_ctype->ctype_ctype == dkinfo->dki_ctype) {
4133ccda647Slclee 			return (ctlr);
4143ccda647Slclee 		}
4153ccda647Slclee 	}
4163ccda647Slclee 
4172f15e7adSIgor Kozhukhov 	impossible("no DIRECT/VBD/BLKDEV controller info");
418f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 	/*NOTREACHED*/
419b12aaafbSToomas Soome 	return (NULL);
420f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China }
421f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 
4223ccda647Slclee static  struct disk_info *
find_disk_info(struct dk_cinfo * dkinfo,ushort_t type)4232f15e7adSIgor Kozhukhov find_disk_info(struct dk_cinfo *dkinfo, ushort_t type)
4243ccda647Slclee {
4253ccda647Slclee 	struct disk_info	*disk;
4263ccda647Slclee 	struct dk_cinfo		*dp;
4273ccda647Slclee 
4282f15e7adSIgor Kozhukhov 	assert(type == DKC_DIRECT ||
4292f15e7adSIgor Kozhukhov 	    type == DKC_VBD ||
4302f15e7adSIgor Kozhukhov 	    type == DKC_BLKDEV);
431f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 
432f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 	for (disk = disk_list; disk != NULL; disk = disk->disk_next) {
433f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 		dp = &disk->disk_dkinfo;
434f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 		if (dp->dki_ctype == dkinfo->dki_ctype &&
435f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 		    dp->dki_cnum == dkinfo->dki_cnum &&
436f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 		    dp->dki_unit == dkinfo->dki_unit &&
437f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 		    strcmp(dp->dki_dname, dkinfo->dki_dname) == 0) {
438f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 			return (disk);
439f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 		}
440f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 	}
441f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 
4422f15e7adSIgor Kozhukhov 	impossible("No DIRECT/VBD/BLKDEV disk info instance\n");
443f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 	/*NOTREACHED*/
444b12aaafbSToomas Soome 	return (NULL);
445f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China }
446f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 
4473ccda647Slclee /*
4483ccda647Slclee  * To convert EFI to SMI labels, we need to get label geometry.
4493ccda647Slclee  * Unfortunately at this time there is no good way to do so.
4503ccda647Slclee  * DKIOCGGEOM will fail if disk is EFI labeled. So we hack around
4513ccda647Slclee  * it and clear EFI label, do a DKIOCGGEOM and put the EFI label
4523ccda647Slclee  * back on disk.
4533ccda647Slclee  * This routine gets the label geometry and initializes the label
4543ccda647Slclee  * It uses cur_file as opened device.
4553ccda647Slclee  * returns 0 if succeeds or -1 if failed.
4563ccda647Slclee  */
4573ccda647Slclee static int
auto_label_init(struct dk_label * label)4583ccda647Slclee auto_label_init(struct dk_label *label)
4593ccda647Slclee {
4603ccda647Slclee 	dk_efi_t	dk_ioc;
4613ccda647Slclee 	dk_efi_t	dk_ioc_back;
4623ccda647Slclee 	efi_gpt_t	*data = NULL;
4633ccda647Slclee 	efi_gpt_t	*databack = NULL;
4643ccda647Slclee 	struct dk_geom	disk_geom;
4653ccda647Slclee 	struct dk_minfo	disk_info;
46632a71e42SToomas Soome 	efi_gpt_t	*backsigp;
4673ccda647Slclee 	int		fd = cur_file;
4683ccda647Slclee 	int		rval = -1;
4693ccda647Slclee 	int		efisize = EFI_LABEL_SIZE * 2;
4703ccda647Slclee 	int		success = 0;
4713ccda647Slclee 	uint64_t	sig;
4723ccda647Slclee 	uint64_t	backsig;
4733ccda647Slclee 
4743ccda647Slclee 	if ((data = calloc(efisize, 1)) == NULL) {
4753ccda647Slclee 		err_print("auto_label_init: calloc failed\n");
4763ccda647Slclee 		goto auto_label_init_out;
4773ccda647Slclee 	}
4783ccda647Slclee 
4793ccda647Slclee 	dk_ioc.dki_data = data;
4803ccda647Slclee 	dk_ioc.dki_lba = 1;
4813ccda647Slclee 	dk_ioc.dki_length = efisize;
4823ccda647Slclee 
4833ccda647Slclee 	if (efi_ioctl(fd, DKIOCGETEFI, &dk_ioc) != 0) {
4843ccda647Slclee 		err_print("auto_label_init: GETEFI failed\n");
4853ccda647Slclee 		goto auto_label_init_out;
4863ccda647Slclee 	}
4873ccda647Slclee 
4883ccda647Slclee 	if ((databack = calloc(efisize, 1)) == NULL) {
4893ccda647Slclee 		err_print("auto_label_init calloc2 failed");
4903ccda647Slclee 		goto auto_label_init_out;
4913ccda647Slclee 	}
4923ccda647Slclee 
4933ccda647Slclee 	/* get the LBA size and capacity */
4943ccda647Slclee 	if (ioctl(fd, DKIOCGMEDIAINFO, (caddr_t)&disk_info) == -1) {
4953ccda647Slclee 		err_print("auto_label_init: dkiocgmediainfo failed\n");
4963ccda647Slclee 		goto auto_label_init_out;
4973ccda647Slclee 	}
4983ccda647Slclee 
4993ccda647Slclee 	if (disk_info.dki_lbsize == 0) {
5003ccda647Slclee 		if (option_msg && diag_msg) {
5013ccda647Slclee 			err_print("auto_lbal_init: assuming 512 byte"
5023ccda647Slclee 			    "block size");
5033ccda647Slclee 		}
5043ccda647Slclee 		disk_info.dki_lbsize = DEV_BSIZE;
5053ccda647Slclee 	}
5063ccda647Slclee 
5073ccda647Slclee 	dk_ioc_back.dki_data = databack;
5083ccda647Slclee 
5093ccda647Slclee 	/*
5103ccda647Slclee 	 * back up efi label goes to capacity - 1, we are reading an extra block
5113ccda647Slclee 	 * before the back up label.
5123ccda647Slclee 	 */
5133ccda647Slclee 	dk_ioc_back.dki_lba = disk_info.dki_capacity - 1 - 1;
5143ccda647Slclee 	dk_ioc_back.dki_length = efisize;
5153ccda647Slclee 
5163ccda647Slclee 	if (efi_ioctl(fd, DKIOCGETEFI, &dk_ioc_back) != 0) {
5173ccda647Slclee 		err_print("auto_label_init: GETEFI backup failed\n");
5183ccda647Slclee 		goto auto_label_init_out;
5193ccda647Slclee 	}
5203ccda647Slclee 
5213ccda647Slclee 	sig = dk_ioc.dki_data->efi_gpt_Signature;
5223ccda647Slclee 	dk_ioc.dki_data->efi_gpt_Signature = 0x0;
5233ccda647Slclee 
5243ccda647Slclee 	enter_critical();
5253ccda647Slclee 
5263ccda647Slclee 	if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc) == -1) {
5273ccda647Slclee 		err_print("auto_label_init: SETEFI failed\n");
5283ccda647Slclee 		exit_critical();
5293ccda647Slclee 		goto auto_label_init_out;
5303ccda647Slclee 	}
5313ccda647Slclee 
53265908c77Syu, larry liu - Sun Microsystems - Beijing China 	backsigp = (efi_gpt_t *)((uintptr_t)dk_ioc_back.dki_data + cur_blksz);
5333ccda647Slclee 
5343ccda647Slclee 	backsig = backsigp->efi_gpt_Signature;
5353ccda647Slclee 
5363ccda647Slclee 	backsigp->efi_gpt_Signature = 0;
5373ccda647Slclee 
5383ccda647Slclee 	if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc_back) == -1) {
5393ccda647Slclee 		err_print("auto_label_init: SETEFI backup failed\n");
5403ccda647Slclee 	}
5413ccda647Slclee 
5423ccda647Slclee 	if (ioctl(cur_file, DKIOCGGEOM, &disk_geom) != 0)
5433ccda647Slclee 		err_print("auto_label_init: GGEOM failed\n");
5443ccda647Slclee 	else
5453ccda647Slclee 		success = 1;
5463ccda647Slclee 
5473ccda647Slclee 	dk_ioc.dki_data->efi_gpt_Signature = sig;
5483ccda647Slclee 	backsigp->efi_gpt_Signature = backsig;
5493ccda647Slclee 
5503ccda647Slclee 	if (efi_ioctl(cur_file, DKIOCSETEFI, &dk_ioc_back) == -1) {
5513ccda647Slclee 		err_print("auto_label_init: SETEFI revert backup failed\n");
5523ccda647Slclee 		success = 0;
5533ccda647Slclee 	}
5543ccda647Slclee 
5553ccda647Slclee 	if (efi_ioctl(cur_file, DKIOCSETEFI, &dk_ioc) == -1) {
5563ccda647Slclee 		err_print("auto_label_init: SETEFI revert failed\n");
5573ccda647Slclee 		success = 0;
5583ccda647Slclee 	}
5593ccda647Slclee 
5603ccda647Slclee 	exit_critical();
5613ccda647Slclee 
5623ccda647Slclee 	if (success == 0)
5633ccda647Slclee 		goto auto_label_init_out;
5643ccda647Slclee 
5653ccda647Slclee 	ncyl = disk_geom.dkg_ncyl;
5663ccda647Slclee 	acyl = disk_geom.dkg_acyl;
5673ccda647Slclee 	nhead =  disk_geom.dkg_nhead;
5683ccda647Slclee 	nsect = disk_geom.dkg_nsect;
5693ccda647Slclee 	pcyl = ncyl + acyl;
5703ccda647Slclee 
5713ccda647Slclee 	label->dkl_pcyl = pcyl;
5723ccda647Slclee 	label->dkl_ncyl = ncyl;
5733ccda647Slclee 	label->dkl_acyl = acyl;
5743ccda647Slclee 	label->dkl_nhead = nhead;
5753ccda647Slclee 	label->dkl_nsect = nsect;
5763ccda647Slclee 	label->dkl_apc = 0;
5773ccda647Slclee 	label->dkl_intrlv = 1;
5783ccda647Slclee 	label->dkl_rpm = disk_geom.dkg_rpm;
5793ccda647Slclee 
5803ccda647Slclee 	label->dkl_magic = DKL_MAGIC;
5813ccda647Slclee 
5823ccda647Slclee 	(void) snprintf(label->dkl_asciilabel, sizeof (label->dkl_asciilabel),
583342440ecSPrasad Singamsetty 	    "%s cyl %u alt %u hd %u sec %u",
5843ccda647Slclee 	    "DEFAULT", ncyl, acyl, nhead, nsect);
5853ccda647Slclee 
5863ccda647Slclee 	rval = 0;
5873ccda647Slclee #if defined(_FIRMWARE_NEEDS_FDISK)
5883ccda647Slclee 	(void) auto_solaris_part(label);
5893ccda647Slclee 	ncyl = label->dkl_ncyl;
5903ccda647Slclee 
5913ccda647Slclee #endif	/* defined(_FIRMWARE_NEEDS_FDISK) */
5923ccda647Slclee 
5933ccda647Slclee 	if (!build_default_partition(label, DKC_DIRECT)) {
5943ccda647Slclee 		rval = -1;
5953ccda647Slclee 	}
5963ccda647Slclee 
5973ccda647Slclee 	(void) checksum(label, CK_MAKESUM);
5983ccda647Slclee 
5993ccda647Slclee 
6003ccda647Slclee auto_label_init_out:
6013ccda647Slclee 	if (data)
6023ccda647Slclee 		free(data);
6033ccda647Slclee 	if (databack)
6043ccda647Slclee 		free(databack);
6053ccda647Slclee 
6063ccda647Slclee 	return (rval);
6073ccda647Slclee }
6083ccda647Slclee 
6093ccda647Slclee static struct disk_type *
new_direct_disk_type(int fd,char * disk_name,struct dk_label * label)6103ccda647Slclee new_direct_disk_type(
6113ccda647Slclee 	int		fd,
6123ccda647Slclee 	char		*disk_name,
6133ccda647Slclee 	struct dk_label	*label)
6143ccda647Slclee {
6153ccda647Slclee 	struct disk_type	*dp;
6163ccda647Slclee 	struct disk_type	*disk;
6173ccda647Slclee 	struct ctlr_info	*ctlr;
6183ccda647Slclee 	struct dk_cinfo		dkinfo;
6193ccda647Slclee 	struct partition_info	*part = NULL;
6203ccda647Slclee 	struct partition_info	*pt;
6213ccda647Slclee 	struct disk_info	*disk_info;
6223ccda647Slclee 	int			i;
6233ccda647Slclee 
6243ccda647Slclee 	/*
6253ccda647Slclee 	 * Get the disk controller info for this disk
6263ccda647Slclee 	 */
6273ccda647Slclee 	if (ioctl(fd, DKIOCINFO, &dkinfo) == -1) {
6283ccda647Slclee 		if (option_msg && diag_msg) {
6293ccda647Slclee 			err_print("DKIOCINFO failed\n");
6303ccda647Slclee 		}
6313ccda647Slclee 		return (NULL);
6323ccda647Slclee 	}
6333ccda647Slclee 
6343ccda647Slclee 	/*
6353ccda647Slclee 	 * Find the ctlr_info for this disk.
6363ccda647Slclee 	 */
6372f15e7adSIgor Kozhukhov 	ctlr = find_ctlr_info(&dkinfo, dkinfo.dki_ctype);
6383ccda647Slclee 
6393ccda647Slclee 	/*
6403ccda647Slclee 	 * Allocate a new disk type for the direct controller.
6413ccda647Slclee 	 */
6423ccda647Slclee 	disk = (struct disk_type *)zalloc(sizeof (struct disk_type));
6433ccda647Slclee 
6443ccda647Slclee 	/*
6453ccda647Slclee 	 * Find the disk_info instance for this disk.
6463ccda647Slclee 	 */
6472f15e7adSIgor Kozhukhov 	disk_info = find_disk_info(&dkinfo, dkinfo.dki_ctype);
6483ccda647Slclee 
6493ccda647Slclee 	/*
6503ccda647Slclee 	 * The controller and the disk should match.
6513ccda647Slclee 	 */
6523ccda647Slclee 	assert(disk_info->disk_ctlr == ctlr);
6533ccda647Slclee 
6543ccda647Slclee 	/*
6553ccda647Slclee 	 * Link the disk into the list of disks
6563ccda647Slclee 	 */
6573ccda647Slclee 	dp = ctlr->ctlr_ctype->ctype_dlist;
6583ccda647Slclee 	if (dp == NULL) {
6593ccda647Slclee 		ctlr->ctlr_ctype->ctype_dlist = dp;
6603ccda647Slclee 	} else {
6613ccda647Slclee 		while (dp->dtype_next != NULL) {
6623ccda647Slclee 			dp = dp->dtype_next;
6633ccda647Slclee 		}
6643ccda647Slclee 		dp->dtype_next = disk;
6653ccda647Slclee 	}
6663ccda647Slclee 	disk->dtype_next = NULL;
6673ccda647Slclee 
6683ccda647Slclee 	/*
6693ccda647Slclee 	 * Allocate and initialize the disk name.
6703ccda647Slclee 	 */
6713ccda647Slclee 	disk->dtype_asciilabel = alloc_string(disk_name);
6723ccda647Slclee 
6733ccda647Slclee 	/*
6743ccda647Slclee 	 * Initialize disk geometry info
6753ccda647Slclee 	 */
6763ccda647Slclee 	disk->dtype_pcyl = label->dkl_pcyl;
6773ccda647Slclee 	disk->dtype_ncyl = label->dkl_ncyl;
6783ccda647Slclee 	disk->dtype_acyl = label->dkl_acyl;
6793ccda647Slclee 	disk->dtype_nhead = label->dkl_nhead;
6803ccda647Slclee 	disk->dtype_nsect = label->dkl_nsect;
6813ccda647Slclee 	disk->dtype_rpm = label->dkl_rpm;
6823ccda647Slclee 
6833ccda647Slclee 	part = (struct partition_info *)
68465908c77Syu, larry liu - Sun Microsystems - Beijing China 	    zalloc(sizeof (struct partition_info));
6853ccda647Slclee 	pt = disk->dtype_plist;
6863ccda647Slclee 	if (pt == NULL) {
6873ccda647Slclee 		disk->dtype_plist = part;
6883ccda647Slclee 	} else {
6893ccda647Slclee 		while (pt->pinfo_next != NULL) {
6903ccda647Slclee 			pt = pt->pinfo_next;
6913ccda647Slclee 		}
6923ccda647Slclee 		pt->pinfo_next = part;
6933ccda647Slclee 	}
6943ccda647Slclee 
6953ccda647Slclee 	part->pinfo_next = NULL;
6963ccda647Slclee 
6973ccda647Slclee 	/*
6983ccda647Slclee 	 * Set up the partition name
6993ccda647Slclee 	 */
7003ccda647Slclee 	part->pinfo_name = alloc_string("default");
7013ccda647Slclee 
7023ccda647Slclee 	/*
7033ccda647Slclee 	 * Fill in the partition info from the label
7043ccda647Slclee 	 */
7053ccda647Slclee 	for (i = 0; i < NDKMAP; i++) {
7063ccda647Slclee 
7073ccda647Slclee #if defined(_SUNOS_VTOC_8)
7083ccda647Slclee 		part->pinfo_map[i] = label->dkl_map[i];
7093ccda647Slclee 
7103ccda647Slclee #elif defined(_SUNOS_VTOC_16)
7113ccda647Slclee 		part->pinfo_map[i].dkl_cylno =
71265908c77Syu, larry liu - Sun Microsystems - Beijing China 		    label->dkl_vtoc.v_part[i].p_start /
71365908c77Syu, larry liu - Sun Microsystems - Beijing China 		    ((blkaddr_t)(disk->dtype_nhead *
71465908c77Syu, larry liu - Sun Microsystems - Beijing China 		    disk->dtype_nsect - apc));
7153ccda647Slclee 		part->pinfo_map[i].dkl_nblk =
71665908c77Syu, larry liu - Sun Microsystems - Beijing China 		    label->dkl_vtoc.v_part[i].p_size;
7173ccda647Slclee #else
7183ccda647Slclee #error No VTOC format defined.
7193ccda647Slclee #endif				/* defined(_SUNOS_VTOC_8) */
7203ccda647Slclee 	}
7213ccda647Slclee 
7223ccda647Slclee 	/*
7233ccda647Slclee 	 * Use the VTOC if valid, or install a default
7243ccda647Slclee 	 */
7253ccda647Slclee 	if (label->dkl_vtoc.v_version == V_VERSION) {
7263ccda647Slclee 		(void) memcpy(disk_info->v_volume, label->dkl_vtoc.v_volume,
72765908c77Syu, larry liu - Sun Microsystems - Beijing China 		    LEN_DKL_VVOL);
7283ccda647Slclee 		part->vtoc = label->dkl_vtoc;
7293ccda647Slclee 	} else {
7303ccda647Slclee 		(void) memset(disk_info->v_volume, 0, LEN_DKL_VVOL);
7313ccda647Slclee 		set_vtoc_defaults(part);
7323ccda647Slclee 	}
7333ccda647Slclee 
7343ccda647Slclee 	/*
7353ccda647Slclee 	 * Link the disk to the partition map
7363ccda647Slclee 	 */
7373ccda647Slclee 	disk_info->disk_parts = part;
7383ccda647Slclee 
7393ccda647Slclee 	return (disk);
7403ccda647Slclee }
7413ccda647Slclee 
7423ccda647Slclee /*
7433ccda647Slclee  * Get a disk type that has label info. This is used to convert
7443ccda647Slclee  * EFI label to SMI label
7453ccda647Slclee  */
7463ccda647Slclee struct disk_type *
auto_direct_get_geom_label(int fd,struct dk_label * label)7473ccda647Slclee auto_direct_get_geom_label(int fd, struct dk_label *label)
7483ccda647Slclee {
7493ccda647Slclee 	struct disk_type		*disk_type;
7503ccda647Slclee 
7513ccda647Slclee 	if (auto_label_init(label) != 0) {
7523ccda647Slclee 		err_print("auto_direct_get_geom_label: failed to get label"
7533ccda647Slclee 		    "geometry");
7543ccda647Slclee 		return (NULL);
7553ccda647Slclee 	} else {
7563ccda647Slclee 		disk_type = new_direct_disk_type(fd, "DEFAULT", label);
7573ccda647Slclee 		return (disk_type);
7583ccda647Slclee 	}
7593ccda647Slclee }
7603ccda647Slclee 
7617c478bd9Sstevel@tonic-gate /*
7627c478bd9Sstevel@tonic-gate  * Auto-sense a scsi disk configuration, ie get the information
7637c478bd9Sstevel@tonic-gate  * necessary to construct a label.  We have two different
7647c478bd9Sstevel@tonic-gate  * ways to auto-sense a scsi disk:
7657c478bd9Sstevel@tonic-gate  *	- format.dat override, via inquiry name
7667c478bd9Sstevel@tonic-gate  *	- generic scsi, via standard mode sense and inquiry
7677c478bd9Sstevel@tonic-gate  * Depending on how and when we are called, and/or
7687c478bd9Sstevel@tonic-gate  * change geometry and reformat.
7697c478bd9Sstevel@tonic-gate  */
7707c478bd9Sstevel@tonic-gate struct disk_type *
auto_sense(int fd,int can_prompt,struct dk_label * label)7717c478bd9Sstevel@tonic-gate auto_sense(
7727c478bd9Sstevel@tonic-gate 	int		fd,
7737c478bd9Sstevel@tonic-gate 	int		can_prompt,
7747c478bd9Sstevel@tonic-gate 	struct dk_label	*label)
7757c478bd9Sstevel@tonic-gate {
7767c478bd9Sstevel@tonic-gate 	struct scsi_inquiry		inquiry;
7777c478bd9Sstevel@tonic-gate 	struct scsi_capacity_16		capacity;
7787c478bd9Sstevel@tonic-gate 	struct disk_type		*disk_type;
7797c478bd9Sstevel@tonic-gate 	char				disk_name[DISK_NAME_MAX];
7807c478bd9Sstevel@tonic-gate 	int				force_format_dat = 0;
7817c478bd9Sstevel@tonic-gate 	int				force_generic = 0;
7827c478bd9Sstevel@tonic-gate 	u_ioparam_t			ioparam;
7837c478bd9Sstevel@tonic-gate 	int				deflt;
7844ee50ec3Sbo zhou - Sun Microsystems - Beijing China 	char				*buf;
7857c478bd9Sstevel@tonic-gate 
7867c478bd9Sstevel@tonic-gate 	/*
7877c478bd9Sstevel@tonic-gate 	 * First, if expert mode, find out if the user
7887c478bd9Sstevel@tonic-gate 	 * wants to override any of the standard methods.
7897c478bd9Sstevel@tonic-gate 	 */
7907c478bd9Sstevel@tonic-gate 	if (can_prompt && expert_mode) {
7917c478bd9Sstevel@tonic-gate 		deflt = 1;
7927c478bd9Sstevel@tonic-gate 		ioparam.io_charlist = confirm_list;
7937c478bd9Sstevel@tonic-gate 		if (input(FIO_MSTR, FORMAT_MSG, '?', &ioparam,
79465908c77Syu, larry liu - Sun Microsystems - Beijing China 		    &deflt, DATA_INPUT) == 0) {
7957c478bd9Sstevel@tonic-gate 			force_format_dat = 1;
7967c478bd9Sstevel@tonic-gate 		} else if (input(FIO_MSTR, GENERIC_MSG, '?', &ioparam,
79765908c77Syu, larry liu - Sun Microsystems - Beijing China 		    &deflt, DATA_INPUT) == 0) {
7987c478bd9Sstevel@tonic-gate 			force_generic = 1;
7997c478bd9Sstevel@tonic-gate 		}
8007c478bd9Sstevel@tonic-gate 	}
8017c478bd9Sstevel@tonic-gate 
8027c478bd9Sstevel@tonic-gate 	/*
8037c478bd9Sstevel@tonic-gate 	 * Get the Inquiry data.  If this fails, there's
8047c478bd9Sstevel@tonic-gate 	 * no hope for this disk, so give up.
8057c478bd9Sstevel@tonic-gate 	 */
8067c478bd9Sstevel@tonic-gate 	if (uscsi_inquiry(fd, (char *)&inquiry, sizeof (inquiry))) {
807b12aaafbSToomas Soome 		return (NULL);
8087c478bd9Sstevel@tonic-gate 	}
8097c478bd9Sstevel@tonic-gate 	if (option_msg && diag_msg) {
8107c478bd9Sstevel@tonic-gate 		err_print("Product id: ");
8117c478bd9Sstevel@tonic-gate 		print_buf(inquiry.inq_pid, sizeof (inquiry.inq_pid));
8127c478bd9Sstevel@tonic-gate 		err_print("\n");
8137c478bd9Sstevel@tonic-gate 	}
8147c478bd9Sstevel@tonic-gate 
8157c478bd9Sstevel@tonic-gate 	/*
8167c478bd9Sstevel@tonic-gate 	 * Get the Read Capacity
8177c478bd9Sstevel@tonic-gate 	 */
8187c478bd9Sstevel@tonic-gate 	if (uscsi_read_capacity(fd, &capacity)) {
819b12aaafbSToomas Soome 		return (NULL);
8200972747aSyl 	}
8210972747aSyl 
8220972747aSyl 	/*
8230972747aSyl 	 * If the reported capacity is set to zero, then the disk
8240972747aSyl 	 * is not usable. If the reported capacity is set to all
8250972747aSyl 	 * 0xf's, then this disk is too large.  These could only
8260972747aSyl 	 * happen with a device that supports LBAs larger than 64
8270972747aSyl 	 * bits which are not defined by any current T10 standards
8280972747aSyl 	 * or by error responding from target.
8290972747aSyl 	 */
8300972747aSyl 	if ((capacity.sc_capacity == 0) ||
8310972747aSyl 	    (capacity.sc_capacity == UINT_MAX64)) {
8320972747aSyl 		if (option_msg && diag_msg) {
8330972747aSyl 			err_print("Invalid capacity\n");
8340972747aSyl 		}
835b12aaafbSToomas Soome 		return (NULL);
8367c478bd9Sstevel@tonic-gate 	}
8377c478bd9Sstevel@tonic-gate 	if (option_msg && diag_msg) {
8387c478bd9Sstevel@tonic-gate 		err_print("blocks:  %llu (0x%llx)\n",
83965908c77Syu, larry liu - Sun Microsystems - Beijing China 		    capacity.sc_capacity, capacity.sc_capacity);
8407c478bd9Sstevel@tonic-gate 		err_print("blksize: %u\n", capacity.sc_lbasize);
8417c478bd9Sstevel@tonic-gate 	}
8427c478bd9Sstevel@tonic-gate 
8437c478bd9Sstevel@tonic-gate 	/*
8447c478bd9Sstevel@tonic-gate 	 * Extract the disk name for the format.dat override
8457c478bd9Sstevel@tonic-gate 	 */
8467c478bd9Sstevel@tonic-gate 	(void) get_sun_disk_name(disk_name, &inquiry);
8477c478bd9Sstevel@tonic-gate 	if (option_msg && diag_msg) {
8487c478bd9Sstevel@tonic-gate 		err_print("disk name:  `%s`\n", disk_name);
8497c478bd9Sstevel@tonic-gate 	}
8507c478bd9Sstevel@tonic-gate 
8514ee50ec3Sbo zhou - Sun Microsystems - Beijing China 	buf = zalloc(cur_blksz);
8524ee50ec3Sbo zhou - Sun Microsystems - Beijing China 	if (scsi_rdwr(DIR_READ, fd, (diskaddr_t)0, 1, (caddr_t)buf,
8534ee50ec3Sbo zhou - Sun Microsystems - Beijing China 	    F_SILENT, NULL)) {
8544ee50ec3Sbo zhou - Sun Microsystems - Beijing China 		free(buf);
855b12aaafbSToomas Soome 		return (NULL);
8564ee50ec3Sbo zhou - Sun Microsystems - Beijing China 	}
8574ee50ec3Sbo zhou - Sun Microsystems - Beijing China 	free(buf);
858b63e7ecbSAbhinandan Ekande 
8597c478bd9Sstevel@tonic-gate 	/*
8607c478bd9Sstevel@tonic-gate 	 * Figure out which method we use for auto sense.
8617c478bd9Sstevel@tonic-gate 	 * If a particular method fails, we fall back to
8627c478bd9Sstevel@tonic-gate 	 * the next possibility.
8637c478bd9Sstevel@tonic-gate 	 */
8647c478bd9Sstevel@tonic-gate 
8657c478bd9Sstevel@tonic-gate 	if (force_generic) {
8667c478bd9Sstevel@tonic-gate 		return (generic_disk_sense(fd, can_prompt, label,
86765908c77Syu, larry liu - Sun Microsystems - Beijing China 		    &inquiry, &capacity, disk_name));
8687c478bd9Sstevel@tonic-gate 	}
8697c478bd9Sstevel@tonic-gate 
8707c478bd9Sstevel@tonic-gate 	/*
8717c478bd9Sstevel@tonic-gate 	 * Try for an existing format.dat first
8727c478bd9Sstevel@tonic-gate 	 */
8737c478bd9Sstevel@tonic-gate 	if ((disk_type = find_scsi_disk_by_name(disk_name)) != NULL) {
8747c478bd9Sstevel@tonic-gate 		if (use_existing_disk_type(fd, can_prompt, label,
87565908c77Syu, larry liu - Sun Microsystems - Beijing China 		    &inquiry, disk_type, &capacity)) {
8767c478bd9Sstevel@tonic-gate 			return (disk_type);
8777c478bd9Sstevel@tonic-gate 		}
8787c478bd9Sstevel@tonic-gate 		if (force_format_dat) {
8797c478bd9Sstevel@tonic-gate 			return (NULL);
8807c478bd9Sstevel@tonic-gate 		}
8817c478bd9Sstevel@tonic-gate 	}
8827c478bd9Sstevel@tonic-gate 
8837c478bd9Sstevel@tonic-gate 	/*
8847c478bd9Sstevel@tonic-gate 	 * Otherwise, try using generic SCSI-2 sense and inquiry.
8857c478bd9Sstevel@tonic-gate 	 */
8867c478bd9Sstevel@tonic-gate 
8877c478bd9Sstevel@tonic-gate 	return (generic_disk_sense(fd, can_prompt, label,
88865908c77Syu, larry liu - Sun Microsystems - Beijing China 	    &inquiry, &capacity, disk_name));
8897c478bd9Sstevel@tonic-gate }
8907c478bd9Sstevel@tonic-gate 
8917c478bd9Sstevel@tonic-gate 
8927c478bd9Sstevel@tonic-gate 
8937c478bd9Sstevel@tonic-gate /*ARGSUSED*/
8947c478bd9Sstevel@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)8957c478bd9Sstevel@tonic-gate generic_disk_sense(
8967c478bd9Sstevel@tonic-gate 	int			fd,
8977c478bd9Sstevel@tonic-gate 	int			can_prompt,
8987c478bd9Sstevel@tonic-gate 	struct dk_label		*label,
8997c478bd9Sstevel@tonic-gate 	struct scsi_inquiry	*inquiry,
9007c478bd9Sstevel@tonic-gate 	struct scsi_capacity_16	*capacity,
9017c478bd9Sstevel@tonic-gate 	char			*disk_name)
9027c478bd9Sstevel@tonic-gate {
9037c478bd9Sstevel@tonic-gate 	struct disk_type		*disk;
904bc067c09Sqd 	int				setdefault = 0;
905342440ecSPrasad Singamsetty 	uint_t				pcyl = 0;
906342440ecSPrasad Singamsetty 	uint_t				ncyl = 0;
907342440ecSPrasad Singamsetty 	uint_t				acyl = 0;
908342440ecSPrasad Singamsetty 	uint_t				nhead = 0;
909342440ecSPrasad Singamsetty 	uint_t				nsect = 0;
910bc067c09Sqd 	int				rpm = 0;
911342440ecSPrasad Singamsetty 	diskaddr_t			nblocks = 0;
912342440ecSPrasad Singamsetty 	diskaddr_t			tblocks = 0;
9137c478bd9Sstevel@tonic-gate 	union {
9147c478bd9Sstevel@tonic-gate 		struct mode_format	page3;
9157c478bd9Sstevel@tonic-gate 		uchar_t			buf3[MAX_MODE_SENSE_SIZE];
9167c478bd9Sstevel@tonic-gate 	} u_page3;
9177c478bd9Sstevel@tonic-gate 	union {
9187c478bd9Sstevel@tonic-gate 		struct mode_geometry	page4;
9197c478bd9Sstevel@tonic-gate 		uchar_t			buf4[MAX_MODE_SENSE_SIZE];
9207c478bd9Sstevel@tonic-gate 	} u_page4;
9217c478bd9Sstevel@tonic-gate 	struct mode_format		*page3 = &u_page3.page3;
9227c478bd9Sstevel@tonic-gate 	struct mode_geometry		*page4 = &u_page4.page4;
9237c478bd9Sstevel@tonic-gate 	struct scsi_ms_header		header;
9247c478bd9Sstevel@tonic-gate 
9257c478bd9Sstevel@tonic-gate 	/*
9267c478bd9Sstevel@tonic-gate 	 * If the name of this disk appears to be "SUN", use it,
9277c478bd9Sstevel@tonic-gate 	 * otherwise construct a name out of the generic
9287c478bd9Sstevel@tonic-gate 	 * Inquiry info.  If it turns out that we already
9297c478bd9Sstevel@tonic-gate 	 * have a SUN disk type of this name that differs
9307c478bd9Sstevel@tonic-gate 	 * in geometry, we will revert to the generic name
9317c478bd9Sstevel@tonic-gate 	 * anyway.
9327c478bd9Sstevel@tonic-gate 	 */
9337c478bd9Sstevel@tonic-gate 	if (memcmp(disk_name, "SUN", strlen("SUN")) != 0) {
9347c478bd9Sstevel@tonic-gate 		(void) get_generic_disk_name(disk_name, inquiry);
9357c478bd9Sstevel@tonic-gate 	}
9367c478bd9Sstevel@tonic-gate 
937bc067c09Sqd 	/*
938bc067c09Sqd 	 * Get the number of blocks from Read Capacity data. Note that
939bc067c09Sqd 	 * the logical block address range from 0 to capacity->sc_capacity.
940342440ecSPrasad Singamsetty 	 * Limit the size to 2 TB (UINT32_MAX) to use with SMI labels.
941bc067c09Sqd 	 */
942342440ecSPrasad Singamsetty 	tblocks = (capacity->sc_capacity + 1);
943342440ecSPrasad Singamsetty 	if (tblocks > UINT32_MAX)
944342440ecSPrasad Singamsetty 		nblocks = UINT32_MAX;
945342440ecSPrasad Singamsetty 	else
946342440ecSPrasad Singamsetty 		nblocks = tblocks;
947bc067c09Sqd 
9487c478bd9Sstevel@tonic-gate 	/*
9497c478bd9Sstevel@tonic-gate 	 * Get current Page 3 - Format Parameters page
9507c478bd9Sstevel@tonic-gate 	 */
9517c478bd9Sstevel@tonic-gate 	if (uscsi_mode_sense(fd, DAD_MODE_FORMAT, MODE_SENSE_PC_CURRENT,
95265908c77Syu, larry liu - Sun Microsystems - Beijing China 	    (caddr_t)&u_page3, MAX_MODE_SENSE_SIZE, &header)) {
953bc067c09Sqd 		setdefault = 1;
9547c478bd9Sstevel@tonic-gate 	}
9557c478bd9Sstevel@tonic-gate 
9567c478bd9Sstevel@tonic-gate 	/*
9577c478bd9Sstevel@tonic-gate 	 * Get current Page 4 - Drive Geometry page
9587c478bd9Sstevel@tonic-gate 	 */
9597c478bd9Sstevel@tonic-gate 	if (uscsi_mode_sense(fd, DAD_MODE_GEOMETRY, MODE_SENSE_PC_CURRENT,
96065908c77Syu, larry liu - Sun Microsystems - Beijing China 	    (caddr_t)&u_page4, MAX_MODE_SENSE_SIZE, &header)) {
961bc067c09Sqd 		setdefault = 1;
9627c478bd9Sstevel@tonic-gate 	}
9637c478bd9Sstevel@tonic-gate 
964bc067c09Sqd 	if (setdefault != 1) {
965bc067c09Sqd 		/* The inquiry of mode page 3 & page 4 are successful */
966bc067c09Sqd 		/*
967bc067c09Sqd 		 * Correct for byte order if necessary
968bc067c09Sqd 		 */
969bc067c09Sqd 		page4->rpm = BE_16(page4->rpm);
970bc067c09Sqd 		page4->step_rate = BE_16(page4->step_rate);
971bc067c09Sqd 		page3->tracks_per_zone = BE_16(page3->tracks_per_zone);
972bc067c09Sqd 		page3->alt_sect_zone = BE_16(page3->alt_sect_zone);
973bc067c09Sqd 		page3->alt_tracks_zone = BE_16(page3->alt_tracks_zone);
974bc067c09Sqd 		page3->alt_tracks_vol = BE_16(page3->alt_tracks_vol);
975bc067c09Sqd 		page3->sect_track = BE_16(page3->sect_track);
976bc067c09Sqd 		page3->data_bytes_sect = BE_16(page3->data_bytes_sect);
977bc067c09Sqd 		page3->interleave = BE_16(page3->interleave);
978bc067c09Sqd 		page3->track_skew = BE_16(page3->track_skew);
979bc067c09Sqd 		page3->cylinder_skew = BE_16(page3->cylinder_skew);
9807c478bd9Sstevel@tonic-gate 
9817c478bd9Sstevel@tonic-gate 
982bc067c09Sqd 		/*
983bc067c09Sqd 		 * Construct a new label out of the sense data,
984bc067c09Sqd 		 * Inquiry and Capacity.
985342440ecSPrasad Singamsetty 		 *
986342440ecSPrasad Singamsetty 		 * If the disk capacity is > 1TB then simply compute
987342440ecSPrasad Singamsetty 		 * the CHS values based on the total disk capacity and
988342440ecSPrasad Singamsetty 		 * not use the values from mode-sense data.
989bc067c09Sqd 		 */
990342440ecSPrasad Singamsetty 		if (tblocks > INT32_MAX) {
991342440ecSPrasad Singamsetty 			compute_chs_values(tblocks, nblocks, &pcyl, &nhead,
992342440ecSPrasad Singamsetty 			    &nsect);
993342440ecSPrasad Singamsetty 		} else {
994342440ecSPrasad Singamsetty 			pcyl = (page4->cyl_ub << 16) + (page4->cyl_mb << 8) +
99565908c77Syu, larry liu - Sun Microsystems - Beijing China 			    page4->cyl_lb;
996342440ecSPrasad Singamsetty 			nhead = page4->heads;
997342440ecSPrasad Singamsetty 			nsect = page3->sect_track;
998342440ecSPrasad Singamsetty 		}
999342440ecSPrasad Singamsetty 
1000bc067c09Sqd 		rpm = page4->rpm;
10017c478bd9Sstevel@tonic-gate 
1002bc067c09Sqd 		/*
1003bc067c09Sqd 		 * If the number of physical cylinders reported is less
1004bc067c09Sqd 		 * the SUN_MIN_CYL(3) then try to adjust the geometry so that
1005bc067c09Sqd 		 * we have atleast SUN_MIN_CYL cylinders.
1006bc067c09Sqd 		 */
1007bc067c09Sqd 		if (pcyl < SUN_MIN_CYL) {
1008342440ecSPrasad Singamsetty 			if (nhead == 0 || nsect == 0) {
1009bc067c09Sqd 				setdefault = 1;
101056507910Sqd 			} else if (adjust_disk_geometry(
1011342440ecSPrasad Singamsetty 			    (diskaddr_t)(capacity->sc_capacity + 1),
1012bc067c09Sqd 			    &pcyl, &nhead, &nsect)) {
1013bc067c09Sqd 				setdefault = 1;
1014bc067c09Sqd 			}
1015bc067c09Sqd 		}
1016bc067c09Sqd 	}
1017bc067c09Sqd 
101865908c77Syu, larry liu - Sun Microsystems - Beijing China 	/*
101965908c77Syu, larry liu - Sun Microsystems - Beijing China 	 * Mode sense page 3 and page 4 are obsolete in SCSI-3. For
102065908c77Syu, larry liu - Sun Microsystems - Beijing China 	 * newly developed large sector size disk, we will not rely on
102165908c77Syu, larry liu - Sun Microsystems - Beijing China 	 * those two pages but compute geometry directly.
102265908c77Syu, larry liu - Sun Microsystems - Beijing China 	 */
102365908c77Syu, larry liu - Sun Microsystems - Beijing China 	if ((setdefault == 1) || (capacity->sc_lbasize != DEV_BSIZE)) {
1024bc067c09Sqd 		/*
1025bc067c09Sqd 		 * If the number of cylinders or the number of heads reported
1026bc067c09Sqd 		 * is zero, we think the inquiry of page 3 and page 4 failed.
1027bc067c09Sqd 		 * We will set the geometry infomation by ourselves.
1028bc067c09Sqd 		 */
1029342440ecSPrasad Singamsetty 		compute_chs_values(tblocks, nblocks, &pcyl, &nhead, &nsect);
10307c478bd9Sstevel@tonic-gate 	}
10317c478bd9Sstevel@tonic-gate 
10327c478bd9Sstevel@tonic-gate 	/*
10337c478bd9Sstevel@tonic-gate 	 * The sd driver reserves 2 cylinders the backup disk label and
10347c478bd9Sstevel@tonic-gate 	 * the deviceid.  Set the number of data cylinders to pcyl-acyl.
10357c478bd9Sstevel@tonic-gate 	 */
10367c478bd9Sstevel@tonic-gate 	acyl = DK_ACYL;
10377c478bd9Sstevel@tonic-gate 	ncyl = pcyl - acyl;
10387c478bd9Sstevel@tonic-gate 
10397c478bd9Sstevel@tonic-gate 	if (option_msg && diag_msg) {
10407c478bd9Sstevel@tonic-gate 		err_print("Geometry:\n");
1041342440ecSPrasad Singamsetty 		err_print("    pcyl:    %u\n", pcyl);
1042342440ecSPrasad Singamsetty 		err_print("    ncyl:    %u\n", ncyl);
1043342440ecSPrasad Singamsetty 		err_print("    heads:   %u\n", nhead);
1044342440ecSPrasad Singamsetty 		err_print("    nsects:  %u\n", nsect);
1045342440ecSPrasad Singamsetty 		err_print("    acyl:    %u\n", acyl);
10467c478bd9Sstevel@tonic-gate 
10477c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_16)
1048342440ecSPrasad Singamsetty 		err_print("    bcyl:    %u\n", bcyl);
10497c478bd9Sstevel@tonic-gate #endif			/* defined(_SUNOS_VTOC_16) */
10507c478bd9Sstevel@tonic-gate 
10517c478bd9Sstevel@tonic-gate 		err_print("    rpm:     %d\n", rpm);
1052342440ecSPrasad Singamsetty 		err_print("    nblocks:     %llu\n", nblocks);
10537c478bd9Sstevel@tonic-gate 	}
10547c478bd9Sstevel@tonic-gate 
10557c478bd9Sstevel@tonic-gate 	/*
1056bc067c09Sqd 	 * Some drives do not support page4 or report 0 for page4->rpm,
1057bc067c09Sqd 	 * adjust it to AVG_RPM, 3600.
10587c478bd9Sstevel@tonic-gate 	 */
10597c478bd9Sstevel@tonic-gate 	if (rpm < MIN_RPM || rpm > MAX_RPM) {
1060b63e7ecbSAbhinandan Ekande 		if (option_msg && diag_msg)
1061b63e7ecbSAbhinandan Ekande 			err_print("The current rpm value %d is invalid,"
1062b63e7ecbSAbhinandan Ekande 			    " adjusting it to %d\n", rpm, AVG_RPM);
10637c478bd9Sstevel@tonic-gate 		rpm = AVG_RPM;
10647c478bd9Sstevel@tonic-gate 	}
10657c478bd9Sstevel@tonic-gate 
10667c478bd9Sstevel@tonic-gate 	/*
10677c478bd9Sstevel@tonic-gate 	 * Some drives report 0 for nsect (page 3, byte 10 and 11) if they
10687c478bd9Sstevel@tonic-gate 	 * have variable number of sectors per track. So adjust nsect.
10697c478bd9Sstevel@tonic-gate 	 * Also the value is defined as vendor specific, hence check if
10707c478bd9Sstevel@tonic-gate 	 * it is in a tolerable range. The values (32 and 4 below) are
10717c478bd9Sstevel@tonic-gate 	 * chosen so that this change below does not generate a different
10727c478bd9Sstevel@tonic-gate 	 * geometry for currently supported sun disks.
10737c478bd9Sstevel@tonic-gate 	 */
1074342440ecSPrasad Singamsetty 	if ((nsect == 0) ||
1075342440ecSPrasad Singamsetty 	    ((diskaddr_t)pcyl * nhead * nsect) < (nblocks - nblocks/32) ||
1076342440ecSPrasad Singamsetty 	    ((diskaddr_t)pcyl * nhead * nsect) > (nblocks + nblocks/4)) {
1077342440ecSPrasad Singamsetty 		if (nblocks > (pcyl * nhead)) {
1078342440ecSPrasad Singamsetty 			err_print("Mode sense page(3) reports nsect value"
1079342440ecSPrasad Singamsetty 			    " as %d, adjusting it to %llu\n",
1080342440ecSPrasad Singamsetty 			    nsect, nblocks / (pcyl * nhead));
1081342440ecSPrasad Singamsetty 			nsect = nblocks / (pcyl * nhead);
1082342440ecSPrasad Singamsetty 		} else {
1083342440ecSPrasad Singamsetty 			/* convert capacity to nsect * nhead * pcyl */
1084342440ecSPrasad Singamsetty 			err_print("\nWARNING: Disk geometry is based on "
1085342440ecSPrasad Singamsetty 			    "capacity data.\n\n");
1086342440ecSPrasad Singamsetty 			compute_chs_values(tblocks, nblocks, &pcyl, &nhead,
1087342440ecSPrasad Singamsetty 			    &nsect);
1088342440ecSPrasad Singamsetty 			ncyl = pcyl - acyl;
1089342440ecSPrasad Singamsetty 			if (option_msg && diag_msg) {
1090342440ecSPrasad Singamsetty 				err_print("Geometry:(after adjustment)\n");
1091342440ecSPrasad Singamsetty 				err_print("    pcyl:    %u\n", pcyl);
1092342440ecSPrasad Singamsetty 				err_print("    ncyl:    %u\n", ncyl);
1093342440ecSPrasad Singamsetty 				err_print("    heads:   %u\n", nhead);
1094342440ecSPrasad Singamsetty 				err_print("    nsects:  %u\n", nsect);
1095342440ecSPrasad Singamsetty 				err_print("    acyl:    %u\n", acyl);
1096342440ecSPrasad Singamsetty 
1097342440ecSPrasad Singamsetty #if defined(_SUNOS_VTOC_16)
1098342440ecSPrasad Singamsetty 				err_print("    bcyl:    %u\n", bcyl);
1099342440ecSPrasad Singamsetty #endif
1100342440ecSPrasad Singamsetty 
1101342440ecSPrasad Singamsetty 				err_print("    rpm:     %d\n", rpm);
1102342440ecSPrasad Singamsetty 				err_print("    nblocks:     %llu\n", nblocks);
1103342440ecSPrasad Singamsetty 			}
1104342440ecSPrasad Singamsetty 		}
11057c478bd9Sstevel@tonic-gate 	}
11067c478bd9Sstevel@tonic-gate 
11077c478bd9Sstevel@tonic-gate 	/*
11087c478bd9Sstevel@tonic-gate 	 * Some drives report their physical geometry such that
11097c478bd9Sstevel@tonic-gate 	 * it is greater than the actual capacity.  Adjust the
11107c478bd9Sstevel@tonic-gate 	 * geometry to allow for this, so we don't run off
11117c478bd9Sstevel@tonic-gate 	 * the end of the disk.
11127c478bd9Sstevel@tonic-gate 	 */
1113342440ecSPrasad Singamsetty 	if (((diskaddr_t)pcyl * nhead * nsect) > nblocks) {
1114342440ecSPrasad Singamsetty 		uint_t	p = pcyl;
11157c478bd9Sstevel@tonic-gate 		if (option_msg && diag_msg) {
1116342440ecSPrasad Singamsetty 			err_print("Computed capacity (%llu) exceeds actual "
1117342440ecSPrasad Singamsetty 			    "disk capacity (%llu)\n",
1118342440ecSPrasad Singamsetty 			    (diskaddr_t)pcyl * nhead * nsect, nblocks);
11197c478bd9Sstevel@tonic-gate 		}
11207c478bd9Sstevel@tonic-gate 		do {
11217c478bd9Sstevel@tonic-gate 			pcyl--;
1122342440ecSPrasad Singamsetty 		} while (((diskaddr_t)pcyl * nhead * nsect) > nblocks);
11237c478bd9Sstevel@tonic-gate 
11247c478bd9Sstevel@tonic-gate 		if (can_prompt && expert_mode && !option_f) {
11257c478bd9Sstevel@tonic-gate 			/*
11267c478bd9Sstevel@tonic-gate 			 * Try to adjust nsect instead of pcyl to see if we
11277c478bd9Sstevel@tonic-gate 			 * can optimize. For compatability reasons do this
11287c478bd9Sstevel@tonic-gate 			 * only in expert mode (refer to bug 1144812).
11297c478bd9Sstevel@tonic-gate 			 */
1130342440ecSPrasad Singamsetty 			uint_t	n = nsect;
11317c478bd9Sstevel@tonic-gate 			do {
11327c478bd9Sstevel@tonic-gate 				n--;
1133342440ecSPrasad Singamsetty 			} while (((diskaddr_t)p * nhead * n) > nblocks);
1134342440ecSPrasad Singamsetty 			if (((diskaddr_t)p * nhead * n) >
1135342440ecSPrasad Singamsetty 			    ((diskaddr_t)pcyl * nhead * nsect)) {
11367c478bd9Sstevel@tonic-gate 				u_ioparam_t	ioparam;
11377c478bd9Sstevel@tonic-gate 				int		deflt = 1;
11387c478bd9Sstevel@tonic-gate 				/*
11397c478bd9Sstevel@tonic-gate 				 * Ask the user for a choice here.
11407c478bd9Sstevel@tonic-gate 				 */
11417c478bd9Sstevel@tonic-gate 				ioparam.io_bounds.lower = 1;
11427c478bd9Sstevel@tonic-gate 				ioparam.io_bounds.upper = 2;
1143342440ecSPrasad Singamsetty 				err_print("1. Capacity = %llu, with pcyl = %u "
1144342440ecSPrasad Singamsetty 				    "nhead = %u nsect = %u\n",
1145342440ecSPrasad Singamsetty 				    ((diskaddr_t)pcyl * nhead * nsect),
1146342440ecSPrasad Singamsetty 				    pcyl, nhead, nsect);
1147342440ecSPrasad Singamsetty 				err_print("2. Capacity = %llu, with pcyl = %u "
1148342440ecSPrasad Singamsetty 				    "nhead = %u nsect = %u\n",
1149342440ecSPrasad Singamsetty 				    ((diskaddr_t)p * nhead * n),
1150342440ecSPrasad Singamsetty 				    p, nhead, n);
11517c478bd9Sstevel@tonic-gate 				if (input(FIO_INT, "Select one of the above "
11527c478bd9Sstevel@tonic-gate 				    "choices ", ':', &ioparam,
115365908c77Syu, larry liu - Sun Microsystems - Beijing China 				    &deflt, DATA_INPUT) == 2) {
11547c478bd9Sstevel@tonic-gate 					pcyl = p;
11557c478bd9Sstevel@tonic-gate 					nsect = n;
11567c478bd9Sstevel@tonic-gate 				}
11577c478bd9Sstevel@tonic-gate 			}
11587c478bd9Sstevel@tonic-gate 		}
11597c478bd9Sstevel@tonic-gate 	}
11607c478bd9Sstevel@tonic-gate 
11617c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
11627c478bd9Sstevel@tonic-gate 	/*
11637c478bd9Sstevel@tonic-gate 	 * Finally, we need to make sure we don't overflow any of the
11647c478bd9Sstevel@tonic-gate 	 * fields in our disk label.  To do this we need to `square
11657c478bd9Sstevel@tonic-gate 	 * the box' so to speak.  We will lose bits here.
11667c478bd9Sstevel@tonic-gate 	 */
11677c478bd9Sstevel@tonic-gate 
11687c478bd9Sstevel@tonic-gate 	if ((pcyl > MAXIMUM_NO_CYLINDERS &&
116965908c77Syu, larry liu - Sun Microsystems - Beijing China 	    ((nsect > MAXIMUM_NO_SECTORS) ||
117065908c77Syu, larry liu - Sun Microsystems - Beijing China 	    (nhead > MAXIMUM_NO_HEADS))) ||
117165908c77Syu, larry liu - Sun Microsystems - Beijing China 	    ((nsect > MAXIMUM_NO_SECTORS) &&
117265908c77Syu, larry liu - Sun Microsystems - Beijing China 	    (nhead > MAXIMUM_NO_HEADS))) {
11737c478bd9Sstevel@tonic-gate 		err_print("This disk is too big to label. "
117465908c77Syu, larry liu - Sun Microsystems - Beijing China 		    " You will lose some blocks.\n");
11757c478bd9Sstevel@tonic-gate 	}
11767c478bd9Sstevel@tonic-gate 	if ((pcyl > MAXIMUM_NO_CYLINDERS) ||
117765908c77Syu, larry liu - Sun Microsystems - Beijing China 	    (nsect > MAXIMUM_NO_SECTORS) ||
117865908c77Syu, larry liu - Sun Microsystems - Beijing China 	    (nhead > MAXIMUM_NO_HEADS)) {
11797c478bd9Sstevel@tonic-gate 		u_ioparam_t	ioparam;
11807c478bd9Sstevel@tonic-gate 		int		order;
11817c478bd9Sstevel@tonic-gate 		char		msg[256];
11827c478bd9Sstevel@tonic-gate 
1183d2a20373Sbz 		order = ((pcyl > nhead)<<2) |
1184d2a20373Sbz 		    ((pcyl > nsect)<<1) |
1185d2a20373Sbz 		    (nhead > nsect);
11867c478bd9Sstevel@tonic-gate 		switch (order) {
1187d2a20373Sbz 		case 0x7: /* pcyl > nhead > nsect */
11887c478bd9Sstevel@tonic-gate 			nblocks =
118965908c77Syu, larry liu - Sun Microsystems - Beijing China 			    square_box(nblocks,
119065908c77Syu, larry liu - Sun Microsystems - Beijing China 			    &pcyl, MAXIMUM_NO_CYLINDERS,
119165908c77Syu, larry liu - Sun Microsystems - Beijing China 			    &nhead, MAXIMUM_NO_HEADS,
119265908c77Syu, larry liu - Sun Microsystems - Beijing China 			    &nsect, MAXIMUM_NO_SECTORS);
11937c478bd9Sstevel@tonic-gate 			break;
1194d2a20373Sbz 		case 0x6: /* pcyl > nsect > nhead */
11957c478bd9Sstevel@tonic-gate 			nblocks =
119665908c77Syu, larry liu - Sun Microsystems - Beijing China 			    square_box(nblocks,
119765908c77Syu, larry liu - Sun Microsystems - Beijing China 			    &pcyl, MAXIMUM_NO_CYLINDERS,
119865908c77Syu, larry liu - Sun Microsystems - Beijing China 			    &nsect, MAXIMUM_NO_SECTORS,
119965908c77Syu, larry liu - Sun Microsystems - Beijing China 			    &nhead, MAXIMUM_NO_HEADS);
12007c478bd9Sstevel@tonic-gate 			break;
1201d2a20373Sbz 		case 0x4: /* nsect > pcyl > nhead */
12027c478bd9Sstevel@tonic-gate 			nblocks =
120365908c77Syu, larry liu - Sun Microsystems - Beijing China 			    square_box(nblocks,
120465908c77Syu, larry liu - Sun Microsystems - Beijing China 			    &nsect, MAXIMUM_NO_SECTORS,
120565908c77Syu, larry liu - Sun Microsystems - Beijing China 			    &pcyl, MAXIMUM_NO_CYLINDERS,
120665908c77Syu, larry liu - Sun Microsystems - Beijing China 			    &nhead, MAXIMUM_NO_HEADS);
12077c478bd9Sstevel@tonic-gate 			break;
1208d2a20373Sbz 		case 0x0: /* nsect > nhead > pcyl */
12097c478bd9Sstevel@tonic-gate 			nblocks =
121065908c77Syu, larry liu - Sun Microsystems - Beijing China 			    square_box(nblocks,
121165908c77Syu, larry liu - Sun Microsystems - Beijing China 			    &nsect, MAXIMUM_NO_SECTORS,
121265908c77Syu, larry liu - Sun Microsystems - Beijing China 			    &nhead, MAXIMUM_NO_HEADS,
121365908c77Syu, larry liu - Sun Microsystems - Beijing China 			    &pcyl, MAXIMUM_NO_CYLINDERS);
12147c478bd9Sstevel@tonic-gate 			break;
1215d2a20373Sbz 		case 0x3: /* nhead > pcyl > nsect */
12167c478bd9Sstevel@tonic-gate 			nblocks =
121765908c77Syu, larry liu - Sun Microsystems - Beijing China 			    square_box(nblocks,
121865908c77Syu, larry liu - Sun Microsystems - Beijing China 			    &nhead, MAXIMUM_NO_HEADS,
121965908c77Syu, larry liu - Sun Microsystems - Beijing China 			    &pcyl, MAXIMUM_NO_CYLINDERS,
122065908c77Syu, larry liu - Sun Microsystems - Beijing China 			    &nsect, MAXIMUM_NO_SECTORS);
12217c478bd9Sstevel@tonic-gate 			break;
1222d2a20373Sbz 		case 0x1: /* nhead > nsect > pcyl */
12237c478bd9Sstevel@tonic-gate 			nblocks =
122465908c77Syu, larry liu - Sun Microsystems - Beijing China 			    square_box(nblocks,
122565908c77Syu, larry liu - Sun Microsystems - Beijing China 			    &nhead, MAXIMUM_NO_HEADS,
122665908c77Syu, larry liu - Sun Microsystems - Beijing China 			    &nsect, MAXIMUM_NO_SECTORS,
122765908c77Syu, larry liu - Sun Microsystems - Beijing China 			    &pcyl, MAXIMUM_NO_CYLINDERS);
12287c478bd9Sstevel@tonic-gate 			break;
12297c478bd9Sstevel@tonic-gate 		default:
12307c478bd9Sstevel@tonic-gate 			/* How did we get here? */
12317c478bd9Sstevel@tonic-gate 			impossible("label overflow adjustment");
12327c478bd9Sstevel@tonic-gate 
12337c478bd9Sstevel@tonic-gate 			/* Do something useful */
12347c478bd9Sstevel@tonic-gate 			nblocks =
123565908c77Syu, larry liu - Sun Microsystems - Beijing China 			    square_box(nblocks,
123665908c77Syu, larry liu - Sun Microsystems - Beijing China 			    &nhead, MAXIMUM_NO_HEADS,
123765908c77Syu, larry liu - Sun Microsystems - Beijing China 			    &nsect, MAXIMUM_NO_SECTORS,
123865908c77Syu, larry liu - Sun Microsystems - Beijing China 			    &pcyl, MAXIMUM_NO_CYLINDERS);
12397c478bd9Sstevel@tonic-gate 			break;
12407c478bd9Sstevel@tonic-gate 		}
12417c478bd9Sstevel@tonic-gate 		if (option_msg && diag_msg &&
12427c478bd9Sstevel@tonic-gate 		    (capacity->sc_capacity + 1 != nblocks)) {
12437c478bd9Sstevel@tonic-gate 			err_print("After adjusting geometry you lost"
1244342440ecSPrasad Singamsetty 			    " %llu of %llu blocks.\n",
1245342440ecSPrasad Singamsetty 			    (capacity->sc_capacity + 1 - nblocks),
1246342440ecSPrasad Singamsetty 			    capacity->sc_capacity + 1);
12477c478bd9Sstevel@tonic-gate 		}
12487c478bd9Sstevel@tonic-gate 		while (can_prompt && expert_mode && !option_f) {
12497c478bd9Sstevel@tonic-gate 			int				deflt = 1;
12507c478bd9Sstevel@tonic-gate 
12517c478bd9Sstevel@tonic-gate 			/*
12527c478bd9Sstevel@tonic-gate 			 * Allow user to modify this by hand if desired.
12537c478bd9Sstevel@tonic-gate 			 */
12547c478bd9Sstevel@tonic-gate 			(void) sprintf(msg,
1255342440ecSPrasad Singamsetty 			    "\nGeometry: %u heads, %u sectors %u cylinders"
1256342440ecSPrasad Singamsetty 			    " result in %llu out of %llu blocks.\n"
1257342440ecSPrasad Singamsetty 			    "Do you want to modify the device geometry",
1258342440ecSPrasad Singamsetty 			    nhead, nsect, pcyl,
1259342440ecSPrasad Singamsetty 			    nblocks, capacity->sc_capacity + 1);
12607c478bd9Sstevel@tonic-gate 
12617c478bd9Sstevel@tonic-gate 			ioparam.io_charlist = confirm_list;
12627c478bd9Sstevel@tonic-gate 			if (input(FIO_MSTR, msg, '?', &ioparam,
126365908c77Syu, larry liu - Sun Microsystems - Beijing China 			    &deflt, DATA_INPUT) != 0)
12647c478bd9Sstevel@tonic-gate 				break;
12657c478bd9Sstevel@tonic-gate 
12667c478bd9Sstevel@tonic-gate 			ioparam.io_bounds.lower = MINIMUM_NO_HEADS;
12677c478bd9Sstevel@tonic-gate 			ioparam.io_bounds.upper = MAXIMUM_NO_HEADS;
12687c478bd9Sstevel@tonic-gate 			nhead = input(FIO_INT, "Number of heads", ':',
1269342440ecSPrasad Singamsetty 			    &ioparam, (int *)&nhead, DATA_INPUT);
12707c478bd9Sstevel@tonic-gate 			ioparam.io_bounds.lower = MINIMUM_NO_SECTORS;
12717c478bd9Sstevel@tonic-gate 			ioparam.io_bounds.upper = MAXIMUM_NO_SECTORS;
12727c478bd9Sstevel@tonic-gate 			nsect = input(FIO_INT,
1273342440ecSPrasad Singamsetty 			    "Number of sectors per track",
1274342440ecSPrasad Singamsetty 			    ':', &ioparam, (int *)&nsect, DATA_INPUT);
12757c478bd9Sstevel@tonic-gate 			ioparam.io_bounds.lower = SUN_MIN_CYL;
12767c478bd9Sstevel@tonic-gate 			ioparam.io_bounds.upper = MAXIMUM_NO_CYLINDERS;
12777c478bd9Sstevel@tonic-gate 			pcyl = input(FIO_INT, "Number of cylinders",
1278342440ecSPrasad Singamsetty 			    ':', &ioparam, (int *)&pcyl, DATA_INPUT);
1279342440ecSPrasad Singamsetty 			nblocks = (diskaddr_t)nhead * nsect * pcyl;
12807c478bd9Sstevel@tonic-gate 			if (nblocks > capacity->sc_capacity + 1) {
1281342440ecSPrasad Singamsetty 				err_print("Warning: %llu blocks exceeds "
1282342440ecSPrasad Singamsetty 				    "disk capacity of %llu blocks\n",
1283342440ecSPrasad Singamsetty 				    nblocks,
1284342440ecSPrasad Singamsetty 				    capacity->sc_capacity + 1);
12857c478bd9Sstevel@tonic-gate 			}
12867c478bd9Sstevel@tonic-gate 		}
12877c478bd9Sstevel@tonic-gate 	}
12887c478bd9Sstevel@tonic-gate #endif		/* defined(_SUNOS_VTOC_8) */
12897c478bd9Sstevel@tonic-gate 
12907c478bd9Sstevel@tonic-gate 	ncyl = pcyl - acyl;
12917c478bd9Sstevel@tonic-gate 
12927c478bd9Sstevel@tonic-gate 	if (option_msg && diag_msg) {
12937c478bd9Sstevel@tonic-gate 		err_print("\nGeometry after adjusting for capacity:\n");
1294342440ecSPrasad Singamsetty 		err_print("    pcyl:    %u\n", pcyl);
1295342440ecSPrasad Singamsetty 		err_print("    ncyl:    %u\n", ncyl);
1296342440ecSPrasad Singamsetty 		err_print("    heads:   %u\n", nhead);
1297342440ecSPrasad Singamsetty 		err_print("    nsects:  %u\n", nsect);
1298342440ecSPrasad Singamsetty 		err_print("    acyl:    %u\n", acyl);
12997c478bd9Sstevel@tonic-gate 		err_print("    rpm:     %d\n", rpm);
13007c478bd9Sstevel@tonic-gate 	}
13017c478bd9Sstevel@tonic-gate 
13027c478bd9Sstevel@tonic-gate 	(void) memset((char *)label, 0, sizeof (struct dk_label));
13037c478bd9Sstevel@tonic-gate 
13047c478bd9Sstevel@tonic-gate 	label->dkl_magic = DKL_MAGIC;
13057c478bd9Sstevel@tonic-gate 
13067c478bd9Sstevel@tonic-gate 	(void) snprintf(label->dkl_asciilabel, sizeof (label->dkl_asciilabel),
1307342440ecSPrasad Singamsetty 	    "%s cyl %u alt %u hd %u sec %u",
1308342440ecSPrasad Singamsetty 	    disk_name, ncyl, acyl, nhead, nsect);
13097c478bd9Sstevel@tonic-gate 
13107c478bd9Sstevel@tonic-gate 	label->dkl_pcyl = pcyl;
13117c478bd9Sstevel@tonic-gate 	label->dkl_ncyl = ncyl;
13127c478bd9Sstevel@tonic-gate 	label->dkl_acyl = acyl;
13137c478bd9Sstevel@tonic-gate 	label->dkl_nhead = nhead;
13147c478bd9Sstevel@tonic-gate 	label->dkl_nsect = nsect;
13157c478bd9Sstevel@tonic-gate 	label->dkl_apc = 0;
13167c478bd9Sstevel@tonic-gate 	label->dkl_intrlv = 1;
13177c478bd9Sstevel@tonic-gate 	label->dkl_rpm = rpm;
13187c478bd9Sstevel@tonic-gate 
13197c478bd9Sstevel@tonic-gate #if defined(_FIRMWARE_NEEDS_FDISK)
1320342440ecSPrasad Singamsetty 	if (auto_solaris_part(label) == -1)
1321342440ecSPrasad Singamsetty 		goto err;
13227c478bd9Sstevel@tonic-gate 	ncyl = label->dkl_ncyl;
13237c478bd9Sstevel@tonic-gate #endif		/* defined(_FIRMWARE_NEEDS_FDISK) */
13247c478bd9Sstevel@tonic-gate 
13257c478bd9Sstevel@tonic-gate 
13267c478bd9Sstevel@tonic-gate 	if (!build_default_partition(label, DKC_SCSI_CCS)) {
13277c478bd9Sstevel@tonic-gate 		goto err;
13287c478bd9Sstevel@tonic-gate 	}
13297c478bd9Sstevel@tonic-gate 
13307c478bd9Sstevel@tonic-gate 	(void) checksum(label, CK_MAKESUM);
13317c478bd9Sstevel@tonic-gate 
13327c478bd9Sstevel@tonic-gate 	/*
13337c478bd9Sstevel@tonic-gate 	 * Find an existing disk type defined for this disk.
13347c478bd9Sstevel@tonic-gate 	 * For this to work, both the name and geometry must
13357c478bd9Sstevel@tonic-gate 	 * match.  If there is no such type, but there already
13367c478bd9Sstevel@tonic-gate 	 * is a disk defined with that name, but with a different
13377c478bd9Sstevel@tonic-gate 	 * geometry, construct a new generic disk name out of
13387c478bd9Sstevel@tonic-gate 	 * the inquiry information.  Whatever name we're
13397c478bd9Sstevel@tonic-gate 	 * finally using, if there's no such disk type defined,
13407c478bd9Sstevel@tonic-gate 	 * build a new disk definition.
13417c478bd9Sstevel@tonic-gate 	 */
13427c478bd9Sstevel@tonic-gate 	if ((disk = find_scsi_disk_type(disk_name, label)) == NULL) {
13437c478bd9Sstevel@tonic-gate 		if (find_scsi_disk_by_name(disk_name) != NULL) {
13447c478bd9Sstevel@tonic-gate 			char	old_name[DISK_NAME_MAX];
13457c478bd9Sstevel@tonic-gate 			(void) strcpy(old_name, disk_name);
13467c478bd9Sstevel@tonic-gate 			(void) get_generic_disk_name(disk_name,
134765908c77Syu, larry liu - Sun Microsystems - Beijing China 			    inquiry);
13487c478bd9Sstevel@tonic-gate 			if (option_msg && diag_msg) {
13497c478bd9Sstevel@tonic-gate 				err_print(
13507c478bd9Sstevel@tonic-gate "Changing disk type name from '%s' to '%s'\n", old_name, disk_name);
13517c478bd9Sstevel@tonic-gate 			}
13527c478bd9Sstevel@tonic-gate 			(void) snprintf(label->dkl_asciilabel,
1353342440ecSPrasad Singamsetty 			    sizeof (label->dkl_asciilabel),
1354342440ecSPrasad Singamsetty 			    "%s cyl %u alt %u hd %u sec %u",
1355342440ecSPrasad Singamsetty 			    disk_name, ncyl, acyl, nhead, nsect);
13567c478bd9Sstevel@tonic-gate 			(void) checksum(label, CK_MAKESUM);
13577c478bd9Sstevel@tonic-gate 			disk = find_scsi_disk_type(disk_name, label);
13587c478bd9Sstevel@tonic-gate 		}
13597c478bd9Sstevel@tonic-gate 		if (disk == NULL) {
13607c478bd9Sstevel@tonic-gate 			disk = new_scsi_disk_type(fd, disk_name, label);
13617c478bd9Sstevel@tonic-gate 			if (disk == NULL)
13627c478bd9Sstevel@tonic-gate 				goto err;
13637c478bd9Sstevel@tonic-gate 		}
13647c478bd9Sstevel@tonic-gate 	}
13657c478bd9Sstevel@tonic-gate 
13667c478bd9Sstevel@tonic-gate 	return (disk);
13677c478bd9Sstevel@tonic-gate 
13687c478bd9Sstevel@tonic-gate err:
13697c478bd9Sstevel@tonic-gate 	if (option_msg && diag_msg) {
13707c478bd9Sstevel@tonic-gate 		err_print(
13717c478bd9Sstevel@tonic-gate 		"Configuration via generic SCSI-2 information failed\n");
13727c478bd9Sstevel@tonic-gate 	}
13737c478bd9Sstevel@tonic-gate 	return (NULL);
13747c478bd9Sstevel@tonic-gate }
13757c478bd9Sstevel@tonic-gate 
13767c478bd9Sstevel@tonic-gate 
13777c478bd9Sstevel@tonic-gate /*ARGSUSED*/
13787c478bd9Sstevel@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)13797c478bd9Sstevel@tonic-gate use_existing_disk_type(
13807c478bd9Sstevel@tonic-gate 	int			fd,
13817c478bd9Sstevel@tonic-gate 	int			can_prompt,
13827c478bd9Sstevel@tonic-gate 	struct dk_label		*label,
13837c478bd9Sstevel@tonic-gate 	struct scsi_inquiry	*inquiry,
13847c478bd9Sstevel@tonic-gate 	struct disk_type	*disk_type,
13857c478bd9Sstevel@tonic-gate 	struct scsi_capacity_16	*capacity)
13867c478bd9Sstevel@tonic-gate {
13877c478bd9Sstevel@tonic-gate 	int			pcyl;
13887c478bd9Sstevel@tonic-gate 	int			acyl;
13897c478bd9Sstevel@tonic-gate 	int			nhead;
13907c478bd9Sstevel@tonic-gate 	int			nsect;
13917c478bd9Sstevel@tonic-gate 	int			rpm;
13927c478bd9Sstevel@tonic-gate 
13937c478bd9Sstevel@tonic-gate 	/*
13947c478bd9Sstevel@tonic-gate 	 * Construct a new label out of the format.dat
13957c478bd9Sstevel@tonic-gate 	 */
13967c478bd9Sstevel@tonic-gate 	pcyl = disk_type->dtype_pcyl;
13977c478bd9Sstevel@tonic-gate 	acyl = disk_type->dtype_acyl;
13987c478bd9Sstevel@tonic-gate 	ncyl = disk_type->dtype_ncyl;
13997c478bd9Sstevel@tonic-gate 	nhead = disk_type->dtype_nhead;
14007c478bd9Sstevel@tonic-gate 	nsect = disk_type->dtype_nsect;
14017c478bd9Sstevel@tonic-gate 	rpm = disk_type->dtype_rpm;
14027c478bd9Sstevel@tonic-gate 
14037c478bd9Sstevel@tonic-gate 	if (option_msg && diag_msg) {
14047c478bd9Sstevel@tonic-gate 		err_print("Format.dat geometry:\n");
1405342440ecSPrasad Singamsetty 		err_print("    pcyl:    %u\n", pcyl);
1406342440ecSPrasad Singamsetty 		err_print("    heads:   %u\n", nhead);
1407342440ecSPrasad Singamsetty 		err_print("    nsects:  %u\n", nsect);
1408342440ecSPrasad Singamsetty 		err_print("    acyl:    %u\n", acyl);
14097c478bd9Sstevel@tonic-gate 		err_print("    rpm:     %d\n", rpm);
14107c478bd9Sstevel@tonic-gate 	}
14117c478bd9Sstevel@tonic-gate 
14127c478bd9Sstevel@tonic-gate 	(void) memset((char *)label, 0, sizeof (struct dk_label));
14137c478bd9Sstevel@tonic-gate 
14147c478bd9Sstevel@tonic-gate 	label->dkl_magic = DKL_MAGIC;
14157c478bd9Sstevel@tonic-gate 
14167c478bd9Sstevel@tonic-gate 	(void) snprintf(label->dkl_asciilabel, sizeof (label->dkl_asciilabel),
1417342440ecSPrasad Singamsetty 	    "%s cyl %u alt %u hd %u sec %u",
1418342440ecSPrasad Singamsetty 	    disk_type->dtype_asciilabel,
1419342440ecSPrasad Singamsetty 	    ncyl, acyl, nhead, nsect);
14207c478bd9Sstevel@tonic-gate 
14217c478bd9Sstevel@tonic-gate 	label->dkl_pcyl = pcyl;
14227c478bd9Sstevel@tonic-gate 	label->dkl_ncyl = ncyl;
14237c478bd9Sstevel@tonic-gate 	label->dkl_acyl = acyl;
14247c478bd9Sstevel@tonic-gate 	label->dkl_nhead = nhead;
14257c478bd9Sstevel@tonic-gate 	label->dkl_nsect = nsect;
14267c478bd9Sstevel@tonic-gate 	label->dkl_apc = 0;
14277c478bd9Sstevel@tonic-gate 	label->dkl_intrlv = 1;
14287c478bd9Sstevel@tonic-gate 	label->dkl_rpm = rpm;
14297c478bd9Sstevel@tonic-gate 
14307c478bd9Sstevel@tonic-gate 	if (!build_default_partition(label, DKC_SCSI_CCS)) {
14317c478bd9Sstevel@tonic-gate 		goto err;
14327c478bd9Sstevel@tonic-gate 	}
14337c478bd9Sstevel@tonic-gate 
14347c478bd9Sstevel@tonic-gate 	(void) checksum(label, CK_MAKESUM);
14357c478bd9Sstevel@tonic-gate 	return (1);
14367c478bd9Sstevel@tonic-gate 
14377c478bd9Sstevel@tonic-gate err:
14387c478bd9Sstevel@tonic-gate 	if (option_msg && diag_msg) {
14397c478bd9Sstevel@tonic-gate 		err_print(
144065908c77Syu, larry liu - Sun Microsystems - Beijing China 		    "Configuration via format.dat geometry failed\n");
14417c478bd9Sstevel@tonic-gate 	}
14427c478bd9Sstevel@tonic-gate 	return (0);
14437c478bd9Sstevel@tonic-gate }
14447c478bd9Sstevel@tonic-gate 
14457c478bd9Sstevel@tonic-gate int
build_default_partition(struct dk_label * label,int ctrl_type)14467c478bd9Sstevel@tonic-gate build_default_partition(
14477c478bd9Sstevel@tonic-gate 	struct dk_label			*label,
14487c478bd9Sstevel@tonic-gate 	int				ctrl_type)
14497c478bd9Sstevel@tonic-gate {
14507c478bd9Sstevel@tonic-gate 	int				i;
14517c478bd9Sstevel@tonic-gate 	int				ncyls[NDKMAP];
1452342440ecSPrasad Singamsetty 	diskaddr_t			nblks;
14537c478bd9Sstevel@tonic-gate 	int				cyl;
14547c478bd9Sstevel@tonic-gate 	struct dk_vtoc			*vtoc;
14557c478bd9Sstevel@tonic-gate 	struct part_table		*pt;
14567c478bd9Sstevel@tonic-gate 	struct default_partitions	*dpt;
1457342440ecSPrasad Singamsetty 	diskaddr_t			capacity;
14587c478bd9Sstevel@tonic-gate 	int				freecyls;
14597c478bd9Sstevel@tonic-gate 	int				blks_per_cyl;
14607c478bd9Sstevel@tonic-gate 	int				ncyl;
14617c478bd9Sstevel@tonic-gate 
14627c478bd9Sstevel@tonic-gate #ifdef lint
14637c478bd9Sstevel@tonic-gate 	ctrl_type = ctrl_type;
14647c478bd9Sstevel@tonic-gate #endif
14657c478bd9Sstevel@tonic-gate 
14667c478bd9Sstevel@tonic-gate 	/*
14677c478bd9Sstevel@tonic-gate 	 * Install a default vtoc
14687c478bd9Sstevel@tonic-gate 	 */
14697c478bd9Sstevel@tonic-gate 	vtoc = &label->dkl_vtoc;
14707c478bd9Sstevel@tonic-gate 	vtoc->v_version = V_VERSION;
14717c478bd9Sstevel@tonic-gate 	vtoc->v_nparts = NDKMAP;
14727c478bd9Sstevel@tonic-gate 	vtoc->v_sanity = VTOC_SANE;
14737c478bd9Sstevel@tonic-gate 
14747c478bd9Sstevel@tonic-gate 	for (i = 0; i < NDKMAP; i++) {
14757c478bd9Sstevel@tonic-gate 		vtoc->v_part[i].p_tag = default_vtoc_map[i].p_tag;
14767c478bd9Sstevel@tonic-gate 		vtoc->v_part[i].p_flag = default_vtoc_map[i].p_flag;
14777c478bd9Sstevel@tonic-gate 	}
14787c478bd9Sstevel@tonic-gate 
14797c478bd9Sstevel@tonic-gate 	/*
14807c478bd9Sstevel@tonic-gate 	 * Find a partition that matches this disk.  Capacity
14817c478bd9Sstevel@tonic-gate 	 * is in integral number of megabytes.
14827c478bd9Sstevel@tonic-gate 	 */
1483342440ecSPrasad Singamsetty 	capacity = ((diskaddr_t)(label->dkl_ncyl) * label->dkl_nhead *
148482bff436Sbo zhou - Sun Microsystems - Beijing China 	    label->dkl_nsect) / (diskaddr_t)((1024 * 1024) / cur_blksz);
14857c478bd9Sstevel@tonic-gate 	dpt = default_partitions;
14867c478bd9Sstevel@tonic-gate 	for (i = 0; i < DEFAULT_PARTITION_TABLE_SIZE; i++, dpt++) {
14877c478bd9Sstevel@tonic-gate 		if (capacity >= dpt->min_capacity &&
148865908c77Syu, larry liu - Sun Microsystems - Beijing China 		    capacity < dpt->max_capacity) {
14897c478bd9Sstevel@tonic-gate 			break;
14907c478bd9Sstevel@tonic-gate 		}
14917c478bd9Sstevel@tonic-gate 	}
14927c478bd9Sstevel@tonic-gate 	if (i == DEFAULT_PARTITION_TABLE_SIZE) {
14937c478bd9Sstevel@tonic-gate 		if (option_msg && diag_msg) {
1494342440ecSPrasad Singamsetty 			err_print("No matching default partition (%llu)\n",
1495342440ecSPrasad Singamsetty 			    capacity);
14967c478bd9Sstevel@tonic-gate 		}
14977c478bd9Sstevel@tonic-gate 		return (0);
14987c478bd9Sstevel@tonic-gate 	}
14997c478bd9Sstevel@tonic-gate 	pt = dpt->part_table;
15007c478bd9Sstevel@tonic-gate 
15017c478bd9Sstevel@tonic-gate 	/*
15027c478bd9Sstevel@tonic-gate 	 * Go through default partition table, finding fixed
15037c478bd9Sstevel@tonic-gate 	 * sized entries.
15047c478bd9Sstevel@tonic-gate 	 */
15057c478bd9Sstevel@tonic-gate 	freecyls = label->dkl_ncyl;
15067c478bd9Sstevel@tonic-gate 	blks_per_cyl = label->dkl_nhead * label->dkl_nsect;
15077c478bd9Sstevel@tonic-gate 	for (i = 0; i < NDKMAP; i++) {
15087c478bd9Sstevel@tonic-gate 		if (pt->partitions[i] == HOG || pt->partitions[i] == 0) {
15097c478bd9Sstevel@tonic-gate 			ncyls[i] = 0;
15107c478bd9Sstevel@tonic-gate 		} else {
15117c478bd9Sstevel@tonic-gate 			/*
15127c478bd9Sstevel@tonic-gate 			 * Calculate number of cylinders necessary
15137c478bd9Sstevel@tonic-gate 			 * for specified size, rounding up to
15147c478bd9Sstevel@tonic-gate 			 * the next greatest integral number of
15157c478bd9Sstevel@tonic-gate 			 * cylinders.  Always give what they
15167c478bd9Sstevel@tonic-gate 			 * asked or more, never less.
15177c478bd9Sstevel@tonic-gate 			 */
151865908c77Syu, larry liu - Sun Microsystems - Beijing China 			nblks = pt->partitions[i] * ((1024*1024)/cur_blksz);
15197c478bd9Sstevel@tonic-gate 			nblks += (blks_per_cyl - 1);
15207c478bd9Sstevel@tonic-gate 			ncyls[i] = nblks / blks_per_cyl;
15217c478bd9Sstevel@tonic-gate 			freecyls -= ncyls[i];
15227c478bd9Sstevel@tonic-gate 		}
15237c478bd9Sstevel@tonic-gate 	}
15247c478bd9Sstevel@tonic-gate 
15257c478bd9Sstevel@tonic-gate 	if (freecyls < 0) {
15267c478bd9Sstevel@tonic-gate 		if (option_msg && diag_msg) {
15277c478bd9Sstevel@tonic-gate 			for (i = 0; i < NDKMAP; i++) {
15287c478bd9Sstevel@tonic-gate 				if (ncyls[i] == 0)
15297c478bd9Sstevel@tonic-gate 					continue;
1530342440ecSPrasad Singamsetty 				err_print("Partition %d: %u cyls\n",
1531342440ecSPrasad Singamsetty 				    i, ncyls[i]);
15327c478bd9Sstevel@tonic-gate 			}
15337c478bd9Sstevel@tonic-gate 			err_print("Free cylinders exhausted (%d)\n",
153465908c77Syu, larry liu - Sun Microsystems - Beijing China 			    freecyls);
15357c478bd9Sstevel@tonic-gate 		}
15367c478bd9Sstevel@tonic-gate 		return (0);
15377c478bd9Sstevel@tonic-gate 	}
15387c478bd9Sstevel@tonic-gate #if defined(i386)
15397c478bd9Sstevel@tonic-gate 	/*
15407c478bd9Sstevel@tonic-gate 	 * Set the default boot partition to 1 cylinder
15417c478bd9Sstevel@tonic-gate 	 */
15427c478bd9Sstevel@tonic-gate 	ncyls[8] = 1;
15437c478bd9Sstevel@tonic-gate 	freecyls -= 1;
15447c478bd9Sstevel@tonic-gate 
15457c478bd9Sstevel@tonic-gate 	/*
15467c478bd9Sstevel@tonic-gate 	 * If current disk type is not a SCSI disk,
15477c478bd9Sstevel@tonic-gate 	 * set the default alternates partition to 2 cylinders
15487c478bd9Sstevel@tonic-gate 	 */
15497c478bd9Sstevel@tonic-gate 	if (ctrl_type != DKC_SCSI_CCS) {
15507c478bd9Sstevel@tonic-gate 		ncyls[9] = 2;
15517c478bd9Sstevel@tonic-gate 		freecyls -= 2;
15527c478bd9Sstevel@tonic-gate 	}
15537c478bd9Sstevel@tonic-gate #endif			/* defined(i386) */
15547c478bd9Sstevel@tonic-gate 
15557c478bd9Sstevel@tonic-gate 	/*
15567c478bd9Sstevel@tonic-gate 	 * Set the free hog partition to whatever space remains.
15577c478bd9Sstevel@tonic-gate 	 * It's an error to have more than one HOG partition,
15587c478bd9Sstevel@tonic-gate 	 * but we don't verify that here.
15597c478bd9Sstevel@tonic-gate 	 */
15607c478bd9Sstevel@tonic-gate 	for (i = 0; i < NDKMAP; i++) {
15617c478bd9Sstevel@tonic-gate 		if (pt->partitions[i] == HOG) {
15627c478bd9Sstevel@tonic-gate 			assert(ncyls[i] == 0);
15637c478bd9Sstevel@tonic-gate 			ncyls[i] = freecyls;
15647c478bd9Sstevel@tonic-gate 			break;
15657c478bd9Sstevel@tonic-gate 		}
15667c478bd9Sstevel@tonic-gate 	}
15677c478bd9Sstevel@tonic-gate 
15687c478bd9Sstevel@tonic-gate 	/*
15697c478bd9Sstevel@tonic-gate 	 * Error checking
15707c478bd9Sstevel@tonic-gate 	 */
15717c478bd9Sstevel@tonic-gate 	ncyl = 0;
15727c478bd9Sstevel@tonic-gate 	for (i = 0; i < NDKMAP; i++) {
15737c478bd9Sstevel@tonic-gate 		ncyl += ncyls[i];
15747c478bd9Sstevel@tonic-gate 	}
15757c478bd9Sstevel@tonic-gate 	assert(ncyl == (label->dkl_ncyl));
15767c478bd9Sstevel@tonic-gate 
15777c478bd9Sstevel@tonic-gate 	/*
15787c478bd9Sstevel@tonic-gate 	 * Finally, install the partition in the label.
15797c478bd9Sstevel@tonic-gate 	 */
15807c478bd9Sstevel@tonic-gate 	cyl = 0;
15817c478bd9Sstevel@tonic-gate 
15827c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_16)
15837c478bd9Sstevel@tonic-gate 	for (i = NDKMAP/2; i < NDKMAP; i++) {
15847c478bd9Sstevel@tonic-gate 		if (i == 2 || ncyls[i] == 0)
15857c478bd9Sstevel@tonic-gate 			continue;
15867c478bd9Sstevel@tonic-gate 		label->dkl_vtoc.v_part[i].p_start = cyl * blks_per_cyl;
15877c478bd9Sstevel@tonic-gate 		label->dkl_vtoc.v_part[i].p_size = ncyls[i] * blks_per_cyl;
15887c478bd9Sstevel@tonic-gate 		cyl += ncyls[i];
15897c478bd9Sstevel@tonic-gate 	}
15907c478bd9Sstevel@tonic-gate 	for (i = 0; i < NDKMAP/2; i++) {
15917c478bd9Sstevel@tonic-gate 
15927c478bd9Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_8)
15937c478bd9Sstevel@tonic-gate 	for (i = 0; i < NDKMAP; i++) {
15947c478bd9Sstevel@tonic-gate 
15957c478bd9Sstevel@tonic-gate #else
15967c478bd9Sstevel@tonic-gate #error No VTOC format defined.
15977c478bd9Sstevel@tonic-gate #endif				/* defined(_SUNOS_VTOC_16) */
15987c478bd9Sstevel@tonic-gate 
15993ccda647Slclee 		if (i == 2 || ncyls[i] == 0) {
16003ccda647Slclee #if defined(_SUNOS_VTOC_8)
16013ccda647Slclee 			if (i != 2) {
16023ccda647Slclee 				label->dkl_map[i].dkl_cylno = 0;
16033ccda647Slclee 				label->dkl_map[i].dkl_nblk = 0;
16043ccda647Slclee 			}
16053ccda647Slclee #endif
16067c478bd9Sstevel@tonic-gate 			continue;
16073ccda647Slclee 		}
16087c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
16097c478bd9Sstevel@tonic-gate 		label->dkl_map[i].dkl_cylno = cyl;
16107c478bd9Sstevel@tonic-gate 		label->dkl_map[i].dkl_nblk = ncyls[i] * blks_per_cyl;
16117c478bd9Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16)
16127c478bd9Sstevel@tonic-gate 		label->dkl_vtoc.v_part[i].p_start = cyl * blks_per_cyl;
16137c478bd9Sstevel@tonic-gate 		label->dkl_vtoc.v_part[i].p_size = ncyls[i] * blks_per_cyl;
16147c478bd9Sstevel@tonic-gate 
16157c478bd9Sstevel@tonic-gate #else
16167c478bd9Sstevel@tonic-gate #error No VTOC format defined.
16177c478bd9Sstevel@tonic-gate #endif				/* defined(_SUNOS_VTOC_8) */
16187c478bd9Sstevel@tonic-gate 
16197c478bd9Sstevel@tonic-gate 		cyl += ncyls[i];
16207c478bd9Sstevel@tonic-gate 	}
16217c478bd9Sstevel@tonic-gate 
16227c478bd9Sstevel@tonic-gate 	/*
16237c478bd9Sstevel@tonic-gate 	 * Set the whole disk partition
16247c478bd9Sstevel@tonic-gate 	 */
16257c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
16267c478bd9Sstevel@tonic-gate 	label->dkl_map[2].dkl_cylno = 0;
16277c478bd9Sstevel@tonic-gate 	label->dkl_map[2].dkl_nblk =
162865908c77Syu, larry liu - Sun Microsystems - Beijing China 	    label->dkl_ncyl * label->dkl_nhead * label->dkl_nsect;
16297c478bd9Sstevel@tonic-gate 
16307c478bd9Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16)
16317c478bd9Sstevel@tonic-gate 	label->dkl_vtoc.v_part[2].p_start = 0;
16327c478bd9Sstevel@tonic-gate 	label->dkl_vtoc.v_part[2].p_size =
163365908c77Syu, larry liu - Sun Microsystems - Beijing China 	    (label->dkl_ncyl + label->dkl_acyl) * label->dkl_nhead *
163465908c77Syu, larry liu - Sun Microsystems - Beijing China 	    label->dkl_nsect;
16357c478bd9Sstevel@tonic-gate #else
16367c478bd9Sstevel@tonic-gate #error No VTOC format defined.
16377c478bd9Sstevel@tonic-gate #endif				/* defined(_SUNOS_VTOC_8) */
16387c478bd9Sstevel@tonic-gate 
16397c478bd9Sstevel@tonic-gate 
16407c478bd9Sstevel@tonic-gate 	if (option_msg && diag_msg) {
16417c478bd9Sstevel@tonic-gate 		float	scaled;
16427c478bd9Sstevel@tonic-gate 		err_print("\n");
16437c478bd9Sstevel@tonic-gate 		for (i = 0; i < NDKMAP; i++) {
16447c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
16457c478bd9Sstevel@tonic-gate 			if (label->dkl_map[i].dkl_nblk == 0)
16467c478bd9Sstevel@tonic-gate 
16477c478bd9Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16)
16487c478bd9Sstevel@tonic-gate 			if (label->dkl_vtoc.v_part[i].p_size == 0)
16497c478bd9Sstevel@tonic-gate 
16507c478bd9Sstevel@tonic-gate #else
16517c478bd9Sstevel@tonic-gate #error No VTOC format defined.
16527c478bd9Sstevel@tonic-gate #endif				/* defined(_SUNOS_VTOC_8) */
16537c478bd9Sstevel@tonic-gate 
16547c478bd9Sstevel@tonic-gate 				continue;
16557c478bd9Sstevel@tonic-gate 			err_print("Partition %d:   ", i);
16567c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
16577c478bd9Sstevel@tonic-gate 			scaled = bn2mb(label->dkl_map[i].dkl_nblk);
16587c478bd9Sstevel@tonic-gate 
16597c478bd9Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16)
16607c478bd9Sstevel@tonic-gate 
16617c478bd9Sstevel@tonic-gate 			scaled = bn2mb(label->dkl_vtoc.v_part[i].p_size);
16627c478bd9Sstevel@tonic-gate #else
16637c478bd9Sstevel@tonic-gate #error No VTOC format defined.
16647c478bd9Sstevel@tonic-gate #endif				/* defined(_SUNOS_VTOC_8) */
16657c478bd9Sstevel@tonic-gate 
16667c478bd9Sstevel@tonic-gate 			if (scaled > 1024.0) {
16677c478bd9Sstevel@tonic-gate 				err_print("%6.2fGB  ", scaled/1024.0);
16687c478bd9Sstevel@tonic-gate 			} else {
16697c478bd9Sstevel@tonic-gate 				err_print("%6.2fMB  ", scaled);
16707c478bd9Sstevel@tonic-gate 			}
16717c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
167265908c77Syu, larry liu - Sun Microsystems - Beijing China 			err_print(" %6d cylinders\n",
16737c478bd9Sstevel@tonic-gate 			    label->dkl_map[i].dkl_nblk/blks_per_cyl);
16747c478bd9Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16)
167565908c77Syu, larry liu - Sun Microsystems - Beijing China 			err_print(" %6d cylinders\n",
16767c478bd9Sstevel@tonic-gate 			    label->dkl_vtoc.v_part[i].p_size/blks_per_cyl);
16777c478bd9Sstevel@tonic-gate #else
16787c478bd9Sstevel@tonic-gate #error No VTOC format defined.
16797c478bd9Sstevel@tonic-gate #endif				/* defined(_SUNOS_VTOC_8) */
16807c478bd9Sstevel@tonic-gate 
16817c478bd9Sstevel@tonic-gate 		}
16827c478bd9Sstevel@tonic-gate 		err_print("\n");
16837c478bd9Sstevel@tonic-gate 	}
16847c478bd9Sstevel@tonic-gate 
16857c478bd9Sstevel@tonic-gate 	return (1);
16867c478bd9Sstevel@tonic-gate }
16877c478bd9Sstevel@tonic-gate 
16887c478bd9Sstevel@tonic-gate 
16897c478bd9Sstevel@tonic-gate 
16907c478bd9Sstevel@tonic-gate /*
16917c478bd9Sstevel@tonic-gate  * Find an existing scsi disk definition by this name,
16927c478bd9Sstevel@tonic-gate  * if possible.
16937c478bd9Sstevel@tonic-gate  */
16947c478bd9Sstevel@tonic-gate static struct disk_type *
16957c478bd9Sstevel@tonic-gate find_scsi_disk_type(
16967c478bd9Sstevel@tonic-gate 	char			*disk_name,
16977c478bd9Sstevel@tonic-gate 	struct dk_label		*label)
16987c478bd9Sstevel@tonic-gate {
16997c478bd9Sstevel@tonic-gate 	struct ctlr_type	*ctlr;
17007c478bd9Sstevel@tonic-gate 	struct disk_type	*dp;
17017c478bd9Sstevel@tonic-gate 
17027c478bd9Sstevel@tonic-gate 	ctlr = find_scsi_ctlr_type();
17037c478bd9Sstevel@tonic-gate 	for (dp = ctlr->ctype_dlist; dp != NULL; dp = dp->dtype_next) {
170465908c77Syu, larry liu - Sun Microsystems - Beijing China 		if (dp->dtype_asciilabel) {
170565908c77Syu, larry liu - Sun Microsystems - Beijing China 			if ((strcmp(dp->dtype_asciilabel, disk_name) == 0) &&
170665908c77Syu, larry liu - Sun Microsystems - Beijing China 			    dp->dtype_pcyl == label->dkl_pcyl &&
170765908c77Syu, larry liu - Sun Microsystems - Beijing China 			    dp->dtype_ncyl == label->dkl_ncyl &&
170865908c77Syu, larry liu - Sun Microsystems - Beijing China 			    dp->dtype_acyl == label->dkl_acyl &&
170965908c77Syu, larry liu - Sun Microsystems - Beijing China 			    dp->dtype_nhead == label->dkl_nhead &&
171065908c77Syu, larry liu - Sun Microsystems - Beijing China 			    dp->dtype_nsect == label->dkl_nsect) {
171165908c77Syu, larry liu - Sun Microsystems - Beijing China 				return (dp);
171265908c77Syu, larry liu - Sun Microsystems - Beijing China 			}
17137c478bd9Sstevel@tonic-gate 		}
17147c478bd9Sstevel@tonic-gate 	}
17157c478bd9Sstevel@tonic-gate 
1716b12aaafbSToomas Soome 	return (NULL);
17177c478bd9Sstevel@tonic-gate }
17187c478bd9Sstevel@tonic-gate 
17197c478bd9Sstevel@tonic-gate 
17207c478bd9Sstevel@tonic-gate /*
17217c478bd9Sstevel@tonic-gate  * Find an existing scsi disk definition by this name,
17227c478bd9Sstevel@tonic-gate  * if possible.
17237c478bd9Sstevel@tonic-gate  */
17247c478bd9Sstevel@tonic-gate static struct disk_type *
17257c478bd9Sstevel@tonic-gate find_scsi_disk_by_name(
17267c478bd9Sstevel@tonic-gate 	char			*disk_name)
17277c478bd9Sstevel@tonic-gate {
17287c478bd9Sstevel@tonic-gate 	struct ctlr_type	*ctlr;
17297c478bd9Sstevel@tonic-gate 	struct disk_type	*dp;
17307c478bd9Sstevel@tonic-gate 
17317c478bd9Sstevel@tonic-gate 	ctlr = find_scsi_ctlr_type();
17327c478bd9Sstevel@tonic-gate 	for (dp = ctlr->ctype_dlist; dp != NULL; dp = dp->dtype_next) {
173365908c77Syu, larry liu - Sun Microsystems - Beijing China 		if (dp->dtype_asciilabel) {
173465908c77Syu, larry liu - Sun Microsystems - Beijing China 			if ((strcmp(dp->dtype_asciilabel, disk_name) == 0)) {
173565908c77Syu, larry liu - Sun Microsystems - Beijing China 				return (dp);
173665908c77Syu, larry liu - Sun Microsystems - Beijing China 			}
17377c478bd9Sstevel@tonic-gate 		}
17387c478bd9Sstevel@tonic-gate 	}
17397c478bd9Sstevel@tonic-gate 
1740b12aaafbSToomas Soome 	return (NULL);
17417c478bd9Sstevel@tonic-gate }
17427c478bd9Sstevel@tonic-gate 
17437c478bd9Sstevel@tonic-gate 
17447c478bd9Sstevel@tonic-gate /*
17457c478bd9Sstevel@tonic-gate  * Return a pointer to the ctlr_type structure for SCSI
17467c478bd9Sstevel@tonic-gate  * disks.  This list is built into the program, so there's
17477c478bd9Sstevel@tonic-gate  * no chance of not being able to find it, unless someone
17487c478bd9Sstevel@tonic-gate  * totally mangles the code.
17497c478bd9Sstevel@tonic-gate  */
17507c478bd9Sstevel@tonic-gate static struct ctlr_type *
1751b12aaafbSToomas Soome find_scsi_ctlr_type(void)
17527c478bd9Sstevel@tonic-gate {
17537c478bd9Sstevel@tonic-gate 	struct	mctlr_list	*mlp;
17547c478bd9Sstevel@tonic-gate 
17557c478bd9Sstevel@tonic-gate 	mlp = controlp;
17567c478bd9Sstevel@tonic-gate 
17577c478bd9Sstevel@tonic-gate 	while (mlp != NULL) {
1758f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 		if (mlp->ctlr_type->ctype_ctype == DKC_SCSI_CCS) {
17597c478bd9Sstevel@tonic-gate 			return (mlp->ctlr_type);
17607c478bd9Sstevel@tonic-gate 		}
17613959f00fSbo zhou - Sun Microsystems - Beijing China 		mlp = mlp->next;
17627c478bd9Sstevel@tonic-gate 	}
17637c478bd9Sstevel@tonic-gate 
17647c478bd9Sstevel@tonic-gate 	impossible("no SCSI controller type");
1765052b6e8aSbg 
1766b12aaafbSToomas Soome 	return (NULL);
17677c478bd9Sstevel@tonic-gate }
17687c478bd9Sstevel@tonic-gate 
17697c478bd9Sstevel@tonic-gate 
17707c478bd9Sstevel@tonic-gate 
17717c478bd9Sstevel@tonic-gate /*
17727c478bd9Sstevel@tonic-gate  * Return a pointer to the scsi ctlr_info structure.  This
17737c478bd9Sstevel@tonic-gate  * structure is allocated the first time format sees a
17747c478bd9Sstevel@tonic-gate  * disk on this controller, so it must be present.
17757c478bd9Sstevel@tonic-gate  */
17767c478bd9Sstevel@tonic-gate static struct ctlr_info *
17777c478bd9Sstevel@tonic-gate find_scsi_ctlr_info(
17787c478bd9Sstevel@tonic-gate 	struct dk_cinfo		*dkinfo)
17797c478bd9Sstevel@tonic-gate {
17807c478bd9Sstevel@tonic-gate 	struct ctlr_info	*ctlr;
17817c478bd9Sstevel@tonic-gate 
1782f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 	if (dkinfo->dki_ctype != DKC_SCSI_CCS) {
17837c478bd9Sstevel@tonic-gate 		return (NULL);
17847c478bd9Sstevel@tonic-gate 	}
17857c478bd9Sstevel@tonic-gate 
17867c478bd9Sstevel@tonic-gate 	for (ctlr = ctlr_list; ctlr != NULL; ctlr = ctlr->ctlr_next) {
17877c478bd9Sstevel@tonic-gate 		if (ctlr->ctlr_addr == dkinfo->dki_addr &&
17883959f00fSbo zhou - Sun Microsystems - Beijing China 		    ctlr->ctlr_space == dkinfo->dki_space &&
1789f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 		    ctlr->ctlr_ctype->ctype_ctype == DKC_SCSI_CCS) {
17907c478bd9Sstevel@tonic-gate 			return (ctlr);
17917c478bd9Sstevel@tonic-gate 		}
17927c478bd9Sstevel@tonic-gate 	}
17937c478bd9Sstevel@tonic-gate 
17947c478bd9Sstevel@tonic-gate 	impossible("no SCSI controller info");
1795052b6e8aSbg 
1796b12aaafbSToomas Soome 	return (NULL);
17977c478bd9Sstevel@tonic-gate }
17987c478bd9Sstevel@tonic-gate 
17997c478bd9Sstevel@tonic-gate 
18007c478bd9Sstevel@tonic-gate 
18017c478bd9Sstevel@tonic-gate static struct disk_type *
18027c478bd9Sstevel@tonic-gate new_scsi_disk_type(
18037c478bd9Sstevel@tonic-gate 	int		fd,
18047c478bd9Sstevel@tonic-gate 	char		*disk_name,
18057c478bd9Sstevel@tonic-gate 	struct dk_label	*label)
18067c478bd9Sstevel@tonic-gate {
18077c478bd9Sstevel@tonic-gate 	struct disk_type	*dp;
18087c478bd9Sstevel@tonic-gate 	struct disk_type	*disk;
18097c478bd9Sstevel@tonic-gate 	struct ctlr_info	*ctlr;
18107c478bd9Sstevel@tonic-gate 	struct dk_cinfo		dkinfo;
18117c478bd9Sstevel@tonic-gate 	struct partition_info	*part;
18127c478bd9Sstevel@tonic-gate 	struct partition_info	*pt;
18137c478bd9Sstevel@tonic-gate 	struct disk_info	*disk_info;
18147c478bd9Sstevel@tonic-gate 	int			i;
18157c478bd9Sstevel@tonic-gate 
18167c478bd9Sstevel@tonic-gate 	/*
18177c478bd9Sstevel@tonic-gate 	 * Get the disk controller info for this disk
18187c478bd9Sstevel@tonic-gate 	 */
18197c478bd9Sstevel@tonic-gate 	if (ioctl(fd, DKIOCINFO, &dkinfo) == -1) {
18207c478bd9Sstevel@tonic-gate 		if (option_msg && diag_msg) {
18217c478bd9Sstevel@tonic-gate 			err_print("DKIOCINFO failed\n");
18227c478bd9Sstevel@tonic-gate 		}
18237c478bd9Sstevel@tonic-gate 		return (NULL);
18247c478bd9Sstevel@tonic-gate 	}
18257c478bd9Sstevel@tonic-gate 
18267c478bd9Sstevel@tonic-gate 	/*
18277c478bd9Sstevel@tonic-gate 	 * Find the ctlr_info for this disk.
18287c478bd9Sstevel@tonic-gate 	 */
18297c478bd9Sstevel@tonic-gate 	ctlr = find_scsi_ctlr_info(&dkinfo);
18307c478bd9Sstevel@tonic-gate 
18317c478bd9Sstevel@tonic-gate 	/*
18327c478bd9Sstevel@tonic-gate 	 * Allocate a new disk type for the SCSI controller.
18337c478bd9Sstevel@tonic-gate 	 */
18347c478bd9Sstevel@tonic-gate 	disk = (struct disk_type *)zalloc(sizeof (struct disk_type));
18357c478bd9Sstevel@tonic-gate 
18367c478bd9Sstevel@tonic-gate 	/*
18377c478bd9Sstevel@tonic-gate 	 * Find the disk_info instance for this disk.
18387c478bd9Sstevel@tonic-gate 	 */
18397c478bd9Sstevel@tonic-gate 	disk_info = find_scsi_disk_info(&dkinfo);
18407c478bd9Sstevel@tonic-gate 
18417c478bd9Sstevel@tonic-gate 	/*
18427c478bd9Sstevel@tonic-gate 	 * The controller and the disk should match.
18437c478bd9Sstevel@tonic-gate 	 */
18447c478bd9Sstevel@tonic-gate 	assert(disk_info->disk_ctlr == ctlr);
18457c478bd9Sstevel@tonic-gate 
18467c478bd9Sstevel@tonic-gate 	/*
18477c478bd9Sstevel@tonic-gate 	 * Link the disk into the list of disks
18487c478bd9Sstevel@tonic-gate 	 */
18497c478bd9Sstevel@tonic-gate 	dp = ctlr->ctlr_ctype->ctype_dlist;
18507c478bd9Sstevel@tonic-gate 	if (dp == NULL) {
1851342440ecSPrasad Singamsetty 		ctlr->ctlr_ctype->ctype_dlist = disk;
18527c478bd9Sstevel@tonic-gate 	} else {
18537c478bd9Sstevel@tonic-gate 		while (dp->dtype_next != NULL) {
18547c478bd9Sstevel@tonic-gate 			dp = dp->dtype_next;
18557c478bd9Sstevel@tonic-gate 		}
18567c478bd9Sstevel@tonic-gate 		dp->dtype_next = disk;
18577c478bd9Sstevel@tonic-gate 	}
18587c478bd9Sstevel@tonic-gate 	disk->dtype_next = NULL;
18597c478bd9Sstevel@tonic-gate 
18607c478bd9Sstevel@tonic-gate 	/*
18617c478bd9Sstevel@tonic-gate 	 * Allocate and initialize the disk name.
18627c478bd9Sstevel@tonic-gate 	 */
18637c478bd9Sstevel@tonic-gate 	disk->dtype_asciilabel = alloc_string(disk_name);
18647c478bd9Sstevel@tonic-gate 
18657c478bd9Sstevel@tonic-gate 	/*
18667c478bd9Sstevel@tonic-gate 	 * Initialize disk geometry info
18677c478bd9Sstevel@tonic-gate 	 */
18687c478bd9Sstevel@tonic-gate 	disk->dtype_pcyl = label->dkl_pcyl;
18697c478bd9Sstevel@tonic-gate 	disk->dtype_ncyl = label->dkl_ncyl;
18707c478bd9Sstevel@tonic-gate 	disk->dtype_acyl = label->dkl_acyl;
18717c478bd9Sstevel@tonic-gate 	disk->dtype_nhead = label->dkl_nhead;
18727c478bd9Sstevel@tonic-gate 	disk->dtype_nsect = label->dkl_nsect;
18737c478bd9Sstevel@tonic-gate 	disk->dtype_rpm = label->dkl_rpm;
18747c478bd9Sstevel@tonic-gate 
18757c478bd9Sstevel@tonic-gate 	/*
18767c478bd9Sstevel@tonic-gate 	 * Attempt to match the partition map in the label
18777c478bd9Sstevel@tonic-gate 	 * with a know partition for this disk type.
18787c478bd9Sstevel@tonic-gate 	 */
18797c478bd9Sstevel@tonic-gate 	for (part = disk->dtype_plist; part; part = part->pinfo_next) {
18807c478bd9Sstevel@tonic-gate 		if (parts_match(label, part)) {
18817c478bd9Sstevel@tonic-gate 			break;
18827c478bd9Sstevel@tonic-gate 		}
18837c478bd9Sstevel@tonic-gate 	}
18847c478bd9Sstevel@tonic-gate 
18857c478bd9Sstevel@tonic-gate 	/*
18867c478bd9Sstevel@tonic-gate 	 * If no match was made, we need to create a partition
18877c478bd9Sstevel@tonic-gate 	 * map for this disk.
18887c478bd9Sstevel@tonic-gate 	 */
18897c478bd9Sstevel@tonic-gate 	if (part == NULL) {
18907c478bd9Sstevel@tonic-gate 		part = (struct partition_info *)
189165908c77Syu, larry liu - Sun Microsystems - Beijing China 		    zalloc(sizeof (struct partition_info));
18927c478bd9Sstevel@tonic-gate 		pt = disk->dtype_plist;
18937c478bd9Sstevel@tonic-gate 		if (pt == NULL) {
18947c478bd9Sstevel@tonic-gate 			disk->dtype_plist = part;
18957c478bd9Sstevel@tonic-gate 		} else {
18967c478bd9Sstevel@tonic-gate 			while (pt->pinfo_next != NULL) {
18977c478bd9Sstevel@tonic-gate 				pt = pt->pinfo_next;
18987c478bd9Sstevel@tonic-gate 			}
18997c478bd9Sstevel@tonic-gate 			pt->pinfo_next = part;
19007c478bd9Sstevel@tonic-gate 		}
19017c478bd9Sstevel@tonic-gate 		part->pinfo_next = NULL;
19027c478bd9Sstevel@tonic-gate 
19037c478bd9Sstevel@tonic-gate 		/*
19047c478bd9Sstevel@tonic-gate 		 * Set up the partition name
19057c478bd9Sstevel@tonic-gate 		 */
19067c478bd9Sstevel@tonic-gate 		part->pinfo_name = alloc_string("default");
19077c478bd9Sstevel@tonic-gate 
19087c478bd9Sstevel@tonic-gate 		/*
19097c478bd9Sstevel@tonic-gate 		 * Fill in the partition info from the label
19107c478bd9Sstevel@tonic-gate 		 */
19117c478bd9Sstevel@tonic-gate 		for (i = 0; i < NDKMAP; i++) {
19127c478bd9Sstevel@tonic-gate 
19137c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
19147c478bd9Sstevel@tonic-gate 			part->pinfo_map[i] = label->dkl_map[i];
19157c478bd9Sstevel@tonic-gate 
19167c478bd9Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16)
19177c478bd9Sstevel@tonic-gate 			part->pinfo_map[i].dkl_cylno =
191865908c77Syu, larry liu - Sun Microsystems - Beijing China 			    label->dkl_vtoc.v_part[i].p_start /
191965908c77Syu, larry liu - Sun Microsystems - Beijing China 			    ((blkaddr32_t)(disk->dtype_nhead *
192065908c77Syu, larry liu - Sun Microsystems - Beijing China 			    disk->dtype_nsect - apc));
19217c478bd9Sstevel@tonic-gate 			part->pinfo_map[i].dkl_nblk =
192265908c77Syu, larry liu - Sun Microsystems - Beijing China 			    label->dkl_vtoc.v_part[i].p_size;
19237c478bd9Sstevel@tonic-gate #else
19247c478bd9Sstevel@tonic-gate #error No VTOC format defined.
19257c478bd9Sstevel@tonic-gate #endif				/* defined(_SUNOS_VTOC_8) */
19267c478bd9Sstevel@tonic-gate 
19277c478bd9Sstevel@tonic-gate 		}
19287c478bd9Sstevel@tonic-gate 	}
19297c478bd9Sstevel@tonic-gate 
19307c478bd9Sstevel@tonic-gate 
19317c478bd9Sstevel@tonic-gate 	/*
19327c478bd9Sstevel@tonic-gate 	 * Use the VTOC if valid, or install a default
19337c478bd9Sstevel@tonic-gate 	 */
19347c478bd9Sstevel@tonic-gate 	if (label->dkl_vtoc.v_version == V_VERSION) {
19357c478bd9Sstevel@tonic-gate 		(void) memcpy(disk_info->v_volume, label->dkl_vtoc.v_volume,
193665908c77Syu, larry liu - Sun Microsystems - Beijing China 		    LEN_DKL_VVOL);
19377c478bd9Sstevel@tonic-gate 		part->vtoc = label->dkl_vtoc;
19387c478bd9Sstevel@tonic-gate 	} else {
19397c478bd9Sstevel@tonic-gate 		(void) memset(disk_info->v_volume, 0, LEN_DKL_VVOL);
19407c478bd9Sstevel@tonic-gate 		set_vtoc_defaults(part);
19417c478bd9Sstevel@tonic-gate 	}
19427c478bd9Sstevel@tonic-gate 
19437c478bd9Sstevel@tonic-gate 	/*
19447c478bd9Sstevel@tonic-gate 	 * Link the disk to the partition map
19457c478bd9Sstevel@tonic-gate 	 */
19467c478bd9Sstevel@tonic-gate 	disk_info->disk_parts = part;
19477c478bd9Sstevel@tonic-gate 
19487c478bd9Sstevel@tonic-gate 	return (disk);
19497c478bd9Sstevel@tonic-gate }
19507c478bd9Sstevel@tonic-gate 
19517c478bd9Sstevel@tonic-gate 
1952698107ecSlh /*
1953698107ecSlh  * Delete a disk type from disk type list.
1954698107ecSlh  */
1955698107ecSlh int
19562f15e7adSIgor Kozhukhov delete_disk_type(struct disk_type *disk_type)
1957698107ecSlh {
1958698107ecSlh 	struct ctlr_type	*ctlr;
1959698107ecSlh 	struct disk_type	*dp, *disk;
1960698107ecSlh 
19612f15e7adSIgor Kozhukhov 	if (cur_ctype->ctype_ctype == DKC_DIRECT ||
19622f15e7adSIgor Kozhukhov 	    cur_ctype->ctype_ctype == DKC_VBD ||
19632f15e7adSIgor Kozhukhov 	    cur_ctype->ctype_ctype == DKC_BLKDEV)
19642f15e7adSIgor Kozhukhov 		ctlr = find_ctlr_type(cur_ctype->ctype_ctype);
1965698107ecSlh 	else
1966698107ecSlh 		ctlr = find_scsi_ctlr_type();
1967698107ecSlh 	if (ctlr == NULL || ctlr->ctype_dlist == NULL) {
1968698107ecSlh 		return (-1);
1969698107ecSlh 	}
1970698107ecSlh 
1971698107ecSlh 	disk = ctlr->ctype_dlist;
1972698107ecSlh 	if (disk == disk_type) {
1973698107ecSlh 		ctlr->ctype_dlist = disk->dtype_next;
1974698107ecSlh 		if (cur_label == L_TYPE_EFI)
1975698107ecSlh 			free(disk->dtype_plist->etoc);
1976698107ecSlh 		free(disk->dtype_plist);
1977f1bf0656SHans Rosenfeld 		free(disk->vendor);
1978f1bf0656SHans Rosenfeld 		free(disk->product);
1979f1bf0656SHans Rosenfeld 		free(disk->revision);
1980698107ecSlh 		free(disk);
1981698107ecSlh 		return (0);
1982698107ecSlh 	} else {
1983698107ecSlh 		for (dp = disk->dtype_next; dp != NULL;
1984698107ecSlh 		    disk = disk->dtype_next, dp = dp->dtype_next) {
1985698107ecSlh 			if (dp == disk_type) {
1986698107ecSlh 				disk->dtype_next = dp->dtype_next;
1987698107ecSlh 				if (cur_label == L_TYPE_EFI)
1988698107ecSlh 					free(dp->dtype_plist->etoc);
1989698107ecSlh 				free(dp->dtype_plist);
1990f1bf0656SHans Rosenfeld 				free(dp->vendor);
1991f1bf0656SHans Rosenfeld 				free(dp->product);
1992f1bf0656SHans Rosenfeld 				free(dp->revision);
1993698107ecSlh 				free(dp);
1994698107ecSlh 				return (0);
1995698107ecSlh 			}
1996698107ecSlh 		}
1997698107ecSlh 		return (-1);
1998698107ecSlh 	}
1999698107ecSlh }
2000698107ecSlh 
2001698107ecSlh 
20027c478bd9Sstevel@tonic-gate static struct disk_info *
20037c478bd9Sstevel@tonic-gate find_scsi_disk_info(
20047c478bd9Sstevel@tonic-gate 	struct dk_cinfo		*dkinfo)
20057c478bd9Sstevel@tonic-gate {
20067c478bd9Sstevel@tonic-gate 	struct disk_info	*disk;
20077c478bd9Sstevel@tonic-gate 	struct dk_cinfo		*dp;
20087c478bd9Sstevel@tonic-gate 
20097c478bd9Sstevel@tonic-gate 	for (disk = disk_list; disk != NULL; disk = disk->disk_next) {
2010f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 		assert(dkinfo->dki_ctype == DKC_SCSI_CCS);
20117c478bd9Sstevel@tonic-gate 		dp = &disk->disk_dkinfo;
20127c478bd9Sstevel@tonic-gate 		if (dp->dki_ctype == dkinfo->dki_ctype &&
2013f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 		    dp->dki_cnum == dkinfo->dki_cnum &&
2014f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 		    dp->dki_unit == dkinfo->dki_unit &&
2015f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China 		    strcmp(dp->dki_dname, dkinfo->dki_dname) == 0) {
20167c478bd9Sstevel@tonic-gate 			return (disk);
20177c478bd9Sstevel@tonic-gate 		}
20187c478bd9Sstevel@tonic-gate 	}
20197c478bd9Sstevel@tonic-gate 
20207c478bd9Sstevel@tonic-gate 	impossible("No SCSI disk info instance\n");
2021052b6e8aSbg 
2022b12aaafbSToomas Soome 	return (NULL);
20237c478bd9Sstevel@tonic-gate }
20247c478bd9Sstevel@tonic-gate 
20257c478bd9Sstevel@tonic-gate 
20267c478bd9Sstevel@tonic-gate static char *
20277c478bd9Sstevel@tonic-gate get_sun_disk_name(
20287c478bd9Sstevel@tonic-gate 	char			*disk_name,
20297c478bd9Sstevel@tonic-gate 	struct scsi_inquiry	*inquiry)
20307c478bd9Sstevel@tonic-gate {
20317c478bd9Sstevel@tonic-gate 	/*
20327c478bd9Sstevel@tonic-gate 	 * Extract the sun name of the disk
20337c478bd9Sstevel@tonic-gate 	 */
20347c478bd9Sstevel@tonic-gate 	(void) memset(disk_name, 0, DISK_NAME_MAX);
20357c478bd9Sstevel@tonic-gate 	(void) memcpy(disk_name, (char *)&inquiry->inq_pid[9], 7);
20367c478bd9Sstevel@tonic-gate 
20377c478bd9Sstevel@tonic-gate 	return (disk_name);
20387c478bd9Sstevel@tonic-gate }
20397c478bd9Sstevel@tonic-gate 
20407c478bd9Sstevel@tonic-gate 
20411662a2f2SGary Mills char *
20427c478bd9Sstevel@tonic-gate get_generic_disk_name(
20437c478bd9Sstevel@tonic-gate 	char			*disk_name,
20447c478bd9Sstevel@tonic-gate 	struct scsi_inquiry	*inquiry)
20457c478bd9Sstevel@tonic-gate {
20467c478bd9Sstevel@tonic-gate 	char	*p;
20477c478bd9Sstevel@tonic-gate 
20487c478bd9Sstevel@tonic-gate 	(void) memset(disk_name, 0, DISK_NAME_MAX);
20497c478bd9Sstevel@tonic-gate 	p = strcopy(disk_name, inquiry->inq_vid,
205065908c77Syu, larry liu - Sun Microsystems - Beijing China 	    sizeof (inquiry->inq_vid));
20517c478bd9Sstevel@tonic-gate 	*p++ = '-';
20527c478bd9Sstevel@tonic-gate 	p = strcopy(p, inquiry->inq_pid, sizeof (inquiry->inq_pid));
20537c478bd9Sstevel@tonic-gate 	*p++ = '-';
20547c478bd9Sstevel@tonic-gate 	p = strcopy(p, inquiry->inq_revision,
205565908c77Syu, larry liu - Sun Microsystems - Beijing China 	    sizeof (inquiry->inq_revision));
20567c478bd9Sstevel@tonic-gate 
20577c478bd9Sstevel@tonic-gate 	return (disk_name);
20587c478bd9Sstevel@tonic-gate }
20597c478bd9Sstevel@tonic-gate 
20607c478bd9Sstevel@tonic-gate /*
20617c478bd9Sstevel@tonic-gate  * Copy a string of characters from src to dst, for at
20627c478bd9Sstevel@tonic-gate  * most n bytes.  Strip all leading and trailing spaces,
20637c478bd9Sstevel@tonic-gate  * and stop if there are any non-printable characters.
20647c478bd9Sstevel@tonic-gate  * Return ptr to the next character to be filled.
20657c478bd9Sstevel@tonic-gate  */
20667c478bd9Sstevel@tonic-gate static char *
20677c478bd9Sstevel@tonic-gate strcopy(
20687c478bd9Sstevel@tonic-gate 	char	*dst,
20697c478bd9Sstevel@tonic-gate 	char	*src,
20707c478bd9Sstevel@tonic-gate 	int	n)
20717c478bd9Sstevel@tonic-gate {
20727c478bd9Sstevel@tonic-gate 	int	i;
20737c478bd9Sstevel@tonic-gate 
20747c478bd9Sstevel@tonic-gate 	while (*src == ' ' && n > 0) {
20757c478bd9Sstevel@tonic-gate 		src++;
20767c478bd9Sstevel@tonic-gate 		n--;
20777c478bd9Sstevel@tonic-gate 	}
20787c478bd9Sstevel@tonic-gate 
20797c478bd9Sstevel@tonic-gate 	for (i = 0; n-- > 0 && isascii(*src) && isprint(*src); src++) {
20807c478bd9Sstevel@tonic-gate 		if (*src == ' ') {
20817c478bd9Sstevel@tonic-gate 			i++;
20827c478bd9Sstevel@tonic-gate 		} else {
20837c478bd9Sstevel@tonic-gate 			while (i-- > 0)
20847c478bd9Sstevel@tonic-gate 				*dst++ = ' ';
20857c478bd9Sstevel@tonic-gate 			*dst++ = *src;
20867c478bd9Sstevel@tonic-gate 		}
20877c478bd9Sstevel@tonic-gate 	}
20887c478bd9Sstevel@tonic-gate 
20897c478bd9Sstevel@tonic-gate 	*dst = 0;
20907c478bd9Sstevel@tonic-gate 	return (dst);
20917c478bd9Sstevel@tonic-gate }
20927c478bd9Sstevel@tonic-gate 
20937c478bd9Sstevel@tonic-gate /*
20947c478bd9Sstevel@tonic-gate  * adjust disk geometry.
20957c478bd9Sstevel@tonic-gate  * This is used when disk reports a disk geometry page having
20967c478bd9Sstevel@tonic-gate  * no of physical cylinders is < 3 which is the minimum required
20977c478bd9Sstevel@tonic-gate  * by Solaris (2 for storing labels and at least one as a data
20987c478bd9Sstevel@tonic-gate  * cylinder )
20997c478bd9Sstevel@tonic-gate  */
21007c478bd9Sstevel@tonic-gate int
2101342440ecSPrasad Singamsetty adjust_disk_geometry(diskaddr_t capacity, uint_t *cyl, uint_t *nhead,
21022f15e7adSIgor Kozhukhov     uint_t *nsect)
21037c478bd9Sstevel@tonic-gate {
2104342440ecSPrasad Singamsetty 	uint_t	lcyl = *cyl;
2105342440ecSPrasad Singamsetty 	uint_t	lnhead = *nhead;
2106342440ecSPrasad Singamsetty 	uint_t	lnsect = *nsect;
21077c478bd9Sstevel@tonic-gate 
21087c478bd9Sstevel@tonic-gate 	assert(lcyl < SUN_MIN_CYL);
21097c478bd9Sstevel@tonic-gate 
21107c478bd9Sstevel@tonic-gate 	/*
21117c478bd9Sstevel@tonic-gate 	 * reduce nsect by 2 for each iteration  and re-calculate
21127c478bd9Sstevel@tonic-gate 	 * the number of cylinders.
21137c478bd9Sstevel@tonic-gate 	 */
21147c478bd9Sstevel@tonic-gate 	while (lnsect > MINIMUM_NO_SECTORS &&
211556507910Sqd 	    lcyl < MINIMUM_NO_CYLINDERS) {
21167c478bd9Sstevel@tonic-gate 		/*
21177c478bd9Sstevel@tonic-gate 		 * make sure that we do not go below MINIMUM_NO_SECTORS.
21187c478bd9Sstevel@tonic-gate 		 */
21197c478bd9Sstevel@tonic-gate 		lnsect = max(MINIMUM_NO_SECTORS, lnsect / 2);
21207c478bd9Sstevel@tonic-gate 		lcyl   = (capacity) / (lnhead * lnsect);
21217c478bd9Sstevel@tonic-gate 	}
21227c478bd9Sstevel@tonic-gate 	/*
21237c478bd9Sstevel@tonic-gate 	 * If the geometry still does not satisfy
21247c478bd9Sstevel@tonic-gate 	 * MINIMUM_NO_CYLINDERS then try to reduce the
21257c478bd9Sstevel@tonic-gate 	 * no of heads.
21267c478bd9Sstevel@tonic-gate 	 */
21277c478bd9Sstevel@tonic-gate 	while (lnhead > MINIMUM_NO_HEADS &&
212856507910Sqd 	    lcyl < MINIMUM_NO_CYLINDERS) {
21297c478bd9Sstevel@tonic-gate 		lnhead = max(MINIMUM_NO_HEADS, lnhead / 2);
21307c478bd9Sstevel@tonic-gate 		lcyl =  (capacity) / (lnhead * lnsect);
21317c478bd9Sstevel@tonic-gate 	}
21327c478bd9Sstevel@tonic-gate 	/*
21337c478bd9Sstevel@tonic-gate 	 * now we should have atleast SUN_MIN_CYL cylinders.
21347c478bd9Sstevel@tonic-gate 	 * If we still do not get SUN_MIN_CYL with MINIMUM_NO_HEADS
21357c478bd9Sstevel@tonic-gate 	 * and MINIMUM_NO_HEADS then return error.
21367c478bd9Sstevel@tonic-gate 	 */
21377c478bd9Sstevel@tonic-gate 	if (lcyl < SUN_MIN_CYL)
21387c478bd9Sstevel@tonic-gate 		return (1);
21397c478bd9Sstevel@tonic-gate 	else {
21407c478bd9Sstevel@tonic-gate 		*cyl = lcyl;
21417c478bd9Sstevel@tonic-gate 		*nhead = lnhead;
21427c478bd9Sstevel@tonic-gate 		*nsect = lnsect;
21437c478bd9Sstevel@tonic-gate 		return (0);
21447c478bd9Sstevel@tonic-gate 	}
21457c478bd9Sstevel@tonic-gate }
21467c478bd9Sstevel@tonic-gate 
21477c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
21487c478bd9Sstevel@tonic-gate /*
21497c478bd9Sstevel@tonic-gate  * Reduce the size of one dimention below a specified
21507c478bd9Sstevel@tonic-gate  * limit with a minimum loss of volume.  Dimenstions are
21517c478bd9Sstevel@tonic-gate  * assumed to be passed in form the largest value (the one
21527c478bd9Sstevel@tonic-gate  * that needs to be reduced) to the smallest value.  The
21537c478bd9Sstevel@tonic-gate  * values will be twiddled until they are all less than or
21547c478bd9Sstevel@tonic-gate  * equal to their limit.  Returns the number in the new geometry.
21557c478bd9Sstevel@tonic-gate  */
2156342440ecSPrasad Singamsetty static diskaddr_t
21577c478bd9Sstevel@tonic-gate square_box(
2158342440ecSPrasad Singamsetty 		diskaddr_t capacity,
2159342440ecSPrasad Singamsetty 		uint_t *dim1, uint_t lim1,
2160342440ecSPrasad Singamsetty 		uint_t *dim2, uint_t lim2,
2161342440ecSPrasad Singamsetty 		uint_t *dim3, uint_t lim3)
21627c478bd9Sstevel@tonic-gate {
2163342440ecSPrasad Singamsetty 	uint_t	i;
21647c478bd9Sstevel@tonic-gate 
21657c478bd9Sstevel@tonic-gate 	/*
21667c478bd9Sstevel@tonic-gate 	 * Although the routine should work with any ordering of
21677c478bd9Sstevel@tonic-gate 	 * parameters, it's most efficient if they are passed in
21687c478bd9Sstevel@tonic-gate 	 * in decreasing magnitude.
21697c478bd9Sstevel@tonic-gate 	 */
21707c478bd9Sstevel@tonic-gate 	assert(*dim1 >= *dim2);
21717c478bd9Sstevel@tonic-gate 	assert(*dim2 >= *dim3);
21727c478bd9Sstevel@tonic-gate 
21737c478bd9Sstevel@tonic-gate 	/*
21747c478bd9Sstevel@tonic-gate 	 * This is done in a very arbitrary manner.  We could try to
21757c478bd9Sstevel@tonic-gate 	 * find better values but I can't come up with a method that
21767c478bd9Sstevel@tonic-gate 	 * would run in a reasonable amount of time.  That could take
21777c478bd9Sstevel@tonic-gate 	 * approximately 65535 * 65535 iterations of a dozen flops each
21787c478bd9Sstevel@tonic-gate 	 * or well over 4G flops.
21797c478bd9Sstevel@tonic-gate 	 *
21807c478bd9Sstevel@tonic-gate 	 * First:
21817c478bd9Sstevel@tonic-gate 	 *
21827c478bd9Sstevel@tonic-gate 	 * Let's see how far we can go with bitshifts w/o losing
21837c478bd9Sstevel@tonic-gate 	 * any blocks.
21847c478bd9Sstevel@tonic-gate 	 */
21857c478bd9Sstevel@tonic-gate 
218665908c77Syu, larry liu - Sun Microsystems - Beijing China 	for (i = 0; (((*dim1)>>i)&1) == 0 && ((*dim1)>>i) > lim1; i++)
218765908c77Syu, larry liu - Sun Microsystems - Beijing China 		;
21887c478bd9Sstevel@tonic-gate 	if (i) {
21897c478bd9Sstevel@tonic-gate 		*dim1 = ((*dim1)>>i);
21907c478bd9Sstevel@tonic-gate 		*dim3 = ((*dim3)<<i);
21917c478bd9Sstevel@tonic-gate 	}
21927c478bd9Sstevel@tonic-gate 
21937c478bd9Sstevel@tonic-gate 	if (((*dim1) > lim1) || ((*dim2) > lim2) || ((*dim3) > lim3)) {
219432a71e42SToomas Soome 		double	d[4];
21957c478bd9Sstevel@tonic-gate 
21967c478bd9Sstevel@tonic-gate 		/*
21977c478bd9Sstevel@tonic-gate 		 * Second:
21987c478bd9Sstevel@tonic-gate 		 *
21997c478bd9Sstevel@tonic-gate 		 * Set the highest value at its limit then calculate errors,
22007c478bd9Sstevel@tonic-gate 		 * adjusting the 2nd highest value (we get better resolution
22017c478bd9Sstevel@tonic-gate 		 * that way).
22027c478bd9Sstevel@tonic-gate 		 */
22037c478bd9Sstevel@tonic-gate 		d[1] = lim1;
22047c478bd9Sstevel@tonic-gate 		d[3] = *dim3;
22057c478bd9Sstevel@tonic-gate 		d[2] = (double)capacity/(d[1]*d[3]);
22067c478bd9Sstevel@tonic-gate 
22077c478bd9Sstevel@tonic-gate 		/*
22087c478bd9Sstevel@tonic-gate 		 * If we overflowed the middle term, set it to its limit and
22097c478bd9Sstevel@tonic-gate 		 * chose a new low term.
22107c478bd9Sstevel@tonic-gate 		 */
22117c478bd9Sstevel@tonic-gate 		if (d[2] > lim2) {
22127c478bd9Sstevel@tonic-gate 			d[2] = lim2;
22137c478bd9Sstevel@tonic-gate 			d[3] = (double)capacity/(d[1]*d[2]);
22147c478bd9Sstevel@tonic-gate 		}
22157c478bd9Sstevel@tonic-gate 		/*
22167c478bd9Sstevel@tonic-gate 		 * Convert to integers.
22177c478bd9Sstevel@tonic-gate 		 */
22187c478bd9Sstevel@tonic-gate 		*dim1 = (int)d[1];
22197c478bd9Sstevel@tonic-gate 		*dim2 = (int)d[2];
22207c478bd9Sstevel@tonic-gate 		*dim3 = (int)d[3];
22217c478bd9Sstevel@tonic-gate 	}
22227c478bd9Sstevel@tonic-gate 	/*
22237c478bd9Sstevel@tonic-gate 	 * Fixup any other possible problems.
22247c478bd9Sstevel@tonic-gate 	 * If this happens, we need a new disklabel format.
22257c478bd9Sstevel@tonic-gate 	 */
22267c478bd9Sstevel@tonic-gate 	if (*dim1 > lim1) *dim1 = lim1;
22277c478bd9Sstevel@tonic-gate 	if (*dim2 > lim2) *dim2 = lim2;
22287c478bd9Sstevel@tonic-gate 	if (*dim3 > lim3) *dim3 = lim3;
22297c478bd9Sstevel@tonic-gate 	return (*dim1 * *dim2 * *dim3);
22307c478bd9Sstevel@tonic-gate }
22317c478bd9Sstevel@tonic-gate #endif /* defined(_SUNOS_VTOC_8) */
2232342440ecSPrasad Singamsetty 
2233342440ecSPrasad Singamsetty /*
2234342440ecSPrasad Singamsetty  * Calculate CHS values based on the capacity data.
2235342440ecSPrasad Singamsetty  *
2236342440ecSPrasad Singamsetty  * NOTE: This function is same as cmlb_convert_geomerty() function in
2237342440ecSPrasad Singamsetty  * cmlb kernel module.
2238342440ecSPrasad Singamsetty  */
2239342440ecSPrasad Singamsetty static void
2240342440ecSPrasad Singamsetty compute_chs_values(diskaddr_t total_capacity, diskaddr_t usable_capacity,
22412f15e7adSIgor Kozhukhov     uint_t *pcylp, uint_t *nheadp, uint_t *nsectp)
2242342440ecSPrasad Singamsetty {
2243342440ecSPrasad Singamsetty 
2244342440ecSPrasad Singamsetty 	/* Unlabeled SCSI floppy device */
2245c31fac72SShidokht Yadegari 	if (total_capacity < 160) {
2246c31fac72SShidokht Yadegari 		/* Less than 80K */
2247c31fac72SShidokht Yadegari 		*nheadp = 1;
2248c31fac72SShidokht Yadegari 		*pcylp = total_capacity;
2249c31fac72SShidokht Yadegari 		*nsectp = 1;
2250c31fac72SShidokht Yadegari 		return;
2251c31fac72SShidokht Yadegari 	} else if (total_capacity <= 0x1000) {
2252342440ecSPrasad Singamsetty 		*nheadp = 2;
2253342440ecSPrasad Singamsetty 		*pcylp = 80;
2254342440ecSPrasad Singamsetty 		*nsectp = total_capacity / (80 * 2);
2255342440ecSPrasad Singamsetty 		return;
2256342440ecSPrasad Singamsetty 	}
2257342440ecSPrasad Singamsetty 
2258342440ecSPrasad Singamsetty 	/*
2259342440ecSPrasad Singamsetty 	 * For all devices we calculate cylinders using the heads and sectors
2260342440ecSPrasad Singamsetty 	 * we assign based on capacity of the device.  The algorithm is
2261342440ecSPrasad Singamsetty 	 * designed to be compatible with the way other operating systems
2262342440ecSPrasad Singamsetty 	 * lay out fdisk tables for X86 and to insure that the cylinders never
2263342440ecSPrasad Singamsetty 	 * exceed 65535 to prevent problems with X86 ioctls that report
2264342440ecSPrasad Singamsetty 	 * geometry.
2265342440ecSPrasad Singamsetty 	 * For some smaller disk sizes we report geometry that matches those
2266342440ecSPrasad Singamsetty 	 * used by X86 BIOS usage. For larger disks, we use SPT that are
2267342440ecSPrasad Singamsetty 	 * multiples of 63, since other OSes that are not limited to 16-bits
2268342440ecSPrasad Singamsetty 	 * for cylinders stop at 63 SPT we make do by using multiples of 63 SPT.
2269342440ecSPrasad Singamsetty 	 *
2270342440ecSPrasad Singamsetty 	 * The following table (in order) illustrates some end result
2271342440ecSPrasad Singamsetty 	 * calculations:
2272342440ecSPrasad Singamsetty 	 *
227332a71e42SToomas Soome 	 * Maximum number of blocks		nhead	nsect
2274342440ecSPrasad Singamsetty 	 *
2275342440ecSPrasad Singamsetty 	 * 2097152 (1GB)			64	32
2276342440ecSPrasad Singamsetty 	 * 16777216 (8GB)			128	32
227732a71e42SToomas Soome 	 * 1052819775 (502.02GB)		255	63
2278342440ecSPrasad Singamsetty 	 * 2105639550 (0.98TB)			255	126
227932a71e42SToomas Soome 	 * 3158459325 (1.47TB)			255	189
228032a71e42SToomas Soome 	 * 4211279100 (1.96TB)			255	252
228132a71e42SToomas Soome 	 * 5264098875 (2.45TB)			255	315
2282342440ecSPrasad Singamsetty 	 * ...
2283342440ecSPrasad Singamsetty 	 */
2284342440ecSPrasad Singamsetty 
2285342440ecSPrasad Singamsetty 	if (total_capacity <= 0x200000) {
2286342440ecSPrasad Singamsetty 		*nheadp = 64;
2287342440ecSPrasad Singamsetty 		*nsectp = 32;
2288342440ecSPrasad Singamsetty 	} else if (total_capacity <= 0x01000000) {
2289342440ecSPrasad Singamsetty 		*nheadp = 128;
2290342440ecSPrasad Singamsetty 		*nsectp = 32;
2291342440ecSPrasad Singamsetty 	} else {
2292342440ecSPrasad Singamsetty 		*nheadp = 255;
2293342440ecSPrasad Singamsetty 
2294342440ecSPrasad Singamsetty 		/* make nsect be smallest multiple of 63 */
2295342440ecSPrasad Singamsetty 		*nsectp = ((total_capacity +
2296342440ecSPrasad Singamsetty 		    (UINT16_MAX * 255 * 63) - 1) /
2297342440ecSPrasad Singamsetty 		    (UINT16_MAX * 255 * 63)) * 63;
2298342440ecSPrasad Singamsetty 
2299342440ecSPrasad Singamsetty 		if (*nsectp == 0)
2300342440ecSPrasad Singamsetty 			*nsectp = (UINT16_MAX / 63) * 63;
2301342440ecSPrasad Singamsetty 	}
2302342440ecSPrasad Singamsetty 
2303342440ecSPrasad Singamsetty 	if (usable_capacity < total_capacity)
2304342440ecSPrasad Singamsetty 		*pcylp = usable_capacity / ((*nheadp) * (*nsectp));
2305342440ecSPrasad Singamsetty 	else
2306342440ecSPrasad Singamsetty 		*pcylp = total_capacity / ((*nheadp) * (*nsectp));
2307342440ecSPrasad Singamsetty }
2308