Home | History | Annotate | Download | only in format
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 /*
     27  * This file contains functions to implement automatic configuration
     28  * of scsi disks.
     29  */
     30 #include "global.h"
     31 
     32 #include <fcntl.h>
     33 #include <stdlib.h>
     34 #include <string.h>
     35 #include <strings.h>
     36 #include <stdlib.h>
     37 #include <ctype.h>
     38 
     39 #include "misc.h"
     40 #include "param.h"
     41 #include "ctlr_scsi.h"
     42 #include "auto_sense.h"
     43 #include "partition.h"
     44 #include "label.h"
     45 #include "startup.h"
     46 #include "analyze.h"
     47 #include "io.h"
     48 #include "hardware_structs.h"
     49 #include "menu_fdisk.h"
     50 
     51 
     52 #define	DISK_NAME_MAX		256
     53 
     54 extern	int			nctypes;
     55 extern	struct	ctlr_type	ctlr_types[];
     56 
     57 
     58 /*
     59  * Marker for free hog partition
     60  */
     61 #define	HOG		(-1)
     62 
     63 
     64 
     65 /*
     66  * Default partition tables
     67  *
     68  *	Disk capacity		root	swap	usr
     69  *	-------------		----	----	---
     70  *	0mb to 64mb		0	0	remainder
     71  *	64mb to 180mb		16mb	16mb	remainder
     72  *	180mb to 280mb		16mb	32mb	remainder
     73  *	280mb to 380mb		24mb	32mb	remainder
     74  *	380mb to 600mb		32mb	32mb	remainder
     75  *	600mb to 1gb		32mb	64mb	remainder
     76  *	1gb to 2gb		64mb	128mb	remainder
     77  *	2gb on up		128mb	128mb	remainder
     78  */
     79 struct part_table {
     80 	int	partitions[NDKMAP];
     81 };
     82 
     83 static struct part_table part_table_64mb = {
     84 	{ 0,	0,	0,	0,	0,	0,	HOG,	0}
     85 };
     86 
     87 static struct part_table part_table_180mb = {
     88 	{ 16,	16,	0,	0,	0,	0,	HOG,	0}
     89 };
     90 
     91 static struct part_table part_table_280mb = {
     92 	{ 16,	32,	0,	0,	0,	0,	HOG,	0}
     93 };
     94 
     95 static struct part_table part_table_380mb = {
     96 	{ 24,	32,	0,	0,	0,	0,	HOG,	0}
     97 };
     98 
     99 static struct part_table part_table_600mb = {
    100 	{ 32,	32,	0,	0,	0,	0,	HOG,	0}
    101 };
    102 
    103 static struct part_table part_table_1gb = {
    104 	{ 32,	64,	0,	0,	0,	0,	HOG,	0}
    105 };
    106 
    107 static struct part_table part_table_2gb = {
    108 	{ 64,	128,	0,	0,	0,	0,	HOG,	0}
    109 };
    110 
    111 static struct part_table part_table_infinity = {
    112 	{ 128,	128,	0,	0,	0,	0,	HOG,	0}
    113 };
    114 
    115 
    116 static struct default_partitions {
    117 	diskaddr_t		min_capacity;
    118 	diskaddr_t		max_capacity;
    119 	struct part_table	*part_table;
    120 } default_partitions[] = {
    121 	{ 0,	64,		&part_table_64mb },	/* 0 to 64 mb */
    122 	{ 64,	180,		&part_table_180mb },	/* 64 to 180 mb */
    123 	{ 180,	280,		&part_table_280mb },	/* 180 to 280 mb */
    124 	{ 280,	380,		&part_table_380mb },	/* 280 to 380 mb */
    125 	{ 380,	600,		&part_table_600mb },	/* 380 to 600 mb */
    126 	{ 600,	1024,		&part_table_1gb },	/* 600 to 1 gb */
    127 	{ 1024,	2048,		&part_table_2gb },	/* 1 to 2 gb */
    128 	{ 2048,	INFINITY,	&part_table_infinity },	/* 2 gb on up */
    129 };
    130 
    131 #define	DEFAULT_PARTITION_TABLE_SIZE	\
    132 	(sizeof (default_partitions) / sizeof (struct default_partitions))
    133 
    134 /*
    135  * msgs for check()
    136  */
    137 #define	FORMAT_MSG	"Auto configuration via format.dat"
    138 #define	GENERIC_MSG	"Auto configuration via generic SCSI-2"
    139 
    140 /*
    141  * Disks on symbios(Hardwire raid controller) return a fixed number
    142  * of heads(64)/cylinders(64) and adjust the cylinders depending
    143  * capacity of the configured lun.
    144  * In such a case we get number of physical cylinders < 3 which
    145  * is the minimum required by solaris(2 reserved + 1 data cylinders).
    146  * Hence try to adjust the cylinders by reducing the "nsect/nhead".
    147  *
    148  */
    149 /*
    150  * assuming a minimum of 32 block cylinders.
    151  */
    152 #define	MINIMUM_NO_HEADS	2
    153 #define	MINIMUM_NO_SECTORS	16
    154 
    155 #define	MINIMUM_NO_CYLINDERS	128
    156 
    157 #if defined(_SUNOS_VTOC_8)
    158 
    159 /* These are 16-bit fields */
    160 #define	MAXIMUM_NO_HEADS	65535
    161 #define	MAXIMUM_NO_SECTORS	65535
    162 #define	MAXIMUM_NO_CYLINDERS	65535
    163 
    164 #endif	/* defined(_SUNOS_VTOC_8) */
    165 
    166 /*
    167  * minimum number of cylinders required by Solaris.
    168  */
    169 #define	SUN_MIN_CYL		3
    170 
    171 
    172 
    173 /*
    174  * ANSI prototypes for local static functions
    175  */
    176 static struct disk_type	*generic_disk_sense(
    177 				int		fd,
    178 				int		can_prompt,
    179 				struct dk_label	*label,
    180 				struct scsi_inquiry *inquiry,
    181 				struct scsi_capacity_16 *capacity,
    182 				char		*disk_name);
    183 static int		use_existing_disk_type(
    184 				int		fd,
    185 				int		can_prompt,
    186 				struct dk_label	*label,
    187 				struct scsi_inquiry *inquiry,
    188 				struct disk_type *disk_type,
    189 				struct scsi_capacity_16 *capacity);
    190 int			build_default_partition(struct dk_label *label,
    191 				int ctrl_type);
    192 static struct disk_type	*find_scsi_disk_type(
    193 				char		*disk_name,
    194 				struct dk_label	*label);
    195 static struct disk_type	*find_scsi_disk_by_name(
    196 				char		*disk_name);
    197 static struct ctlr_type	*find_scsi_ctlr_type(void);
    198 static struct ctlr_info	*find_scsi_ctlr_info(
    199 				struct dk_cinfo	*dkinfo);
    200 static struct disk_type	*new_scsi_disk_type(
    201 				int		fd,
    202 				char		*disk_name,
    203 				struct dk_label	*label);
    204 static struct disk_info	*find_scsi_disk_info(
    205 				struct dk_cinfo	*dkinfo);
    206 
    207 static struct disk_type *new_direct_disk_type(int fd, char *disk_name,
    208     struct dk_label *label);
    209 
    210 static struct disk_info *find_direct_disk_info(struct dk_cinfo *dkinfo);
    211 static int efi_ioctl(int fd, int cmd, dk_efi_t *dk_ioc);
    212 static int auto_label_init(struct dk_label *label);
    213 static struct ctlr_type *find_direct_ctlr_type(void);
    214 static struct ctlr_info *find_direct_ctlr_info(struct dk_cinfo	*dkinfo);
    215 static  struct disk_info *find_direct_disk_info(struct dk_cinfo *dkinfo);
    216 static struct ctlr_type *find_vbd_ctlr_type(void);
    217 static struct ctlr_info *find_vbd_ctlr_info(struct dk_cinfo *dkinfo);
    218 static struct disk_info *find_vbd_disk_info(struct dk_cinfo *dkinfo);
    219 
    220 static char		*get_sun_disk_name(
    221 				char		*disk_name,
    222 				struct scsi_inquiry *inquiry);
    223 static char		*get_generic_disk_name(
    224 				char		*disk_name,
    225 				struct scsi_inquiry *inquiry);
    226 static char		*strcopy(
    227 				char	*dst,
    228 				char	*src,
    229 				int	n);
    230 static	int		adjust_disk_geometry(diskaddr_t capacity, uint_t *cyl,
    231 				uint_t *nsect, uint_t *nhead);
    232 static void 		compute_chs_values(diskaddr_t total_capacity,
    233 				diskaddr_t usable_capacity, uint_t *pcylp,
    234 				uint_t *nheadp, uint_t *nsectp);
    235 #if defined(_SUNOS_VTOC_8)
    236 static diskaddr_t square_box(
    237 			diskaddr_t capacity,
    238 			uint_t *dim1, uint_t lim1,
    239 			uint_t *dim2, uint_t lim2,
    240 			uint_t *dim3, uint_t lim3);
    241 #endif	/* defined(_SUNOS_VTOC_8) */
    242 
    243 
    244 /*
    245  * We need to get information necessary to construct a *new* efi
    246  * label type
    247  */
    248 struct disk_type *
    249 auto_efi_sense(int fd, struct efi_info *label)
    250 {
    251 
    252 	struct dk_gpt	*vtoc;
    253 	int		i;
    254 
    255 	struct disk_type *disk, *dp;
    256 	struct disk_info *disk_info;
    257 	struct ctlr_info *ctlr;
    258 	struct dk_cinfo dkinfo;
    259 	struct partition_info *part;
    260 
    261 	/*
    262 	 * get vendor, product, revision and capacity info.
    263 	 */
    264 	if (get_disk_info(fd, label) == -1) {
    265 		return ((struct disk_type *)NULL);
    266 	}
    267 	/*
    268 	 * Now build the default partition table
    269 	 */
    270 	if (efi_alloc_and_init(fd, EFI_NUMPAR, &vtoc) != 0) {
    271 		err_print("efi_alloc_and_init failed. \n");
    272 		return ((struct disk_type *)NULL);
    273 	}
    274 
    275 	label->e_parts = vtoc;
    276 
    277 	/*
    278 	 * Create a whole hog EFI partition table:
    279 	 * S0 takes the whole disk except the primary EFI label,
    280 	 * backup EFI label, and the reserved partition.
    281 	 */
    282 	vtoc->efi_parts[0].p_tag = V_USR;
    283 	vtoc->efi_parts[0].p_start = vtoc->efi_first_u_lba;
    284 	vtoc->efi_parts[0].p_size = vtoc->efi_last_u_lba - vtoc->efi_first_u_lba
    285 	    - EFI_MIN_RESV_SIZE + 1;
    286 
    287 	/*
    288 	 * S1-S6 are unassigned slices.
    289 	 */
    290 	for (i = 1; i < vtoc->efi_nparts - 2; i ++) {
    291 		vtoc->efi_parts[i].p_tag = V_UNASSIGNED;
    292 		vtoc->efi_parts[i].p_start = 0;
    293 		vtoc->efi_parts[i].p_size = 0;
    294 	}
    295 
    296 	/*
    297 	 * The reserved slice
    298 	 */
    299 	vtoc->efi_parts[vtoc->efi_nparts - 1].p_tag = V_RESERVED;
    300 	vtoc->efi_parts[vtoc->efi_nparts - 1].p_start =
    301 	    vtoc->efi_last_u_lba - EFI_MIN_RESV_SIZE + 1;
    302 	vtoc->efi_parts[vtoc->efi_nparts - 1].p_size = EFI_MIN_RESV_SIZE;
    303 
    304 	/*
    305 	 * Now stick all of it into the disk_type struct
    306 	 */
    307 
    308 	if (ioctl(fd, DKIOCINFO, &dkinfo) == -1) {
    309 		if (option_msg && diag_msg) {
    310 			err_print("DKIOCINFO failed\n");
    311 		}
    312 		return (NULL);
    313 	}
    314 	if ((cur_ctype != NULL) && (cur_ctype->ctype_ctype == DKC_DIRECT)) {
    315 		ctlr = find_direct_ctlr_info(&dkinfo);
    316 		disk_info = find_direct_disk_info(&dkinfo);
    317 	} else if ((cur_ctype != NULL) && (cur_ctype->ctype_ctype == DKC_VBD)) {
    318 		ctlr = find_vbd_ctlr_info(&dkinfo);
    319 		disk_info = find_vbd_disk_info(&dkinfo);
    320 	} else {
    321 		ctlr = find_scsi_ctlr_info(&dkinfo);
    322 		disk_info = find_scsi_disk_info(&dkinfo);
    323 	}
    324 	disk = (struct disk_type *)zalloc(sizeof (struct disk_type));
    325 	assert(disk_info->disk_ctlr == ctlr);
    326 	dp = ctlr->ctlr_ctype->ctype_dlist;
    327 	if (dp == NULL) {
    328 		ctlr->ctlr_ctype->ctype_dlist = dp;
    329 	} else {
    330 		while (dp->dtype_next != NULL) {
    331 			dp = dp->dtype_next;
    332 		}
    333 		dp->dtype_next = disk;
    334 	}
    335 	disk->dtype_next = NULL;
    336 
    337 	(void) strlcpy(disk->vendor, label->vendor,
    338 	    sizeof (disk->vendor));
    339 	(void) strlcpy(disk->product, label->product,
    340 	    sizeof (disk->product));
    341 	(void) strlcpy(disk->revision, label->revision,
    342 	    sizeof (disk->revision));
    343 	disk->capacity = label->capacity;
    344 
    345 	part = (struct partition_info *)
    346 	    zalloc(sizeof (struct partition_info));
    347 	disk->dtype_plist = part;
    348 
    349 	part->pinfo_name = alloc_string("default");
    350 	part->pinfo_next = NULL;
    351 	part->etoc = vtoc;
    352 
    353 	bzero(disk_info->v_volume, LEN_DKL_VVOL);
    354 	disk_info->disk_parts = part;
    355 	return (disk);
    356 }
    357 
    358 static int
    359 efi_ioctl(int fd, int cmd, dk_efi_t *dk_ioc)
    360 {
    361 	void *data = dk_ioc->dki_data;
    362 	int error;
    363 
    364 	dk_ioc->dki_data_64 = (uint64_t)(uintptr_t)data;
    365 	error = ioctl(fd, cmd, (void *)dk_ioc);
    366 	dk_ioc->dki_data = data;
    367 
    368 	return (error);
    369 }
    370 
    371 static struct ctlr_type *
    372 find_direct_ctlr_type()
    373 {
    374 	struct	mctlr_list	*mlp;
    375 
    376 	mlp = controlp;
    377 
    378 	while (mlp != NULL) {
    379 		if (mlp->ctlr_type->ctype_ctype == DKC_DIRECT) {
    380 			return (mlp->ctlr_type);
    381 		}
    382 		mlp = mlp->next;
    383 	}
    384 
    385 	impossible("no DIRECT controller type");
    386 
    387 	return ((struct ctlr_type *)NULL);
    388 }
    389 
    390 static struct ctlr_type *
    391 find_vbd_ctlr_type()
    392 {
    393 	struct	mctlr_list	*mlp;
    394 
    395 	mlp = controlp;
    396 
    397 	while (mlp != NULL) {
    398 		if (mlp->ctlr_type->ctype_ctype == DKC_VBD) {
    399 			return (mlp->ctlr_type);
    400 		}
    401 		mlp = mlp->next;
    402 	}
    403 
    404 	impossible("no VBD controller type");
    405 
    406 	return ((struct ctlr_type *)NULL);
    407 }
    408 
    409 static struct ctlr_info *
    410 find_direct_ctlr_info(
    411 	struct dk_cinfo		*dkinfo)
    412 {
    413 	struct ctlr_info	*ctlr;
    414 
    415 	if (dkinfo->dki_ctype != DKC_DIRECT)
    416 		return (NULL);
    417 
    418 	for (ctlr = ctlr_list; ctlr != NULL; ctlr = ctlr->ctlr_next) {
    419 		if (ctlr->ctlr_addr == dkinfo->dki_addr &&
    420 		    ctlr->ctlr_space == dkinfo->dki_space &&
    421 		    ctlr->ctlr_ctype->ctype_ctype == DKC_DIRECT) {
    422 			return (ctlr);
    423 		}
    424 	}
    425 
    426 	impossible("no DIRECT controller info");
    427 	/*NOTREACHED*/
    428 }
    429 
    430 static struct ctlr_info *
    431 find_vbd_ctlr_info(
    432 	struct dk_cinfo		*dkinfo)
    433 {
    434 	struct ctlr_info	*ctlr;
    435 
    436 	if (dkinfo->dki_ctype != DKC_VBD)
    437 		return (NULL);
    438 
    439 	for (ctlr = ctlr_list; ctlr != NULL; ctlr = ctlr->ctlr_next) {
    440 		if (ctlr->ctlr_addr == dkinfo->dki_addr &&
    441 		    ctlr->ctlr_space == dkinfo->dki_space &&
    442 		    ctlr->ctlr_ctype->ctype_ctype == DKC_VBD) {
    443 			return (ctlr);
    444 		}
    445 	}
    446 
    447 	impossible("no VBD controller info");
    448 	/*NOTREACHED*/
    449 }
    450 
    451 static  struct disk_info *
    452 find_direct_disk_info(
    453 	struct dk_cinfo		*dkinfo)
    454 {
    455 	struct disk_info	*disk;
    456 	struct dk_cinfo		*dp;
    457 
    458 	for (disk = disk_list; disk != NULL; disk = disk->disk_next) {
    459 		assert(dkinfo->dki_ctype == DKC_DIRECT);
    460 		dp = &disk->disk_dkinfo;
    461 		if (dp->dki_ctype == dkinfo->dki_ctype &&
    462 		    dp->dki_cnum == dkinfo->dki_cnum &&
    463 		    dp->dki_unit == dkinfo->dki_unit &&
    464 		    strcmp(dp->dki_dname, dkinfo->dki_dname) == 0) {
    465 			return (disk);
    466 		}
    467 	}
    468 
    469 	impossible("No DIRECT disk info instance\n");
    470 	/*NOTREACHED*/
    471 }
    472 
    473 static  struct disk_info *
    474 find_vbd_disk_info(
    475 	struct dk_cinfo		*dkinfo)
    476 {
    477 	struct disk_info	*disk;
    478 	struct dk_cinfo		*dp;
    479 
    480 	for (disk = disk_list; disk != NULL; disk = disk->disk_next) {
    481 		assert(dkinfo->dki_ctype == DKC_VBD);
    482 		dp = &disk->disk_dkinfo;
    483 		if (dp->dki_ctype == dkinfo->dki_ctype &&
    484 		    dp->dki_cnum == dkinfo->dki_cnum &&
    485 		    dp->dki_unit == dkinfo->dki_unit &&
    486 		    strcmp(dp->dki_dname, dkinfo->dki_dname) == 0) {
    487 			return (disk);
    488 		}
    489 	}
    490 
    491 	impossible("No VBD disk info instance\n");
    492 	/*NOTREACHED*/
    493 }
    494 
    495 /*
    496  * To convert EFI to SMI labels, we need to get label geometry.
    497  * Unfortunately at this time there is no good way to do so.
    498  * DKIOCGGEOM will fail if disk is EFI labeled. So we hack around
    499  * it and clear EFI label, do a DKIOCGGEOM and put the EFI label
    500  * back on disk.
    501  * This routine gets the label geometry and initializes the label
    502  * It uses cur_file as opened device.
    503  * returns 0 if succeeds or -1 if failed.
    504  */
    505 static int
    506 auto_label_init(struct dk_label *label)
    507 {
    508 	dk_efi_t	dk_ioc;
    509 	dk_efi_t	dk_ioc_back;
    510 	efi_gpt_t	*data = NULL;
    511 	efi_gpt_t	*databack = NULL;
    512 	struct dk_geom	disk_geom;
    513 	struct dk_minfo	disk_info;
    514 	efi_gpt_t 	*backsigp;
    515 	int		fd = cur_file;
    516 	int		rval = -1;
    517 	int		efisize = EFI_LABEL_SIZE * 2;
    518 	int		success = 0;
    519 	uint64_t	sig;
    520 	uint64_t	backsig;
    521 
    522 	if ((data = calloc(efisize, 1)) == NULL) {
    523 		err_print("auto_label_init: calloc failed\n");
    524 		goto auto_label_init_out;
    525 	}
    526 
    527 	dk_ioc.dki_data = data;
    528 	dk_ioc.dki_lba = 1;
    529 	dk_ioc.dki_length = efisize;
    530 
    531 	if (efi_ioctl(fd, DKIOCGETEFI, &dk_ioc) != 0) {
    532 		err_print("auto_label_init: GETEFI failed\n");
    533 		goto auto_label_init_out;
    534 	}
    535 
    536 	if ((databack = calloc(efisize, 1)) == NULL) {
    537 		err_print("auto_label_init calloc2 failed");
    538 		goto auto_label_init_out;
    539 	}
    540 
    541 	/* get the LBA size and capacity */
    542 	if (ioctl(fd, DKIOCGMEDIAINFO, (caddr_t)&disk_info) == -1) {
    543 		err_print("auto_label_init: dkiocgmediainfo failed\n");
    544 		goto auto_label_init_out;
    545 	}
    546 
    547 	if (disk_info.dki_lbsize == 0) {
    548 		if (option_msg && diag_msg) {
    549 			err_print("auto_lbal_init: assuming 512 byte"
    550 			    "block size");
    551 		}
    552 		disk_info.dki_lbsize = DEV_BSIZE;
    553 	}
    554 
    555 	dk_ioc_back.dki_data = databack;
    556 
    557 	/*
    558 	 * back up efi label goes to capacity - 1, we are reading an extra block
    559 	 * before the back up label.
    560 	 */
    561 	dk_ioc_back.dki_lba = disk_info.dki_capacity - 1 - 1;
    562 	dk_ioc_back.dki_length = efisize;
    563 
    564 	if (efi_ioctl(fd, DKIOCGETEFI, &dk_ioc_back) != 0) {
    565 		err_print("auto_label_init: GETEFI backup failed\n");
    566 		goto auto_label_init_out;
    567 	}
    568 
    569 	sig = dk_ioc.dki_data->efi_gpt_Signature;
    570 	dk_ioc.dki_data->efi_gpt_Signature = 0x0;
    571 
    572 	enter_critical();
    573 
    574 	if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc) == -1) {
    575 		err_print("auto_label_init: SETEFI failed\n");
    576 		exit_critical();
    577 		goto auto_label_init_out;
    578 	}
    579 
    580 	backsigp = (efi_gpt_t *)((uintptr_t)dk_ioc_back.dki_data + cur_blksz);
    581 
    582 	backsig = backsigp->efi_gpt_Signature;
    583 
    584 	backsigp->efi_gpt_Signature = 0;
    585 
    586 	if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc_back) == -1) {
    587 		err_print("auto_label_init: SETEFI backup failed\n");
    588 	}
    589 
    590 	if (ioctl(cur_file, DKIOCGGEOM, &disk_geom) != 0)
    591 		err_print("auto_label_init: GGEOM failed\n");
    592 	else
    593 		success = 1;
    594 
    595 	dk_ioc.dki_data->efi_gpt_Signature = sig;
    596 	backsigp->efi_gpt_Signature = backsig;
    597 
    598 	if (efi_ioctl(cur_file, DKIOCSETEFI, &dk_ioc_back) == -1) {
    599 		err_print("auto_label_init: SETEFI revert backup failed\n");
    600 		success = 0;
    601 	}
    602 
    603 	if (efi_ioctl(cur_file, DKIOCSETEFI, &dk_ioc) == -1) {
    604 		err_print("auto_label_init: SETEFI revert failed\n");
    605 		success = 0;
    606 	}
    607 
    608 	exit_critical();
    609 
    610 	if (success == 0)
    611 		goto auto_label_init_out;
    612 
    613 	ncyl = disk_geom.dkg_ncyl;
    614 	acyl = disk_geom.dkg_acyl;
    615 	nhead =  disk_geom.dkg_nhead;
    616 	nsect = disk_geom.dkg_nsect;
    617 	pcyl = ncyl + acyl;
    618 
    619 	label->dkl_pcyl = pcyl;
    620 	label->dkl_ncyl = ncyl;
    621 	label->dkl_acyl = acyl;
    622 	label->dkl_nhead = nhead;
    623 	label->dkl_nsect = nsect;
    624 	label->dkl_apc = 0;
    625 	label->dkl_intrlv = 1;
    626 	label->dkl_rpm = disk_geom.dkg_rpm;
    627 
    628 	label->dkl_magic = DKL_MAGIC;
    629 
    630 	(void) snprintf(label->dkl_asciilabel, sizeof (label->dkl_asciilabel),
    631 	    "%s cyl %u alt %u hd %u sec %u",
    632 	    "DEFAULT", ncyl, acyl, nhead, nsect);
    633 
    634 	rval = 0;
    635 #if defined(_FIRMWARE_NEEDS_FDISK)
    636 	(void) auto_solaris_part(label);
    637 	ncyl = label->dkl_ncyl;
    638 
    639 #endif	/* defined(_FIRMWARE_NEEDS_FDISK) */
    640 
    641 	if (!build_default_partition(label, DKC_DIRECT)) {
    642 		rval = -1;
    643 	}
    644 
    645 	(void) checksum(label, CK_MAKESUM);
    646 
    647 
    648 auto_label_init_out:
    649 	if (data)
    650 		free(data);
    651 	if (databack)
    652 		free(databack);
    653 
    654 	return (rval);
    655 }
    656 
    657 static struct disk_type *
    658 new_direct_disk_type(
    659 	int		fd,
    660 	char		*disk_name,
    661 	struct dk_label	*label)
    662 {
    663 	struct disk_type	*dp;
    664 	struct disk_type	*disk;
    665 	struct ctlr_info	*ctlr;
    666 	struct dk_cinfo		dkinfo;
    667 	struct partition_info	*part = NULL;
    668 	struct partition_info	*pt;
    669 	struct disk_info	*disk_info;
    670 	int			i;
    671 
    672 	/*
    673 	 * Get the disk controller info for this disk
    674 	 */
    675 	if (ioctl(fd, DKIOCINFO, &dkinfo) == -1) {
    676 		if (option_msg && diag_msg) {
    677 			err_print("DKIOCINFO failed\n");
    678 		}
    679 		return (NULL);
    680 	}
    681 
    682 	/*
    683 	 * Find the ctlr_info for this disk.
    684 	 */
    685 	ctlr = find_direct_ctlr_info(&dkinfo);
    686 
    687 	/*
    688 	 * Allocate a new disk type for the direct controller.
    689 	 */
    690 	disk = (struct disk_type *)zalloc(sizeof (struct disk_type));
    691 
    692 	/*
    693 	 * Find the disk_info instance for this disk.
    694 	 */
    695 	disk_info = find_direct_disk_info(&dkinfo);
    696 
    697 	/*
    698 	 * The controller and the disk should match.
    699 	 */
    700 	assert(disk_info->disk_ctlr == ctlr);
    701 
    702 	/*
    703 	 * Link the disk into the list of disks
    704 	 */
    705 	dp = ctlr->ctlr_ctype->ctype_dlist;
    706 	if (dp == NULL) {
    707 		ctlr->ctlr_ctype->ctype_dlist = dp;
    708 	} else {
    709 		while (dp->dtype_next != NULL) {
    710 			dp = dp->dtype_next;
    711 		}
    712 		dp->dtype_next = disk;
    713 	}
    714 	disk->dtype_next = NULL;
    715 
    716 	/*
    717 	 * Allocate and initialize the disk name.
    718 	 */
    719 	disk->dtype_asciilabel = alloc_string(disk_name);
    720 
    721 	/*
    722 	 * Initialize disk geometry info
    723 	 */
    724 	disk->dtype_pcyl = label->dkl_pcyl;
    725 	disk->dtype_ncyl = label->dkl_ncyl;
    726 	disk->dtype_acyl = label->dkl_acyl;
    727 	disk->dtype_nhead = label->dkl_nhead;
    728 	disk->dtype_nsect = label->dkl_nsect;
    729 	disk->dtype_rpm = label->dkl_rpm;
    730 
    731 	part = (struct partition_info *)
    732 	    zalloc(sizeof (struct partition_info));
    733 	pt = disk->dtype_plist;
    734 	if (pt == NULL) {
    735 		disk->dtype_plist = part;
    736 	} else {
    737 		while (pt->pinfo_next != NULL) {
    738 			pt = pt->pinfo_next;
    739 		}
    740 		pt->pinfo_next = part;
    741 	}
    742 
    743 	part->pinfo_next = NULL;
    744 
    745 	/*
    746 	 * Set up the partition name
    747 	 */
    748 	part->pinfo_name = alloc_string("default");
    749 
    750 	/*
    751 	 * Fill in the partition info from the label
    752 	 */
    753 	for (i = 0; i < NDKMAP; i++) {
    754 
    755 #if defined(_SUNOS_VTOC_8)
    756 		part->pinfo_map[i] = label->dkl_map[i];
    757 
    758 #elif defined(_SUNOS_VTOC_16)
    759 		part->pinfo_map[i].dkl_cylno =
    760 		    label->dkl_vtoc.v_part[i].p_start /
    761 		    ((blkaddr_t)(disk->dtype_nhead *
    762 		    disk->dtype_nsect - apc));
    763 		part->pinfo_map[i].dkl_nblk =
    764 		    label->dkl_vtoc.v_part[i].p_size;
    765 #else
    766 #error No VTOC format defined.
    767 #endif				/* defined(_SUNOS_VTOC_8) */
    768 	}
    769 
    770 	/*
    771 	 * Use the VTOC if valid, or install a default
    772 	 */
    773 	if (label->dkl_vtoc.v_version == V_VERSION) {
    774 		(void) memcpy(disk_info->v_volume, label->dkl_vtoc.v_volume,
    775 		    LEN_DKL_VVOL);
    776 		part->vtoc = label->dkl_vtoc;
    777 	} else {
    778 		(void) memset(disk_info->v_volume, 0, LEN_DKL_VVOL);
    779 		set_vtoc_defaults(part);
    780 	}
    781 
    782 	/*
    783 	 * Link the disk to the partition map
    784 	 */
    785 	disk_info->disk_parts = part;
    786 
    787 	return (disk);
    788 }
    789 
    790 /*
    791  * Get a disk type that has label info. This is used to convert
    792  * EFI label to SMI label
    793  */
    794 struct disk_type *
    795 auto_direct_get_geom_label(int fd, struct dk_label *label)
    796 {
    797 	struct disk_type		*disk_type;
    798 
    799 	if (auto_label_init(label) != 0) {
    800 		err_print("auto_direct_get_geom_label: failed to get label"
    801 		    "geometry");
    802 		return (NULL);
    803 	} else {
    804 		disk_type = new_direct_disk_type(fd, "DEFAULT", label);
    805 		return (disk_type);
    806 	}
    807 }
    808 
    809 /*
    810  * Auto-sense a scsi disk configuration, ie get the information
    811  * necessary to construct a label.  We have two different
    812  * ways to auto-sense a scsi disk:
    813  *	- format.dat override, via inquiry name
    814  *	- generic scsi, via standard mode sense and inquiry
    815  * Depending on how and when we are called, and/or
    816  * change geometry and reformat.
    817  */
    818 struct disk_type *
    819 auto_sense(
    820 	int		fd,
    821 	int		can_prompt,
    822 	struct dk_label	*label)
    823 {
    824 	struct scsi_inquiry		inquiry;
    825 	struct scsi_capacity_16		capacity;
    826 	struct disk_type		*disk_type;
    827 	char				disk_name[DISK_NAME_MAX];
    828 	int				force_format_dat = 0;
    829 	int				force_generic = 0;
    830 	u_ioparam_t			ioparam;
    831 	int				deflt;
    832 
    833 	/*
    834 	 * First, if expert mode, find out if the user
    835 	 * wants to override any of the standard methods.
    836 	 */
    837 	if (can_prompt && expert_mode) {
    838 		deflt = 1;
    839 		ioparam.io_charlist = confirm_list;
    840 		if (input(FIO_MSTR, FORMAT_MSG, '?', &ioparam,
    841 		    &deflt, DATA_INPUT) == 0) {
    842 			force_format_dat = 1;
    843 		} else if (input(FIO_MSTR, GENERIC_MSG, '?', &ioparam,
    844 		    &deflt, DATA_INPUT) == 0) {
    845 			force_generic = 1;
    846 		}
    847 	}
    848 
    849 	/*
    850 	 * Get the Inquiry data.  If this fails, there's
    851 	 * no hope for this disk, so give up.
    852 	 */
    853 	if (uscsi_inquiry(fd, (char *)&inquiry, sizeof (inquiry))) {
    854 		return ((struct disk_type *)NULL);
    855 	}
    856 	if (option_msg && diag_msg) {
    857 		err_print("Product id: ");
    858 		print_buf(inquiry.inq_pid, sizeof (inquiry.inq_pid));
    859 		err_print("\n");
    860 	}
    861 
    862 	/*
    863 	 * Get the Read Capacity
    864 	 */
    865 	if (uscsi_read_capacity(fd, &capacity)) {
    866 		return ((struct disk_type *)NULL);
    867 	}
    868 
    869 	/*
    870 	 * If the reported capacity is set to zero, then the disk
    871 	 * is not usable. If the reported capacity is set to all
    872 	 * 0xf's, then this disk is too large.  These could only
    873 	 * happen with a device that supports LBAs larger than 64
    874 	 * bits which are not defined by any current T10 standards
    875 	 * or by error responding from target.
    876 	 */
    877 	if ((capacity.sc_capacity == 0) ||
    878 	    (capacity.sc_capacity == UINT_MAX64)) {
    879 		if (option_msg && diag_msg) {
    880 			err_print("Invalid capacity\n");
    881 		}
    882 		return ((struct disk_type *)NULL);
    883 	}
    884 	if (option_msg && diag_msg) {
    885 		err_print("blocks:  %llu (0x%llx)\n",
    886 		    capacity.sc_capacity, capacity.sc_capacity);
    887 		err_print("blksize: %u\n", capacity.sc_lbasize);
    888 	}
    889 
    890 	/*
    891 	 * Extract the disk name for the format.dat override
    892 	 */
    893 	(void) get_sun_disk_name(disk_name, &inquiry);
    894 	if (option_msg && diag_msg) {
    895 		err_print("disk name:  `%s`\n", disk_name);
    896 	}
    897 
    898 	if (scsi_rdwr(DIR_READ, fd, (diskaddr_t)0, 1, (caddr_t)label,
    899 	    F_SILENT, NULL))
    900 		return ((struct disk_type *)NULL);
    901 
    902 	/*
    903 	 * Figure out which method we use for auto sense.
    904 	 * If a particular method fails, we fall back to
    905 	 * the next possibility.
    906 	 */
    907 
    908 	if (force_generic) {
    909 		return (generic_disk_sense(fd, can_prompt, label,
    910 		    &inquiry, &capacity, disk_name));
    911 	}
    912 
    913 	/*
    914 	 * Try for an existing format.dat first
    915 	 */
    916 	if ((disk_type = find_scsi_disk_by_name(disk_name)) != NULL) {
    917 		if (use_existing_disk_type(fd, can_prompt, label,
    918 		    &inquiry, disk_type, &capacity)) {
    919 			return (disk_type);
    920 		}
    921 		if (force_format_dat) {
    922 			return (NULL);
    923 		}
    924 	}
    925 
    926 	/*
    927 	 * Otherwise, try using generic SCSI-2 sense and inquiry.
    928 	 */
    929 
    930 	return (generic_disk_sense(fd, can_prompt, label,
    931 	    &inquiry, &capacity, disk_name));
    932 }
    933 
    934 
    935 
    936 /*ARGSUSED*/
    937 static struct disk_type *
    938 generic_disk_sense(
    939 	int			fd,
    940 	int			can_prompt,
    941 	struct dk_label		*label,
    942 	struct scsi_inquiry	*inquiry,
    943 	struct scsi_capacity_16	*capacity,
    944 	char			*disk_name)
    945 {
    946 	struct disk_type		*disk;
    947 	int				setdefault = 0;
    948 	uint_t				pcyl = 0;
    949 	uint_t				ncyl = 0;
    950 	uint_t				acyl = 0;
    951 	uint_t				nhead = 0;
    952 	uint_t				nsect = 0;
    953 	int				rpm = 0;
    954 	diskaddr_t			nblocks = 0;
    955 	diskaddr_t			tblocks = 0;
    956 	union {
    957 		struct mode_format	page3;
    958 		uchar_t			buf3[MAX_MODE_SENSE_SIZE];
    959 	} u_page3;
    960 	union {
    961 		struct mode_geometry	page4;
    962 		uchar_t			buf4[MAX_MODE_SENSE_SIZE];
    963 	} u_page4;
    964 	struct mode_format		*page3 = &u_page3.page3;
    965 	struct mode_geometry		*page4 = &u_page4.page4;
    966 	struct scsi_ms_header		header;
    967 
    968 	/*
    969 	 * If the name of this disk appears to be "SUN", use it,
    970 	 * otherwise construct a name out of the generic
    971 	 * Inquiry info.  If it turns out that we already
    972 	 * have a SUN disk type of this name that differs
    973 	 * in geometry, we will revert to the generic name
    974 	 * anyway.
    975 	 */
    976 	if (memcmp(disk_name, "SUN", strlen("SUN")) != 0) {
    977 		(void) get_generic_disk_name(disk_name, inquiry);
    978 	}
    979 
    980 	/*
    981 	 * Get the number of blocks from Read Capacity data. Note that
    982 	 * the logical block address range from 0 to capacity->sc_capacity.
    983 	 * Limit the size to 2 TB (UINT32_MAX) to use with SMI labels.
    984 	 */
    985 	tblocks = (capacity->sc_capacity + 1);
    986 	if (tblocks > UINT32_MAX)
    987 		nblocks = UINT32_MAX;
    988 	else
    989 		nblocks = tblocks;
    990 
    991 	/*
    992 	 * Get current Page 3 - Format Parameters page
    993 	 */
    994 	if (uscsi_mode_sense(fd, DAD_MODE_FORMAT, MODE_SENSE_PC_CURRENT,
    995 	    (caddr_t)&u_page3, MAX_MODE_SENSE_SIZE, &header)) {
    996 		setdefault = 1;
    997 	}
    998 
    999 	/*
   1000 	 * Get current Page 4 - Drive Geometry page
   1001 	 */
   1002 	if (uscsi_mode_sense(fd, DAD_MODE_GEOMETRY, MODE_SENSE_PC_CURRENT,
   1003 	    (caddr_t)&u_page4, MAX_MODE_SENSE_SIZE, &header)) {
   1004 		setdefault = 1;
   1005 	}
   1006 
   1007 	if (setdefault != 1) {
   1008 		/* The inquiry of mode page 3 & page 4 are successful */
   1009 		/*
   1010 		 * Correct for byte order if necessary
   1011 		 */
   1012 		page4->rpm = BE_16(page4->rpm);
   1013 		page4->step_rate = BE_16(page4->step_rate);
   1014 		page3->tracks_per_zone = BE_16(page3->tracks_per_zone);
   1015 		page3->alt_sect_zone = BE_16(page3->alt_sect_zone);
   1016 		page3->alt_tracks_zone = BE_16(page3->alt_tracks_zone);
   1017 		page3->alt_tracks_vol = BE_16(page3->alt_tracks_vol);
   1018 		page3->sect_track = BE_16(page3->sect_track);
   1019 		page3->data_bytes_sect = BE_16(page3->data_bytes_sect);
   1020 		page3->interleave = BE_16(page3->interleave);
   1021 		page3->track_skew = BE_16(page3->track_skew);
   1022 		page3->cylinder_skew = BE_16(page3->cylinder_skew);
   1023 
   1024 
   1025 		/*
   1026 		 * Construct a new label out of the sense data,
   1027 		 * Inquiry and Capacity.
   1028 		 *
   1029 		 * If the disk capacity is > 1TB then simply compute
   1030 		 * the CHS values based on the total disk capacity and
   1031 		 * not use the values from mode-sense data.
   1032 		 */
   1033 		if (tblocks > INT32_MAX) {
   1034 			compute_chs_values(tblocks, nblocks, &pcyl, &nhead,
   1035 			    &nsect);
   1036 		} else {
   1037 			pcyl = (page4->cyl_ub << 16) + (page4->cyl_mb << 8) +
   1038 			    page4->cyl_lb;
   1039 			nhead = page4->heads;
   1040 			nsect = page3->sect_track;
   1041 		}
   1042 
   1043 		rpm = page4->rpm;
   1044 
   1045 		/*
   1046 		 * If the number of physical cylinders reported is less
   1047 		 * the SUN_MIN_CYL(3) then try to adjust the geometry so that
   1048 		 * we have atleast SUN_MIN_CYL cylinders.
   1049 		 */
   1050 		if (pcyl < SUN_MIN_CYL) {
   1051 			if (nhead == 0 || nsect == 0) {
   1052 				setdefault = 1;
   1053 			} else if (adjust_disk_geometry(
   1054 			    (diskaddr_t)(capacity->sc_capacity + 1),
   1055 			    &pcyl, &nhead, &nsect)) {
   1056 				setdefault = 1;
   1057 			}
   1058 		}
   1059 	}
   1060 
   1061 	/*
   1062 	 * Mode sense page 3 and page 4 are obsolete in SCSI-3. For
   1063 	 * newly developed large sector size disk, we will not rely on
   1064 	 * those two pages but compute geometry directly.
   1065 	 */
   1066 	if ((setdefault == 1) || (capacity->sc_lbasize != DEV_BSIZE)) {
   1067 		/*
   1068 		 * If the number of cylinders or the number of heads reported
   1069 		 * is zero, we think the inquiry of page 3 and page 4 failed.
   1070 		 * We will set the geometry infomation by ourselves.
   1071 		 */
   1072 		compute_chs_values(tblocks, nblocks, &pcyl, &nhead, &nsect);
   1073 	}
   1074 
   1075 	/*
   1076 	 * The sd driver reserves 2 cylinders the backup disk label and
   1077 	 * the deviceid.  Set the number of data cylinders to pcyl-acyl.
   1078 	 */
   1079 	acyl = DK_ACYL;
   1080 	ncyl = pcyl - acyl;
   1081 
   1082 	if (option_msg && diag_msg) {
   1083 		err_print("Geometry:\n");
   1084 		err_print("    pcyl:    %u\n", pcyl);
   1085 		err_print("    ncyl:    %u\n", ncyl);
   1086 		err_print("    heads:   %u\n", nhead);
   1087 		err_print("    nsects:  %u\n", nsect);
   1088 		err_print("    acyl:    %u\n", acyl);
   1089 
   1090 #if defined(_SUNOS_VTOC_16)
   1091 		err_print("    bcyl:    %u\n", bcyl);
   1092 #endif			/* defined(_SUNOS_VTOC_16) */
   1093 
   1094 		err_print("    rpm:     %d\n", rpm);
   1095 		err_print("    nblocks:     %llu\n", nblocks);
   1096 	}
   1097 
   1098 	/*
   1099 	 * Some drives do not support page4 or report 0 for page4->rpm,
   1100 	 * adjust it to AVG_RPM, 3600.
   1101 	 */
   1102 	if (rpm < MIN_RPM || rpm > MAX_RPM) {
   1103 		if (option_msg && diag_msg)
   1104 			err_print("The current rpm value %d is invalid,"
   1105 			    " adjusting it to %d\n", rpm, AVG_RPM);
   1106 		rpm = AVG_RPM;
   1107 	}
   1108 
   1109 	/*
   1110 	 * Some drives report 0 for nsect (page 3, byte 10 and 11) if they
   1111 	 * have variable number of sectors per track. So adjust nsect.
   1112 	 * Also the value is defined as vendor specific, hence check if
   1113 	 * it is in a tolerable range. The values (32 and 4 below) are
   1114 	 * chosen so that this change below does not generate a different
   1115 	 * geometry for currently supported sun disks.
   1116 	 */
   1117 	if ((nsect == 0) ||
   1118 	    ((diskaddr_t)pcyl * nhead * nsect) < (nblocks - nblocks/32) ||
   1119 	    ((diskaddr_t)pcyl * nhead * nsect) > (nblocks + nblocks/4)) {
   1120 		if (nblocks > (pcyl * nhead)) {
   1121 			err_print("Mode sense page(3) reports nsect value"
   1122 			    " as %d, adjusting it to %llu\n",
   1123 			    nsect, nblocks / (pcyl * nhead));
   1124 			nsect = nblocks / (pcyl * nhead);
   1125 		} else {
   1126 			/* convert capacity to nsect * nhead * pcyl */
   1127 			err_print("\nWARNING: Disk geometry is based on "
   1128 			    "capacity data.\n\n");
   1129 			compute_chs_values(tblocks, nblocks, &pcyl, &nhead,
   1130 			    &nsect);
   1131 			ncyl = pcyl - acyl;
   1132 			if (option_msg && diag_msg) {
   1133 				err_print("Geometry:(after adjustment)\n");
   1134 				err_print("    pcyl:    %u\n", pcyl);
   1135 				err_print("    ncyl:    %u\n", ncyl);
   1136 				err_print("    heads:   %u\n", nhead);
   1137 				err_print("    nsects:  %u\n", nsect);
   1138 				err_print("    acyl:    %u\n", acyl);
   1139 
   1140 #if defined(_SUNOS_VTOC_16)
   1141 				err_print("    bcyl:    %u\n", bcyl);
   1142 #endif
   1143 
   1144 				err_print("    rpm:     %d\n", rpm);
   1145 				err_print("    nblocks:     %llu\n", nblocks);
   1146 			}
   1147 		}
   1148 	}
   1149 
   1150 	/*
   1151 	 * Some drives report their physical geometry such that
   1152 	 * it is greater than the actual capacity.  Adjust the
   1153 	 * geometry to allow for this, so we don't run off
   1154 	 * the end of the disk.
   1155 	 */
   1156 	if (((diskaddr_t)pcyl * nhead * nsect) > nblocks) {
   1157 		uint_t	p = pcyl;
   1158 		if (option_msg && diag_msg) {
   1159 			err_print("Computed capacity (%llu) exceeds actual "
   1160 			    "disk capacity (%llu)\n",
   1161 			    (diskaddr_t)pcyl * nhead * nsect, nblocks);
   1162 		}
   1163 		do {
   1164 			pcyl--;
   1165 		} while (((diskaddr_t)pcyl * nhead * nsect) > nblocks);
   1166 
   1167 		if (can_prompt && expert_mode && !option_f) {
   1168 			/*
   1169 			 * Try to adjust nsect instead of pcyl to see if we
   1170 			 * can optimize. For compatability reasons do this
   1171 			 * only in expert mode (refer to bug 1144812).
   1172 			 */
   1173 			uint_t	n = nsect;
   1174 			do {
   1175 				n--;
   1176 			} while (((diskaddr_t)p * nhead * n) > nblocks);
   1177 			if (((diskaddr_t)p * nhead * n) >
   1178 			    ((diskaddr_t)pcyl * nhead * nsect)) {
   1179 				u_ioparam_t	ioparam;
   1180 				int		deflt = 1;
   1181 				/*
   1182 				 * Ask the user for a choice here.
   1183 				 */
   1184 				ioparam.io_bounds.lower = 1;
   1185 				ioparam.io_bounds.upper = 2;
   1186 				err_print("1. Capacity = %llu, with pcyl = %u "
   1187 				    "nhead = %u nsect = %u\n",
   1188 				    ((diskaddr_t)pcyl * nhead * nsect),
   1189 				    pcyl, nhead, nsect);
   1190 				err_print("2. Capacity = %llu, with pcyl = %u "
   1191 				    "nhead = %u nsect = %u\n",
   1192 				    ((diskaddr_t)p * nhead * n),
   1193 				    p, nhead, n);
   1194 				if (input(FIO_INT, "Select one of the above "
   1195 				    "choices ", ':', &ioparam,
   1196 				    &deflt, DATA_INPUT) == 2) {
   1197 					pcyl = p;
   1198 					nsect = n;
   1199 				}
   1200 			}
   1201 		}
   1202 	}
   1203 
   1204 #if defined(_SUNOS_VTOC_8)
   1205 	/*
   1206 	 * Finally, we need to make sure we don't overflow any of the
   1207 	 * fields in our disk label.  To do this we need to `square
   1208 	 * the box' so to speak.  We will lose bits here.
   1209 	 */
   1210 
   1211 	if ((pcyl > MAXIMUM_NO_CYLINDERS &&
   1212 	    ((nsect > MAXIMUM_NO_SECTORS) ||
   1213 	    (nhead > MAXIMUM_NO_HEADS))) ||
   1214 	    ((nsect > MAXIMUM_NO_SECTORS) &&
   1215 	    (nhead > MAXIMUM_NO_HEADS))) {
   1216 		err_print("This disk is too big to label. "
   1217 		    " You will lose some blocks.\n");
   1218 	}
   1219 	if ((pcyl > MAXIMUM_NO_CYLINDERS) ||
   1220 	    (nsect > MAXIMUM_NO_SECTORS) ||
   1221 	    (nhead > MAXIMUM_NO_HEADS)) {
   1222 		u_ioparam_t	ioparam;
   1223 		int		order;
   1224 		char		msg[256];
   1225 
   1226 		order = ((pcyl > nhead)<<2) |
   1227 		    ((pcyl > nsect)<<1) |
   1228 		    (nhead > nsect);
   1229 		switch (order) {
   1230 		case 0x7: /* pcyl > nhead > nsect */
   1231 			nblocks =
   1232 			    square_box(nblocks,
   1233 			    &pcyl, MAXIMUM_NO_CYLINDERS,
   1234 			    &nhead, MAXIMUM_NO_HEADS,
   1235 			    &nsect, MAXIMUM_NO_SECTORS);
   1236 			break;
   1237 		case 0x6: /* pcyl > nsect > nhead */
   1238 			nblocks =
   1239 			    square_box(nblocks,
   1240 			    &pcyl, MAXIMUM_NO_CYLINDERS,
   1241 			    &nsect, MAXIMUM_NO_SECTORS,
   1242 			    &nhead, MAXIMUM_NO_HEADS);
   1243 			break;
   1244 		case 0x4: /* nsect > pcyl > nhead */
   1245 			nblocks =
   1246 			    square_box(nblocks,
   1247 			    &nsect, MAXIMUM_NO_SECTORS,
   1248 			    &pcyl, MAXIMUM_NO_CYLINDERS,
   1249 			    &nhead, MAXIMUM_NO_HEADS);
   1250 			break;
   1251 		case 0x0: /* nsect > nhead > pcyl */
   1252 			nblocks =
   1253 			    square_box(nblocks,
   1254 			    &nsect, MAXIMUM_NO_SECTORS,
   1255 			    &nhead, MAXIMUM_NO_HEADS,
   1256 			    &pcyl, MAXIMUM_NO_CYLINDERS);
   1257 			break;
   1258 		case 0x3: /* nhead > pcyl > nsect */
   1259 			nblocks =
   1260 			    square_box(nblocks,
   1261 			    &nhead, MAXIMUM_NO_HEADS,
   1262 			    &pcyl, MAXIMUM_NO_CYLINDERS,
   1263 			    &nsect, MAXIMUM_NO_SECTORS);
   1264 			break;
   1265 		case 0x1: /* nhead > nsect > pcyl */
   1266 			nblocks =
   1267 			    square_box(nblocks,
   1268 			    &nhead, MAXIMUM_NO_HEADS,
   1269 			    &nsect, MAXIMUM_NO_SECTORS,
   1270 			    &pcyl, MAXIMUM_NO_CYLINDERS);
   1271 			break;
   1272 		default:
   1273 			/* How did we get here? */
   1274 			impossible("label overflow adjustment");
   1275 
   1276 			/* Do something useful */
   1277 			nblocks =
   1278 			    square_box(nblocks,
   1279 			    &nhead, MAXIMUM_NO_HEADS,
   1280 			    &nsect, MAXIMUM_NO_SECTORS,
   1281 			    &pcyl, MAXIMUM_NO_CYLINDERS);
   1282 			break;
   1283 		}
   1284 		if (option_msg && diag_msg &&
   1285 		    (capacity->sc_capacity + 1 != nblocks)) {
   1286 			err_print("After adjusting geometry you lost"
   1287 			    " %llu of %llu blocks.\n",
   1288 			    (capacity->sc_capacity + 1 - nblocks),
   1289 			    capacity->sc_capacity + 1);
   1290 		}
   1291 		while (can_prompt && expert_mode && !option_f) {
   1292 			int				deflt = 1;
   1293 
   1294 			/*
   1295 			 * Allow user to modify this by hand if desired.
   1296 			 */
   1297 			(void) sprintf(msg,
   1298 			    "\nGeometry: %u heads, %u sectors %u cylinders"
   1299 			    " result in %llu out of %llu blocks.\n"
   1300 			    "Do you want to modify the device geometry",
   1301 			    nhead, nsect, pcyl,
   1302 			    nblocks, capacity->sc_capacity + 1);
   1303 
   1304 			ioparam.io_charlist = confirm_list;
   1305 			if (input(FIO_MSTR, msg, '?', &ioparam,
   1306 			    &deflt, DATA_INPUT) != 0)
   1307 				break;
   1308 
   1309 			ioparam.io_bounds.lower = MINIMUM_NO_HEADS;
   1310 			ioparam.io_bounds.upper = MAXIMUM_NO_HEADS;
   1311 			nhead = input(FIO_INT, "Number of heads", ':',
   1312 			    &ioparam, (int *)&nhead, DATA_INPUT);
   1313 			ioparam.io_bounds.lower = MINIMUM_NO_SECTORS;
   1314 			ioparam.io_bounds.upper = MAXIMUM_NO_SECTORS;
   1315 			nsect = input(FIO_INT,
   1316 			    "Number of sectors per track",
   1317 			    ':', &ioparam, (int *)&nsect, DATA_INPUT);
   1318 			ioparam.io_bounds.lower = SUN_MIN_CYL;
   1319 			ioparam.io_bounds.upper = MAXIMUM_NO_CYLINDERS;
   1320 			pcyl = input(FIO_INT, "Number of cylinders",
   1321 			    ':', &ioparam, (int *)&pcyl, DATA_INPUT);
   1322 			nblocks = (diskaddr_t)nhead * nsect * pcyl;
   1323 			if (nblocks > capacity->sc_capacity + 1) {
   1324 				err_print("Warning: %llu blocks exceeds "
   1325 				    "disk capacity of %llu blocks\n",
   1326 				    nblocks,
   1327 				    capacity->sc_capacity + 1);
   1328 			}
   1329 		}
   1330 	}
   1331 #endif		/* defined(_SUNOS_VTOC_8) */
   1332 
   1333 	ncyl = pcyl - acyl;
   1334 
   1335 	if (option_msg && diag_msg) {
   1336 		err_print("\nGeometry after adjusting for capacity:\n");
   1337 		err_print("    pcyl:    %u\n", pcyl);
   1338 		err_print("    ncyl:    %u\n", ncyl);
   1339 		err_print("    heads:   %u\n", nhead);
   1340 		err_print("    nsects:  %u\n", nsect);
   1341 		err_print("    acyl:    %u\n", acyl);
   1342 		err_print("    rpm:     %d\n", rpm);
   1343 	}
   1344 
   1345 	(void) memset((char *)label, 0, sizeof (struct dk_label));
   1346 
   1347 	label->dkl_magic = DKL_MAGIC;
   1348 
   1349 	(void) snprintf(label->dkl_asciilabel, sizeof (label->dkl_asciilabel),
   1350 	    "%s cyl %u alt %u hd %u sec %u",
   1351 	    disk_name, ncyl, acyl, nhead, nsect);
   1352 
   1353 	label->dkl_pcyl = pcyl;
   1354 	label->dkl_ncyl = ncyl;
   1355 	label->dkl_acyl = acyl;
   1356 	label->dkl_nhead = nhead;
   1357 	label->dkl_nsect = nsect;
   1358 	label->dkl_apc = 0;
   1359 	label->dkl_intrlv = 1;
   1360 	label->dkl_rpm = rpm;
   1361 
   1362 #if defined(_FIRMWARE_NEEDS_FDISK)
   1363 	if (auto_solaris_part(label) == -1)
   1364 		goto err;
   1365 	ncyl = label->dkl_ncyl;
   1366 #endif		/* defined(_FIRMWARE_NEEDS_FDISK) */
   1367 
   1368 
   1369 	if (!build_default_partition(label, DKC_SCSI_CCS)) {
   1370 		goto err;
   1371 	}
   1372 
   1373 	(void) checksum(label, CK_MAKESUM);
   1374 
   1375 	/*
   1376 	 * Find an existing disk type defined for this disk.
   1377 	 * For this to work, both the name and geometry must
   1378 	 * match.  If there is no such type, but there already
   1379 	 * is a disk defined with that name, but with a different
   1380 	 * geometry, construct a new generic disk name out of
   1381 	 * the inquiry information.  Whatever name we're
   1382 	 * finally using, if there's no such disk type defined,
   1383 	 * build a new disk definition.
   1384 	 */
   1385 	if ((disk = find_scsi_disk_type(disk_name, label)) == NULL) {
   1386 		if (find_scsi_disk_by_name(disk_name) != NULL) {
   1387 			char	old_name[DISK_NAME_MAX];
   1388 			(void) strcpy(old_name, disk_name);
   1389 			(void) get_generic_disk_name(disk_name,
   1390 			    inquiry);
   1391 			if (option_msg && diag_msg) {
   1392 				err_print(
   1393 "Changing disk type name from '%s' to '%s'\n", old_name, disk_name);
   1394 			}
   1395 			(void) snprintf(label->dkl_asciilabel,
   1396 			    sizeof (label->dkl_asciilabel),
   1397 			    "%s cyl %u alt %u hd %u sec %u",
   1398 			    disk_name, ncyl, acyl, nhead, nsect);
   1399 			(void) checksum(label, CK_MAKESUM);
   1400 			disk = find_scsi_disk_type(disk_name, label);
   1401 		}
   1402 		if (disk == NULL) {
   1403 			disk = new_scsi_disk_type(fd, disk_name, label);
   1404 			if (disk == NULL)
   1405 				goto err;
   1406 		}
   1407 	}
   1408 
   1409 	return (disk);
   1410 
   1411 err:
   1412 	if (option_msg && diag_msg) {
   1413 		err_print(
   1414 		"Configuration via generic SCSI-2 information failed\n");
   1415 	}
   1416 	return (NULL);
   1417 }
   1418 
   1419 
   1420 /*ARGSUSED*/
   1421 static int
   1422 use_existing_disk_type(
   1423 	int			fd,
   1424 	int			can_prompt,
   1425 	struct dk_label		*label,
   1426 	struct scsi_inquiry	*inquiry,
   1427 	struct disk_type	*disk_type,
   1428 	struct scsi_capacity_16	*capacity)
   1429 {
   1430 	int			pcyl;
   1431 	int			acyl;
   1432 	int			nhead;
   1433 	int			nsect;
   1434 	int			rpm;
   1435 
   1436 	/*
   1437 	 * Construct a new label out of the format.dat
   1438 	 */
   1439 	pcyl = disk_type->dtype_pcyl;
   1440 	acyl = disk_type->dtype_acyl;
   1441 	ncyl = disk_type->dtype_ncyl;
   1442 	nhead = disk_type->dtype_nhead;
   1443 	nsect = disk_type->dtype_nsect;
   1444 	rpm = disk_type->dtype_rpm;
   1445 
   1446 	if (option_msg && diag_msg) {
   1447 		err_print("Format.dat geometry:\n");
   1448 		err_print("    pcyl:    %u\n", pcyl);
   1449 		err_print("    heads:   %u\n", nhead);
   1450 		err_print("    nsects:  %u\n", nsect);
   1451 		err_print("    acyl:    %u\n", acyl);
   1452 		err_print("    rpm:     %d\n", rpm);
   1453 	}
   1454 
   1455 	(void) memset((char *)label, 0, sizeof (struct dk_label));
   1456 
   1457 	label->dkl_magic = DKL_MAGIC;
   1458 
   1459 	(void) snprintf(label->dkl_asciilabel, sizeof (label->dkl_asciilabel),
   1460 	    "%s cyl %u alt %u hd %u sec %u",
   1461 	    disk_type->dtype_asciilabel,
   1462 	    ncyl, acyl, nhead, nsect);
   1463 
   1464 	label->dkl_pcyl = pcyl;
   1465 	label->dkl_ncyl = ncyl;
   1466 	label->dkl_acyl = acyl;
   1467 	label->dkl_nhead = nhead;
   1468 	label->dkl_nsect = nsect;
   1469 	label->dkl_apc = 0;
   1470 	label->dkl_intrlv = 1;
   1471 	label->dkl_rpm = rpm;
   1472 
   1473 	if (!build_default_partition(label, DKC_SCSI_CCS)) {
   1474 		goto err;
   1475 	}
   1476 
   1477 	(void) checksum(label, CK_MAKESUM);
   1478 	return (1);
   1479 
   1480 err:
   1481 	if (option_msg && diag_msg) {
   1482 		err_print(
   1483 		    "Configuration via format.dat geometry failed\n");
   1484 	}
   1485 	return (0);
   1486 }
   1487 
   1488 int
   1489 build_default_partition(
   1490 	struct dk_label			*label,
   1491 	int				ctrl_type)
   1492 {
   1493 	int				i;
   1494 	int				ncyls[NDKMAP];
   1495 	diskaddr_t			nblks;
   1496 	int				cyl;
   1497 	struct dk_vtoc			*vtoc;
   1498 	struct part_table		*pt;
   1499 	struct default_partitions	*dpt;
   1500 	diskaddr_t			capacity;
   1501 	int				freecyls;
   1502 	int				blks_per_cyl;
   1503 	int				ncyl;
   1504 
   1505 #ifdef lint
   1506 	ctrl_type = ctrl_type;
   1507 #endif
   1508 
   1509 	/*
   1510 	 * Install a default vtoc
   1511 	 */
   1512 	vtoc = &label->dkl_vtoc;
   1513 	vtoc->v_version = V_VERSION;
   1514 	vtoc->v_nparts = NDKMAP;
   1515 	vtoc->v_sanity = VTOC_SANE;
   1516 
   1517 	for (i = 0; i < NDKMAP; i++) {
   1518 		vtoc->v_part[i].p_tag = default_vtoc_map[i].p_tag;
   1519 		vtoc->v_part[i].p_flag = default_vtoc_map[i].p_flag;
   1520 	}
   1521 
   1522 	/*
   1523 	 * Find a partition that matches this disk.  Capacity
   1524 	 * is in integral number of megabytes.
   1525 	 */
   1526 	capacity = ((diskaddr_t)(label->dkl_ncyl) * label->dkl_nhead *
   1527 	    label->dkl_nsect) / (diskaddr_t)((1024 * 1024) / cur_blksz);
   1528 	dpt = default_partitions;
   1529 	for (i = 0; i < DEFAULT_PARTITION_TABLE_SIZE; i++, dpt++) {
   1530 		if (capacity >= dpt->min_capacity &&
   1531 		    capacity < dpt->max_capacity) {
   1532 			break;
   1533 		}
   1534 	}
   1535 	if (i == DEFAULT_PARTITION_TABLE_SIZE) {
   1536 		if (option_msg && diag_msg) {
   1537 			err_print("No matching default partition (%llu)\n",
   1538 			    capacity);
   1539 		}
   1540 		return (0);
   1541 	}
   1542 	pt = dpt->part_table;
   1543 
   1544 	/*
   1545 	 * Go through default partition table, finding fixed
   1546 	 * sized entries.
   1547 	 */
   1548 	freecyls = label->dkl_ncyl;
   1549 	blks_per_cyl = label->dkl_nhead * label->dkl_nsect;
   1550 	for (i = 0; i < NDKMAP; i++) {
   1551 		if (pt->partitions[i] == HOG || pt->partitions[i] == 0) {
   1552 			ncyls[i] = 0;
   1553 		} else {
   1554 			/*
   1555 			 * Calculate number of cylinders necessary
   1556 			 * for specified size, rounding up to
   1557 			 * the next greatest integral number of
   1558 			 * cylinders.  Always give what they
   1559 			 * asked or more, never less.
   1560 			 */
   1561 			nblks = pt->partitions[i] * ((1024*1024)/cur_blksz);
   1562 			nblks += (blks_per_cyl - 1);
   1563 			ncyls[i] = nblks / blks_per_cyl;
   1564 			freecyls -= ncyls[i];
   1565 		}
   1566 	}
   1567 
   1568 	if (freecyls < 0) {
   1569 		if (option_msg && diag_msg) {
   1570 			for (i = 0; i < NDKMAP; i++) {
   1571 				if (ncyls[i] == 0)
   1572 					continue;
   1573 				err_print("Partition %d: %u cyls\n",
   1574 				    i, ncyls[i]);
   1575 			}
   1576 			err_print("Free cylinders exhausted (%d)\n",
   1577 			    freecyls);
   1578 		}
   1579 		return (0);
   1580 	}
   1581 #if defined(i386)
   1582 	/*
   1583 	 * Set the default boot partition to 1 cylinder
   1584 	 */
   1585 	ncyls[8] = 1;
   1586 	freecyls -= 1;
   1587 
   1588 	/*
   1589 	 * If current disk type is not a SCSI disk,
   1590 	 * set the default alternates partition to 2 cylinders
   1591 	 */
   1592 	if (ctrl_type != DKC_SCSI_CCS) {
   1593 		ncyls[9] = 2;
   1594 		freecyls -= 2;
   1595 	}
   1596 #endif			/* defined(i386) */
   1597 
   1598 	/*
   1599 	 * Set the free hog partition to whatever space remains.
   1600 	 * It's an error to have more than one HOG partition,
   1601 	 * but we don't verify that here.
   1602 	 */
   1603 	for (i = 0; i < NDKMAP; i++) {
   1604 		if (pt->partitions[i] == HOG) {
   1605 			assert(ncyls[i] == 0);
   1606 			ncyls[i] = freecyls;
   1607 			break;
   1608 		}
   1609 	}
   1610 
   1611 	/*
   1612 	 * Error checking
   1613 	 */
   1614 	ncyl = 0;
   1615 	for (i = 0; i < NDKMAP; i++) {
   1616 		ncyl += ncyls[i];
   1617 	}
   1618 	assert(ncyl == (label->dkl_ncyl));
   1619 
   1620 	/*
   1621 	 * Finally, install the partition in the label.
   1622 	 */
   1623 	cyl = 0;
   1624 
   1625 #if defined(_SUNOS_VTOC_16)
   1626 	for (i = NDKMAP/2; i < NDKMAP; i++) {
   1627 		if (i == 2 || ncyls[i] == 0)
   1628 			continue;
   1629 		label->dkl_vtoc.v_part[i].p_start = cyl * blks_per_cyl;
   1630 		label->dkl_vtoc.v_part[i].p_size = ncyls[i] * blks_per_cyl;
   1631 		cyl += ncyls[i];
   1632 	}
   1633 	for (i = 0; i < NDKMAP/2; i++) {
   1634 
   1635 #elif defined(_SUNOS_VTOC_8)
   1636 	for (i = 0; i < NDKMAP; i++) {
   1637 
   1638 #else
   1639 #error No VTOC format defined.
   1640 #endif				/* defined(_SUNOS_VTOC_16) */
   1641 
   1642 		if (i == 2 || ncyls[i] == 0) {
   1643 #if defined(_SUNOS_VTOC_8)
   1644 			if (i != 2) {
   1645 				label->dkl_map[i].dkl_cylno = 0;
   1646 				label->dkl_map[i].dkl_nblk = 0;
   1647 			}
   1648 #endif
   1649 			continue;
   1650 		}
   1651 #if defined(_SUNOS_VTOC_8)
   1652 		label->dkl_map[i].dkl_cylno = cyl;
   1653 		label->dkl_map[i].dkl_nblk = ncyls[i] * blks_per_cyl;
   1654 #elif defined(_SUNOS_VTOC_16)
   1655 		label->dkl_vtoc.v_part[i].p_start = cyl * blks_per_cyl;
   1656 		label->dkl_vtoc.v_part[i].p_size = ncyls[i] * blks_per_cyl;
   1657 
   1658 #else
   1659 #error No VTOC format defined.
   1660 #endif				/* defined(_SUNOS_VTOC_8) */
   1661 
   1662 		cyl += ncyls[i];
   1663 	}
   1664 
   1665 	/*
   1666 	 * Set the whole disk partition
   1667 	 */
   1668 #if defined(_SUNOS_VTOC_8)
   1669 	label->dkl_map[2].dkl_cylno = 0;
   1670 	label->dkl_map[2].dkl_nblk =
   1671 	    label->dkl_ncyl * label->dkl_nhead * label->dkl_nsect;
   1672 
   1673 #elif defined(_SUNOS_VTOC_16)
   1674 	label->dkl_vtoc.v_part[2].p_start = 0;
   1675 	label->dkl_vtoc.v_part[2].p_size =
   1676 	    (label->dkl_ncyl + label->dkl_acyl) * label->dkl_nhead *
   1677 	    label->dkl_nsect;
   1678 #else
   1679 #error No VTOC format defined.
   1680 #endif				/* defined(_SUNOS_VTOC_8) */
   1681 
   1682 
   1683 	if (option_msg && diag_msg) {
   1684 		float	scaled;
   1685 		err_print("\n");
   1686 		for (i = 0; i < NDKMAP; i++) {
   1687 #if defined(_SUNOS_VTOC_8)
   1688 			if (label->dkl_map[i].dkl_nblk == 0)
   1689 
   1690 #elif defined(_SUNOS_VTOC_16)
   1691 			if (label->dkl_vtoc.v_part[i].p_size == 0)
   1692 
   1693 #else
   1694 #error No VTOC format defined.
   1695 #endif				/* defined(_SUNOS_VTOC_8) */
   1696 
   1697 				continue;
   1698 			err_print("Partition %d:   ", i);
   1699 #if defined(_SUNOS_VTOC_8)
   1700 			scaled = bn2mb(label->dkl_map[i].dkl_nblk);
   1701 
   1702 #elif defined(_SUNOS_VTOC_16)
   1703 
   1704 			scaled = bn2mb(label->dkl_vtoc.v_part[i].p_size);
   1705 #else
   1706 #error No VTOC format defined.
   1707 #endif				/* defined(_SUNOS_VTOC_8) */
   1708 
   1709 			if (scaled > 1024.0) {
   1710 				err_print("%6.2fGB  ", scaled/1024.0);
   1711 			} else {
   1712 				err_print("%6.2fMB  ", scaled);
   1713 			}
   1714 #if defined(_SUNOS_VTOC_8)
   1715 			err_print(" %6d cylinders\n",
   1716 			    label->dkl_map[i].dkl_nblk/blks_per_cyl);
   1717 #elif defined(_SUNOS_VTOC_16)
   1718 			err_print(" %6d cylinders\n",
   1719 			    label->dkl_vtoc.v_part[i].p_size/blks_per_cyl);
   1720 #else
   1721 #error No VTOC format defined.
   1722 #endif				/* defined(_SUNOS_VTOC_8) */
   1723 
   1724 		}
   1725 		err_print("\n");
   1726 	}
   1727 
   1728 	return (1);
   1729 }
   1730 
   1731 
   1732 
   1733 /*
   1734  * Find an existing scsi disk definition by this name,
   1735  * if possible.
   1736  */
   1737 static struct disk_type *
   1738 find_scsi_disk_type(
   1739 	char			*disk_name,
   1740 	struct dk_label		*label)
   1741 {
   1742 	struct ctlr_type	*ctlr;
   1743 	struct disk_type	*dp;
   1744 
   1745 	ctlr = find_scsi_ctlr_type();
   1746 	for (dp = ctlr->ctype_dlist; dp != NULL; dp = dp->dtype_next) {
   1747 		if (dp->dtype_asciilabel) {
   1748 			if ((strcmp(dp->dtype_asciilabel, disk_name) == 0) &&
   1749 			    dp->dtype_pcyl == label->dkl_pcyl &&
   1750 			    dp->dtype_ncyl == label->dkl_ncyl &&
   1751 			    dp->dtype_acyl == label->dkl_acyl &&
   1752 			    dp->dtype_nhead == label->dkl_nhead &&
   1753 			    dp->dtype_nsect == label->dkl_nsect) {
   1754 				return (dp);
   1755 			}
   1756 		}
   1757 	}
   1758 
   1759 	return ((struct disk_type *)NULL);
   1760 }
   1761 
   1762 
   1763 /*
   1764  * Find an existing scsi disk definition by this name,
   1765  * if possible.
   1766  */
   1767 static struct disk_type *
   1768 find_scsi_disk_by_name(
   1769 	char			*disk_name)
   1770 {
   1771 	struct ctlr_type	*ctlr;
   1772 	struct disk_type	*dp;
   1773 
   1774 	ctlr = find_scsi_ctlr_type();
   1775 	for (dp = ctlr->ctype_dlist; dp != NULL; dp = dp->dtype_next) {
   1776 		if (dp->dtype_asciilabel) {
   1777 			if ((strcmp(dp->dtype_asciilabel, disk_name) == 0)) {
   1778 				return (dp);
   1779 			}
   1780 		}
   1781 	}
   1782 
   1783 	return ((struct disk_type *)NULL);
   1784 }
   1785 
   1786 
   1787 /*
   1788  * Return a pointer to the ctlr_type structure for SCSI
   1789  * disks.  This list is built into the program, so there's
   1790  * no chance of not being able to find it, unless someone
   1791  * totally mangles the code.
   1792  */
   1793 static struct ctlr_type *
   1794 find_scsi_ctlr_type()
   1795 {
   1796 	struct	mctlr_list	*mlp;
   1797 
   1798 	mlp = controlp;
   1799 
   1800 	while (mlp != NULL) {
   1801 		if (mlp->ctlr_type->ctype_ctype == DKC_SCSI_CCS) {
   1802 			return (mlp->ctlr_type);
   1803 		}
   1804 		mlp = mlp->next;
   1805 	}
   1806 
   1807 	impossible("no SCSI controller type");
   1808 
   1809 	return ((struct ctlr_type *)NULL);
   1810 }
   1811 
   1812 
   1813 
   1814 /*
   1815  * Return a pointer to the scsi ctlr_info structure.  This
   1816  * structure is allocated the first time format sees a
   1817  * disk on this controller, so it must be present.
   1818  */
   1819 static struct ctlr_info *
   1820 find_scsi_ctlr_info(
   1821 	struct dk_cinfo		*dkinfo)
   1822 {
   1823 	struct ctlr_info	*ctlr;
   1824 
   1825 	if (dkinfo->dki_ctype != DKC_SCSI_CCS) {
   1826 		return (NULL);
   1827 	}
   1828 
   1829 	for (ctlr = ctlr_list; ctlr != NULL; ctlr = ctlr->ctlr_next) {
   1830 		if (ctlr->ctlr_addr == dkinfo->dki_addr &&
   1831 		    ctlr->ctlr_space == dkinfo->dki_space &&
   1832 		    ctlr->ctlr_ctype->ctype_ctype == DKC_SCSI_CCS) {
   1833 			return (ctlr);
   1834 		}
   1835 	}
   1836 
   1837 	impossible("no SCSI controller info");
   1838 
   1839 	return ((struct ctlr_info *)NULL);
   1840 }
   1841 
   1842 
   1843 
   1844 static struct disk_type *
   1845 new_scsi_disk_type(
   1846 	int		fd,
   1847 	char		*disk_name,
   1848 	struct dk_label	*label)
   1849 {
   1850 	struct disk_type	*dp;
   1851 	struct disk_type	*disk;
   1852 	struct ctlr_info	*ctlr;
   1853 	struct dk_cinfo		dkinfo;
   1854 	struct partition_info	*part;
   1855 	struct partition_info	*pt;
   1856 	struct disk_info	*disk_info;
   1857 	int			i;
   1858 
   1859 	/*
   1860 	 * Get the disk controller info for this disk
   1861 	 */
   1862 	if (ioctl(fd, DKIOCINFO, &dkinfo) == -1) {
   1863 		if (option_msg && diag_msg) {
   1864 			err_print("DKIOCINFO failed\n");
   1865 		}
   1866 		return (NULL);
   1867 	}
   1868 
   1869 	/*
   1870 	 * Find the ctlr_info for this disk.
   1871 	 */
   1872 	ctlr = find_scsi_ctlr_info(&dkinfo);
   1873 
   1874 	/*
   1875 	 * Allocate a new disk type for the SCSI controller.
   1876 	 */
   1877 	disk = (struct disk_type *)zalloc(sizeof (struct disk_type));
   1878 
   1879 	/*
   1880 	 * Find the disk_info instance for this disk.
   1881 	 */
   1882 	disk_info = find_scsi_disk_info(&dkinfo);
   1883 
   1884 	/*
   1885 	 * The controller and the disk should match.
   1886 	 */
   1887 	assert(disk_info->disk_ctlr == ctlr);
   1888 
   1889 	/*
   1890 	 * Link the disk into the list of disks
   1891 	 */
   1892 	dp = ctlr->ctlr_ctype->ctype_dlist;
   1893 	if (dp == NULL) {
   1894 		ctlr->ctlr_ctype->ctype_dlist = disk;
   1895 	} else {
   1896 		while (dp->dtype_next != NULL) {
   1897 			dp = dp->dtype_next;
   1898 		}
   1899 		dp->dtype_next = disk;
   1900 	}
   1901 	disk->dtype_next = NULL;
   1902 
   1903 	/*
   1904 	 * Allocate and initialize the disk name.
   1905 	 */
   1906 	disk->dtype_asciilabel = alloc_string(disk_name);
   1907 
   1908 	/*
   1909 	 * Initialize disk geometry info
   1910 	 */
   1911 	disk->dtype_pcyl = label->dkl_pcyl;
   1912 	disk->dtype_ncyl = label->dkl_ncyl;
   1913 	disk->dtype_acyl = label->dkl_acyl;
   1914 	disk->dtype_nhead = label->dkl_nhead;
   1915 	disk->dtype_nsect = label->dkl_nsect;
   1916 	disk->dtype_rpm = label->dkl_rpm;
   1917 
   1918 	/*
   1919 	 * Attempt to match the partition map in the label
   1920 	 * with a know partition for this disk type.
   1921 	 */
   1922 	for (part = disk->dtype_plist; part; part = part->pinfo_next) {
   1923 		if (parts_match(label, part)) {
   1924 			break;
   1925 		}
   1926 	}
   1927 
   1928 	/*
   1929 	 * If no match was made, we need to create a partition
   1930 	 * map for this disk.
   1931 	 */
   1932 	if (part == NULL) {
   1933 		part = (struct partition_info *)
   1934 		    zalloc(sizeof (struct partition_info));
   1935 		pt = disk->dtype_plist;
   1936 		if (pt == NULL) {
   1937 			disk->dtype_plist = part;
   1938 		} else {
   1939 			while (pt->pinfo_next != NULL) {
   1940 				pt = pt->pinfo_next;
   1941 			}
   1942 			pt->pinfo_next = part;
   1943 		}
   1944 		part->pinfo_next = NULL;
   1945 
   1946 		/*
   1947 		 * Set up the partition name
   1948 		 */
   1949 		part->pinfo_name = alloc_string("default");
   1950 
   1951 		/*
   1952 		 * Fill in the partition info from the label
   1953 		 */
   1954 		for (i = 0; i < NDKMAP; i++) {
   1955 
   1956 #if defined(_SUNOS_VTOC_8)
   1957 			part->pinfo_map[i] = label->dkl_map[i];
   1958 
   1959 #elif defined(_SUNOS_VTOC_16)
   1960 			part->pinfo_map[i].dkl_cylno =
   1961 			    label->dkl_vtoc.v_part[i].p_start /
   1962 			    ((blkaddr32_t)(disk->dtype_nhead *
   1963 			    disk->dtype_nsect - apc));
   1964 			part->pinfo_map[i].dkl_nblk =
   1965 			    label->dkl_vtoc.v_part[i].p_size;
   1966 #else
   1967 #error No VTOC format defined.
   1968 #endif				/* defined(_SUNOS_VTOC_8) */
   1969 
   1970 		}
   1971 	}
   1972 
   1973 
   1974 	/*
   1975 	 * Use the VTOC if valid, or install a default
   1976 	 */
   1977 	if (label->dkl_vtoc.v_version == V_VERSION) {
   1978 		(void) memcpy(disk_info->v_volume, label->dkl_vtoc.v_volume,
   1979 		    LEN_DKL_VVOL);
   1980 		part->vtoc = label->dkl_vtoc;
   1981 	} else {
   1982 		(void) memset(disk_info->v_volume, 0, LEN_DKL_VVOL);
   1983 		set_vtoc_defaults(part);
   1984 	}
   1985 
   1986 	/*
   1987 	 * Link the disk to the partition map
   1988 	 */
   1989 	disk_info->disk_parts = part;
   1990 
   1991 	return (disk);
   1992 }
   1993 
   1994 
   1995 /*
   1996  * Delete a disk type from disk type list.
   1997  */
   1998 int
   1999 delete_disk_type(
   2000 		struct disk_type *disk_type)
   2001 {
   2002 	struct ctlr_type	*ctlr;
   2003 	struct disk_type	*dp, *disk;
   2004 
   2005 	if (cur_ctype->ctype_ctype == DKC_DIRECT)
   2006 		ctlr = find_direct_ctlr_type();
   2007 	else if (cur_ctype->ctype_ctype == DKC_VBD)
   2008 		ctlr = find_vbd_ctlr_type();
   2009 	else
   2010 		ctlr = find_scsi_ctlr_type();
   2011 	if (ctlr == NULL || ctlr->ctype_dlist == NULL) {
   2012 		return (-1);
   2013 	}
   2014 
   2015 	disk = ctlr->ctype_dlist;
   2016 	if (disk == disk_type) {
   2017 		ctlr->ctype_dlist = disk->dtype_next;
   2018 		if (cur_label == L_TYPE_EFI)
   2019 			free(disk->dtype_plist->etoc);
   2020 		free(disk->dtype_plist);
   2021 		free(disk);
   2022 		return (0);
   2023 	} else {
   2024 		for (dp = disk->dtype_next; dp != NULL;
   2025 		    disk = disk->dtype_next, dp = dp->dtype_next) {
   2026 			if (dp == disk_type) {
   2027 				disk->dtype_next = dp->dtype_next;
   2028 				if (cur_label == L_TYPE_EFI)
   2029 					free(dp->dtype_plist->etoc);
   2030 				free(dp->dtype_plist);
   2031 				free(dp);
   2032 				return (0);
   2033 			}
   2034 		}
   2035 		return (-1);
   2036 	}
   2037 }
   2038 
   2039 
   2040 static struct disk_info *
   2041 find_scsi_disk_info(
   2042 	struct dk_cinfo		*dkinfo)
   2043 {
   2044 	struct disk_info	*disk;
   2045 	struct dk_cinfo		*dp;
   2046 
   2047 	for (disk = disk_list; disk != NULL; disk = disk->disk_next) {
   2048 		assert(dkinfo->dki_ctype == DKC_SCSI_CCS);
   2049 		dp = &disk->disk_dkinfo;
   2050 		if (dp->dki_ctype == dkinfo->dki_ctype &&
   2051 		    dp->dki_cnum == dkinfo->dki_cnum &&
   2052 		    dp->dki_unit == dkinfo->dki_unit &&
   2053 		    strcmp(dp->dki_dname, dkinfo->dki_dname) == 0) {
   2054 			return (disk);
   2055 		}
   2056 	}
   2057 
   2058 	impossible("No SCSI disk info instance\n");
   2059 
   2060 	return ((struct disk_info *)NULL);
   2061 }
   2062 
   2063 
   2064 static char *
   2065 get_sun_disk_name(
   2066 	char			*disk_name,
   2067 	struct scsi_inquiry	*inquiry)
   2068 {
   2069 	/*
   2070 	 * Extract the sun name of the disk
   2071 	 */
   2072 	(void) memset(disk_name, 0, DISK_NAME_MAX);
   2073 	(void) memcpy(disk_name, (char *)&inquiry->inq_pid[9], 7);
   2074 
   2075 	return (disk_name);
   2076 }
   2077 
   2078 
   2079 static char *
   2080 get_generic_disk_name(
   2081 	char			*disk_name,
   2082 	struct scsi_inquiry	*inquiry)
   2083 {
   2084 	char	*p;
   2085 
   2086 	(void) memset(disk_name, 0, DISK_NAME_MAX);
   2087 	p = strcopy(disk_name, inquiry->inq_vid,
   2088 	    sizeof (inquiry->inq_vid));
   2089 	*p++ = '-';
   2090 	p = strcopy(p, inquiry->inq_pid, sizeof (inquiry->inq_pid));
   2091 	*p++ = '-';
   2092 	p = strcopy(p, inquiry->inq_revision,
   2093 	    sizeof (inquiry->inq_revision));
   2094 
   2095 	return (disk_name);
   2096 }
   2097 
   2098 /*
   2099  * Copy a string of characters from src to dst, for at
   2100  * most n bytes.  Strip all leading and trailing spaces,
   2101  * and stop if there are any non-printable characters.
   2102  * Return ptr to the next character to be filled.
   2103  */
   2104 static char *
   2105 strcopy(
   2106 	char	*dst,
   2107 	char	*src,
   2108 	int	n)
   2109 {
   2110 	int	i;
   2111 
   2112 	while (*src == ' ' && n > 0) {
   2113 		src++;
   2114 		n--;
   2115 	}
   2116 
   2117 	for (i = 0; n-- > 0 && isascii(*src) && isprint(*src); src++) {
   2118 		if (*src == ' ') {
   2119 			i++;
   2120 		} else {
   2121 			while (i-- > 0)
   2122 				*dst++ = ' ';
   2123 			*dst++ = *src;
   2124 		}
   2125 	}
   2126 
   2127 	*dst = 0;
   2128 	return (dst);
   2129 }
   2130 
   2131 /*
   2132  * adjust disk geometry.
   2133  * This is used when disk reports a disk geometry page having
   2134  * no of physical cylinders is < 3 which is the minimum required
   2135  * by Solaris (2 for storing labels and at least one as a data
   2136  * cylinder )
   2137  */
   2138 int
   2139 adjust_disk_geometry(diskaddr_t capacity, uint_t *cyl, uint_t *nhead,
   2140 	uint_t *nsect)
   2141 {
   2142 	uint_t	lcyl = *cyl;
   2143 	uint_t	lnhead = *nhead;
   2144 	uint_t	lnsect = *nsect;
   2145 
   2146 	assert(lcyl < SUN_MIN_CYL);
   2147 
   2148 	/*
   2149 	 * reduce nsect by 2 for each iteration  and re-calculate
   2150 	 * the number of cylinders.
   2151 	 */
   2152 	while (lnsect > MINIMUM_NO_SECTORS &&
   2153 	    lcyl < MINIMUM_NO_CYLINDERS) {
   2154 		/*
   2155 		 * make sure that we do not go below MINIMUM_NO_SECTORS.
   2156 		 */
   2157 		lnsect = max(MINIMUM_NO_SECTORS, lnsect / 2);
   2158 		lcyl   = (capacity) / (lnhead * lnsect);
   2159 	}
   2160 	/*
   2161 	 * If the geometry still does not satisfy
   2162 	 * MINIMUM_NO_CYLINDERS then try to reduce the
   2163 	 * no of heads.
   2164 	 */
   2165 	while (lnhead > MINIMUM_NO_HEADS &&
   2166 	    lcyl < MINIMUM_NO_CYLINDERS) {
   2167 		lnhead = max(MINIMUM_NO_HEADS, lnhead / 2);
   2168 		lcyl =  (capacity) / (lnhead * lnsect);
   2169 	}
   2170 	/*
   2171 	 * now we should have atleast SUN_MIN_CYL cylinders.
   2172 	 * If we still do not get SUN_MIN_CYL with MINIMUM_NO_HEADS
   2173 	 * and MINIMUM_NO_HEADS then return error.
   2174 	 */
   2175 	if (lcyl < SUN_MIN_CYL)
   2176 		return (1);
   2177 	else {
   2178 		*cyl = lcyl;
   2179 		*nhead = lnhead;
   2180 		*nsect = lnsect;
   2181 		return (0);
   2182 	}
   2183 }
   2184 
   2185 #if defined(_SUNOS_VTOC_8)
   2186 /*
   2187  * Reduce the size of one dimention below a specified
   2188  * limit with a minimum loss of volume.  Dimenstions are
   2189  * assumed to be passed in form the largest value (the one
   2190  * that needs to be reduced) to the smallest value.  The
   2191  * values will be twiddled until they are all less than or
   2192  * equal to their limit.  Returns the number in the new geometry.
   2193  */
   2194 static diskaddr_t
   2195 square_box(
   2196 		diskaddr_t capacity,
   2197 		uint_t *dim1, uint_t lim1,
   2198 		uint_t *dim2, uint_t lim2,
   2199 		uint_t *dim3, uint_t lim3)
   2200 {
   2201 	uint_t	i;
   2202 
   2203 	/*
   2204 	 * Although the routine should work with any ordering of
   2205 	 * parameters, it's most efficient if they are passed in
   2206 	 * in decreasing magnitude.
   2207 	 */
   2208 	assert(*dim1 >= *dim2);
   2209 	assert(*dim2 >= *dim3);
   2210 
   2211 	/*
   2212 	 * This is done in a very arbitrary manner.  We could try to
   2213 	 * find better values but I can't come up with a method that
   2214 	 * would run in a reasonable amount of time.  That could take
   2215 	 * approximately 65535 * 65535 iterations of a dozen flops each
   2216 	 * or well over 4G flops.
   2217 	 *
   2218 	 * First:
   2219 	 *
   2220 	 * Let's see how far we can go with bitshifts w/o losing
   2221 	 * any blocks.
   2222 	 */
   2223 
   2224 	for (i = 0; (((*dim1)>>i)&1) == 0 && ((*dim1)>>i) > lim1; i++)
   2225 		;
   2226 	if (i) {
   2227 		*dim1 = ((*dim1)>>i);
   2228 		*dim3 = ((*dim3)<<i);
   2229 	}
   2230 
   2231 	if (((*dim1) > lim1) || ((*dim2) > lim2) || ((*dim3) > lim3)) {
   2232 		double 	d[4];
   2233 
   2234 		/*
   2235 		 * Second:
   2236 		 *
   2237 		 * Set the highest value at its limit then calculate errors,
   2238 		 * adjusting the 2nd highest value (we get better resolution
   2239 		 * that way).
   2240 		 */
   2241 		d[1] = lim1;
   2242 		d[3] = *dim3;
   2243 		d[2] = (double)capacity/(d[1]*d[3]);
   2244 
   2245 		/*
   2246 		 * If we overflowed the middle term, set it to its limit and
   2247 		 * chose a new low term.
   2248 		 */
   2249 		if (d[2] > lim2) {
   2250 			d[2] = lim2;
   2251 			d[3] = (double)capacity/(d[1]*d[2]);
   2252 		}
   2253 		/*
   2254 		 * Convert to integers.
   2255 		 */
   2256 		*dim1 = (int)d[1];
   2257 		*dim2 = (int)d[2];
   2258 		*dim3 = (int)d[3];
   2259 	}
   2260 	/*
   2261 	 * Fixup any other possible problems.
   2262 	 * If this happens, we need a new disklabel format.
   2263 	 */
   2264 	if (*dim1 > lim1) *dim1 = lim1;
   2265 	if (*dim2 > lim2) *dim2 = lim2;
   2266 	if (*dim3 > lim3) *dim3 = lim3;
   2267 	return (*dim1 * *dim2 * *dim3);
   2268 }
   2269 #endif /* defined(_SUNOS_VTOC_8) */
   2270 
   2271 /*
   2272  * Calculate CHS values based on the capacity data.
   2273  *
   2274  * NOTE: This function is same as cmlb_convert_geomerty() function in
   2275  * cmlb kernel module.
   2276  */
   2277 static void
   2278 compute_chs_values(diskaddr_t total_capacity, diskaddr_t usable_capacity,
   2279 	uint_t *pcylp, uint_t *nheadp, uint_t *nsectp)
   2280 {
   2281 
   2282 	/* Unlabeled SCSI floppy device */
   2283 	if (total_capacity <= 0x1000) {
   2284 		*nheadp = 2;
   2285 		*pcylp = 80;
   2286 		*nsectp = total_capacity / (80 * 2);
   2287 		return;
   2288 	}
   2289 
   2290 	/*
   2291 	 * For all devices we calculate cylinders using the heads and sectors
   2292 	 * we assign based on capacity of the device.  The algorithm is
   2293 	 * designed to be compatible with the way other operating systems
   2294 	 * lay out fdisk tables for X86 and to insure that the cylinders never
   2295 	 * exceed 65535 to prevent problems with X86 ioctls that report
   2296 	 * geometry.
   2297 	 * For some smaller disk sizes we report geometry that matches those
   2298 	 * used by X86 BIOS usage. For larger disks, we use SPT that are
   2299 	 * multiples of 63, since other OSes that are not limited to 16-bits
   2300 	 * for cylinders stop at 63 SPT we make do by using multiples of 63 SPT.
   2301 	 *
   2302 	 * The following table (in order) illustrates some end result
   2303 	 * calculations:
   2304 	 *
   2305 	 * Maximum number of blocks 		nhead	nsect
   2306 	 *
   2307 	 * 2097152 (1GB)			64	32
   2308 	 * 16777216 (8GB)			128	32
   2309 	 * 1052819775 (502.02GB)		255  	63
   2310 	 * 2105639550 (0.98TB)			255	126
   2311 	 * 3158459325 (1.47TB)			255  	189
   2312 	 * 4211279100 (1.96TB)			255  	252
   2313 	 * 5264098875 (2.45TB)			255  	315
   2314 	 * ...
   2315 	 */
   2316 
   2317 	if (total_capacity <= 0x200000) {
   2318 		*nheadp = 64;
   2319 		*nsectp = 32;
   2320 	} else if (total_capacity <= 0x01000000) {
   2321 		*nheadp = 128;
   2322 		*nsectp = 32;
   2323 	} else {
   2324 		*nheadp = 255;
   2325 
   2326 		/* make nsect be smallest multiple of 63 */
   2327 		*nsectp = ((total_capacity +
   2328 		    (UINT16_MAX * 255 * 63) - 1) /
   2329 		    (UINT16_MAX * 255 * 63)) * 63;
   2330 
   2331 		if (*nsectp == 0)
   2332 			*nsectp = (UINT16_MAX / 63) * 63;
   2333 	}
   2334 
   2335 	if (usable_capacity < total_capacity)
   2336 		*pcylp = usable_capacity / ((*nheadp) * (*nsectp));
   2337 	else
   2338 		*pcylp = total_capacity / ((*nheadp) * (*nsectp));
   2339 }
   2340