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