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