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