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.
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.
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]
22 * Copyright (c) 2011 Gary Mills
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.
30 * This file contains functions to implement automatic configuration
44 #include "ctlr_scsi.h"
45 #include "auto_sense.h"
46 #include "partition.h"
51 #include "hardware_structs.h"
52 #include "menu_fdisk.h"
55 #define DISK_NAME_MAX 256
58 extern struct ctlr_type ctlr_types
[];
62 * Marker for free hog partition
69 * Default partition tables
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
83 int partitions
[NDKMAP
];
86 static struct part_table part_table_64mb
= {
87 { 0, 0, 0, 0, 0, 0, HOG
, 0}
90 static struct part_table part_table_180mb
= {
91 { 16, 16, 0, 0, 0, 0, HOG
, 0}
94 static struct part_table part_table_280mb
= {
95 { 16, 32, 0, 0, 0, 0, HOG
, 0}
98 static struct part_table part_table_380mb
= {
99 { 24, 32, 0, 0, 0, 0, HOG
, 0}
102 static struct part_table part_table_600mb
= {
103 { 32, 32, 0, 0, 0, 0, HOG
, 0}
106 static struct part_table part_table_1gb
= {
107 { 32, 64, 0, 0, 0, 0, HOG
, 0}
110 static struct part_table part_table_2gb
= {
111 { 64, 128, 0, 0, 0, 0, HOG
, 0}
114 static struct part_table part_table_infinity
= {
115 { 128, 128, 0, 0, 0, 0, HOG
, 0}
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 */
134 #define DEFAULT_PARTITION_TABLE_SIZE \
135 (sizeof (default_partitions) / sizeof (struct default_partitions))
140 #define FORMAT_MSG "Auto configuration via format.dat"
141 #define GENERIC_MSG "Auto configuration via generic SCSI-2"
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".
153 * assuming a minimum of 32 block cylinders.
155 #define MINIMUM_NO_HEADS 2
156 #define MINIMUM_NO_SECTORS 16
158 #define MINIMUM_NO_CYLINDERS 128
160 #if defined(_SUNOS_VTOC_8)
162 /* These are 16-bit fields */
163 #define MAXIMUM_NO_HEADS 65535
164 #define MAXIMUM_NO_SECTORS 65535
165 #define MAXIMUM_NO_CYLINDERS 65535
167 #endif /* defined(_SUNOS_VTOC_8) */
170 * minimum number of cylinders required by Solaris.
172 #define SUN_MIN_CYL 3
177 * ANSI prototypes for local static functions
179 static struct disk_type
*generic_disk_sense(
182 struct dk_label
*label
,
183 struct scsi_inquiry
*inquiry
,
184 struct scsi_capacity_16
*capacity
,
186 static int use_existing_disk_type(
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
,
195 static struct disk_type
*find_scsi_disk_type(
197 struct dk_label
*label
);
198 static struct disk_type
*find_scsi_disk_by_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(
206 struct dk_label
*label
);
207 static struct disk_info
*find_scsi_disk_info(
208 struct dk_cinfo
*dkinfo
);
210 static struct disk_type
*new_direct_disk_type(int fd
, char *disk_name
,
211 struct dk_label
*label
);
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
);
223 static char *get_sun_disk_name(
225 struct scsi_inquiry
*inquiry
);
226 static char *strcopy(
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(
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) */
245 * We need to get information necessary to construct a *new* efi
249 auto_efi_sense(int fd
, struct efi_info
*label
)
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
;
261 if (ioctl(fd
, DKIOCINFO
, &dkinfo
) == -1) {
262 if (option_msg
&& diag_msg
) {
263 err_print("DKIOCINFO failed\n");
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
);
274 ctlr
= find_scsi_ctlr_info(&dkinfo
);
275 disk_info
= find_scsi_disk_info(&dkinfo
);
279 * get vendor, product, revision and capacity info.
281 if (get_disk_info(fd
, label
, disk_info
) == -1) {
282 return ((struct disk_type
*)NULL
);
285 * Now build the default partition table
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
);
292 label
->e_parts
= vtoc
;
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.
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;
305 * S1-S6 are unassigned slices.
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;
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
;
322 * Now stick all of it into the disk_type struct
325 disk
= (struct disk_type
*)zalloc(sizeof (struct disk_type
));
326 assert(disk_info
->disk_ctlr
== ctlr
);
327 dp
= ctlr
->ctlr_ctype
->ctype_dlist
;
329 ctlr
->ctlr_ctype
->ctype_dlist
= dp
;
331 while (dp
->dtype_next
!= NULL
) {
334 dp
->dtype_next
= disk
;
336 disk
->dtype_next
= NULL
;
338 disk
->vendor
= strdup(label
->vendor
);
339 disk
->product
= strdup(label
->product
);
340 disk
->revision
= strdup(label
->revision
);
342 if (disk
->vendor
== NULL
||
343 disk
->product
== NULL
||
344 disk
->revision
== NULL
) {
347 free(disk
->revision
);
352 disk
->capacity
= label
->capacity
;
354 part
= (struct partition_info
*)
355 zalloc(sizeof (struct partition_info
));
356 disk
->dtype_plist
= part
;
358 part
->pinfo_name
= alloc_string("default");
359 part
->pinfo_next
= NULL
;
362 bzero(disk_info
->v_volume
, LEN_DKL_VVOL
);
363 disk_info
->disk_parts
= part
;
368 efi_ioctl(int fd
, int cmd
, dk_efi_t
*dk_ioc
)
370 void *data
= dk_ioc
->dki_data
;
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
;
380 static struct ctlr_type
*
381 find_direct_ctlr_type()
383 struct mctlr_list
*mlp
;
387 while (mlp
!= NULL
) {
388 if (mlp
->ctlr_type
->ctype_ctype
== DKC_DIRECT
) {
389 return (mlp
->ctlr_type
);
394 impossible("no DIRECT controller type");
396 return ((struct ctlr_type
*)NULL
);
399 static struct ctlr_type
*
402 struct mctlr_list
*mlp
;
406 while (mlp
!= NULL
) {
407 if (mlp
->ctlr_type
->ctype_ctype
== DKC_VBD
) {
408 return (mlp
->ctlr_type
);
413 impossible("no VBD controller type");
415 return ((struct ctlr_type
*)NULL
);
418 static struct ctlr_info
*
419 find_direct_ctlr_info(
420 struct dk_cinfo
*dkinfo
)
422 struct ctlr_info
*ctlr
;
424 if (dkinfo
->dki_ctype
!= DKC_DIRECT
)
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
) {
435 impossible("no DIRECT controller info");
439 static struct ctlr_info
*
441 struct dk_cinfo
*dkinfo
)
443 struct ctlr_info
*ctlr
;
445 if (dkinfo
->dki_ctype
!= DKC_VBD
)
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
) {
456 impossible("no VBD controller info");
460 static struct disk_info
*
461 find_direct_disk_info(
462 struct dk_cinfo
*dkinfo
)
464 struct disk_info
*disk
;
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) {
478 impossible("No DIRECT disk info instance\n");
482 static struct disk_info
*
484 struct dk_cinfo
*dkinfo
)
486 struct disk_info
*disk
;
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) {
500 impossible("No VBD disk info instance\n");
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
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.
515 auto_label_init(struct dk_label
*label
)
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
;
526 int efisize
= EFI_LABEL_SIZE
* 2;
531 if ((data
= calloc(efisize
, 1)) == NULL
) {
532 err_print("auto_label_init: calloc failed\n");
533 goto auto_label_init_out
;
536 dk_ioc
.dki_data
= data
;
538 dk_ioc
.dki_length
= efisize
;
540 if (efi_ioctl(fd
, DKIOCGETEFI
, &dk_ioc
) != 0) {
541 err_print("auto_label_init: GETEFI failed\n");
542 goto auto_label_init_out
;
545 if ((databack
= calloc(efisize
, 1)) == NULL
) {
546 err_print("auto_label_init calloc2 failed");
547 goto auto_label_init_out
;
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
;
556 if (disk_info
.dki_lbsize
== 0) {
557 if (option_msg
&& diag_msg
) {
558 err_print("auto_lbal_init: assuming 512 byte"
561 disk_info
.dki_lbsize
= DEV_BSIZE
;
564 dk_ioc_back
.dki_data
= databack
;
567 * back up efi label goes to capacity - 1, we are reading an extra block
568 * before the back up label.
570 dk_ioc_back
.dki_lba
= disk_info
.dki_capacity
- 1 - 1;
571 dk_ioc_back
.dki_length
= efisize
;
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
;
578 sig
= dk_ioc
.dki_data
->efi_gpt_Signature
;
579 dk_ioc
.dki_data
->efi_gpt_Signature
= 0x0;
583 if (efi_ioctl(fd
, DKIOCSETEFI
, &dk_ioc
) == -1) {
584 err_print("auto_label_init: SETEFI failed\n");
586 goto auto_label_init_out
;
589 backsigp
= (efi_gpt_t
*)((uintptr_t)dk_ioc_back
.dki_data
+ cur_blksz
);
591 backsig
= backsigp
->efi_gpt_Signature
;
593 backsigp
->efi_gpt_Signature
= 0;
595 if (efi_ioctl(fd
, DKIOCSETEFI
, &dk_ioc_back
) == -1) {
596 err_print("auto_label_init: SETEFI backup failed\n");
599 if (ioctl(cur_file
, DKIOCGGEOM
, &disk_geom
) != 0)
600 err_print("auto_label_init: GGEOM failed\n");
604 dk_ioc
.dki_data
->efi_gpt_Signature
= sig
;
605 backsigp
->efi_gpt_Signature
= backsig
;
607 if (efi_ioctl(cur_file
, DKIOCSETEFI
, &dk_ioc_back
) == -1) {
608 err_print("auto_label_init: SETEFI revert backup failed\n");
612 if (efi_ioctl(cur_file
, DKIOCSETEFI
, &dk_ioc
) == -1) {
613 err_print("auto_label_init: SETEFI revert failed\n");
620 goto auto_label_init_out
;
622 ncyl
= disk_geom
.dkg_ncyl
;
623 acyl
= disk_geom
.dkg_acyl
;
624 nhead
= disk_geom
.dkg_nhead
;
625 nsect
= disk_geom
.dkg_nsect
;
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
;
634 label
->dkl_intrlv
= 1;
635 label
->dkl_rpm
= disk_geom
.dkg_rpm
;
637 label
->dkl_magic
= DKL_MAGIC
;
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
);
644 #if defined(_FIRMWARE_NEEDS_FDISK)
645 (void) auto_solaris_part(label
);
646 ncyl
= label
->dkl_ncyl
;
648 #endif /* defined(_FIRMWARE_NEEDS_FDISK) */
650 if (!build_default_partition(label
, DKC_DIRECT
)) {
654 (void) checksum(label
, CK_MAKESUM
);
666 static struct disk_type
*
667 new_direct_disk_type(
670 struct dk_label
*label
)
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
;
682 * Get the disk controller info for this disk
684 if (ioctl(fd
, DKIOCINFO
, &dkinfo
) == -1) {
685 if (option_msg
&& diag_msg
) {
686 err_print("DKIOCINFO failed\n");
692 * Find the ctlr_info for this disk.
694 ctlr
= find_direct_ctlr_info(&dkinfo
);
697 * Allocate a new disk type for the direct controller.
699 disk
= (struct disk_type
*)zalloc(sizeof (struct disk_type
));
702 * Find the disk_info instance for this disk.
704 disk_info
= find_direct_disk_info(&dkinfo
);
707 * The controller and the disk should match.
709 assert(disk_info
->disk_ctlr
== ctlr
);
712 * Link the disk into the list of disks
714 dp
= ctlr
->ctlr_ctype
->ctype_dlist
;
716 ctlr
->ctlr_ctype
->ctype_dlist
= dp
;
718 while (dp
->dtype_next
!= NULL
) {
721 dp
->dtype_next
= disk
;
723 disk
->dtype_next
= NULL
;
726 * Allocate and initialize the disk name.
728 disk
->dtype_asciilabel
= alloc_string(disk_name
);
731 * Initialize disk geometry info
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
;
740 part
= (struct partition_info
*)
741 zalloc(sizeof (struct partition_info
));
742 pt
= disk
->dtype_plist
;
744 disk
->dtype_plist
= part
;
746 while (pt
->pinfo_next
!= NULL
) {
749 pt
->pinfo_next
= part
;
752 part
->pinfo_next
= NULL
;
755 * Set up the partition name
757 part
->pinfo_name
= alloc_string("default");
760 * Fill in the partition info from the label
762 for (i
= 0; i
< NDKMAP
; i
++) {
764 #if defined(_SUNOS_VTOC_8)
765 part
->pinfo_map
[i
] = label
->dkl_map
[i
];
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
;
775 #error No VTOC format defined.
776 #endif /* defined(_SUNOS_VTOC_8) */
780 * Use the VTOC if valid, or install a default
782 if (label
->dkl_vtoc
.v_version
== V_VERSION
) {
783 (void) memcpy(disk_info
->v_volume
, label
->dkl_vtoc
.v_volume
,
785 part
->vtoc
= label
->dkl_vtoc
;
787 (void) memset(disk_info
->v_volume
, 0, LEN_DKL_VVOL
);
788 set_vtoc_defaults(part
);
792 * Link the disk to the partition map
794 disk_info
->disk_parts
= part
;
800 * Get a disk type that has label info. This is used to convert
801 * EFI label to SMI label
804 auto_direct_get_geom_label(int fd
, struct dk_label
*label
)
806 struct disk_type
*disk_type
;
808 if (auto_label_init(label
) != 0) {
809 err_print("auto_direct_get_geom_label: failed to get label"
813 disk_type
= new_direct_disk_type(fd
, "DEFAULT", label
);
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.
831 struct dk_label
*label
)
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;
844 * First, if expert mode, find out if the user
845 * wants to override any of the standard methods.
847 if (can_prompt
&& expert_mode
) {
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) {
860 * Get the Inquiry data. If this fails, there's
861 * no hope for this disk, so give up.
863 if (uscsi_inquiry(fd
, (char *)&inquiry
, sizeof (inquiry
))) {
864 return ((struct disk_type
*)NULL
);
866 if (option_msg
&& diag_msg
) {
867 err_print("Product id: ");
868 print_buf(inquiry
.inq_pid
, sizeof (inquiry
.inq_pid
));
873 * Get the Read Capacity
875 if (uscsi_read_capacity(fd
, &capacity
)) {
876 return ((struct disk_type
*)NULL
);
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.
887 if ((capacity
.sc_capacity
== 0) ||
888 (capacity
.sc_capacity
== UINT_MAX64
)) {
889 if (option_msg
&& diag_msg
) {
890 err_print("Invalid capacity\n");
892 return ((struct disk_type
*)NULL
);
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
);
901 * Extract the disk name for the format.dat override
903 (void) get_sun_disk_name(disk_name
, &inquiry
);
904 if (option_msg
&& diag_msg
) {
905 err_print("disk name: `%s`\n", disk_name
);
908 buf
= zalloc(cur_blksz
);
909 if (scsi_rdwr(DIR_READ
, fd
, (diskaddr_t
)0, 1, (caddr_t
)buf
,
912 return ((struct disk_type
*)NULL
);
917 * Figure out which method we use for auto sense.
918 * If a particular method fails, we fall back to
919 * the next possibility.
923 return (generic_disk_sense(fd
, can_prompt
, label
,
924 &inquiry
, &capacity
, disk_name
));
928 * Try for an existing format.dat first
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
)) {
935 if (force_format_dat
) {
941 * Otherwise, try using generic SCSI-2 sense and inquiry.
944 return (generic_disk_sense(fd
, can_prompt
, label
,
945 &inquiry
, &capacity
, disk_name
));
951 static struct disk_type
*
955 struct dk_label
*label
,
956 struct scsi_inquiry
*inquiry
,
957 struct scsi_capacity_16
*capacity
,
960 struct disk_type
*disk
;
968 diskaddr_t nblocks
= 0;
969 diskaddr_t tblocks
= 0;
971 struct mode_format page3
;
972 uchar_t buf3
[MAX_MODE_SENSE_SIZE
];
975 struct mode_geometry page4
;
976 uchar_t buf4
[MAX_MODE_SENSE_SIZE
];
978 struct mode_format
*page3
= &u_page3
.page3
;
979 struct mode_geometry
*page4
= &u_page4
.page4
;
980 struct scsi_ms_header header
;
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
990 if (memcmp(disk_name
, "SUN", strlen("SUN")) != 0) {
991 (void) get_generic_disk_name(disk_name
, inquiry
);
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.
999 tblocks
= (capacity
->sc_capacity
+ 1);
1000 if (tblocks
> UINT32_MAX
)
1001 nblocks
= UINT32_MAX
;
1006 * Get current Page 3 - Format Parameters page
1008 if (uscsi_mode_sense(fd
, DAD_MODE_FORMAT
, MODE_SENSE_PC_CURRENT
,
1009 (caddr_t
)&u_page3
, MAX_MODE_SENSE_SIZE
, &header
)) {
1014 * Get current Page 4 - Drive Geometry page
1016 if (uscsi_mode_sense(fd
, DAD_MODE_GEOMETRY
, MODE_SENSE_PC_CURRENT
,
1017 (caddr_t
)&u_page4
, MAX_MODE_SENSE_SIZE
, &header
)) {
1021 if (setdefault
!= 1) {
1022 /* The inquiry of mode page 3 & page 4 are successful */
1024 * Correct for byte order if necessary
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
);
1040 * Construct a new label out of the sense data,
1041 * Inquiry and Capacity.
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.
1047 if (tblocks
> INT32_MAX
) {
1048 compute_chs_values(tblocks
, nblocks
, &pcyl
, &nhead
,
1051 pcyl
= (page4
->cyl_ub
<< 16) + (page4
->cyl_mb
<< 8) +
1053 nhead
= page4
->heads
;
1054 nsect
= page3
->sect_track
;
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.
1064 if (pcyl
< SUN_MIN_CYL
) {
1065 if (nhead
== 0 || nsect
== 0) {
1067 } else if (adjust_disk_geometry(
1068 (diskaddr_t
)(capacity
->sc_capacity
+ 1),
1069 &pcyl
, &nhead
, &nsect
)) {
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.
1080 if ((setdefault
== 1) || (capacity
->sc_lbasize
!= DEV_BSIZE
)) {
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.
1086 compute_chs_values(tblocks
, nblocks
, &pcyl
, &nhead
, &nsect
);
1090 * The sd driver reserves 2 cylinders the backup disk label and
1091 * the deviceid. Set the number of data cylinders to pcyl-acyl.
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
);
1104 #if defined(_SUNOS_VTOC_16)
1105 err_print(" bcyl: %u\n", bcyl
);
1106 #endif /* defined(_SUNOS_VTOC_16) */
1108 err_print(" rpm: %d\n", rpm
);
1109 err_print(" nblocks: %llu\n", nblocks
);
1113 * Some drives do not support page4 or report 0 for page4->rpm,
1114 * adjust it to AVG_RPM, 3600.
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
);
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.
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
);
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
,
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
);
1154 #if defined(_SUNOS_VTOC_16)
1155 err_print(" bcyl: %u\n", bcyl
);
1158 err_print(" rpm: %d\n", rpm
);
1159 err_print(" nblocks: %llu\n", nblocks
);
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.
1170 if (((diskaddr_t
)pcyl
* nhead
* nsect
) > nblocks
) {
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
);
1179 } while (((diskaddr_t
)pcyl
* nhead
* nsect
) > nblocks
);
1181 if (can_prompt
&& expert_mode
&& !option_f
) {
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).
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
;
1196 * Ask the user for a choice here.
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
),
1208 if (input(FIO_INT
, "Select one of the above "
1209 "choices ", ':', &ioparam
,
1210 &deflt
, DATA_INPUT
) == 2) {
1218 #if defined(_SUNOS_VTOC_8)
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.
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");
1233 if ((pcyl
> MAXIMUM_NO_CYLINDERS
) ||
1234 (nsect
> MAXIMUM_NO_SECTORS
) ||
1235 (nhead
> MAXIMUM_NO_HEADS
)) {
1236 u_ioparam_t ioparam
;
1240 order
= ((pcyl
> nhead
)<<2) |
1241 ((pcyl
> nsect
)<<1) |
1244 case 0x7: /* pcyl > nhead > nsect */
1247 &pcyl
, MAXIMUM_NO_CYLINDERS
,
1248 &nhead
, MAXIMUM_NO_HEADS
,
1249 &nsect
, MAXIMUM_NO_SECTORS
);
1251 case 0x6: /* pcyl > nsect > nhead */
1254 &pcyl
, MAXIMUM_NO_CYLINDERS
,
1255 &nsect
, MAXIMUM_NO_SECTORS
,
1256 &nhead
, MAXIMUM_NO_HEADS
);
1258 case 0x4: /* nsect > pcyl > nhead */
1261 &nsect
, MAXIMUM_NO_SECTORS
,
1262 &pcyl
, MAXIMUM_NO_CYLINDERS
,
1263 &nhead
, MAXIMUM_NO_HEADS
);
1265 case 0x0: /* nsect > nhead > pcyl */
1268 &nsect
, MAXIMUM_NO_SECTORS
,
1269 &nhead
, MAXIMUM_NO_HEADS
,
1270 &pcyl
, MAXIMUM_NO_CYLINDERS
);
1272 case 0x3: /* nhead > pcyl > nsect */
1275 &nhead
, MAXIMUM_NO_HEADS
,
1276 &pcyl
, MAXIMUM_NO_CYLINDERS
,
1277 &nsect
, MAXIMUM_NO_SECTORS
);
1279 case 0x1: /* nhead > nsect > pcyl */
1282 &nhead
, MAXIMUM_NO_HEADS
,
1283 &nsect
, MAXIMUM_NO_SECTORS
,
1284 &pcyl
, MAXIMUM_NO_CYLINDERS
);
1287 /* How did we get here? */
1288 impossible("label overflow adjustment");
1290 /* Do something useful */
1293 &nhead
, MAXIMUM_NO_HEADS
,
1294 &nsect
, MAXIMUM_NO_SECTORS
,
1295 &pcyl
, MAXIMUM_NO_CYLINDERS
);
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);
1305 while (can_prompt
&& expert_mode
&& !option_f
) {
1309 * Allow user to modify this by hand if desired.
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",
1316 nblocks
, capacity
->sc_capacity
+ 1);
1318 ioparam
.io_charlist
= confirm_list
;
1319 if (input(FIO_MSTR
, msg
, '?', &ioparam
,
1320 &deflt
, DATA_INPUT
) != 0)
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",
1341 capacity
->sc_capacity
+ 1);
1345 #endif /* defined(_SUNOS_VTOC_8) */
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
);
1359 (void) memset((char *)label
, 0, sizeof (struct dk_label
));
1361 label
->dkl_magic
= DKL_MAGIC
;
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
);
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
;
1373 label
->dkl_intrlv
= 1;
1374 label
->dkl_rpm
= rpm
;
1376 #if defined(_FIRMWARE_NEEDS_FDISK)
1377 if (auto_solaris_part(label
) == -1)
1379 ncyl
= label
->dkl_ncyl
;
1380 #endif /* defined(_FIRMWARE_NEEDS_FDISK) */
1383 if (!build_default_partition(label
, DKC_SCSI_CCS
)) {
1387 (void) checksum(label
, CK_MAKESUM
);
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.
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
,
1405 if (option_msg
&& diag_msg
) {
1407 "Changing disk type name from '%s' to '%s'\n", old_name
, disk_name
);
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
);
1417 disk
= new_scsi_disk_type(fd
, disk_name
, label
);
1426 if (option_msg
&& diag_msg
) {
1428 "Configuration via generic SCSI-2 information failed\n");
1436 use_existing_disk_type(
1439 struct dk_label
*label
,
1440 struct scsi_inquiry
*inquiry
,
1441 struct disk_type
*disk_type
,
1442 struct scsi_capacity_16
*capacity
)
1451 * Construct a new label out of the format.dat
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
;
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
);
1469 (void) memset((char *)label
, 0, sizeof (struct dk_label
));
1471 label
->dkl_magic
= DKL_MAGIC
;
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
);
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
;
1484 label
->dkl_intrlv
= 1;
1485 label
->dkl_rpm
= rpm
;
1487 if (!build_default_partition(label
, DKC_SCSI_CCS
)) {
1491 (void) checksum(label
, CK_MAKESUM
);
1495 if (option_msg
&& diag_msg
) {
1497 "Configuration via format.dat geometry failed\n");
1503 build_default_partition(
1504 struct dk_label
*label
,
1511 struct dk_vtoc
*vtoc
;
1512 struct part_table
*pt
;
1513 struct default_partitions
*dpt
;
1514 diskaddr_t capacity
;
1520 ctrl_type
= ctrl_type
;
1524 * Install a default vtoc
1526 vtoc
= &label
->dkl_vtoc
;
1527 vtoc
->v_version
= V_VERSION
;
1528 vtoc
->v_nparts
= NDKMAP
;
1529 vtoc
->v_sanity
= VTOC_SANE
;
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
;
1537 * Find a partition that matches this disk. Capacity
1538 * is in integral number of megabytes.
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
) {
1549 if (i
== DEFAULT_PARTITION_TABLE_SIZE
) {
1550 if (option_msg
&& diag_msg
) {
1551 err_print("No matching default partition (%llu)\n",
1556 pt
= dpt
->part_table
;
1559 * Go through default partition table, finding fixed
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) {
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.
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
];
1583 if (option_msg
&& diag_msg
) {
1584 for (i
= 0; i
< NDKMAP
; i
++) {
1587 err_print("Partition %d: %u cyls\n",
1590 err_print("Free cylinders exhausted (%d)\n",
1597 * Set the default boot partition to 1 cylinder
1603 * If current disk type is not a SCSI disk,
1604 * set the default alternates partition to 2 cylinders
1606 if (ctrl_type
!= DKC_SCSI_CCS
) {
1610 #endif /* defined(i386) */
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.
1617 for (i
= 0; i
< NDKMAP
; i
++) {
1618 if (pt
->partitions
[i
] == HOG
) {
1619 assert(ncyls
[i
] == 0);
1620 ncyls
[i
] = freecyls
;
1629 for (i
= 0; i
< NDKMAP
; i
++) {
1632 assert(ncyl
== (label
->dkl_ncyl
));
1635 * Finally, install the partition in the label.
1639 #if defined(_SUNOS_VTOC_16)
1640 for (i
= NDKMAP
/2; i
< NDKMAP
; i
++) {
1641 if (i
== 2 || ncyls
[i
] == 0)
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
;
1647 for (i
= 0; i
< NDKMAP
/2; i
++) {
1649 #elif defined(_SUNOS_VTOC_8)
1650 for (i
= 0; i
< NDKMAP
; i
++) {
1653 #error No VTOC format defined.
1654 #endif /* defined(_SUNOS_VTOC_16) */
1656 if (i
== 2 || ncyls
[i
] == 0) {
1657 #if defined(_SUNOS_VTOC_8)
1659 label
->dkl_map
[i
].dkl_cylno
= 0;
1660 label
->dkl_map
[i
].dkl_nblk
= 0;
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
;
1673 #error No VTOC format defined.
1674 #endif /* defined(_SUNOS_VTOC_8) */
1680 * Set the whole disk partition
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
;
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
*
1693 #error No VTOC format defined.
1694 #endif /* defined(_SUNOS_VTOC_8) */
1697 if (option_msg
&& diag_msg
) {
1700 for (i
= 0; i
< NDKMAP
; i
++) {
1701 #if defined(_SUNOS_VTOC_8)
1702 if (label
->dkl_map
[i
].dkl_nblk
== 0)
1704 #elif defined(_SUNOS_VTOC_16)
1705 if (label
->dkl_vtoc
.v_part
[i
].p_size
== 0)
1708 #error No VTOC format defined.
1709 #endif /* defined(_SUNOS_VTOC_8) */
1712 err_print("Partition %d: ", i
);
1713 #if defined(_SUNOS_VTOC_8)
1714 scaled
= bn2mb(label
->dkl_map
[i
].dkl_nblk
);
1716 #elif defined(_SUNOS_VTOC_16)
1718 scaled
= bn2mb(label
->dkl_vtoc
.v_part
[i
].p_size
);
1720 #error No VTOC format defined.
1721 #endif /* defined(_SUNOS_VTOC_8) */
1723 if (scaled
> 1024.0) {
1724 err_print("%6.2fGB ", scaled
/1024.0);
1726 err_print("%6.2fMB ", scaled
);
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
);
1735 #error No VTOC format defined.
1736 #endif /* defined(_SUNOS_VTOC_8) */
1748 * Find an existing scsi disk definition by this name,
1751 static struct disk_type
*
1752 find_scsi_disk_type(
1754 struct dk_label
*label
)
1756 struct ctlr_type
*ctlr
;
1757 struct disk_type
*dp
;
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
) {
1773 return ((struct disk_type
*)NULL
);
1778 * Find an existing scsi disk definition by this name,
1781 static struct disk_type
*
1782 find_scsi_disk_by_name(
1785 struct ctlr_type
*ctlr
;
1786 struct disk_type
*dp
;
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)) {
1797 return ((struct disk_type
*)NULL
);
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.
1807 static struct ctlr_type
*
1808 find_scsi_ctlr_type()
1810 struct mctlr_list
*mlp
;
1814 while (mlp
!= NULL
) {
1815 if (mlp
->ctlr_type
->ctype_ctype
== DKC_SCSI_CCS
) {
1816 return (mlp
->ctlr_type
);
1821 impossible("no SCSI controller type");
1823 return ((struct ctlr_type
*)NULL
);
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.
1833 static struct ctlr_info
*
1834 find_scsi_ctlr_info(
1835 struct dk_cinfo
*dkinfo
)
1837 struct ctlr_info
*ctlr
;
1839 if (dkinfo
->dki_ctype
!= DKC_SCSI_CCS
) {
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
) {
1851 impossible("no SCSI controller info");
1853 return ((struct ctlr_info
*)NULL
);
1858 static struct disk_type
*
1862 struct dk_label
*label
)
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
;
1874 * Get the disk controller info for this disk
1876 if (ioctl(fd
, DKIOCINFO
, &dkinfo
) == -1) {
1877 if (option_msg
&& diag_msg
) {
1878 err_print("DKIOCINFO failed\n");
1884 * Find the ctlr_info for this disk.
1886 ctlr
= find_scsi_ctlr_info(&dkinfo
);
1889 * Allocate a new disk type for the SCSI controller.
1891 disk
= (struct disk_type
*)zalloc(sizeof (struct disk_type
));
1894 * Find the disk_info instance for this disk.
1896 disk_info
= find_scsi_disk_info(&dkinfo
);
1899 * The controller and the disk should match.
1901 assert(disk_info
->disk_ctlr
== ctlr
);
1904 * Link the disk into the list of disks
1906 dp
= ctlr
->ctlr_ctype
->ctype_dlist
;
1908 ctlr
->ctlr_ctype
->ctype_dlist
= disk
;
1910 while (dp
->dtype_next
!= NULL
) {
1911 dp
= dp
->dtype_next
;
1913 dp
->dtype_next
= disk
;
1915 disk
->dtype_next
= NULL
;
1918 * Allocate and initialize the disk name.
1920 disk
->dtype_asciilabel
= alloc_string(disk_name
);
1923 * Initialize disk geometry info
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
;
1933 * Attempt to match the partition map in the label
1934 * with a know partition for this disk type.
1936 for (part
= disk
->dtype_plist
; part
; part
= part
->pinfo_next
) {
1937 if (parts_match(label
, part
)) {
1943 * If no match was made, we need to create a partition
1944 * map for this disk.
1947 part
= (struct partition_info
*)
1948 zalloc(sizeof (struct partition_info
));
1949 pt
= disk
->dtype_plist
;
1951 disk
->dtype_plist
= part
;
1953 while (pt
->pinfo_next
!= NULL
) {
1954 pt
= pt
->pinfo_next
;
1956 pt
->pinfo_next
= part
;
1958 part
->pinfo_next
= NULL
;
1961 * Set up the partition name
1963 part
->pinfo_name
= alloc_string("default");
1966 * Fill in the partition info from the label
1968 for (i
= 0; i
< NDKMAP
; i
++) {
1970 #if defined(_SUNOS_VTOC_8)
1971 part
->pinfo_map
[i
] = label
->dkl_map
[i
];
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
;
1981 #error No VTOC format defined.
1982 #endif /* defined(_SUNOS_VTOC_8) */
1989 * Use the VTOC if valid, or install a default
1991 if (label
->dkl_vtoc
.v_version
== V_VERSION
) {
1992 (void) memcpy(disk_info
->v_volume
, label
->dkl_vtoc
.v_volume
,
1994 part
->vtoc
= label
->dkl_vtoc
;
1996 (void) memset(disk_info
->v_volume
, 0, LEN_DKL_VVOL
);
1997 set_vtoc_defaults(part
);
2001 * Link the disk to the partition map
2003 disk_info
->disk_parts
= part
;
2010 * Delete a disk type from disk type list.
2014 struct disk_type
*disk_type
)
2016 struct ctlr_type
*ctlr
;
2017 struct disk_type
*dp
, *disk
;
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();
2024 ctlr
= find_scsi_ctlr_type();
2025 if (ctlr
== NULL
|| ctlr
->ctype_dlist
== NULL
) {
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
);
2036 free(disk
->product
);
2037 free(disk
->revision
);
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
);
2060 static struct disk_info
*
2061 find_scsi_disk_info(
2062 struct dk_cinfo
*dkinfo
)
2064 struct disk_info
*disk
;
2065 struct dk_cinfo
*dp
;
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) {
2078 impossible("No SCSI disk info instance\n");
2080 return ((struct disk_info
*)NULL
);
2087 struct scsi_inquiry
*inquiry
)
2090 * Extract the sun name of the disk
2092 (void) memset(disk_name
, 0, DISK_NAME_MAX
);
2093 (void) memcpy(disk_name
, (char *)&inquiry
->inq_pid
[9], 7);
2100 get_generic_disk_name(
2102 struct scsi_inquiry
*inquiry
)
2106 (void) memset(disk_name
, 0, DISK_NAME_MAX
);
2107 p
= strcopy(disk_name
, inquiry
->inq_vid
,
2108 sizeof (inquiry
->inq_vid
));
2110 p
= strcopy(p
, inquiry
->inq_pid
, sizeof (inquiry
->inq_pid
));
2112 p
= strcopy(p
, inquiry
->inq_revision
,
2113 sizeof (inquiry
->inq_revision
));
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.
2132 while (*src
== ' ' && n
> 0) {
2137 for (i
= 0; n
-- > 0 && isascii(*src
) && isprint(*src
); src
++) {
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
2159 adjust_disk_geometry(diskaddr_t capacity
, uint_t
*cyl
, uint_t
*nhead
,
2163 uint_t lnhead
= *nhead
;
2164 uint_t lnsect
= *nsect
;
2166 assert(lcyl
< SUN_MIN_CYL
);
2169 * reduce nsect by 2 for each iteration and re-calculate
2170 * the number of cylinders.
2172 while (lnsect
> MINIMUM_NO_SECTORS
&&
2173 lcyl
< MINIMUM_NO_CYLINDERS
) {
2175 * make sure that we do not go below MINIMUM_NO_SECTORS.
2177 lnsect
= max(MINIMUM_NO_SECTORS
, lnsect
/ 2);
2178 lcyl
= (capacity
) / (lnhead
* lnsect
);
2181 * If the geometry still does not satisfy
2182 * MINIMUM_NO_CYLINDERS then try to reduce the
2185 while (lnhead
> MINIMUM_NO_HEADS
&&
2186 lcyl
< MINIMUM_NO_CYLINDERS
) {
2187 lnhead
= max(MINIMUM_NO_HEADS
, lnhead
/ 2);
2188 lcyl
= (capacity
) / (lnhead
* lnsect
);
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.
2195 if (lcyl
< SUN_MIN_CYL
)
2205 #if defined(_SUNOS_VTOC_8)
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.
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
)
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.
2228 assert(*dim1
>= *dim2
);
2229 assert(*dim2
>= *dim3
);
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.
2240 * Let's see how far we can go with bitshifts w/o losing
2244 for (i
= 0; (((*dim1
)>>i
)&1) == 0 && ((*dim1
)>>i
) > lim1
; i
++)
2247 *dim1
= ((*dim1
)>>i
);
2248 *dim3
= ((*dim3
)<<i
);
2251 if (((*dim1
) > lim1
) || ((*dim2
) > lim2
) || ((*dim3
) > lim3
)) {
2257 * Set the highest value at its limit then calculate errors,
2258 * adjusting the 2nd highest value (we get better resolution
2263 d
[2] = (double)capacity
/(d
[1]*d
[3]);
2266 * If we overflowed the middle term, set it to its limit and
2267 * chose a new low term.
2271 d
[3] = (double)capacity
/(d
[1]*d
[2]);
2274 * Convert to integers.
2281 * Fixup any other possible problems.
2282 * If this happens, we need a new disklabel format.
2284 if (*dim1
> lim1
) *dim1
= lim1
;
2285 if (*dim2
> lim2
) *dim2
= lim2
;
2286 if (*dim3
> lim3
) *dim3
= lim3
;
2287 return (*dim1
* *dim2
* *dim3
);
2289 #endif /* defined(_SUNOS_VTOC_8) */
2292 * Calculate CHS values based on the capacity data.
2294 * NOTE: This function is same as cmlb_convert_geomerty() function in
2295 * cmlb kernel module.
2298 compute_chs_values(diskaddr_t total_capacity
, diskaddr_t usable_capacity
,
2299 uint_t
*pcylp
, uint_t
*nheadp
, uint_t
*nsectp
)
2302 /* Unlabeled SCSI floppy device */
2303 if (total_capacity
< 160) {
2306 *pcylp
= total_capacity
;
2309 } else if (total_capacity
<= 0x1000) {
2312 *nsectp
= total_capacity
/ (80 * 2);
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
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.
2328 * The following table (in order) illustrates some end result
2331 * Maximum number of blocks nhead nsect
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
2343 if (total_capacity
<= 0x200000) {
2346 } else if (total_capacity
<= 0x01000000) {
2352 /* make nsect be smallest multiple of 63 */
2353 *nsectp
= ((total_capacity
+
2354 (UINT16_MAX
* 255 * 63) - 1) /
2355 (UINT16_MAX
* 255 * 63)) * 63;
2358 *nsectp
= (UINT16_MAX
/ 63) * 63;
2361 if (usable_capacity
< total_capacity
)
2362 *pcylp
= usable_capacity
/ ((*nheadp
) * (*nsectp
));
2364 *pcylp
= total_capacity
/ ((*nheadp
) * (*nsectp
));