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