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