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