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