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