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