17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5698107ecSlh195018 * Common Development and Distribution License (the "License").
6698107ecSlh195018 * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
221662a2f2SGary Mills * Copyright (c) 2011 Gary Mills
231662a2f2SGary Mills *
24b63e7ecbSAbhinandan Ekande * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
257c478bd9Sstevel@tonic-gate * Use is subject to license terms.
26*9aa4340aSHans Rosenfeld * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
277c478bd9Sstevel@tonic-gate */
287c478bd9Sstevel@tonic-gate
297c478bd9Sstevel@tonic-gate /*
307c478bd9Sstevel@tonic-gate * This file contains functions to implement automatic configuration
317c478bd9Sstevel@tonic-gate * of scsi disks.
327c478bd9Sstevel@tonic-gate */
337c478bd9Sstevel@tonic-gate #include "global.h"
347c478bd9Sstevel@tonic-gate
357c478bd9Sstevel@tonic-gate #include <fcntl.h>
367c478bd9Sstevel@tonic-gate #include <stdlib.h>
377c478bd9Sstevel@tonic-gate #include <string.h>
387c478bd9Sstevel@tonic-gate #include <strings.h>
397c478bd9Sstevel@tonic-gate #include <stdlib.h>
407c478bd9Sstevel@tonic-gate #include <ctype.h>
417c478bd9Sstevel@tonic-gate
427c478bd9Sstevel@tonic-gate #include "misc.h"
437c478bd9Sstevel@tonic-gate #include "param.h"
447c478bd9Sstevel@tonic-gate #include "ctlr_scsi.h"
457c478bd9Sstevel@tonic-gate #include "auto_sense.h"
467c478bd9Sstevel@tonic-gate #include "partition.h"
477c478bd9Sstevel@tonic-gate #include "label.h"
487c478bd9Sstevel@tonic-gate #include "startup.h"
497c478bd9Sstevel@tonic-gate #include "analyze.h"
507c478bd9Sstevel@tonic-gate #include "io.h"
517c478bd9Sstevel@tonic-gate #include "hardware_structs.h"
527c478bd9Sstevel@tonic-gate #include "menu_fdisk.h"
537c478bd9Sstevel@tonic-gate
547c478bd9Sstevel@tonic-gate
557c478bd9Sstevel@tonic-gate #define DISK_NAME_MAX 256
567c478bd9Sstevel@tonic-gate
577c478bd9Sstevel@tonic-gate extern int nctypes;
587c478bd9Sstevel@tonic-gate extern struct ctlr_type ctlr_types[];
597c478bd9Sstevel@tonic-gate
607c478bd9Sstevel@tonic-gate
617c478bd9Sstevel@tonic-gate /*
627c478bd9Sstevel@tonic-gate * Marker for free hog partition
637c478bd9Sstevel@tonic-gate */
647c478bd9Sstevel@tonic-gate #define HOG (-1)
657c478bd9Sstevel@tonic-gate
667c478bd9Sstevel@tonic-gate
677c478bd9Sstevel@tonic-gate
687c478bd9Sstevel@tonic-gate /*
697c478bd9Sstevel@tonic-gate * Default partition tables
707c478bd9Sstevel@tonic-gate *
717c478bd9Sstevel@tonic-gate * Disk capacity root swap usr
727c478bd9Sstevel@tonic-gate * ------------- ---- ---- ---
737c478bd9Sstevel@tonic-gate * 0mb to 64mb 0 0 remainder
747c478bd9Sstevel@tonic-gate * 64mb to 180mb 16mb 16mb remainder
757c478bd9Sstevel@tonic-gate * 180mb to 280mb 16mb 32mb remainder
767c478bd9Sstevel@tonic-gate * 280mb to 380mb 24mb 32mb remainder
777c478bd9Sstevel@tonic-gate * 380mb to 600mb 32mb 32mb remainder
787c478bd9Sstevel@tonic-gate * 600mb to 1gb 32mb 64mb remainder
797c478bd9Sstevel@tonic-gate * 1gb to 2gb 64mb 128mb remainder
807c478bd9Sstevel@tonic-gate * 2gb on up 128mb 128mb remainder
817c478bd9Sstevel@tonic-gate */
827c478bd9Sstevel@tonic-gate struct part_table {
837c478bd9Sstevel@tonic-gate int partitions[NDKMAP];
847c478bd9Sstevel@tonic-gate };
857c478bd9Sstevel@tonic-gate
867c478bd9Sstevel@tonic-gate static struct part_table part_table_64mb = {
877c478bd9Sstevel@tonic-gate { 0, 0, 0, 0, 0, 0, HOG, 0}
887c478bd9Sstevel@tonic-gate };
897c478bd9Sstevel@tonic-gate
907c478bd9Sstevel@tonic-gate static struct part_table part_table_180mb = {
917c478bd9Sstevel@tonic-gate { 16, 16, 0, 0, 0, 0, HOG, 0}
927c478bd9Sstevel@tonic-gate };
937c478bd9Sstevel@tonic-gate
947c478bd9Sstevel@tonic-gate static struct part_table part_table_280mb = {
957c478bd9Sstevel@tonic-gate { 16, 32, 0, 0, 0, 0, HOG, 0}
967c478bd9Sstevel@tonic-gate };
977c478bd9Sstevel@tonic-gate
987c478bd9Sstevel@tonic-gate static struct part_table part_table_380mb = {
997c478bd9Sstevel@tonic-gate { 24, 32, 0, 0, 0, 0, HOG, 0}
1007c478bd9Sstevel@tonic-gate };
1017c478bd9Sstevel@tonic-gate
1027c478bd9Sstevel@tonic-gate static struct part_table part_table_600mb = {
1037c478bd9Sstevel@tonic-gate { 32, 32, 0, 0, 0, 0, HOG, 0}
1047c478bd9Sstevel@tonic-gate };
1057c478bd9Sstevel@tonic-gate
1067c478bd9Sstevel@tonic-gate static struct part_table part_table_1gb = {
1077c478bd9Sstevel@tonic-gate { 32, 64, 0, 0, 0, 0, HOG, 0}
1087c478bd9Sstevel@tonic-gate };
1097c478bd9Sstevel@tonic-gate
1107c478bd9Sstevel@tonic-gate static struct part_table part_table_2gb = {
1117c478bd9Sstevel@tonic-gate { 64, 128, 0, 0, 0, 0, HOG, 0}
1127c478bd9Sstevel@tonic-gate };
1137c478bd9Sstevel@tonic-gate
1147c478bd9Sstevel@tonic-gate static struct part_table part_table_infinity = {
1157c478bd9Sstevel@tonic-gate { 128, 128, 0, 0, 0, 0, HOG, 0}
1167c478bd9Sstevel@tonic-gate };
1177c478bd9Sstevel@tonic-gate
1187c478bd9Sstevel@tonic-gate
1197c478bd9Sstevel@tonic-gate static struct default_partitions {
120342440ecSPrasad Singamsetty diskaddr_t min_capacity;
121342440ecSPrasad Singamsetty diskaddr_t max_capacity;
1227c478bd9Sstevel@tonic-gate struct part_table *part_table;
1237c478bd9Sstevel@tonic-gate } default_partitions[] = {
1247c478bd9Sstevel@tonic-gate { 0, 64, &part_table_64mb }, /* 0 to 64 mb */
1257c478bd9Sstevel@tonic-gate { 64, 180, &part_table_180mb }, /* 64 to 180 mb */
1267c478bd9Sstevel@tonic-gate { 180, 280, &part_table_280mb }, /* 180 to 280 mb */
1277c478bd9Sstevel@tonic-gate { 280, 380, &part_table_380mb }, /* 280 to 380 mb */
1287c478bd9Sstevel@tonic-gate { 380, 600, &part_table_600mb }, /* 380 to 600 mb */
1297c478bd9Sstevel@tonic-gate { 600, 1024, &part_table_1gb }, /* 600 to 1 gb */
1307c478bd9Sstevel@tonic-gate { 1024, 2048, &part_table_2gb }, /* 1 to 2 gb */
1317c478bd9Sstevel@tonic-gate { 2048, INFINITY, &part_table_infinity }, /* 2 gb on up */
1327c478bd9Sstevel@tonic-gate };
1337c478bd9Sstevel@tonic-gate
1347c478bd9Sstevel@tonic-gate #define DEFAULT_PARTITION_TABLE_SIZE \
1357c478bd9Sstevel@tonic-gate (sizeof (default_partitions) / sizeof (struct default_partitions))
1367c478bd9Sstevel@tonic-gate
1377c478bd9Sstevel@tonic-gate /*
1387c478bd9Sstevel@tonic-gate * msgs for check()
1397c478bd9Sstevel@tonic-gate */
1407c478bd9Sstevel@tonic-gate #define FORMAT_MSG "Auto configuration via format.dat"
1417c478bd9Sstevel@tonic-gate #define GENERIC_MSG "Auto configuration via generic SCSI-2"
1427c478bd9Sstevel@tonic-gate
1437c478bd9Sstevel@tonic-gate /*
1447c478bd9Sstevel@tonic-gate * Disks on symbios(Hardwire raid controller) return a fixed number
1457c478bd9Sstevel@tonic-gate * of heads(64)/cylinders(64) and adjust the cylinders depending
1467c478bd9Sstevel@tonic-gate * capacity of the configured lun.
1477c478bd9Sstevel@tonic-gate * In such a case we get number of physical cylinders < 3 which
1487c478bd9Sstevel@tonic-gate * is the minimum required by solaris(2 reserved + 1 data cylinders).
1497c478bd9Sstevel@tonic-gate * Hence try to adjust the cylinders by reducing the "nsect/nhead".
1507c478bd9Sstevel@tonic-gate *
1517c478bd9Sstevel@tonic-gate */
1527c478bd9Sstevel@tonic-gate /*
1537c478bd9Sstevel@tonic-gate * assuming a minimum of 32 block cylinders.
1547c478bd9Sstevel@tonic-gate */
1557c478bd9Sstevel@tonic-gate #define MINIMUM_NO_HEADS 2
1567c478bd9Sstevel@tonic-gate #define MINIMUM_NO_SECTORS 16
1577c478bd9Sstevel@tonic-gate
1587c478bd9Sstevel@tonic-gate #define MINIMUM_NO_CYLINDERS 128
1597c478bd9Sstevel@tonic-gate
1607c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
1617c478bd9Sstevel@tonic-gate
1627c478bd9Sstevel@tonic-gate /* These are 16-bit fields */
1637c478bd9Sstevel@tonic-gate #define MAXIMUM_NO_HEADS 65535
1647c478bd9Sstevel@tonic-gate #define MAXIMUM_NO_SECTORS 65535
1657c478bd9Sstevel@tonic-gate #define MAXIMUM_NO_CYLINDERS 65535
1667c478bd9Sstevel@tonic-gate
1677c478bd9Sstevel@tonic-gate #endif /* defined(_SUNOS_VTOC_8) */
1687c478bd9Sstevel@tonic-gate
1697c478bd9Sstevel@tonic-gate /*
1707c478bd9Sstevel@tonic-gate * minimum number of cylinders required by Solaris.
1717c478bd9Sstevel@tonic-gate */
1727c478bd9Sstevel@tonic-gate #define SUN_MIN_CYL 3
1737c478bd9Sstevel@tonic-gate
1747c478bd9Sstevel@tonic-gate
1757c478bd9Sstevel@tonic-gate
1767c478bd9Sstevel@tonic-gate /*
1777c478bd9Sstevel@tonic-gate * ANSI prototypes for local static functions
1787c478bd9Sstevel@tonic-gate */
1797c478bd9Sstevel@tonic-gate static struct disk_type *generic_disk_sense(
1807c478bd9Sstevel@tonic-gate int fd,
1817c478bd9Sstevel@tonic-gate int can_prompt,
1827c478bd9Sstevel@tonic-gate struct dk_label *label,
1837c478bd9Sstevel@tonic-gate struct scsi_inquiry *inquiry,
1847c478bd9Sstevel@tonic-gate struct scsi_capacity_16 *capacity,
1857c478bd9Sstevel@tonic-gate char *disk_name);
1867c478bd9Sstevel@tonic-gate static int use_existing_disk_type(
1877c478bd9Sstevel@tonic-gate int fd,
1887c478bd9Sstevel@tonic-gate int can_prompt,
1897c478bd9Sstevel@tonic-gate struct dk_label *label,
1907c478bd9Sstevel@tonic-gate struct scsi_inquiry *inquiry,
1917c478bd9Sstevel@tonic-gate struct disk_type *disk_type,
1927c478bd9Sstevel@tonic-gate struct scsi_capacity_16 *capacity);
1937c478bd9Sstevel@tonic-gate int build_default_partition(struct dk_label *label,
1947c478bd9Sstevel@tonic-gate int ctrl_type);
1957c478bd9Sstevel@tonic-gate static struct disk_type *find_scsi_disk_type(
1967c478bd9Sstevel@tonic-gate char *disk_name,
1977c478bd9Sstevel@tonic-gate struct dk_label *label);
1987c478bd9Sstevel@tonic-gate static struct disk_type *find_scsi_disk_by_name(
1997c478bd9Sstevel@tonic-gate char *disk_name);
2007c478bd9Sstevel@tonic-gate static struct ctlr_type *find_scsi_ctlr_type(void);
2017c478bd9Sstevel@tonic-gate static struct ctlr_info *find_scsi_ctlr_info(
2027c478bd9Sstevel@tonic-gate struct dk_cinfo *dkinfo);
2037c478bd9Sstevel@tonic-gate static struct disk_type *new_scsi_disk_type(
2047c478bd9Sstevel@tonic-gate int fd,
2057c478bd9Sstevel@tonic-gate char *disk_name,
2067c478bd9Sstevel@tonic-gate struct dk_label *label);
2077c478bd9Sstevel@tonic-gate static struct disk_info *find_scsi_disk_info(
2087c478bd9Sstevel@tonic-gate struct dk_cinfo *dkinfo);
2093ccda647Slclee
2103ccda647Slclee static struct disk_type *new_direct_disk_type(int fd, char *disk_name,
2113ccda647Slclee struct dk_label *label);
2123ccda647Slclee
2133ccda647Slclee static struct disk_info *find_direct_disk_info(struct dk_cinfo *dkinfo);
2143ccda647Slclee static int efi_ioctl(int fd, int cmd, dk_efi_t *dk_ioc);
2153ccda647Slclee static int auto_label_init(struct dk_label *label);
216698107ecSlh195018 static struct ctlr_type *find_direct_ctlr_type(void);
2173ccda647Slclee static struct ctlr_info *find_direct_ctlr_info(struct dk_cinfo *dkinfo);
2183ccda647Slclee static struct disk_info *find_direct_disk_info(struct dk_cinfo *dkinfo);
219f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China static struct ctlr_type *find_vbd_ctlr_type(void);
220f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China static struct ctlr_info *find_vbd_ctlr_info(struct dk_cinfo *dkinfo);
221f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China static struct disk_info *find_vbd_disk_info(struct dk_cinfo *dkinfo);
2223ccda647Slclee
2237c478bd9Sstevel@tonic-gate static char *get_sun_disk_name(
2247c478bd9Sstevel@tonic-gate char *disk_name,
2257c478bd9Sstevel@tonic-gate struct scsi_inquiry *inquiry);
2267c478bd9Sstevel@tonic-gate static char *strcopy(
2277c478bd9Sstevel@tonic-gate char *dst,
2287c478bd9Sstevel@tonic-gate char *src,
2297c478bd9Sstevel@tonic-gate int n);
230342440ecSPrasad Singamsetty static int adjust_disk_geometry(diskaddr_t capacity, uint_t *cyl,
231342440ecSPrasad Singamsetty uint_t *nsect, uint_t *nhead);
232342440ecSPrasad Singamsetty static void compute_chs_values(diskaddr_t total_capacity,
233342440ecSPrasad Singamsetty diskaddr_t usable_capacity, uint_t *pcylp,
234342440ecSPrasad Singamsetty uint_t *nheadp, uint_t *nsectp);
2357c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
236342440ecSPrasad Singamsetty static diskaddr_t square_box(
237342440ecSPrasad Singamsetty diskaddr_t capacity,
238342440ecSPrasad Singamsetty uint_t *dim1, uint_t lim1,
239342440ecSPrasad Singamsetty uint_t *dim2, uint_t lim2,
240342440ecSPrasad Singamsetty uint_t *dim3, uint_t lim3);
2417c478bd9Sstevel@tonic-gate #endif /* defined(_SUNOS_VTOC_8) */
2427c478bd9Sstevel@tonic-gate
2437c478bd9Sstevel@tonic-gate
2447c478bd9Sstevel@tonic-gate /*
2457c478bd9Sstevel@tonic-gate * We need to get information necessary to construct a *new* efi
2467c478bd9Sstevel@tonic-gate * label type
2477c478bd9Sstevel@tonic-gate */
2487c478bd9Sstevel@tonic-gate struct disk_type *
auto_efi_sense(int fd,struct efi_info * label)2497c478bd9Sstevel@tonic-gate auto_efi_sense(int fd, struct efi_info *label)
2507c478bd9Sstevel@tonic-gate {
2517c478bd9Sstevel@tonic-gate
2527c478bd9Sstevel@tonic-gate struct dk_gpt *vtoc;
2537c478bd9Sstevel@tonic-gate int i;
2547c478bd9Sstevel@tonic-gate
2557c478bd9Sstevel@tonic-gate struct disk_type *disk, *dp;
2567c478bd9Sstevel@tonic-gate struct disk_info *disk_info;
2577c478bd9Sstevel@tonic-gate struct ctlr_info *ctlr;
2587c478bd9Sstevel@tonic-gate struct dk_cinfo dkinfo;
2597c478bd9Sstevel@tonic-gate struct partition_info *part;
2607c478bd9Sstevel@tonic-gate
261*9aa4340aSHans Rosenfeld if (ioctl(fd, DKIOCINFO, &dkinfo) == -1) {
262*9aa4340aSHans Rosenfeld if (option_msg && diag_msg) {
263*9aa4340aSHans Rosenfeld err_print("DKIOCINFO failed\n");
264*9aa4340aSHans Rosenfeld }
265*9aa4340aSHans Rosenfeld return (NULL);
266*9aa4340aSHans Rosenfeld }
267*9aa4340aSHans Rosenfeld if ((cur_ctype != NULL) && (cur_ctype->ctype_ctype == DKC_DIRECT)) {
268*9aa4340aSHans Rosenfeld ctlr = find_direct_ctlr_info(&dkinfo);
269*9aa4340aSHans Rosenfeld disk_info = find_direct_disk_info(&dkinfo);
270*9aa4340aSHans Rosenfeld } else if ((cur_ctype != NULL) && (cur_ctype->ctype_ctype == DKC_VBD)) {
271*9aa4340aSHans Rosenfeld ctlr = find_vbd_ctlr_info(&dkinfo);
272*9aa4340aSHans Rosenfeld disk_info = find_vbd_disk_info(&dkinfo);
273*9aa4340aSHans Rosenfeld } else {
274*9aa4340aSHans Rosenfeld ctlr = find_scsi_ctlr_info(&dkinfo);
275*9aa4340aSHans Rosenfeld disk_info = find_scsi_disk_info(&dkinfo);
276*9aa4340aSHans Rosenfeld }
277*9aa4340aSHans Rosenfeld
2787c478bd9Sstevel@tonic-gate /*
2797c478bd9Sstevel@tonic-gate * get vendor, product, revision and capacity info.
2807c478bd9Sstevel@tonic-gate */
281*9aa4340aSHans Rosenfeld if (get_disk_info(fd, label, disk_info) == -1) {
2827c478bd9Sstevel@tonic-gate return ((struct disk_type *)NULL);
2837c478bd9Sstevel@tonic-gate }
2847c478bd9Sstevel@tonic-gate /*
2857c478bd9Sstevel@tonic-gate * Now build the default partition table
2867c478bd9Sstevel@tonic-gate */
2877c478bd9Sstevel@tonic-gate if (efi_alloc_and_init(fd, EFI_NUMPAR, &vtoc) != 0) {
2887c478bd9Sstevel@tonic-gate err_print("efi_alloc_and_init failed. \n");
2897c478bd9Sstevel@tonic-gate return ((struct disk_type *)NULL);
2907c478bd9Sstevel@tonic-gate }
2917c478bd9Sstevel@tonic-gate
2927c478bd9Sstevel@tonic-gate label->e_parts = vtoc;
2937c478bd9Sstevel@tonic-gate
2941cce8a3fSyl194034 /*
2951cce8a3fSyl194034 * Create a whole hog EFI partition table:
2961cce8a3fSyl194034 * S0 takes the whole disk except the primary EFI label,
2971cce8a3fSyl194034 * backup EFI label, and the reserved partition.
2981cce8a3fSyl194034 */
2991cce8a3fSyl194034 vtoc->efi_parts[0].p_tag = V_USR;
3001cce8a3fSyl194034 vtoc->efi_parts[0].p_start = vtoc->efi_first_u_lba;
3011cce8a3fSyl194034 vtoc->efi_parts[0].p_size = vtoc->efi_last_u_lba - vtoc->efi_first_u_lba
3021cce8a3fSyl194034 - EFI_MIN_RESV_SIZE + 1;
3031cce8a3fSyl194034
3041cce8a3fSyl194034 /*
3051cce8a3fSyl194034 * S1-S6 are unassigned slices.
3061cce8a3fSyl194034 */
3071cce8a3fSyl194034 for (i = 1; i < vtoc->efi_nparts - 2; i ++) {
3081cce8a3fSyl194034 vtoc->efi_parts[i].p_tag = V_UNASSIGNED;
3097c478bd9Sstevel@tonic-gate vtoc->efi_parts[i].p_start = 0;
3107c478bd9Sstevel@tonic-gate vtoc->efi_parts[i].p_size = 0;
3117c478bd9Sstevel@tonic-gate }
3121cce8a3fSyl194034
3137c478bd9Sstevel@tonic-gate /*
3141cce8a3fSyl194034 * The reserved slice
3157c478bd9Sstevel@tonic-gate */
3161cce8a3fSyl194034 vtoc->efi_parts[vtoc->efi_nparts - 1].p_tag = V_RESERVED;
3171cce8a3fSyl194034 vtoc->efi_parts[vtoc->efi_nparts - 1].p_start =
3181cce8a3fSyl194034 vtoc->efi_last_u_lba - EFI_MIN_RESV_SIZE + 1;
3191cce8a3fSyl194034 vtoc->efi_parts[vtoc->efi_nparts - 1].p_size = EFI_MIN_RESV_SIZE;
3207c478bd9Sstevel@tonic-gate
3217c478bd9Sstevel@tonic-gate /*
3227c478bd9Sstevel@tonic-gate * Now stick all of it into the disk_type struct
3237c478bd9Sstevel@tonic-gate */
3247c478bd9Sstevel@tonic-gate
325698107ecSlh195018 disk = (struct disk_type *)zalloc(sizeof (struct disk_type));
3267c478bd9Sstevel@tonic-gate assert(disk_info->disk_ctlr == ctlr);
3277c478bd9Sstevel@tonic-gate dp = ctlr->ctlr_ctype->ctype_dlist;
3287c478bd9Sstevel@tonic-gate if (dp == NULL) {
3297c478bd9Sstevel@tonic-gate ctlr->ctlr_ctype->ctype_dlist = dp;
3307c478bd9Sstevel@tonic-gate } else {
3317c478bd9Sstevel@tonic-gate while (dp->dtype_next != NULL) {
3327c478bd9Sstevel@tonic-gate dp = dp->dtype_next;
3337c478bd9Sstevel@tonic-gate }
3347c478bd9Sstevel@tonic-gate dp->dtype_next = disk;
3357c478bd9Sstevel@tonic-gate }
3367c478bd9Sstevel@tonic-gate disk->dtype_next = NULL;
3377c478bd9Sstevel@tonic-gate
338*9aa4340aSHans Rosenfeld disk->vendor = strdup(label->vendor);
339*9aa4340aSHans Rosenfeld disk->product = strdup(label->product);
340*9aa4340aSHans Rosenfeld disk->revision = strdup(label->revision);
341*9aa4340aSHans Rosenfeld
342*9aa4340aSHans Rosenfeld if (disk->vendor == NULL ||
343*9aa4340aSHans Rosenfeld disk->product == NULL ||
344*9aa4340aSHans Rosenfeld disk->revision == NULL) {
345*9aa4340aSHans Rosenfeld free(disk->vendor);
346*9aa4340aSHans Rosenfeld free(disk->product);
347*9aa4340aSHans Rosenfeld free(disk->revision);
348*9aa4340aSHans Rosenfeld free(disk);
349*9aa4340aSHans Rosenfeld return (NULL);
350*9aa4340aSHans Rosenfeld }
351*9aa4340aSHans Rosenfeld
3527c478bd9Sstevel@tonic-gate disk->capacity = label->capacity;
3537c478bd9Sstevel@tonic-gate
3547c478bd9Sstevel@tonic-gate part = (struct partition_info *)
3557c478bd9Sstevel@tonic-gate zalloc(sizeof (struct partition_info));
3567c478bd9Sstevel@tonic-gate disk->dtype_plist = part;
3577c478bd9Sstevel@tonic-gate
3587c478bd9Sstevel@tonic-gate part->pinfo_name = alloc_string("default");
3597c478bd9Sstevel@tonic-gate part->pinfo_next = NULL;
3607c478bd9Sstevel@tonic-gate part->etoc = vtoc;
3617c478bd9Sstevel@tonic-gate
3627c478bd9Sstevel@tonic-gate bzero(disk_info->v_volume, LEN_DKL_VVOL);
3637c478bd9Sstevel@tonic-gate disk_info->disk_parts = part;
3647c478bd9Sstevel@tonic-gate return (disk);
3657c478bd9Sstevel@tonic-gate }
3667c478bd9Sstevel@tonic-gate
3673ccda647Slclee static int
efi_ioctl(int fd,int cmd,dk_efi_t * dk_ioc)3683ccda647Slclee efi_ioctl(int fd, int cmd, dk_efi_t *dk_ioc)
3693ccda647Slclee {
3703ccda647Slclee void *data = dk_ioc->dki_data;
3713ccda647Slclee int error;
3723ccda647Slclee
3733ccda647Slclee dk_ioc->dki_data_64 = (uint64_t)(uintptr_t)data;
3743ccda647Slclee error = ioctl(fd, cmd, (void *)dk_ioc);
3753ccda647Slclee dk_ioc->dki_data = data;
3763ccda647Slclee
3773ccda647Slclee return (error);
3783ccda647Slclee }
3793ccda647Slclee
380698107ecSlh195018 static struct ctlr_type *
find_direct_ctlr_type()381698107ecSlh195018 find_direct_ctlr_type()
382698107ecSlh195018 {
383698107ecSlh195018 struct mctlr_list *mlp;
384698107ecSlh195018
385698107ecSlh195018 mlp = controlp;
386698107ecSlh195018
387698107ecSlh195018 while (mlp != NULL) {
388698107ecSlh195018 if (mlp->ctlr_type->ctype_ctype == DKC_DIRECT) {
389698107ecSlh195018 return (mlp->ctlr_type);
390698107ecSlh195018 }
391698107ecSlh195018 mlp = mlp->next;
392698107ecSlh195018 }
393698107ecSlh195018
394698107ecSlh195018 impossible("no DIRECT controller type");
395698107ecSlh195018
396698107ecSlh195018 return ((struct ctlr_type *)NULL);
397698107ecSlh195018 }
398698107ecSlh195018
399f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China static struct ctlr_type *
find_vbd_ctlr_type()400f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China find_vbd_ctlr_type()
401f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China {
402f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China struct mctlr_list *mlp;
403f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China
404f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China mlp = controlp;
405f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China
406f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China while (mlp != NULL) {
407f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China if (mlp->ctlr_type->ctype_ctype == DKC_VBD) {
408f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China return (mlp->ctlr_type);
409f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China }
410f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China mlp = mlp->next;
411f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China }
412f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China
413f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China impossible("no VBD controller type");
414f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China
415f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China return ((struct ctlr_type *)NULL);
416f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China }
417f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China
4183ccda647Slclee static struct ctlr_info *
find_direct_ctlr_info(struct dk_cinfo * dkinfo)4193ccda647Slclee find_direct_ctlr_info(
4203ccda647Slclee struct dk_cinfo *dkinfo)
4213ccda647Slclee {
4223ccda647Slclee struct ctlr_info *ctlr;
4233ccda647Slclee
4243ccda647Slclee if (dkinfo->dki_ctype != DKC_DIRECT)
4253ccda647Slclee return (NULL);
4263ccda647Slclee
4273ccda647Slclee for (ctlr = ctlr_list; ctlr != NULL; ctlr = ctlr->ctlr_next) {
4283ccda647Slclee if (ctlr->ctlr_addr == dkinfo->dki_addr &&
4293ccda647Slclee ctlr->ctlr_space == dkinfo->dki_space &&
4303ccda647Slclee ctlr->ctlr_ctype->ctype_ctype == DKC_DIRECT) {
4313ccda647Slclee return (ctlr);
4323ccda647Slclee }
4333ccda647Slclee }
4343ccda647Slclee
4353ccda647Slclee impossible("no DIRECT controller info");
4363ccda647Slclee /*NOTREACHED*/
4373ccda647Slclee }
4383ccda647Slclee
439f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China static struct ctlr_info *
find_vbd_ctlr_info(struct dk_cinfo * dkinfo)440f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China find_vbd_ctlr_info(
441f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China struct dk_cinfo *dkinfo)
442f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China {
443f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China struct ctlr_info *ctlr;
444f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China
445f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China if (dkinfo->dki_ctype != DKC_VBD)
446f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China return (NULL);
447f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China
448f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China for (ctlr = ctlr_list; ctlr != NULL; ctlr = ctlr->ctlr_next) {
449f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China if (ctlr->ctlr_addr == dkinfo->dki_addr &&
450f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China ctlr->ctlr_space == dkinfo->dki_space &&
451f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China ctlr->ctlr_ctype->ctype_ctype == DKC_VBD) {
452f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China return (ctlr);
453f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China }
454f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China }
455f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China
456f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China impossible("no VBD controller info");
457f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China /*NOTREACHED*/
458f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China }
459f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China
4603ccda647Slclee static struct disk_info *
find_direct_disk_info(struct dk_cinfo * dkinfo)4613ccda647Slclee find_direct_disk_info(
4623ccda647Slclee struct dk_cinfo *dkinfo)
4633ccda647Slclee {
4643ccda647Slclee struct disk_info *disk;
4653ccda647Slclee struct dk_cinfo *dp;
4663ccda647Slclee
4673ccda647Slclee for (disk = disk_list; disk != NULL; disk = disk->disk_next) {
4683ccda647Slclee assert(dkinfo->dki_ctype == DKC_DIRECT);
4693ccda647Slclee dp = &disk->disk_dkinfo;
4703ccda647Slclee if (dp->dki_ctype == dkinfo->dki_ctype &&
4713ccda647Slclee dp->dki_cnum == dkinfo->dki_cnum &&
4723ccda647Slclee dp->dki_unit == dkinfo->dki_unit &&
4733ccda647Slclee strcmp(dp->dki_dname, dkinfo->dki_dname) == 0) {
4743ccda647Slclee return (disk);
4753ccda647Slclee }
4763ccda647Slclee }
4773ccda647Slclee
4783ccda647Slclee impossible("No DIRECT disk info instance\n");
4793ccda647Slclee /*NOTREACHED*/
4803ccda647Slclee }
4813ccda647Slclee
482f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China static struct disk_info *
find_vbd_disk_info(struct dk_cinfo * dkinfo)483f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China find_vbd_disk_info(
484f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China struct dk_cinfo *dkinfo)
485f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China {
486f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China struct disk_info *disk;
487f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China struct dk_cinfo *dp;
488f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China
489f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China for (disk = disk_list; disk != NULL; disk = disk->disk_next) {
490f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China assert(dkinfo->dki_ctype == DKC_VBD);
491f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China dp = &disk->disk_dkinfo;
492f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China if (dp->dki_ctype == dkinfo->dki_ctype &&
493f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China dp->dki_cnum == dkinfo->dki_cnum &&
494f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China dp->dki_unit == dkinfo->dki_unit &&
495f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China strcmp(dp->dki_dname, dkinfo->dki_dname) == 0) {
496f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China return (disk);
497f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China }
498f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China }
499f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China
500f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China impossible("No VBD disk info instance\n");
501f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China /*NOTREACHED*/
502f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China }
503f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China
5043ccda647Slclee /*
5053ccda647Slclee * To convert EFI to SMI labels, we need to get label geometry.
5063ccda647Slclee * Unfortunately at this time there is no good way to do so.
5073ccda647Slclee * DKIOCGGEOM will fail if disk is EFI labeled. So we hack around
5083ccda647Slclee * it and clear EFI label, do a DKIOCGGEOM and put the EFI label
5093ccda647Slclee * back on disk.
5103ccda647Slclee * This routine gets the label geometry and initializes the label
5113ccda647Slclee * It uses cur_file as opened device.
5123ccda647Slclee * returns 0 if succeeds or -1 if failed.
5133ccda647Slclee */
5143ccda647Slclee static int
auto_label_init(struct dk_label * label)5153ccda647Slclee auto_label_init(struct dk_label *label)
5163ccda647Slclee {
5173ccda647Slclee dk_efi_t dk_ioc;
5183ccda647Slclee dk_efi_t dk_ioc_back;
5193ccda647Slclee efi_gpt_t *data = NULL;
5203ccda647Slclee efi_gpt_t *databack = NULL;
5213ccda647Slclee struct dk_geom disk_geom;
5223ccda647Slclee struct dk_minfo disk_info;
5233ccda647Slclee efi_gpt_t *backsigp;
5243ccda647Slclee int fd = cur_file;
5253ccda647Slclee int rval = -1;
5263ccda647Slclee int efisize = EFI_LABEL_SIZE * 2;
5273ccda647Slclee int success = 0;
5283ccda647Slclee uint64_t sig;
5293ccda647Slclee uint64_t backsig;
5303ccda647Slclee
5313ccda647Slclee if ((data = calloc(efisize, 1)) == NULL) {
5323ccda647Slclee err_print("auto_label_init: calloc failed\n");
5333ccda647Slclee goto auto_label_init_out;
5343ccda647Slclee }
5353ccda647Slclee
5363ccda647Slclee dk_ioc.dki_data = data;
5373ccda647Slclee dk_ioc.dki_lba = 1;
5383ccda647Slclee dk_ioc.dki_length = efisize;
5393ccda647Slclee
5403ccda647Slclee if (efi_ioctl(fd, DKIOCGETEFI, &dk_ioc) != 0) {
5413ccda647Slclee err_print("auto_label_init: GETEFI failed\n");
5423ccda647Slclee goto auto_label_init_out;
5433ccda647Slclee }
5443ccda647Slclee
5453ccda647Slclee if ((databack = calloc(efisize, 1)) == NULL) {
5463ccda647Slclee err_print("auto_label_init calloc2 failed");
5473ccda647Slclee goto auto_label_init_out;
5483ccda647Slclee }
5493ccda647Slclee
5503ccda647Slclee /* get the LBA size and capacity */
5513ccda647Slclee if (ioctl(fd, DKIOCGMEDIAINFO, (caddr_t)&disk_info) == -1) {
5523ccda647Slclee err_print("auto_label_init: dkiocgmediainfo failed\n");
5533ccda647Slclee goto auto_label_init_out;
5543ccda647Slclee }
5553ccda647Slclee
5563ccda647Slclee if (disk_info.dki_lbsize == 0) {
5573ccda647Slclee if (option_msg && diag_msg) {
5583ccda647Slclee err_print("auto_lbal_init: assuming 512 byte"
5593ccda647Slclee "block size");
5603ccda647Slclee }
5613ccda647Slclee disk_info.dki_lbsize = DEV_BSIZE;
5623ccda647Slclee }
5633ccda647Slclee
5643ccda647Slclee dk_ioc_back.dki_data = databack;
5653ccda647Slclee
5663ccda647Slclee /*
5673ccda647Slclee * back up efi label goes to capacity - 1, we are reading an extra block
5683ccda647Slclee * before the back up label.
5693ccda647Slclee */
5703ccda647Slclee dk_ioc_back.dki_lba = disk_info.dki_capacity - 1 - 1;
5713ccda647Slclee dk_ioc_back.dki_length = efisize;
5723ccda647Slclee
5733ccda647Slclee if (efi_ioctl(fd, DKIOCGETEFI, &dk_ioc_back) != 0) {
5743ccda647Slclee err_print("auto_label_init: GETEFI backup failed\n");
5753ccda647Slclee goto auto_label_init_out;
5763ccda647Slclee }
5773ccda647Slclee
5783ccda647Slclee sig = dk_ioc.dki_data->efi_gpt_Signature;
5793ccda647Slclee dk_ioc.dki_data->efi_gpt_Signature = 0x0;
5803ccda647Slclee
5813ccda647Slclee enter_critical();
5823ccda647Slclee
5833ccda647Slclee if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc) == -1) {
5843ccda647Slclee err_print("auto_label_init: SETEFI failed\n");
5853ccda647Slclee exit_critical();
5863ccda647Slclee goto auto_label_init_out;
5873ccda647Slclee }
5883ccda647Slclee
58965908c77Syu, larry liu - Sun Microsystems - Beijing China backsigp = (efi_gpt_t *)((uintptr_t)dk_ioc_back.dki_data + cur_blksz);
5903ccda647Slclee
5913ccda647Slclee backsig = backsigp->efi_gpt_Signature;
5923ccda647Slclee
5933ccda647Slclee backsigp->efi_gpt_Signature = 0;
5943ccda647Slclee
5953ccda647Slclee if (efi_ioctl(fd, DKIOCSETEFI, &dk_ioc_back) == -1) {
5963ccda647Slclee err_print("auto_label_init: SETEFI backup failed\n");
5973ccda647Slclee }
5983ccda647Slclee
5993ccda647Slclee if (ioctl(cur_file, DKIOCGGEOM, &disk_geom) != 0)
6003ccda647Slclee err_print("auto_label_init: GGEOM failed\n");
6013ccda647Slclee else
6023ccda647Slclee success = 1;
6033ccda647Slclee
6043ccda647Slclee dk_ioc.dki_data->efi_gpt_Signature = sig;
6053ccda647Slclee backsigp->efi_gpt_Signature = backsig;
6063ccda647Slclee
6073ccda647Slclee if (efi_ioctl(cur_file, DKIOCSETEFI, &dk_ioc_back) == -1) {
6083ccda647Slclee err_print("auto_label_init: SETEFI revert backup failed\n");
6093ccda647Slclee success = 0;
6103ccda647Slclee }
6113ccda647Slclee
6123ccda647Slclee if (efi_ioctl(cur_file, DKIOCSETEFI, &dk_ioc) == -1) {
6133ccda647Slclee err_print("auto_label_init: SETEFI revert failed\n");
6143ccda647Slclee success = 0;
6153ccda647Slclee }
6163ccda647Slclee
6173ccda647Slclee exit_critical();
6183ccda647Slclee
6193ccda647Slclee if (success == 0)
6203ccda647Slclee goto auto_label_init_out;
6213ccda647Slclee
6223ccda647Slclee ncyl = disk_geom.dkg_ncyl;
6233ccda647Slclee acyl = disk_geom.dkg_acyl;
6243ccda647Slclee nhead = disk_geom.dkg_nhead;
6253ccda647Slclee nsect = disk_geom.dkg_nsect;
6263ccda647Slclee pcyl = ncyl + acyl;
6273ccda647Slclee
6283ccda647Slclee label->dkl_pcyl = pcyl;
6293ccda647Slclee label->dkl_ncyl = ncyl;
6303ccda647Slclee label->dkl_acyl = acyl;
6313ccda647Slclee label->dkl_nhead = nhead;
6323ccda647Slclee label->dkl_nsect = nsect;
6333ccda647Slclee label->dkl_apc = 0;
6343ccda647Slclee label->dkl_intrlv = 1;
6353ccda647Slclee label->dkl_rpm = disk_geom.dkg_rpm;
6363ccda647Slclee
6373ccda647Slclee label->dkl_magic = DKL_MAGIC;
6383ccda647Slclee
6393ccda647Slclee (void) snprintf(label->dkl_asciilabel, sizeof (label->dkl_asciilabel),
640342440ecSPrasad Singamsetty "%s cyl %u alt %u hd %u sec %u",
6413ccda647Slclee "DEFAULT", ncyl, acyl, nhead, nsect);
6423ccda647Slclee
6433ccda647Slclee rval = 0;
6443ccda647Slclee #if defined(_FIRMWARE_NEEDS_FDISK)
6453ccda647Slclee (void) auto_solaris_part(label);
6463ccda647Slclee ncyl = label->dkl_ncyl;
6473ccda647Slclee
6483ccda647Slclee #endif /* defined(_FIRMWARE_NEEDS_FDISK) */
6493ccda647Slclee
6503ccda647Slclee if (!build_default_partition(label, DKC_DIRECT)) {
6513ccda647Slclee rval = -1;
6523ccda647Slclee }
6533ccda647Slclee
6543ccda647Slclee (void) checksum(label, CK_MAKESUM);
6553ccda647Slclee
6563ccda647Slclee
6573ccda647Slclee auto_label_init_out:
6583ccda647Slclee if (data)
6593ccda647Slclee free(data);
6603ccda647Slclee if (databack)
6613ccda647Slclee free(databack);
6623ccda647Slclee
6633ccda647Slclee return (rval);
6643ccda647Slclee }
6653ccda647Slclee
6663ccda647Slclee static struct disk_type *
new_direct_disk_type(int fd,char * disk_name,struct dk_label * label)6673ccda647Slclee new_direct_disk_type(
6683ccda647Slclee int fd,
6693ccda647Slclee char *disk_name,
6703ccda647Slclee struct dk_label *label)
6713ccda647Slclee {
6723ccda647Slclee struct disk_type *dp;
6733ccda647Slclee struct disk_type *disk;
6743ccda647Slclee struct ctlr_info *ctlr;
6753ccda647Slclee struct dk_cinfo dkinfo;
6763ccda647Slclee struct partition_info *part = NULL;
6773ccda647Slclee struct partition_info *pt;
6783ccda647Slclee struct disk_info *disk_info;
6793ccda647Slclee int i;
6803ccda647Slclee
6813ccda647Slclee /*
6823ccda647Slclee * Get the disk controller info for this disk
6833ccda647Slclee */
6843ccda647Slclee if (ioctl(fd, DKIOCINFO, &dkinfo) == -1) {
6853ccda647Slclee if (option_msg && diag_msg) {
6863ccda647Slclee err_print("DKIOCINFO failed\n");
6873ccda647Slclee }
6883ccda647Slclee return (NULL);
6893ccda647Slclee }
6903ccda647Slclee
6913ccda647Slclee /*
6923ccda647Slclee * Find the ctlr_info for this disk.
6933ccda647Slclee */
6943ccda647Slclee ctlr = find_direct_ctlr_info(&dkinfo);
6953ccda647Slclee
6963ccda647Slclee /*
6973ccda647Slclee * Allocate a new disk type for the direct controller.
6983ccda647Slclee */
6993ccda647Slclee disk = (struct disk_type *)zalloc(sizeof (struct disk_type));
7003ccda647Slclee
7013ccda647Slclee /*
7023ccda647Slclee * Find the disk_info instance for this disk.
7033ccda647Slclee */
7043ccda647Slclee disk_info = find_direct_disk_info(&dkinfo);
7053ccda647Slclee
7063ccda647Slclee /*
7073ccda647Slclee * The controller and the disk should match.
7083ccda647Slclee */
7093ccda647Slclee assert(disk_info->disk_ctlr == ctlr);
7103ccda647Slclee
7113ccda647Slclee /*
7123ccda647Slclee * Link the disk into the list of disks
7133ccda647Slclee */
7143ccda647Slclee dp = ctlr->ctlr_ctype->ctype_dlist;
7153ccda647Slclee if (dp == NULL) {
7163ccda647Slclee ctlr->ctlr_ctype->ctype_dlist = dp;
7173ccda647Slclee } else {
7183ccda647Slclee while (dp->dtype_next != NULL) {
7193ccda647Slclee dp = dp->dtype_next;
7203ccda647Slclee }
7213ccda647Slclee dp->dtype_next = disk;
7223ccda647Slclee }
7233ccda647Slclee disk->dtype_next = NULL;
7243ccda647Slclee
7253ccda647Slclee /*
7263ccda647Slclee * Allocate and initialize the disk name.
7273ccda647Slclee */
7283ccda647Slclee disk->dtype_asciilabel = alloc_string(disk_name);
7293ccda647Slclee
7303ccda647Slclee /*
7313ccda647Slclee * Initialize disk geometry info
7323ccda647Slclee */
7333ccda647Slclee disk->dtype_pcyl = label->dkl_pcyl;
7343ccda647Slclee disk->dtype_ncyl = label->dkl_ncyl;
7353ccda647Slclee disk->dtype_acyl = label->dkl_acyl;
7363ccda647Slclee disk->dtype_nhead = label->dkl_nhead;
7373ccda647Slclee disk->dtype_nsect = label->dkl_nsect;
7383ccda647Slclee disk->dtype_rpm = label->dkl_rpm;
7393ccda647Slclee
7403ccda647Slclee part = (struct partition_info *)
7413ccda647Slclee zalloc(sizeof (struct partition_info));
7423ccda647Slclee pt = disk->dtype_plist;
7433ccda647Slclee if (pt == NULL) {
7443ccda647Slclee disk->dtype_plist = part;
7453ccda647Slclee } else {
7463ccda647Slclee while (pt->pinfo_next != NULL) {
7473ccda647Slclee pt = pt->pinfo_next;
7483ccda647Slclee }
7493ccda647Slclee pt->pinfo_next = part;
7503ccda647Slclee }
7513ccda647Slclee
7523ccda647Slclee part->pinfo_next = NULL;
7533ccda647Slclee
7543ccda647Slclee /*
7553ccda647Slclee * Set up the partition name
7563ccda647Slclee */
7573ccda647Slclee part->pinfo_name = alloc_string("default");
7583ccda647Slclee
7593ccda647Slclee /*
7603ccda647Slclee * Fill in the partition info from the label
7613ccda647Slclee */
7623ccda647Slclee for (i = 0; i < NDKMAP; i++) {
7633ccda647Slclee
7643ccda647Slclee #if defined(_SUNOS_VTOC_8)
7653ccda647Slclee part->pinfo_map[i] = label->dkl_map[i];
7663ccda647Slclee
7673ccda647Slclee #elif defined(_SUNOS_VTOC_16)
7683ccda647Slclee part->pinfo_map[i].dkl_cylno =
7693ccda647Slclee label->dkl_vtoc.v_part[i].p_start /
770342440ecSPrasad Singamsetty ((blkaddr_t)(disk->dtype_nhead *
7713ccda647Slclee disk->dtype_nsect - apc));
7723ccda647Slclee part->pinfo_map[i].dkl_nblk =
7733ccda647Slclee label->dkl_vtoc.v_part[i].p_size;
7743ccda647Slclee #else
7753ccda647Slclee #error No VTOC format defined.
7763ccda647Slclee #endif /* defined(_SUNOS_VTOC_8) */
7773ccda647Slclee }
7783ccda647Slclee
7793ccda647Slclee /*
7803ccda647Slclee * Use the VTOC if valid, or install a default
7813ccda647Slclee */
7823ccda647Slclee if (label->dkl_vtoc.v_version == V_VERSION) {
7833ccda647Slclee (void) memcpy(disk_info->v_volume, label->dkl_vtoc.v_volume,
7843ccda647Slclee LEN_DKL_VVOL);
7853ccda647Slclee part->vtoc = label->dkl_vtoc;
7863ccda647Slclee } else {
7873ccda647Slclee (void) memset(disk_info->v_volume, 0, LEN_DKL_VVOL);
7883ccda647Slclee set_vtoc_defaults(part);
7893ccda647Slclee }
7903ccda647Slclee
7913ccda647Slclee /*
7923ccda647Slclee * Link the disk to the partition map
7933ccda647Slclee */
7943ccda647Slclee disk_info->disk_parts = part;
7953ccda647Slclee
7963ccda647Slclee return (disk);
7973ccda647Slclee }
7983ccda647Slclee
7993ccda647Slclee /*
8003ccda647Slclee * Get a disk type that has label info. This is used to convert
8013ccda647Slclee * EFI label to SMI label
8023ccda647Slclee */
8033ccda647Slclee struct disk_type *
auto_direct_get_geom_label(int fd,struct dk_label * label)8043ccda647Slclee auto_direct_get_geom_label(int fd, struct dk_label *label)
8053ccda647Slclee {
8063ccda647Slclee struct disk_type *disk_type;
8073ccda647Slclee
8083ccda647Slclee if (auto_label_init(label) != 0) {
8093ccda647Slclee err_print("auto_direct_get_geom_label: failed to get label"
8103ccda647Slclee "geometry");
8113ccda647Slclee return (NULL);
8123ccda647Slclee } else {
8133ccda647Slclee disk_type = new_direct_disk_type(fd, "DEFAULT", label);
8143ccda647Slclee return (disk_type);
8153ccda647Slclee }
8163ccda647Slclee }
8173ccda647Slclee
8187c478bd9Sstevel@tonic-gate /*
8197c478bd9Sstevel@tonic-gate * Auto-sense a scsi disk configuration, ie get the information
8207c478bd9Sstevel@tonic-gate * necessary to construct a label. We have two different
8217c478bd9Sstevel@tonic-gate * ways to auto-sense a scsi disk:
8227c478bd9Sstevel@tonic-gate * - format.dat override, via inquiry name
8237c478bd9Sstevel@tonic-gate * - generic scsi, via standard mode sense and inquiry
8247c478bd9Sstevel@tonic-gate * Depending on how and when we are called, and/or
8257c478bd9Sstevel@tonic-gate * change geometry and reformat.
8267c478bd9Sstevel@tonic-gate */
8277c478bd9Sstevel@tonic-gate struct disk_type *
auto_sense(int fd,int can_prompt,struct dk_label * label)8287c478bd9Sstevel@tonic-gate auto_sense(
8297c478bd9Sstevel@tonic-gate int fd,
8307c478bd9Sstevel@tonic-gate int can_prompt,
8317c478bd9Sstevel@tonic-gate struct dk_label *label)
8327c478bd9Sstevel@tonic-gate {
8337c478bd9Sstevel@tonic-gate struct scsi_inquiry inquiry;
8347c478bd9Sstevel@tonic-gate struct scsi_capacity_16 capacity;
8357c478bd9Sstevel@tonic-gate struct disk_type *disk_type;
8367c478bd9Sstevel@tonic-gate char disk_name[DISK_NAME_MAX];
8377c478bd9Sstevel@tonic-gate int force_format_dat = 0;
8387c478bd9Sstevel@tonic-gate int force_generic = 0;
8397c478bd9Sstevel@tonic-gate u_ioparam_t ioparam;
8407c478bd9Sstevel@tonic-gate int deflt;
8414ee50ec3Sbo zhou - Sun Microsystems - Beijing China char *buf;
8427c478bd9Sstevel@tonic-gate
8437c478bd9Sstevel@tonic-gate /*
8447c478bd9Sstevel@tonic-gate * First, if expert mode, find out if the user
8457c478bd9Sstevel@tonic-gate * wants to override any of the standard methods.
8467c478bd9Sstevel@tonic-gate */
8477c478bd9Sstevel@tonic-gate if (can_prompt && expert_mode) {
8487c478bd9Sstevel@tonic-gate deflt = 1;
8497c478bd9Sstevel@tonic-gate ioparam.io_charlist = confirm_list;
8507c478bd9Sstevel@tonic-gate if (input(FIO_MSTR, FORMAT_MSG, '?', &ioparam,
8517c478bd9Sstevel@tonic-gate &deflt, DATA_INPUT) == 0) {
8527c478bd9Sstevel@tonic-gate force_format_dat = 1;
8537c478bd9Sstevel@tonic-gate } else if (input(FIO_MSTR, GENERIC_MSG, '?', &ioparam,
8547c478bd9Sstevel@tonic-gate &deflt, DATA_INPUT) == 0) {
8557c478bd9Sstevel@tonic-gate force_generic = 1;
8567c478bd9Sstevel@tonic-gate }
8577c478bd9Sstevel@tonic-gate }
8587c478bd9Sstevel@tonic-gate
8597c478bd9Sstevel@tonic-gate /*
8607c478bd9Sstevel@tonic-gate * Get the Inquiry data. If this fails, there's
8617c478bd9Sstevel@tonic-gate * no hope for this disk, so give up.
8627c478bd9Sstevel@tonic-gate */
8637c478bd9Sstevel@tonic-gate if (uscsi_inquiry(fd, (char *)&inquiry, sizeof (inquiry))) {
8647c478bd9Sstevel@tonic-gate return ((struct disk_type *)NULL);
8657c478bd9Sstevel@tonic-gate }
8667c478bd9Sstevel@tonic-gate if (option_msg && diag_msg) {
8677c478bd9Sstevel@tonic-gate err_print("Product id: ");
8687c478bd9Sstevel@tonic-gate print_buf(inquiry.inq_pid, sizeof (inquiry.inq_pid));
8697c478bd9Sstevel@tonic-gate err_print("\n");
8707c478bd9Sstevel@tonic-gate }
8717c478bd9Sstevel@tonic-gate
8727c478bd9Sstevel@tonic-gate /*
8737c478bd9Sstevel@tonic-gate * Get the Read Capacity
8747c478bd9Sstevel@tonic-gate */
8757c478bd9Sstevel@tonic-gate if (uscsi_read_capacity(fd, &capacity)) {
8767c478bd9Sstevel@tonic-gate return ((struct disk_type *)NULL);
8777c478bd9Sstevel@tonic-gate }
8780972747aSyl194034
8790972747aSyl194034 /*
8800972747aSyl194034 * If the reported capacity is set to zero, then the disk
8810972747aSyl194034 * is not usable. If the reported capacity is set to all
8820972747aSyl194034 * 0xf's, then this disk is too large. These could only
8830972747aSyl194034 * happen with a device that supports LBAs larger than 64
8840972747aSyl194034 * bits which are not defined by any current T10 standards
8850972747aSyl194034 * or by error responding from target.
8860972747aSyl194034 */
8870972747aSyl194034 if ((capacity.sc_capacity == 0) ||
8880972747aSyl194034 (capacity.sc_capacity == UINT_MAX64)) {
8890972747aSyl194034 if (option_msg && diag_msg) {
8900972747aSyl194034 err_print("Invalid capacity\n");
8910972747aSyl194034 }
8920972747aSyl194034 return ((struct disk_type *)NULL);
8930972747aSyl194034 }
8947c478bd9Sstevel@tonic-gate if (option_msg && diag_msg) {
8957c478bd9Sstevel@tonic-gate err_print("blocks: %llu (0x%llx)\n",
8967c478bd9Sstevel@tonic-gate capacity.sc_capacity, capacity.sc_capacity);
8977c478bd9Sstevel@tonic-gate err_print("blksize: %u\n", capacity.sc_lbasize);
8987c478bd9Sstevel@tonic-gate }
8997c478bd9Sstevel@tonic-gate
9007c478bd9Sstevel@tonic-gate /*
9017c478bd9Sstevel@tonic-gate * Extract the disk name for the format.dat override
9027c478bd9Sstevel@tonic-gate */
9037c478bd9Sstevel@tonic-gate (void) get_sun_disk_name(disk_name, &inquiry);
9047c478bd9Sstevel@tonic-gate if (option_msg && diag_msg) {
9057c478bd9Sstevel@tonic-gate err_print("disk name: `%s`\n", disk_name);
9067c478bd9Sstevel@tonic-gate }
9077c478bd9Sstevel@tonic-gate
9084ee50ec3Sbo zhou - Sun Microsystems - Beijing China buf = zalloc(cur_blksz);
9094ee50ec3Sbo zhou - Sun Microsystems - Beijing China if (scsi_rdwr(DIR_READ, fd, (diskaddr_t)0, 1, (caddr_t)buf,
9104ee50ec3Sbo zhou - Sun Microsystems - Beijing China F_SILENT, NULL)) {
9114ee50ec3Sbo zhou - Sun Microsystems - Beijing China free(buf);
912b63e7ecbSAbhinandan Ekande return ((struct disk_type *)NULL);
9134ee50ec3Sbo zhou - Sun Microsystems - Beijing China }
9144ee50ec3Sbo zhou - Sun Microsystems - Beijing China free(buf);
915b63e7ecbSAbhinandan Ekande
9167c478bd9Sstevel@tonic-gate /*
9177c478bd9Sstevel@tonic-gate * Figure out which method we use for auto sense.
9187c478bd9Sstevel@tonic-gate * If a particular method fails, we fall back to
9197c478bd9Sstevel@tonic-gate * the next possibility.
9207c478bd9Sstevel@tonic-gate */
9217c478bd9Sstevel@tonic-gate
9227c478bd9Sstevel@tonic-gate if (force_generic) {
9237c478bd9Sstevel@tonic-gate return (generic_disk_sense(fd, can_prompt, label,
9247c478bd9Sstevel@tonic-gate &inquiry, &capacity, disk_name));
9257c478bd9Sstevel@tonic-gate }
9267c478bd9Sstevel@tonic-gate
9277c478bd9Sstevel@tonic-gate /*
9287c478bd9Sstevel@tonic-gate * Try for an existing format.dat first
9297c478bd9Sstevel@tonic-gate */
9307c478bd9Sstevel@tonic-gate if ((disk_type = find_scsi_disk_by_name(disk_name)) != NULL) {
9317c478bd9Sstevel@tonic-gate if (use_existing_disk_type(fd, can_prompt, label,
9327c478bd9Sstevel@tonic-gate &inquiry, disk_type, &capacity)) {
9337c478bd9Sstevel@tonic-gate return (disk_type);
9347c478bd9Sstevel@tonic-gate }
9357c478bd9Sstevel@tonic-gate if (force_format_dat) {
9367c478bd9Sstevel@tonic-gate return (NULL);
9377c478bd9Sstevel@tonic-gate }
9387c478bd9Sstevel@tonic-gate }
9397c478bd9Sstevel@tonic-gate
9407c478bd9Sstevel@tonic-gate /*
9417c478bd9Sstevel@tonic-gate * Otherwise, try using generic SCSI-2 sense and inquiry.
9427c478bd9Sstevel@tonic-gate */
9437c478bd9Sstevel@tonic-gate
9447c478bd9Sstevel@tonic-gate return (generic_disk_sense(fd, can_prompt, label,
9457c478bd9Sstevel@tonic-gate &inquiry, &capacity, disk_name));
9467c478bd9Sstevel@tonic-gate }
9477c478bd9Sstevel@tonic-gate
9487c478bd9Sstevel@tonic-gate
9497c478bd9Sstevel@tonic-gate
9507c478bd9Sstevel@tonic-gate /*ARGSUSED*/
9517c478bd9Sstevel@tonic-gate 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)9527c478bd9Sstevel@tonic-gate generic_disk_sense(
9537c478bd9Sstevel@tonic-gate int fd,
9547c478bd9Sstevel@tonic-gate int can_prompt,
9557c478bd9Sstevel@tonic-gate struct dk_label *label,
9567c478bd9Sstevel@tonic-gate struct scsi_inquiry *inquiry,
9577c478bd9Sstevel@tonic-gate struct scsi_capacity_16 *capacity,
9587c478bd9Sstevel@tonic-gate char *disk_name)
9597c478bd9Sstevel@tonic-gate {
9607c478bd9Sstevel@tonic-gate struct disk_type *disk;
961bc067c09Sqd208687 int setdefault = 0;
962342440ecSPrasad Singamsetty uint_t pcyl = 0;
963342440ecSPrasad Singamsetty uint_t ncyl = 0;
964342440ecSPrasad Singamsetty uint_t acyl = 0;
965342440ecSPrasad Singamsetty uint_t nhead = 0;
966342440ecSPrasad Singamsetty uint_t nsect = 0;
967bc067c09Sqd208687 int rpm = 0;
968342440ecSPrasad Singamsetty diskaddr_t nblocks = 0;
969342440ecSPrasad Singamsetty diskaddr_t tblocks = 0;
9707c478bd9Sstevel@tonic-gate union {
9717c478bd9Sstevel@tonic-gate struct mode_format page3;
9727c478bd9Sstevel@tonic-gate uchar_t buf3[MAX_MODE_SENSE_SIZE];
9737c478bd9Sstevel@tonic-gate } u_page3;
9747c478bd9Sstevel@tonic-gate union {
9757c478bd9Sstevel@tonic-gate struct mode_geometry page4;
9767c478bd9Sstevel@tonic-gate uchar_t buf4[MAX_MODE_SENSE_SIZE];
9777c478bd9Sstevel@tonic-gate } u_page4;
9787c478bd9Sstevel@tonic-gate struct mode_format *page3 = &u_page3.page3;
9797c478bd9Sstevel@tonic-gate struct mode_geometry *page4 = &u_page4.page4;
9807c478bd9Sstevel@tonic-gate struct scsi_ms_header header;
9817c478bd9Sstevel@tonic-gate
9827c478bd9Sstevel@tonic-gate /*
9837c478bd9Sstevel@tonic-gate * If the name of this disk appears to be "SUN", use it,
9847c478bd9Sstevel@tonic-gate * otherwise construct a name out of the generic
9857c478bd9Sstevel@tonic-gate * Inquiry info. If it turns out that we already
9867c478bd9Sstevel@tonic-gate * have a SUN disk type of this name that differs
9877c478bd9Sstevel@tonic-gate * in geometry, we will revert to the generic name
9887c478bd9Sstevel@tonic-gate * anyway.
9897c478bd9Sstevel@tonic-gate */
9907c478bd9Sstevel@tonic-gate if (memcmp(disk_name, "SUN", strlen("SUN")) != 0) {
9917c478bd9Sstevel@tonic-gate (void) get_generic_disk_name(disk_name, inquiry);
9927c478bd9Sstevel@tonic-gate }
9937c478bd9Sstevel@tonic-gate
9947c478bd9Sstevel@tonic-gate /*
995bc067c09Sqd208687 * Get the number of blocks from Read Capacity data. Note that
996bc067c09Sqd208687 * the logical block address range from 0 to capacity->sc_capacity.
997342440ecSPrasad Singamsetty * Limit the size to 2 TB (UINT32_MAX) to use with SMI labels.
998bc067c09Sqd208687 */
999342440ecSPrasad Singamsetty tblocks = (capacity->sc_capacity + 1);
1000342440ecSPrasad Singamsetty if (tblocks > UINT32_MAX)
1001342440ecSPrasad Singamsetty nblocks = UINT32_MAX;
1002342440ecSPrasad Singamsetty else
1003342440ecSPrasad Singamsetty nblocks = tblocks;
1004bc067c09Sqd208687
1005bc067c09Sqd208687 /*
10067c478bd9Sstevel@tonic-gate * Get current Page 3 - Format Parameters page
10077c478bd9Sstevel@tonic-gate */
10087c478bd9Sstevel@tonic-gate if (uscsi_mode_sense(fd, DAD_MODE_FORMAT, MODE_SENSE_PC_CURRENT,
10097c478bd9Sstevel@tonic-gate (caddr_t)&u_page3, MAX_MODE_SENSE_SIZE, &header)) {
1010bc067c09Sqd208687 setdefault = 1;
10117c478bd9Sstevel@tonic-gate }
10127c478bd9Sstevel@tonic-gate
10137c478bd9Sstevel@tonic-gate /*
10147c478bd9Sstevel@tonic-gate * Get current Page 4 - Drive Geometry page
10157c478bd9Sstevel@tonic-gate */
10167c478bd9Sstevel@tonic-gate if (uscsi_mode_sense(fd, DAD_MODE_GEOMETRY, MODE_SENSE_PC_CURRENT,
10177c478bd9Sstevel@tonic-gate (caddr_t)&u_page4, MAX_MODE_SENSE_SIZE, &header)) {
1018bc067c09Sqd208687 setdefault = 1;
10197c478bd9Sstevel@tonic-gate }
10207c478bd9Sstevel@tonic-gate
1021bc067c09Sqd208687 if (setdefault != 1) {
1022bc067c09Sqd208687 /* The inquiry of mode page 3 & page 4 are successful */
10237c478bd9Sstevel@tonic-gate /*
10247c478bd9Sstevel@tonic-gate * Correct for byte order if necessary
10257c478bd9Sstevel@tonic-gate */
10267c478bd9Sstevel@tonic-gate page4->rpm = BE_16(page4->rpm);
10277c478bd9Sstevel@tonic-gate page4->step_rate = BE_16(page4->step_rate);
10287c478bd9Sstevel@tonic-gate page3->tracks_per_zone = BE_16(page3->tracks_per_zone);
10297c478bd9Sstevel@tonic-gate page3->alt_sect_zone = BE_16(page3->alt_sect_zone);
10307c478bd9Sstevel@tonic-gate page3->alt_tracks_zone = BE_16(page3->alt_tracks_zone);
10317c478bd9Sstevel@tonic-gate page3->alt_tracks_vol = BE_16(page3->alt_tracks_vol);
10327c478bd9Sstevel@tonic-gate page3->sect_track = BE_16(page3->sect_track);
10337c478bd9Sstevel@tonic-gate page3->data_bytes_sect = BE_16(page3->data_bytes_sect);
10347c478bd9Sstevel@tonic-gate page3->interleave = BE_16(page3->interleave);
10357c478bd9Sstevel@tonic-gate page3->track_skew = BE_16(page3->track_skew);
10367c478bd9Sstevel@tonic-gate page3->cylinder_skew = BE_16(page3->cylinder_skew);
10377c478bd9Sstevel@tonic-gate
10387c478bd9Sstevel@tonic-gate
10397c478bd9Sstevel@tonic-gate /*
10407c478bd9Sstevel@tonic-gate * Construct a new label out of the sense data,
10417c478bd9Sstevel@tonic-gate * Inquiry and Capacity.
1042342440ecSPrasad Singamsetty *
1043342440ecSPrasad Singamsetty * If the disk capacity is > 1TB then simply compute
1044342440ecSPrasad Singamsetty * the CHS values based on the total disk capacity and
1045342440ecSPrasad Singamsetty * not use the values from mode-sense data.
10467c478bd9Sstevel@tonic-gate */
1047342440ecSPrasad Singamsetty if (tblocks > INT32_MAX) {
1048342440ecSPrasad Singamsetty compute_chs_values(tblocks, nblocks, &pcyl, &nhead,
1049342440ecSPrasad Singamsetty &nsect);
1050342440ecSPrasad Singamsetty } else {
105156507910Sqd208687 pcyl = (page4->cyl_ub << 16) + (page4->cyl_mb << 8) +
105256507910Sqd208687 page4->cyl_lb;
10537c478bd9Sstevel@tonic-gate nhead = page4->heads;
10547c478bd9Sstevel@tonic-gate nsect = page3->sect_track;
1055342440ecSPrasad Singamsetty }
1056342440ecSPrasad Singamsetty
10577c478bd9Sstevel@tonic-gate rpm = page4->rpm;
10587c478bd9Sstevel@tonic-gate
10597c478bd9Sstevel@tonic-gate /*
10607c478bd9Sstevel@tonic-gate * If the number of physical cylinders reported is less
10617c478bd9Sstevel@tonic-gate * the SUN_MIN_CYL(3) then try to adjust the geometry so that
10627c478bd9Sstevel@tonic-gate * we have atleast SUN_MIN_CYL cylinders.
10637c478bd9Sstevel@tonic-gate */
10647c478bd9Sstevel@tonic-gate if (pcyl < SUN_MIN_CYL) {
1065342440ecSPrasad Singamsetty if (nhead == 0 || nsect == 0) {
1066bc067c09Sqd208687 setdefault = 1;
106756507910Sqd208687 } else if (adjust_disk_geometry(
1068342440ecSPrasad Singamsetty (diskaddr_t)(capacity->sc_capacity + 1),
10697c478bd9Sstevel@tonic-gate &pcyl, &nhead, &nsect)) {
1070bc067c09Sqd208687 setdefault = 1;
1071bc067c09Sqd208687 }
1072bc067c09Sqd208687 }
1073bc067c09Sqd208687 }
1074bc067c09Sqd208687
107565908c77Syu, larry liu - Sun Microsystems - Beijing China /*
107665908c77Syu, larry liu - Sun Microsystems - Beijing China * Mode sense page 3 and page 4 are obsolete in SCSI-3. For
107765908c77Syu, larry liu - Sun Microsystems - Beijing China * newly developed large sector size disk, we will not rely on
107865908c77Syu, larry liu - Sun Microsystems - Beijing China * those two pages but compute geometry directly.
107965908c77Syu, larry liu - Sun Microsystems - Beijing China */
108065908c77Syu, larry liu - Sun Microsystems - Beijing China if ((setdefault == 1) || (capacity->sc_lbasize != DEV_BSIZE)) {
1081bc067c09Sqd208687 /*
1082bc067c09Sqd208687 * If the number of cylinders or the number of heads reported
1083bc067c09Sqd208687 * is zero, we think the inquiry of page 3 and page 4 failed.
1084bc067c09Sqd208687 * We will set the geometry infomation by ourselves.
1085bc067c09Sqd208687 */
1086342440ecSPrasad Singamsetty compute_chs_values(tblocks, nblocks, &pcyl, &nhead, &nsect);
10877c478bd9Sstevel@tonic-gate }
10887c478bd9Sstevel@tonic-gate
10897c478bd9Sstevel@tonic-gate /*
10907c478bd9Sstevel@tonic-gate * The sd driver reserves 2 cylinders the backup disk label and
10917c478bd9Sstevel@tonic-gate * the deviceid. Set the number of data cylinders to pcyl-acyl.
10927c478bd9Sstevel@tonic-gate */
10937c478bd9Sstevel@tonic-gate acyl = DK_ACYL;
10947c478bd9Sstevel@tonic-gate ncyl = pcyl - acyl;
10957c478bd9Sstevel@tonic-gate
10967c478bd9Sstevel@tonic-gate if (option_msg && diag_msg) {
10977c478bd9Sstevel@tonic-gate err_print("Geometry:\n");
1098342440ecSPrasad Singamsetty err_print(" pcyl: %u\n", pcyl);
1099342440ecSPrasad Singamsetty err_print(" ncyl: %u\n", ncyl);
1100342440ecSPrasad Singamsetty err_print(" heads: %u\n", nhead);
1101342440ecSPrasad Singamsetty err_print(" nsects: %u\n", nsect);
1102342440ecSPrasad Singamsetty err_print(" acyl: %u\n", acyl);
11037c478bd9Sstevel@tonic-gate
11047c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_16)
1105342440ecSPrasad Singamsetty err_print(" bcyl: %u\n", bcyl);
11067c478bd9Sstevel@tonic-gate #endif /* defined(_SUNOS_VTOC_16) */
11077c478bd9Sstevel@tonic-gate
11087c478bd9Sstevel@tonic-gate err_print(" rpm: %d\n", rpm);
1109342440ecSPrasad Singamsetty err_print(" nblocks: %llu\n", nblocks);
11107c478bd9Sstevel@tonic-gate }
11117c478bd9Sstevel@tonic-gate
11127c478bd9Sstevel@tonic-gate /*
1113bc067c09Sqd208687 * Some drives do not support page4 or report 0 for page4->rpm,
1114bc067c09Sqd208687 * adjust it to AVG_RPM, 3600.
11157c478bd9Sstevel@tonic-gate */
11167c478bd9Sstevel@tonic-gate if (rpm < MIN_RPM || rpm > MAX_RPM) {
1117b63e7ecbSAbhinandan Ekande if (option_msg && diag_msg)
1118bc067c09Sqd208687 err_print("The current rpm value %d is invalid,"
11197c478bd9Sstevel@tonic-gate " adjusting it to %d\n", rpm, AVG_RPM);
11207c478bd9Sstevel@tonic-gate rpm = AVG_RPM;
11217c478bd9Sstevel@tonic-gate }
11227c478bd9Sstevel@tonic-gate
11237c478bd9Sstevel@tonic-gate /*
11247c478bd9Sstevel@tonic-gate * Some drives report 0 for nsect (page 3, byte 10 and 11) if they
11257c478bd9Sstevel@tonic-gate * have variable number of sectors per track. So adjust nsect.
11267c478bd9Sstevel@tonic-gate * Also the value is defined as vendor specific, hence check if
11277c478bd9Sstevel@tonic-gate * it is in a tolerable range. The values (32 and 4 below) are
11287c478bd9Sstevel@tonic-gate * chosen so that this change below does not generate a different
11297c478bd9Sstevel@tonic-gate * geometry for currently supported sun disks.
11307c478bd9Sstevel@tonic-gate */
1131342440ecSPrasad Singamsetty if ((nsect == 0) ||
1132342440ecSPrasad Singamsetty ((diskaddr_t)pcyl * nhead * nsect) < (nblocks - nblocks/32) ||
1133342440ecSPrasad Singamsetty ((diskaddr_t)pcyl * nhead * nsect) > (nblocks + nblocks/4)) {
1134342440ecSPrasad Singamsetty if (nblocks > (pcyl * nhead)) {
1135342440ecSPrasad Singamsetty err_print("Mode sense page(3) reports nsect value"
1136342440ecSPrasad Singamsetty " as %d, adjusting it to %llu\n",
1137342440ecSPrasad Singamsetty nsect, nblocks / (pcyl * nhead));
11387c478bd9Sstevel@tonic-gate nsect = nblocks / (pcyl * nhead);
1139342440ecSPrasad Singamsetty } else {
1140342440ecSPrasad Singamsetty /* convert capacity to nsect * nhead * pcyl */
1141342440ecSPrasad Singamsetty err_print("\nWARNING: Disk geometry is based on "
1142342440ecSPrasad Singamsetty "capacity data.\n\n");
1143342440ecSPrasad Singamsetty compute_chs_values(tblocks, nblocks, &pcyl, &nhead,
1144342440ecSPrasad Singamsetty &nsect);
1145342440ecSPrasad Singamsetty ncyl = pcyl - acyl;
1146342440ecSPrasad Singamsetty if (option_msg && diag_msg) {
1147342440ecSPrasad Singamsetty err_print("Geometry:(after adjustment)\n");
1148342440ecSPrasad Singamsetty err_print(" pcyl: %u\n", pcyl);
1149342440ecSPrasad Singamsetty err_print(" ncyl: %u\n", ncyl);
1150342440ecSPrasad Singamsetty err_print(" heads: %u\n", nhead);
1151342440ecSPrasad Singamsetty err_print(" nsects: %u\n", nsect);
1152342440ecSPrasad Singamsetty err_print(" acyl: %u\n", acyl);
1153342440ecSPrasad Singamsetty
1154342440ecSPrasad Singamsetty #if defined(_SUNOS_VTOC_16)
1155342440ecSPrasad Singamsetty err_print(" bcyl: %u\n", bcyl);
1156342440ecSPrasad Singamsetty #endif
1157342440ecSPrasad Singamsetty
1158342440ecSPrasad Singamsetty err_print(" rpm: %d\n", rpm);
1159342440ecSPrasad Singamsetty err_print(" nblocks: %llu\n", nblocks);
1160342440ecSPrasad Singamsetty }
1161342440ecSPrasad Singamsetty }
11627c478bd9Sstevel@tonic-gate }
11637c478bd9Sstevel@tonic-gate
11647c478bd9Sstevel@tonic-gate /*
11657c478bd9Sstevel@tonic-gate * Some drives report their physical geometry such that
11667c478bd9Sstevel@tonic-gate * it is greater than the actual capacity. Adjust the
11677c478bd9Sstevel@tonic-gate * geometry to allow for this, so we don't run off
11687c478bd9Sstevel@tonic-gate * the end of the disk.
11697c478bd9Sstevel@tonic-gate */
1170342440ecSPrasad Singamsetty if (((diskaddr_t)pcyl * nhead * nsect) > nblocks) {
1171342440ecSPrasad Singamsetty uint_t p = pcyl;
11727c478bd9Sstevel@tonic-gate if (option_msg && diag_msg) {
1173342440ecSPrasad Singamsetty err_print("Computed capacity (%llu) exceeds actual "
1174342440ecSPrasad Singamsetty "disk capacity (%llu)\n",
1175342440ecSPrasad Singamsetty (diskaddr_t)pcyl * nhead * nsect, nblocks);
11767c478bd9Sstevel@tonic-gate }
11777c478bd9Sstevel@tonic-gate do {
11787c478bd9Sstevel@tonic-gate pcyl--;
1179342440ecSPrasad Singamsetty } while (((diskaddr_t)pcyl * nhead * nsect) > nblocks);
11807c478bd9Sstevel@tonic-gate
11817c478bd9Sstevel@tonic-gate if (can_prompt && expert_mode && !option_f) {
11827c478bd9Sstevel@tonic-gate /*
11837c478bd9Sstevel@tonic-gate * Try to adjust nsect instead of pcyl to see if we
11847c478bd9Sstevel@tonic-gate * can optimize. For compatability reasons do this
11857c478bd9Sstevel@tonic-gate * only in expert mode (refer to bug 1144812).
11867c478bd9Sstevel@tonic-gate */
1187342440ecSPrasad Singamsetty uint_t n = nsect;
11887c478bd9Sstevel@tonic-gate do {
11897c478bd9Sstevel@tonic-gate n--;
1190342440ecSPrasad Singamsetty } while (((diskaddr_t)p * nhead * n) > nblocks);
1191342440ecSPrasad Singamsetty if (((diskaddr_t)p * nhead * n) >
1192342440ecSPrasad Singamsetty ((diskaddr_t)pcyl * nhead * nsect)) {
11937c478bd9Sstevel@tonic-gate u_ioparam_t ioparam;
11947c478bd9Sstevel@tonic-gate int deflt = 1;
11957c478bd9Sstevel@tonic-gate /*
11967c478bd9Sstevel@tonic-gate * Ask the user for a choice here.
11977c478bd9Sstevel@tonic-gate */
11987c478bd9Sstevel@tonic-gate ioparam.io_bounds.lower = 1;
11997c478bd9Sstevel@tonic-gate ioparam.io_bounds.upper = 2;
1200342440ecSPrasad Singamsetty err_print("1. Capacity = %llu, with pcyl = %u "
1201342440ecSPrasad Singamsetty "nhead = %u nsect = %u\n",
1202342440ecSPrasad Singamsetty ((diskaddr_t)pcyl * nhead * nsect),
12037c478bd9Sstevel@tonic-gate pcyl, nhead, nsect);
1204342440ecSPrasad Singamsetty err_print("2. Capacity = %llu, with pcyl = %u "
1205342440ecSPrasad Singamsetty "nhead = %u nsect = %u\n",
1206342440ecSPrasad Singamsetty ((diskaddr_t)p * nhead * n),
12077c478bd9Sstevel@tonic-gate p, nhead, n);
12087c478bd9Sstevel@tonic-gate if (input(FIO_INT, "Select one of the above "
12097c478bd9Sstevel@tonic-gate "choices ", ':', &ioparam,
12107c478bd9Sstevel@tonic-gate &deflt, DATA_INPUT) == 2) {
12117c478bd9Sstevel@tonic-gate pcyl = p;
12127c478bd9Sstevel@tonic-gate nsect = n;
12137c478bd9Sstevel@tonic-gate }
12147c478bd9Sstevel@tonic-gate }
12157c478bd9Sstevel@tonic-gate }
12167c478bd9Sstevel@tonic-gate }
12177c478bd9Sstevel@tonic-gate
12187c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
12197c478bd9Sstevel@tonic-gate /*
12207c478bd9Sstevel@tonic-gate * Finally, we need to make sure we don't overflow any of the
12217c478bd9Sstevel@tonic-gate * fields in our disk label. To do this we need to `square
12227c478bd9Sstevel@tonic-gate * the box' so to speak. We will lose bits here.
12237c478bd9Sstevel@tonic-gate */
12247c478bd9Sstevel@tonic-gate
12257c478bd9Sstevel@tonic-gate if ((pcyl > MAXIMUM_NO_CYLINDERS &&
12267c478bd9Sstevel@tonic-gate ((nsect > MAXIMUM_NO_SECTORS) ||
12277c478bd9Sstevel@tonic-gate (nhead > MAXIMUM_NO_HEADS))) ||
12287c478bd9Sstevel@tonic-gate ((nsect > MAXIMUM_NO_SECTORS) &&
12297c478bd9Sstevel@tonic-gate (nhead > MAXIMUM_NO_HEADS))) {
12307c478bd9Sstevel@tonic-gate err_print("This disk is too big to label. "
12317c478bd9Sstevel@tonic-gate " You will lose some blocks.\n");
12327c478bd9Sstevel@tonic-gate }
12337c478bd9Sstevel@tonic-gate if ((pcyl > MAXIMUM_NO_CYLINDERS) ||
12347c478bd9Sstevel@tonic-gate (nsect > MAXIMUM_NO_SECTORS) ||
12357c478bd9Sstevel@tonic-gate (nhead > MAXIMUM_NO_HEADS)) {
12367c478bd9Sstevel@tonic-gate u_ioparam_t ioparam;
12377c478bd9Sstevel@tonic-gate int order;
12387c478bd9Sstevel@tonic-gate char msg[256];
12397c478bd9Sstevel@tonic-gate
1240d2a20373Sbz211116 order = ((pcyl > nhead)<<2) |
1241d2a20373Sbz211116 ((pcyl > nsect)<<1) |
12427c478bd9Sstevel@tonic-gate (nhead > nsect);
12437c478bd9Sstevel@tonic-gate switch (order) {
1244d2a20373Sbz211116 case 0x7: /* pcyl > nhead > nsect */
12457c478bd9Sstevel@tonic-gate nblocks =
12467c478bd9Sstevel@tonic-gate square_box(nblocks,
12477c478bd9Sstevel@tonic-gate &pcyl, MAXIMUM_NO_CYLINDERS,
12487c478bd9Sstevel@tonic-gate &nhead, MAXIMUM_NO_HEADS,
12497c478bd9Sstevel@tonic-gate &nsect, MAXIMUM_NO_SECTORS);
12507c478bd9Sstevel@tonic-gate break;
1251d2a20373Sbz211116 case 0x6: /* pcyl > nsect > nhead */
12527c478bd9Sstevel@tonic-gate nblocks =
12537c478bd9Sstevel@tonic-gate square_box(nblocks,
12547c478bd9Sstevel@tonic-gate &pcyl, MAXIMUM_NO_CYLINDERS,
12557c478bd9Sstevel@tonic-gate &nsect, MAXIMUM_NO_SECTORS,
12567c478bd9Sstevel@tonic-gate &nhead, MAXIMUM_NO_HEADS);
12577c478bd9Sstevel@tonic-gate break;
1258d2a20373Sbz211116 case 0x4: /* nsect > pcyl > nhead */
12597c478bd9Sstevel@tonic-gate nblocks =
12607c478bd9Sstevel@tonic-gate square_box(nblocks,
12617c478bd9Sstevel@tonic-gate &nsect, MAXIMUM_NO_SECTORS,
12627c478bd9Sstevel@tonic-gate &pcyl, MAXIMUM_NO_CYLINDERS,
12637c478bd9Sstevel@tonic-gate &nhead, MAXIMUM_NO_HEADS);
12647c478bd9Sstevel@tonic-gate break;
1265d2a20373Sbz211116 case 0x0: /* nsect > nhead > pcyl */
12667c478bd9Sstevel@tonic-gate nblocks =
12677c478bd9Sstevel@tonic-gate square_box(nblocks,
12687c478bd9Sstevel@tonic-gate &nsect, MAXIMUM_NO_SECTORS,
12697c478bd9Sstevel@tonic-gate &nhead, MAXIMUM_NO_HEADS,
12707c478bd9Sstevel@tonic-gate &pcyl, MAXIMUM_NO_CYLINDERS);
12717c478bd9Sstevel@tonic-gate break;
1272d2a20373Sbz211116 case 0x3: /* nhead > pcyl > nsect */
12737c478bd9Sstevel@tonic-gate nblocks =
12747c478bd9Sstevel@tonic-gate square_box(nblocks,
12757c478bd9Sstevel@tonic-gate &nhead, MAXIMUM_NO_HEADS,
12767c478bd9Sstevel@tonic-gate &pcyl, MAXIMUM_NO_CYLINDERS,
12777c478bd9Sstevel@tonic-gate &nsect, MAXIMUM_NO_SECTORS);
12787c478bd9Sstevel@tonic-gate break;
1279d2a20373Sbz211116 case 0x1: /* nhead > nsect > pcyl */
12807c478bd9Sstevel@tonic-gate nblocks =
12817c478bd9Sstevel@tonic-gate square_box(nblocks,
12827c478bd9Sstevel@tonic-gate &nhead, MAXIMUM_NO_HEADS,
12837c478bd9Sstevel@tonic-gate &nsect, MAXIMUM_NO_SECTORS,
12847c478bd9Sstevel@tonic-gate &pcyl, MAXIMUM_NO_CYLINDERS);
12857c478bd9Sstevel@tonic-gate break;
12867c478bd9Sstevel@tonic-gate default:
12877c478bd9Sstevel@tonic-gate /* How did we get here? */
12887c478bd9Sstevel@tonic-gate impossible("label overflow adjustment");
12897c478bd9Sstevel@tonic-gate
12907c478bd9Sstevel@tonic-gate /* Do something useful */
12917c478bd9Sstevel@tonic-gate nblocks =
12927c478bd9Sstevel@tonic-gate square_box(nblocks,
12937c478bd9Sstevel@tonic-gate &nhead, MAXIMUM_NO_HEADS,
12947c478bd9Sstevel@tonic-gate &nsect, MAXIMUM_NO_SECTORS,
12957c478bd9Sstevel@tonic-gate &pcyl, MAXIMUM_NO_CYLINDERS);
12967c478bd9Sstevel@tonic-gate break;
12977c478bd9Sstevel@tonic-gate }
12987c478bd9Sstevel@tonic-gate if (option_msg && diag_msg &&
12997c478bd9Sstevel@tonic-gate (capacity->sc_capacity + 1 != nblocks)) {
13007c478bd9Sstevel@tonic-gate err_print("After adjusting geometry you lost"
1301342440ecSPrasad Singamsetty " %llu of %llu blocks.\n",
13027c478bd9Sstevel@tonic-gate (capacity->sc_capacity + 1 - nblocks),
13037c478bd9Sstevel@tonic-gate capacity->sc_capacity + 1);
13047c478bd9Sstevel@tonic-gate }
13057c478bd9Sstevel@tonic-gate while (can_prompt && expert_mode && !option_f) {
13067c478bd9Sstevel@tonic-gate int deflt = 1;
13077c478bd9Sstevel@tonic-gate
13087c478bd9Sstevel@tonic-gate /*
13097c478bd9Sstevel@tonic-gate * Allow user to modify this by hand if desired.
13107c478bd9Sstevel@tonic-gate */
13117c478bd9Sstevel@tonic-gate (void) sprintf(msg,
1312342440ecSPrasad Singamsetty "\nGeometry: %u heads, %u sectors %u cylinders"
1313342440ecSPrasad Singamsetty " result in %llu out of %llu blocks.\n"
13147c478bd9Sstevel@tonic-gate "Do you want to modify the device geometry",
13157c478bd9Sstevel@tonic-gate nhead, nsect, pcyl,
1316342440ecSPrasad Singamsetty nblocks, capacity->sc_capacity + 1);
13177c478bd9Sstevel@tonic-gate
13187c478bd9Sstevel@tonic-gate ioparam.io_charlist = confirm_list;
13197c478bd9Sstevel@tonic-gate if (input(FIO_MSTR, msg, '?', &ioparam,
13207c478bd9Sstevel@tonic-gate &deflt, DATA_INPUT) != 0)
13217c478bd9Sstevel@tonic-gate break;
13227c478bd9Sstevel@tonic-gate
13237c478bd9Sstevel@tonic-gate ioparam.io_bounds.lower = MINIMUM_NO_HEADS;
13247c478bd9Sstevel@tonic-gate ioparam.io_bounds.upper = MAXIMUM_NO_HEADS;
13257c478bd9Sstevel@tonic-gate nhead = input(FIO_INT, "Number of heads", ':',
1326342440ecSPrasad Singamsetty &ioparam, (int *)&nhead, DATA_INPUT);
13277c478bd9Sstevel@tonic-gate ioparam.io_bounds.lower = MINIMUM_NO_SECTORS;
13287c478bd9Sstevel@tonic-gate ioparam.io_bounds.upper = MAXIMUM_NO_SECTORS;
13297c478bd9Sstevel@tonic-gate nsect = input(FIO_INT,
13307c478bd9Sstevel@tonic-gate "Number of sectors per track",
1331342440ecSPrasad Singamsetty ':', &ioparam, (int *)&nsect, DATA_INPUT);
13327c478bd9Sstevel@tonic-gate ioparam.io_bounds.lower = SUN_MIN_CYL;
13337c478bd9Sstevel@tonic-gate ioparam.io_bounds.upper = MAXIMUM_NO_CYLINDERS;
13347c478bd9Sstevel@tonic-gate pcyl = input(FIO_INT, "Number of cylinders",
1335342440ecSPrasad Singamsetty ':', &ioparam, (int *)&pcyl, DATA_INPUT);
1336342440ecSPrasad Singamsetty nblocks = (diskaddr_t)nhead * nsect * pcyl;
13377c478bd9Sstevel@tonic-gate if (nblocks > capacity->sc_capacity + 1) {
1338342440ecSPrasad Singamsetty err_print("Warning: %llu blocks exceeds "
1339342440ecSPrasad Singamsetty "disk capacity of %llu blocks\n",
13407c478bd9Sstevel@tonic-gate nblocks,
13417c478bd9Sstevel@tonic-gate capacity->sc_capacity + 1);
13427c478bd9Sstevel@tonic-gate }
13437c478bd9Sstevel@tonic-gate }
13447c478bd9Sstevel@tonic-gate }
13457c478bd9Sstevel@tonic-gate #endif /* defined(_SUNOS_VTOC_8) */
13467c478bd9Sstevel@tonic-gate
13477c478bd9Sstevel@tonic-gate ncyl = pcyl - acyl;
13487c478bd9Sstevel@tonic-gate
13497c478bd9Sstevel@tonic-gate if (option_msg && diag_msg) {
13507c478bd9Sstevel@tonic-gate err_print("\nGeometry after adjusting for capacity:\n");
1351342440ecSPrasad Singamsetty err_print(" pcyl: %u\n", pcyl);
1352342440ecSPrasad Singamsetty err_print(" ncyl: %u\n", ncyl);
1353342440ecSPrasad Singamsetty err_print(" heads: %u\n", nhead);
1354342440ecSPrasad Singamsetty err_print(" nsects: %u\n", nsect);
1355342440ecSPrasad Singamsetty err_print(" acyl: %u\n", acyl);
13567c478bd9Sstevel@tonic-gate err_print(" rpm: %d\n", rpm);
13577c478bd9Sstevel@tonic-gate }
13587c478bd9Sstevel@tonic-gate
13597c478bd9Sstevel@tonic-gate (void) memset((char *)label, 0, sizeof (struct dk_label));
13607c478bd9Sstevel@tonic-gate
13617c478bd9Sstevel@tonic-gate label->dkl_magic = DKL_MAGIC;
13627c478bd9Sstevel@tonic-gate
13637c478bd9Sstevel@tonic-gate (void) snprintf(label->dkl_asciilabel, sizeof (label->dkl_asciilabel),
1364342440ecSPrasad Singamsetty "%s cyl %u alt %u hd %u sec %u",
13657c478bd9Sstevel@tonic-gate disk_name, ncyl, acyl, nhead, nsect);
13667c478bd9Sstevel@tonic-gate
13677c478bd9Sstevel@tonic-gate label->dkl_pcyl = pcyl;
13687c478bd9Sstevel@tonic-gate label->dkl_ncyl = ncyl;
13697c478bd9Sstevel@tonic-gate label->dkl_acyl = acyl;
13707c478bd9Sstevel@tonic-gate label->dkl_nhead = nhead;
13717c478bd9Sstevel@tonic-gate label->dkl_nsect = nsect;
13727c478bd9Sstevel@tonic-gate label->dkl_apc = 0;
13737c478bd9Sstevel@tonic-gate label->dkl_intrlv = 1;
13747c478bd9Sstevel@tonic-gate label->dkl_rpm = rpm;
13757c478bd9Sstevel@tonic-gate
13767c478bd9Sstevel@tonic-gate #if defined(_FIRMWARE_NEEDS_FDISK)
1377342440ecSPrasad Singamsetty if (auto_solaris_part(label) == -1)
1378342440ecSPrasad Singamsetty goto err;
13797c478bd9Sstevel@tonic-gate ncyl = label->dkl_ncyl;
13807c478bd9Sstevel@tonic-gate #endif /* defined(_FIRMWARE_NEEDS_FDISK) */
13817c478bd9Sstevel@tonic-gate
13827c478bd9Sstevel@tonic-gate
13837c478bd9Sstevel@tonic-gate if (!build_default_partition(label, DKC_SCSI_CCS)) {
13847c478bd9Sstevel@tonic-gate goto err;
13857c478bd9Sstevel@tonic-gate }
13867c478bd9Sstevel@tonic-gate
13877c478bd9Sstevel@tonic-gate (void) checksum(label, CK_MAKESUM);
13887c478bd9Sstevel@tonic-gate
13897c478bd9Sstevel@tonic-gate /*
13907c478bd9Sstevel@tonic-gate * Find an existing disk type defined for this disk.
13917c478bd9Sstevel@tonic-gate * For this to work, both the name and geometry must
13927c478bd9Sstevel@tonic-gate * match. If there is no such type, but there already
13937c478bd9Sstevel@tonic-gate * is a disk defined with that name, but with a different
13947c478bd9Sstevel@tonic-gate * geometry, construct a new generic disk name out of
13957c478bd9Sstevel@tonic-gate * the inquiry information. Whatever name we're
13967c478bd9Sstevel@tonic-gate * finally using, if there's no such disk type defined,
13977c478bd9Sstevel@tonic-gate * build a new disk definition.
13987c478bd9Sstevel@tonic-gate */
13997c478bd9Sstevel@tonic-gate if ((disk = find_scsi_disk_type(disk_name, label)) == NULL) {
14007c478bd9Sstevel@tonic-gate if (find_scsi_disk_by_name(disk_name) != NULL) {
14017c478bd9Sstevel@tonic-gate char old_name[DISK_NAME_MAX];
14027c478bd9Sstevel@tonic-gate (void) strcpy(old_name, disk_name);
14037c478bd9Sstevel@tonic-gate (void) get_generic_disk_name(disk_name,
14047c478bd9Sstevel@tonic-gate inquiry);
14057c478bd9Sstevel@tonic-gate if (option_msg && diag_msg) {
14067c478bd9Sstevel@tonic-gate err_print(
14077c478bd9Sstevel@tonic-gate "Changing disk type name from '%s' to '%s'\n", old_name, disk_name);
14087c478bd9Sstevel@tonic-gate }
14097c478bd9Sstevel@tonic-gate (void) snprintf(label->dkl_asciilabel,
14107c478bd9Sstevel@tonic-gate sizeof (label->dkl_asciilabel),
1411342440ecSPrasad Singamsetty "%s cyl %u alt %u hd %u sec %u",
14127c478bd9Sstevel@tonic-gate disk_name, ncyl, acyl, nhead, nsect);
14137c478bd9Sstevel@tonic-gate (void) checksum(label, CK_MAKESUM);
14147c478bd9Sstevel@tonic-gate disk = find_scsi_disk_type(disk_name, label);
14157c478bd9Sstevel@tonic-gate }
14167c478bd9Sstevel@tonic-gate if (disk == NULL) {
14177c478bd9Sstevel@tonic-gate disk = new_scsi_disk_type(fd, disk_name, label);
14187c478bd9Sstevel@tonic-gate if (disk == NULL)
14197c478bd9Sstevel@tonic-gate goto err;
14207c478bd9Sstevel@tonic-gate }
14217c478bd9Sstevel@tonic-gate }
14227c478bd9Sstevel@tonic-gate
14237c478bd9Sstevel@tonic-gate return (disk);
14247c478bd9Sstevel@tonic-gate
14257c478bd9Sstevel@tonic-gate err:
14267c478bd9Sstevel@tonic-gate if (option_msg && diag_msg) {
14277c478bd9Sstevel@tonic-gate err_print(
14287c478bd9Sstevel@tonic-gate "Configuration via generic SCSI-2 information failed\n");
14297c478bd9Sstevel@tonic-gate }
14307c478bd9Sstevel@tonic-gate return (NULL);
14317c478bd9Sstevel@tonic-gate }
14327c478bd9Sstevel@tonic-gate
14337c478bd9Sstevel@tonic-gate
14347c478bd9Sstevel@tonic-gate /*ARGSUSED*/
14357c478bd9Sstevel@tonic-gate 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)14367c478bd9Sstevel@tonic-gate use_existing_disk_type(
14377c478bd9Sstevel@tonic-gate int fd,
14387c478bd9Sstevel@tonic-gate int can_prompt,
14397c478bd9Sstevel@tonic-gate struct dk_label *label,
14407c478bd9Sstevel@tonic-gate struct scsi_inquiry *inquiry,
14417c478bd9Sstevel@tonic-gate struct disk_type *disk_type,
14427c478bd9Sstevel@tonic-gate struct scsi_capacity_16 *capacity)
14437c478bd9Sstevel@tonic-gate {
14447c478bd9Sstevel@tonic-gate int pcyl;
14457c478bd9Sstevel@tonic-gate int acyl;
14467c478bd9Sstevel@tonic-gate int nhead;
14477c478bd9Sstevel@tonic-gate int nsect;
14487c478bd9Sstevel@tonic-gate int rpm;
14497c478bd9Sstevel@tonic-gate
14507c478bd9Sstevel@tonic-gate /*
14517c478bd9Sstevel@tonic-gate * Construct a new label out of the format.dat
14527c478bd9Sstevel@tonic-gate */
14537c478bd9Sstevel@tonic-gate pcyl = disk_type->dtype_pcyl;
14547c478bd9Sstevel@tonic-gate acyl = disk_type->dtype_acyl;
14557c478bd9Sstevel@tonic-gate ncyl = disk_type->dtype_ncyl;
14567c478bd9Sstevel@tonic-gate nhead = disk_type->dtype_nhead;
14577c478bd9Sstevel@tonic-gate nsect = disk_type->dtype_nsect;
14587c478bd9Sstevel@tonic-gate rpm = disk_type->dtype_rpm;
14597c478bd9Sstevel@tonic-gate
14607c478bd9Sstevel@tonic-gate if (option_msg && diag_msg) {
14617c478bd9Sstevel@tonic-gate err_print("Format.dat geometry:\n");
1462342440ecSPrasad Singamsetty err_print(" pcyl: %u\n", pcyl);
1463342440ecSPrasad Singamsetty err_print(" heads: %u\n", nhead);
1464342440ecSPrasad Singamsetty err_print(" nsects: %u\n", nsect);
1465342440ecSPrasad Singamsetty err_print(" acyl: %u\n", acyl);
14667c478bd9Sstevel@tonic-gate err_print(" rpm: %d\n", rpm);
14677c478bd9Sstevel@tonic-gate }
14687c478bd9Sstevel@tonic-gate
14697c478bd9Sstevel@tonic-gate (void) memset((char *)label, 0, sizeof (struct dk_label));
14707c478bd9Sstevel@tonic-gate
14717c478bd9Sstevel@tonic-gate label->dkl_magic = DKL_MAGIC;
14727c478bd9Sstevel@tonic-gate
14737c478bd9Sstevel@tonic-gate (void) snprintf(label->dkl_asciilabel, sizeof (label->dkl_asciilabel),
1474342440ecSPrasad Singamsetty "%s cyl %u alt %u hd %u sec %u",
14757c478bd9Sstevel@tonic-gate disk_type->dtype_asciilabel,
14767c478bd9Sstevel@tonic-gate ncyl, acyl, nhead, nsect);
14777c478bd9Sstevel@tonic-gate
14787c478bd9Sstevel@tonic-gate label->dkl_pcyl = pcyl;
14797c478bd9Sstevel@tonic-gate label->dkl_ncyl = ncyl;
14807c478bd9Sstevel@tonic-gate label->dkl_acyl = acyl;
14817c478bd9Sstevel@tonic-gate label->dkl_nhead = nhead;
14827c478bd9Sstevel@tonic-gate label->dkl_nsect = nsect;
14837c478bd9Sstevel@tonic-gate label->dkl_apc = 0;
14847c478bd9Sstevel@tonic-gate label->dkl_intrlv = 1;
14857c478bd9Sstevel@tonic-gate label->dkl_rpm = rpm;
14867c478bd9Sstevel@tonic-gate
14877c478bd9Sstevel@tonic-gate if (!build_default_partition(label, DKC_SCSI_CCS)) {
14887c478bd9Sstevel@tonic-gate goto err;
14897c478bd9Sstevel@tonic-gate }
14907c478bd9Sstevel@tonic-gate
14917c478bd9Sstevel@tonic-gate (void) checksum(label, CK_MAKESUM);
14927c478bd9Sstevel@tonic-gate return (1);
14937c478bd9Sstevel@tonic-gate
14947c478bd9Sstevel@tonic-gate err:
14957c478bd9Sstevel@tonic-gate if (option_msg && diag_msg) {
14967c478bd9Sstevel@tonic-gate err_print(
14977c478bd9Sstevel@tonic-gate "Configuration via format.dat geometry failed\n");
14987c478bd9Sstevel@tonic-gate }
14997c478bd9Sstevel@tonic-gate return (0);
15007c478bd9Sstevel@tonic-gate }
15017c478bd9Sstevel@tonic-gate
15027c478bd9Sstevel@tonic-gate int
build_default_partition(struct dk_label * label,int ctrl_type)15037c478bd9Sstevel@tonic-gate build_default_partition(
15047c478bd9Sstevel@tonic-gate struct dk_label *label,
15057c478bd9Sstevel@tonic-gate int ctrl_type)
15067c478bd9Sstevel@tonic-gate {
15077c478bd9Sstevel@tonic-gate int i;
15087c478bd9Sstevel@tonic-gate int ncyls[NDKMAP];
1509342440ecSPrasad Singamsetty diskaddr_t nblks;
15107c478bd9Sstevel@tonic-gate int cyl;
15117c478bd9Sstevel@tonic-gate struct dk_vtoc *vtoc;
15127c478bd9Sstevel@tonic-gate struct part_table *pt;
15137c478bd9Sstevel@tonic-gate struct default_partitions *dpt;
1514342440ecSPrasad Singamsetty diskaddr_t capacity;
15157c478bd9Sstevel@tonic-gate int freecyls;
15167c478bd9Sstevel@tonic-gate int blks_per_cyl;
15177c478bd9Sstevel@tonic-gate int ncyl;
15187c478bd9Sstevel@tonic-gate
15197c478bd9Sstevel@tonic-gate #ifdef lint
15207c478bd9Sstevel@tonic-gate ctrl_type = ctrl_type;
15217c478bd9Sstevel@tonic-gate #endif
15227c478bd9Sstevel@tonic-gate
15237c478bd9Sstevel@tonic-gate /*
15247c478bd9Sstevel@tonic-gate * Install a default vtoc
15257c478bd9Sstevel@tonic-gate */
15267c478bd9Sstevel@tonic-gate vtoc = &label->dkl_vtoc;
15277c478bd9Sstevel@tonic-gate vtoc->v_version = V_VERSION;
15287c478bd9Sstevel@tonic-gate vtoc->v_nparts = NDKMAP;
15297c478bd9Sstevel@tonic-gate vtoc->v_sanity = VTOC_SANE;
15307c478bd9Sstevel@tonic-gate
15317c478bd9Sstevel@tonic-gate for (i = 0; i < NDKMAP; i++) {
15327c478bd9Sstevel@tonic-gate vtoc->v_part[i].p_tag = default_vtoc_map[i].p_tag;
15337c478bd9Sstevel@tonic-gate vtoc->v_part[i].p_flag = default_vtoc_map[i].p_flag;
15347c478bd9Sstevel@tonic-gate }
15357c478bd9Sstevel@tonic-gate
15367c478bd9Sstevel@tonic-gate /*
15377c478bd9Sstevel@tonic-gate * Find a partition that matches this disk. Capacity
15387c478bd9Sstevel@tonic-gate * is in integral number of megabytes.
15397c478bd9Sstevel@tonic-gate */
1540342440ecSPrasad Singamsetty capacity = ((diskaddr_t)(label->dkl_ncyl) * label->dkl_nhead *
154182bff436Sbo zhou - Sun Microsystems - Beijing China label->dkl_nsect) / (diskaddr_t)((1024 * 1024) / cur_blksz);
15427c478bd9Sstevel@tonic-gate dpt = default_partitions;
15437c478bd9Sstevel@tonic-gate for (i = 0; i < DEFAULT_PARTITION_TABLE_SIZE; i++, dpt++) {
15447c478bd9Sstevel@tonic-gate if (capacity >= dpt->min_capacity &&
15457c478bd9Sstevel@tonic-gate capacity < dpt->max_capacity) {
15467c478bd9Sstevel@tonic-gate break;
15477c478bd9Sstevel@tonic-gate }
15487c478bd9Sstevel@tonic-gate }
15497c478bd9Sstevel@tonic-gate if (i == DEFAULT_PARTITION_TABLE_SIZE) {
15507c478bd9Sstevel@tonic-gate if (option_msg && diag_msg) {
1551342440ecSPrasad Singamsetty err_print("No matching default partition (%llu)\n",
15527c478bd9Sstevel@tonic-gate capacity);
15537c478bd9Sstevel@tonic-gate }
15547c478bd9Sstevel@tonic-gate return (0);
15557c478bd9Sstevel@tonic-gate }
15567c478bd9Sstevel@tonic-gate pt = dpt->part_table;
15577c478bd9Sstevel@tonic-gate
15587c478bd9Sstevel@tonic-gate /*
15597c478bd9Sstevel@tonic-gate * Go through default partition table, finding fixed
15607c478bd9Sstevel@tonic-gate * sized entries.
15617c478bd9Sstevel@tonic-gate */
15627c478bd9Sstevel@tonic-gate freecyls = label->dkl_ncyl;
15637c478bd9Sstevel@tonic-gate blks_per_cyl = label->dkl_nhead * label->dkl_nsect;
15647c478bd9Sstevel@tonic-gate for (i = 0; i < NDKMAP; i++) {
15657c478bd9Sstevel@tonic-gate if (pt->partitions[i] == HOG || pt->partitions[i] == 0) {
15667c478bd9Sstevel@tonic-gate ncyls[i] = 0;
15677c478bd9Sstevel@tonic-gate } else {
15687c478bd9Sstevel@tonic-gate /*
15697c478bd9Sstevel@tonic-gate * Calculate number of cylinders necessary
15707c478bd9Sstevel@tonic-gate * for specified size, rounding up to
15717c478bd9Sstevel@tonic-gate * the next greatest integral number of
15727c478bd9Sstevel@tonic-gate * cylinders. Always give what they
15737c478bd9Sstevel@tonic-gate * asked or more, never less.
15747c478bd9Sstevel@tonic-gate */
157565908c77Syu, larry liu - Sun Microsystems - Beijing China nblks = pt->partitions[i] * ((1024*1024)/cur_blksz);
15767c478bd9Sstevel@tonic-gate nblks += (blks_per_cyl - 1);
15777c478bd9Sstevel@tonic-gate ncyls[i] = nblks / blks_per_cyl;
15787c478bd9Sstevel@tonic-gate freecyls -= ncyls[i];
15797c478bd9Sstevel@tonic-gate }
15807c478bd9Sstevel@tonic-gate }
15817c478bd9Sstevel@tonic-gate
15827c478bd9Sstevel@tonic-gate if (freecyls < 0) {
15837c478bd9Sstevel@tonic-gate if (option_msg && diag_msg) {
15847c478bd9Sstevel@tonic-gate for (i = 0; i < NDKMAP; i++) {
15857c478bd9Sstevel@tonic-gate if (ncyls[i] == 0)
15867c478bd9Sstevel@tonic-gate continue;
1587342440ecSPrasad Singamsetty err_print("Partition %d: %u cyls\n",
15887c478bd9Sstevel@tonic-gate i, ncyls[i]);
15897c478bd9Sstevel@tonic-gate }
15907c478bd9Sstevel@tonic-gate err_print("Free cylinders exhausted (%d)\n",
15917c478bd9Sstevel@tonic-gate freecyls);
15927c478bd9Sstevel@tonic-gate }
15937c478bd9Sstevel@tonic-gate return (0);
15947c478bd9Sstevel@tonic-gate }
15957c478bd9Sstevel@tonic-gate #if defined(i386)
15967c478bd9Sstevel@tonic-gate /*
15977c478bd9Sstevel@tonic-gate * Set the default boot partition to 1 cylinder
15987c478bd9Sstevel@tonic-gate */
15997c478bd9Sstevel@tonic-gate ncyls[8] = 1;
16007c478bd9Sstevel@tonic-gate freecyls -= 1;
16017c478bd9Sstevel@tonic-gate
16027c478bd9Sstevel@tonic-gate /*
16037c478bd9Sstevel@tonic-gate * If current disk type is not a SCSI disk,
16047c478bd9Sstevel@tonic-gate * set the default alternates partition to 2 cylinders
16057c478bd9Sstevel@tonic-gate */
16067c478bd9Sstevel@tonic-gate if (ctrl_type != DKC_SCSI_CCS) {
16077c478bd9Sstevel@tonic-gate ncyls[9] = 2;
16087c478bd9Sstevel@tonic-gate freecyls -= 2;
16097c478bd9Sstevel@tonic-gate }
16107c478bd9Sstevel@tonic-gate #endif /* defined(i386) */
16117c478bd9Sstevel@tonic-gate
16127c478bd9Sstevel@tonic-gate /*
16137c478bd9Sstevel@tonic-gate * Set the free hog partition to whatever space remains.
16147c478bd9Sstevel@tonic-gate * It's an error to have more than one HOG partition,
16157c478bd9Sstevel@tonic-gate * but we don't verify that here.
16167c478bd9Sstevel@tonic-gate */
16177c478bd9Sstevel@tonic-gate for (i = 0; i < NDKMAP; i++) {
16187c478bd9Sstevel@tonic-gate if (pt->partitions[i] == HOG) {
16197c478bd9Sstevel@tonic-gate assert(ncyls[i] == 0);
16207c478bd9Sstevel@tonic-gate ncyls[i] = freecyls;
16217c478bd9Sstevel@tonic-gate break;
16227c478bd9Sstevel@tonic-gate }
16237c478bd9Sstevel@tonic-gate }
16247c478bd9Sstevel@tonic-gate
16257c478bd9Sstevel@tonic-gate /*
16267c478bd9Sstevel@tonic-gate * Error checking
16277c478bd9Sstevel@tonic-gate */
16287c478bd9Sstevel@tonic-gate ncyl = 0;
16297c478bd9Sstevel@tonic-gate for (i = 0; i < NDKMAP; i++) {
16307c478bd9Sstevel@tonic-gate ncyl += ncyls[i];
16317c478bd9Sstevel@tonic-gate }
16327c478bd9Sstevel@tonic-gate assert(ncyl == (label->dkl_ncyl));
16337c478bd9Sstevel@tonic-gate
16347c478bd9Sstevel@tonic-gate /*
16357c478bd9Sstevel@tonic-gate * Finally, install the partition in the label.
16367c478bd9Sstevel@tonic-gate */
16377c478bd9Sstevel@tonic-gate cyl = 0;
16387c478bd9Sstevel@tonic-gate
16397c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_16)
16407c478bd9Sstevel@tonic-gate for (i = NDKMAP/2; i < NDKMAP; i++) {
16417c478bd9Sstevel@tonic-gate if (i == 2 || ncyls[i] == 0)
16427c478bd9Sstevel@tonic-gate continue;
16437c478bd9Sstevel@tonic-gate label->dkl_vtoc.v_part[i].p_start = cyl * blks_per_cyl;
16447c478bd9Sstevel@tonic-gate label->dkl_vtoc.v_part[i].p_size = ncyls[i] * blks_per_cyl;
16457c478bd9Sstevel@tonic-gate cyl += ncyls[i];
16467c478bd9Sstevel@tonic-gate }
16477c478bd9Sstevel@tonic-gate for (i = 0; i < NDKMAP/2; i++) {
16487c478bd9Sstevel@tonic-gate
16497c478bd9Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_8)
16507c478bd9Sstevel@tonic-gate for (i = 0; i < NDKMAP; i++) {
16517c478bd9Sstevel@tonic-gate
16527c478bd9Sstevel@tonic-gate #else
16537c478bd9Sstevel@tonic-gate #error No VTOC format defined.
16547c478bd9Sstevel@tonic-gate #endif /* defined(_SUNOS_VTOC_16) */
16557c478bd9Sstevel@tonic-gate
16563ccda647Slclee if (i == 2 || ncyls[i] == 0) {
16573ccda647Slclee #if defined(_SUNOS_VTOC_8)
16583ccda647Slclee if (i != 2) {
16593ccda647Slclee label->dkl_map[i].dkl_cylno = 0;
16603ccda647Slclee label->dkl_map[i].dkl_nblk = 0;
16613ccda647Slclee }
16623ccda647Slclee #endif
16637c478bd9Sstevel@tonic-gate continue;
16643ccda647Slclee }
16657c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
16667c478bd9Sstevel@tonic-gate label->dkl_map[i].dkl_cylno = cyl;
16677c478bd9Sstevel@tonic-gate label->dkl_map[i].dkl_nblk = ncyls[i] * blks_per_cyl;
16687c478bd9Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16)
16697c478bd9Sstevel@tonic-gate label->dkl_vtoc.v_part[i].p_start = cyl * blks_per_cyl;
16707c478bd9Sstevel@tonic-gate label->dkl_vtoc.v_part[i].p_size = ncyls[i] * blks_per_cyl;
16717c478bd9Sstevel@tonic-gate
16727c478bd9Sstevel@tonic-gate #else
16737c478bd9Sstevel@tonic-gate #error No VTOC format defined.
16747c478bd9Sstevel@tonic-gate #endif /* defined(_SUNOS_VTOC_8) */
16757c478bd9Sstevel@tonic-gate
16767c478bd9Sstevel@tonic-gate cyl += ncyls[i];
16777c478bd9Sstevel@tonic-gate }
16787c478bd9Sstevel@tonic-gate
16797c478bd9Sstevel@tonic-gate /*
16807c478bd9Sstevel@tonic-gate * Set the whole disk partition
16817c478bd9Sstevel@tonic-gate */
16827c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
16837c478bd9Sstevel@tonic-gate label->dkl_map[2].dkl_cylno = 0;
16847c478bd9Sstevel@tonic-gate label->dkl_map[2].dkl_nblk =
16857c478bd9Sstevel@tonic-gate label->dkl_ncyl * label->dkl_nhead * label->dkl_nsect;
16867c478bd9Sstevel@tonic-gate
16877c478bd9Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16)
16887c478bd9Sstevel@tonic-gate label->dkl_vtoc.v_part[2].p_start = 0;
16897c478bd9Sstevel@tonic-gate label->dkl_vtoc.v_part[2].p_size =
16907c478bd9Sstevel@tonic-gate (label->dkl_ncyl + label->dkl_acyl) * label->dkl_nhead *
16917c478bd9Sstevel@tonic-gate label->dkl_nsect;
16927c478bd9Sstevel@tonic-gate #else
16937c478bd9Sstevel@tonic-gate #error No VTOC format defined.
16947c478bd9Sstevel@tonic-gate #endif /* defined(_SUNOS_VTOC_8) */
16957c478bd9Sstevel@tonic-gate
16967c478bd9Sstevel@tonic-gate
16977c478bd9Sstevel@tonic-gate if (option_msg && diag_msg) {
16987c478bd9Sstevel@tonic-gate float scaled;
16997c478bd9Sstevel@tonic-gate err_print("\n");
17007c478bd9Sstevel@tonic-gate for (i = 0; i < NDKMAP; i++) {
17017c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
17027c478bd9Sstevel@tonic-gate if (label->dkl_map[i].dkl_nblk == 0)
17037c478bd9Sstevel@tonic-gate
17047c478bd9Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16)
17057c478bd9Sstevel@tonic-gate if (label->dkl_vtoc.v_part[i].p_size == 0)
17067c478bd9Sstevel@tonic-gate
17077c478bd9Sstevel@tonic-gate #else
17087c478bd9Sstevel@tonic-gate #error No VTOC format defined.
17097c478bd9Sstevel@tonic-gate #endif /* defined(_SUNOS_VTOC_8) */
17107c478bd9Sstevel@tonic-gate
17117c478bd9Sstevel@tonic-gate continue;
17127c478bd9Sstevel@tonic-gate err_print("Partition %d: ", i);
17137c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
17147c478bd9Sstevel@tonic-gate scaled = bn2mb(label->dkl_map[i].dkl_nblk);
17157c478bd9Sstevel@tonic-gate
17167c478bd9Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16)
17177c478bd9Sstevel@tonic-gate
17187c478bd9Sstevel@tonic-gate scaled = bn2mb(label->dkl_vtoc.v_part[i].p_size);
17197c478bd9Sstevel@tonic-gate #else
17207c478bd9Sstevel@tonic-gate #error No VTOC format defined.
17217c478bd9Sstevel@tonic-gate #endif /* defined(_SUNOS_VTOC_8) */
17227c478bd9Sstevel@tonic-gate
17237c478bd9Sstevel@tonic-gate if (scaled > 1024.0) {
17247c478bd9Sstevel@tonic-gate err_print("%6.2fGB ", scaled/1024.0);
17257c478bd9Sstevel@tonic-gate } else {
17267c478bd9Sstevel@tonic-gate err_print("%6.2fMB ", scaled);
17277c478bd9Sstevel@tonic-gate }
17287c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
172965908c77Syu, larry liu - Sun Microsystems - Beijing China err_print(" %6d cylinders\n",
17307c478bd9Sstevel@tonic-gate label->dkl_map[i].dkl_nblk/blks_per_cyl);
17317c478bd9Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16)
173265908c77Syu, larry liu - Sun Microsystems - Beijing China err_print(" %6d cylinders\n",
17337c478bd9Sstevel@tonic-gate label->dkl_vtoc.v_part[i].p_size/blks_per_cyl);
17347c478bd9Sstevel@tonic-gate #else
17357c478bd9Sstevel@tonic-gate #error No VTOC format defined.
17367c478bd9Sstevel@tonic-gate #endif /* defined(_SUNOS_VTOC_8) */
17377c478bd9Sstevel@tonic-gate
17387c478bd9Sstevel@tonic-gate }
17397c478bd9Sstevel@tonic-gate err_print("\n");
17407c478bd9Sstevel@tonic-gate }
17417c478bd9Sstevel@tonic-gate
17427c478bd9Sstevel@tonic-gate return (1);
17437c478bd9Sstevel@tonic-gate }
17447c478bd9Sstevel@tonic-gate
17457c478bd9Sstevel@tonic-gate
17467c478bd9Sstevel@tonic-gate
17477c478bd9Sstevel@tonic-gate /*
17487c478bd9Sstevel@tonic-gate * Find an existing scsi disk definition by this name,
17497c478bd9Sstevel@tonic-gate * if possible.
17507c478bd9Sstevel@tonic-gate */
17517c478bd9Sstevel@tonic-gate static struct disk_type *
17527c478bd9Sstevel@tonic-gate find_scsi_disk_type(
17537c478bd9Sstevel@tonic-gate char *disk_name,
17547c478bd9Sstevel@tonic-gate struct dk_label *label)
17557c478bd9Sstevel@tonic-gate {
17567c478bd9Sstevel@tonic-gate struct ctlr_type *ctlr;
17577c478bd9Sstevel@tonic-gate struct disk_type *dp;
17587c478bd9Sstevel@tonic-gate
17597c478bd9Sstevel@tonic-gate ctlr = find_scsi_ctlr_type();
17607c478bd9Sstevel@tonic-gate for (dp = ctlr->ctype_dlist; dp != NULL; dp = dp->dtype_next) {
17617c478bd9Sstevel@tonic-gate if (dp->dtype_asciilabel) {
17627c478bd9Sstevel@tonic-gate if ((strcmp(dp->dtype_asciilabel, disk_name) == 0) &&
17637c478bd9Sstevel@tonic-gate dp->dtype_pcyl == label->dkl_pcyl &&
17647c478bd9Sstevel@tonic-gate dp->dtype_ncyl == label->dkl_ncyl &&
17657c478bd9Sstevel@tonic-gate dp->dtype_acyl == label->dkl_acyl &&
17667c478bd9Sstevel@tonic-gate dp->dtype_nhead == label->dkl_nhead &&
17677c478bd9Sstevel@tonic-gate dp->dtype_nsect == label->dkl_nsect) {
17687c478bd9Sstevel@tonic-gate return (dp);
17697c478bd9Sstevel@tonic-gate }
17707c478bd9Sstevel@tonic-gate }
17717c478bd9Sstevel@tonic-gate }
17727c478bd9Sstevel@tonic-gate
17737c478bd9Sstevel@tonic-gate return ((struct disk_type *)NULL);
17747c478bd9Sstevel@tonic-gate }
17757c478bd9Sstevel@tonic-gate
17767c478bd9Sstevel@tonic-gate
17777c478bd9Sstevel@tonic-gate /*
17787c478bd9Sstevel@tonic-gate * Find an existing scsi disk definition by this name,
17797c478bd9Sstevel@tonic-gate * if possible.
17807c478bd9Sstevel@tonic-gate */
17817c478bd9Sstevel@tonic-gate static struct disk_type *
17827c478bd9Sstevel@tonic-gate find_scsi_disk_by_name(
17837c478bd9Sstevel@tonic-gate char *disk_name)
17847c478bd9Sstevel@tonic-gate {
17857c478bd9Sstevel@tonic-gate struct ctlr_type *ctlr;
17867c478bd9Sstevel@tonic-gate struct disk_type *dp;
17877c478bd9Sstevel@tonic-gate
17887c478bd9Sstevel@tonic-gate ctlr = find_scsi_ctlr_type();
17897c478bd9Sstevel@tonic-gate for (dp = ctlr->ctype_dlist; dp != NULL; dp = dp->dtype_next) {
17907c478bd9Sstevel@tonic-gate if (dp->dtype_asciilabel) {
17917c478bd9Sstevel@tonic-gate if ((strcmp(dp->dtype_asciilabel, disk_name) == 0)) {
17927c478bd9Sstevel@tonic-gate return (dp);
17937c478bd9Sstevel@tonic-gate }
17947c478bd9Sstevel@tonic-gate }
17957c478bd9Sstevel@tonic-gate }
17967c478bd9Sstevel@tonic-gate
17977c478bd9Sstevel@tonic-gate return ((struct disk_type *)NULL);
17987c478bd9Sstevel@tonic-gate }
17997c478bd9Sstevel@tonic-gate
18007c478bd9Sstevel@tonic-gate
18017c478bd9Sstevel@tonic-gate /*
18027c478bd9Sstevel@tonic-gate * Return a pointer to the ctlr_type structure for SCSI
18037c478bd9Sstevel@tonic-gate * disks. This list is built into the program, so there's
18047c478bd9Sstevel@tonic-gate * no chance of not being able to find it, unless someone
18057c478bd9Sstevel@tonic-gate * totally mangles the code.
18067c478bd9Sstevel@tonic-gate */
18077c478bd9Sstevel@tonic-gate static struct ctlr_type *
18087c478bd9Sstevel@tonic-gate find_scsi_ctlr_type()
18097c478bd9Sstevel@tonic-gate {
18107c478bd9Sstevel@tonic-gate struct mctlr_list *mlp;
18117c478bd9Sstevel@tonic-gate
18127c478bd9Sstevel@tonic-gate mlp = controlp;
18137c478bd9Sstevel@tonic-gate
18147c478bd9Sstevel@tonic-gate while (mlp != NULL) {
1815f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China if (mlp->ctlr_type->ctype_ctype == DKC_SCSI_CCS) {
18167c478bd9Sstevel@tonic-gate return (mlp->ctlr_type);
18177c478bd9Sstevel@tonic-gate }
18187c478bd9Sstevel@tonic-gate mlp = mlp->next;
18197c478bd9Sstevel@tonic-gate }
18207c478bd9Sstevel@tonic-gate
18217c478bd9Sstevel@tonic-gate impossible("no SCSI controller type");
1822052b6e8aSbg159949
1823052b6e8aSbg159949 return ((struct ctlr_type *)NULL);
18247c478bd9Sstevel@tonic-gate }
18257c478bd9Sstevel@tonic-gate
18267c478bd9Sstevel@tonic-gate
18277c478bd9Sstevel@tonic-gate
18287c478bd9Sstevel@tonic-gate /*
18297c478bd9Sstevel@tonic-gate * Return a pointer to the scsi ctlr_info structure. This
18307c478bd9Sstevel@tonic-gate * structure is allocated the first time format sees a
18317c478bd9Sstevel@tonic-gate * disk on this controller, so it must be present.
18327c478bd9Sstevel@tonic-gate */
18337c478bd9Sstevel@tonic-gate static struct ctlr_info *
18347c478bd9Sstevel@tonic-gate find_scsi_ctlr_info(
18357c478bd9Sstevel@tonic-gate struct dk_cinfo *dkinfo)
18367c478bd9Sstevel@tonic-gate {
18377c478bd9Sstevel@tonic-gate struct ctlr_info *ctlr;
18387c478bd9Sstevel@tonic-gate
1839f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China if (dkinfo->dki_ctype != DKC_SCSI_CCS) {
18407c478bd9Sstevel@tonic-gate return (NULL);
18417c478bd9Sstevel@tonic-gate }
18427c478bd9Sstevel@tonic-gate
18437c478bd9Sstevel@tonic-gate for (ctlr = ctlr_list; ctlr != NULL; ctlr = ctlr->ctlr_next) {
18447c478bd9Sstevel@tonic-gate if (ctlr->ctlr_addr == dkinfo->dki_addr &&
18457c478bd9Sstevel@tonic-gate ctlr->ctlr_space == dkinfo->dki_space &&
1846f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China ctlr->ctlr_ctype->ctype_ctype == DKC_SCSI_CCS) {
18477c478bd9Sstevel@tonic-gate return (ctlr);
18487c478bd9Sstevel@tonic-gate }
18497c478bd9Sstevel@tonic-gate }
18507c478bd9Sstevel@tonic-gate
18517c478bd9Sstevel@tonic-gate impossible("no SCSI controller info");
1852052b6e8aSbg159949
1853052b6e8aSbg159949 return ((struct ctlr_info *)NULL);
18547c478bd9Sstevel@tonic-gate }
18557c478bd9Sstevel@tonic-gate
18567c478bd9Sstevel@tonic-gate
18577c478bd9Sstevel@tonic-gate
18587c478bd9Sstevel@tonic-gate static struct disk_type *
18597c478bd9Sstevel@tonic-gate new_scsi_disk_type(
18607c478bd9Sstevel@tonic-gate int fd,
18617c478bd9Sstevel@tonic-gate char *disk_name,
18627c478bd9Sstevel@tonic-gate struct dk_label *label)
18637c478bd9Sstevel@tonic-gate {
18647c478bd9Sstevel@tonic-gate struct disk_type *dp;
18657c478bd9Sstevel@tonic-gate struct disk_type *disk;
18667c478bd9Sstevel@tonic-gate struct ctlr_info *ctlr;
18677c478bd9Sstevel@tonic-gate struct dk_cinfo dkinfo;
18687c478bd9Sstevel@tonic-gate struct partition_info *part;
18697c478bd9Sstevel@tonic-gate struct partition_info *pt;
18707c478bd9Sstevel@tonic-gate struct disk_info *disk_info;
18717c478bd9Sstevel@tonic-gate int i;
18727c478bd9Sstevel@tonic-gate
18737c478bd9Sstevel@tonic-gate /*
18747c478bd9Sstevel@tonic-gate * Get the disk controller info for this disk
18757c478bd9Sstevel@tonic-gate */
18767c478bd9Sstevel@tonic-gate if (ioctl(fd, DKIOCINFO, &dkinfo) == -1) {
18777c478bd9Sstevel@tonic-gate if (option_msg && diag_msg) {
18787c478bd9Sstevel@tonic-gate err_print("DKIOCINFO failed\n");
18797c478bd9Sstevel@tonic-gate }
18807c478bd9Sstevel@tonic-gate return (NULL);
18817c478bd9Sstevel@tonic-gate }
18827c478bd9Sstevel@tonic-gate
18837c478bd9Sstevel@tonic-gate /*
18847c478bd9Sstevel@tonic-gate * Find the ctlr_info for this disk.
18857c478bd9Sstevel@tonic-gate */
18867c478bd9Sstevel@tonic-gate ctlr = find_scsi_ctlr_info(&dkinfo);
18877c478bd9Sstevel@tonic-gate
18887c478bd9Sstevel@tonic-gate /*
18897c478bd9Sstevel@tonic-gate * Allocate a new disk type for the SCSI controller.
18907c478bd9Sstevel@tonic-gate */
18917c478bd9Sstevel@tonic-gate disk = (struct disk_type *)zalloc(sizeof (struct disk_type));
18927c478bd9Sstevel@tonic-gate
18937c478bd9Sstevel@tonic-gate /*
18947c478bd9Sstevel@tonic-gate * Find the disk_info instance for this disk.
18957c478bd9Sstevel@tonic-gate */
18967c478bd9Sstevel@tonic-gate disk_info = find_scsi_disk_info(&dkinfo);
18977c478bd9Sstevel@tonic-gate
18987c478bd9Sstevel@tonic-gate /*
18997c478bd9Sstevel@tonic-gate * The controller and the disk should match.
19007c478bd9Sstevel@tonic-gate */
19017c478bd9Sstevel@tonic-gate assert(disk_info->disk_ctlr == ctlr);
19027c478bd9Sstevel@tonic-gate
19037c478bd9Sstevel@tonic-gate /*
19047c478bd9Sstevel@tonic-gate * Link the disk into the list of disks
19057c478bd9Sstevel@tonic-gate */
19067c478bd9Sstevel@tonic-gate dp = ctlr->ctlr_ctype->ctype_dlist;
19077c478bd9Sstevel@tonic-gate if (dp == NULL) {
1908342440ecSPrasad Singamsetty ctlr->ctlr_ctype->ctype_dlist = disk;
19097c478bd9Sstevel@tonic-gate } else {
19107c478bd9Sstevel@tonic-gate while (dp->dtype_next != NULL) {
19117c478bd9Sstevel@tonic-gate dp = dp->dtype_next;
19127c478bd9Sstevel@tonic-gate }
19137c478bd9Sstevel@tonic-gate dp->dtype_next = disk;
19147c478bd9Sstevel@tonic-gate }
19157c478bd9Sstevel@tonic-gate disk->dtype_next = NULL;
19167c478bd9Sstevel@tonic-gate
19177c478bd9Sstevel@tonic-gate /*
19187c478bd9Sstevel@tonic-gate * Allocate and initialize the disk name.
19197c478bd9Sstevel@tonic-gate */
19207c478bd9Sstevel@tonic-gate disk->dtype_asciilabel = alloc_string(disk_name);
19217c478bd9Sstevel@tonic-gate
19227c478bd9Sstevel@tonic-gate /*
19237c478bd9Sstevel@tonic-gate * Initialize disk geometry info
19247c478bd9Sstevel@tonic-gate */
19257c478bd9Sstevel@tonic-gate disk->dtype_pcyl = label->dkl_pcyl;
19267c478bd9Sstevel@tonic-gate disk->dtype_ncyl = label->dkl_ncyl;
19277c478bd9Sstevel@tonic-gate disk->dtype_acyl = label->dkl_acyl;
19287c478bd9Sstevel@tonic-gate disk->dtype_nhead = label->dkl_nhead;
19297c478bd9Sstevel@tonic-gate disk->dtype_nsect = label->dkl_nsect;
19307c478bd9Sstevel@tonic-gate disk->dtype_rpm = label->dkl_rpm;
19317c478bd9Sstevel@tonic-gate
19327c478bd9Sstevel@tonic-gate /*
19337c478bd9Sstevel@tonic-gate * Attempt to match the partition map in the label
19347c478bd9Sstevel@tonic-gate * with a know partition for this disk type.
19357c478bd9Sstevel@tonic-gate */
19367c478bd9Sstevel@tonic-gate for (part = disk->dtype_plist; part; part = part->pinfo_next) {
19377c478bd9Sstevel@tonic-gate if (parts_match(label, part)) {
19387c478bd9Sstevel@tonic-gate break;
19397c478bd9Sstevel@tonic-gate }
19407c478bd9Sstevel@tonic-gate }
19417c478bd9Sstevel@tonic-gate
19427c478bd9Sstevel@tonic-gate /*
19437c478bd9Sstevel@tonic-gate * If no match was made, we need to create a partition
19447c478bd9Sstevel@tonic-gate * map for this disk.
19457c478bd9Sstevel@tonic-gate */
19467c478bd9Sstevel@tonic-gate if (part == NULL) {
19477c478bd9Sstevel@tonic-gate part = (struct partition_info *)
19487c478bd9Sstevel@tonic-gate zalloc(sizeof (struct partition_info));
19497c478bd9Sstevel@tonic-gate pt = disk->dtype_plist;
19507c478bd9Sstevel@tonic-gate if (pt == NULL) {
19517c478bd9Sstevel@tonic-gate disk->dtype_plist = part;
19527c478bd9Sstevel@tonic-gate } else {
19537c478bd9Sstevel@tonic-gate while (pt->pinfo_next != NULL) {
19547c478bd9Sstevel@tonic-gate pt = pt->pinfo_next;
19557c478bd9Sstevel@tonic-gate }
19567c478bd9Sstevel@tonic-gate pt->pinfo_next = part;
19577c478bd9Sstevel@tonic-gate }
19587c478bd9Sstevel@tonic-gate part->pinfo_next = NULL;
19597c478bd9Sstevel@tonic-gate
19607c478bd9Sstevel@tonic-gate /*
19617c478bd9Sstevel@tonic-gate * Set up the partition name
19627c478bd9Sstevel@tonic-gate */
19637c478bd9Sstevel@tonic-gate part->pinfo_name = alloc_string("default");
19647c478bd9Sstevel@tonic-gate
19657c478bd9Sstevel@tonic-gate /*
19667c478bd9Sstevel@tonic-gate * Fill in the partition info from the label
19677c478bd9Sstevel@tonic-gate */
19687c478bd9Sstevel@tonic-gate for (i = 0; i < NDKMAP; i++) {
19697c478bd9Sstevel@tonic-gate
19707c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
19717c478bd9Sstevel@tonic-gate part->pinfo_map[i] = label->dkl_map[i];
19727c478bd9Sstevel@tonic-gate
19737c478bd9Sstevel@tonic-gate #elif defined(_SUNOS_VTOC_16)
19747c478bd9Sstevel@tonic-gate part->pinfo_map[i].dkl_cylno =
19757c478bd9Sstevel@tonic-gate label->dkl_vtoc.v_part[i].p_start /
1976342440ecSPrasad Singamsetty ((blkaddr32_t)(disk->dtype_nhead *
19777c478bd9Sstevel@tonic-gate disk->dtype_nsect - apc));
19787c478bd9Sstevel@tonic-gate part->pinfo_map[i].dkl_nblk =
19797c478bd9Sstevel@tonic-gate label->dkl_vtoc.v_part[i].p_size;
19807c478bd9Sstevel@tonic-gate #else
19817c478bd9Sstevel@tonic-gate #error No VTOC format defined.
19827c478bd9Sstevel@tonic-gate #endif /* defined(_SUNOS_VTOC_8) */
19837c478bd9Sstevel@tonic-gate
19847c478bd9Sstevel@tonic-gate }
19857c478bd9Sstevel@tonic-gate }
19867c478bd9Sstevel@tonic-gate
19877c478bd9Sstevel@tonic-gate
19887c478bd9Sstevel@tonic-gate /*
19897c478bd9Sstevel@tonic-gate * Use the VTOC if valid, or install a default
19907c478bd9Sstevel@tonic-gate */
19917c478bd9Sstevel@tonic-gate if (label->dkl_vtoc.v_version == V_VERSION) {
19927c478bd9Sstevel@tonic-gate (void) memcpy(disk_info->v_volume, label->dkl_vtoc.v_volume,
19937c478bd9Sstevel@tonic-gate LEN_DKL_VVOL);
19947c478bd9Sstevel@tonic-gate part->vtoc = label->dkl_vtoc;
19957c478bd9Sstevel@tonic-gate } else {
19967c478bd9Sstevel@tonic-gate (void) memset(disk_info->v_volume, 0, LEN_DKL_VVOL);
19977c478bd9Sstevel@tonic-gate set_vtoc_defaults(part);
19987c478bd9Sstevel@tonic-gate }
19997c478bd9Sstevel@tonic-gate
20007c478bd9Sstevel@tonic-gate /*
20017c478bd9Sstevel@tonic-gate * Link the disk to the partition map
20027c478bd9Sstevel@tonic-gate */
20037c478bd9Sstevel@tonic-gate disk_info->disk_parts = part;
20047c478bd9Sstevel@tonic-gate
20057c478bd9Sstevel@tonic-gate return (disk);
20067c478bd9Sstevel@tonic-gate }
20077c478bd9Sstevel@tonic-gate
20087c478bd9Sstevel@tonic-gate
2009698107ecSlh195018 /*
2010698107ecSlh195018 * Delete a disk type from disk type list.
2011698107ecSlh195018 */
2012698107ecSlh195018 int
2013698107ecSlh195018 delete_disk_type(
2014698107ecSlh195018 struct disk_type *disk_type)
2015698107ecSlh195018 {
2016698107ecSlh195018 struct ctlr_type *ctlr;
2017698107ecSlh195018 struct disk_type *dp, *disk;
2018698107ecSlh195018
2019698107ecSlh195018 if (cur_ctype->ctype_ctype == DKC_DIRECT)
2020698107ecSlh195018 ctlr = find_direct_ctlr_type();
2021f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China else if (cur_ctype->ctype_ctype == DKC_VBD)
2022f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China ctlr = find_vbd_ctlr_type();
2023698107ecSlh195018 else
2024698107ecSlh195018 ctlr = find_scsi_ctlr_type();
2025698107ecSlh195018 if (ctlr == NULL || ctlr->ctype_dlist == NULL) {
2026698107ecSlh195018 return (-1);
2027698107ecSlh195018 }
2028698107ecSlh195018
2029698107ecSlh195018 disk = ctlr->ctype_dlist;
2030698107ecSlh195018 if (disk == disk_type) {
2031698107ecSlh195018 ctlr->ctype_dlist = disk->dtype_next;
2032698107ecSlh195018 if (cur_label == L_TYPE_EFI)
2033698107ecSlh195018 free(disk->dtype_plist->etoc);
2034698107ecSlh195018 free(disk->dtype_plist);
2035*9aa4340aSHans Rosenfeld free(disk->vendor);
2036*9aa4340aSHans Rosenfeld free(disk->product);
2037*9aa4340aSHans Rosenfeld free(disk->revision);
2038698107ecSlh195018 free(disk);
2039698107ecSlh195018 return (0);
2040698107ecSlh195018 } else {
2041698107ecSlh195018 for (dp = disk->dtype_next; dp != NULL;
2042698107ecSlh195018 disk = disk->dtype_next, dp = dp->dtype_next) {
2043698107ecSlh195018 if (dp == disk_type) {
2044698107ecSlh195018 disk->dtype_next = dp->dtype_next;
2045698107ecSlh195018 if (cur_label == L_TYPE_EFI)
2046698107ecSlh195018 free(dp->dtype_plist->etoc);
2047698107ecSlh195018 free(dp->dtype_plist);
2048*9aa4340aSHans Rosenfeld free(dp->vendor);
2049*9aa4340aSHans Rosenfeld free(dp->product);
2050*9aa4340aSHans Rosenfeld free(dp->revision);
2051698107ecSlh195018 free(dp);
2052698107ecSlh195018 return (0);
2053698107ecSlh195018 }
2054698107ecSlh195018 }
2055698107ecSlh195018 return (-1);
2056698107ecSlh195018 }
2057698107ecSlh195018 }
2058698107ecSlh195018
2059698107ecSlh195018
20607c478bd9Sstevel@tonic-gate static struct disk_info *
20617c478bd9Sstevel@tonic-gate find_scsi_disk_info(
20627c478bd9Sstevel@tonic-gate struct dk_cinfo *dkinfo)
20637c478bd9Sstevel@tonic-gate {
20647c478bd9Sstevel@tonic-gate struct disk_info *disk;
20657c478bd9Sstevel@tonic-gate struct dk_cinfo *dp;
20667c478bd9Sstevel@tonic-gate
20677c478bd9Sstevel@tonic-gate for (disk = disk_list; disk != NULL; disk = disk->disk_next) {
2068f2d9bcd7Sbo zhou - Sun Microsystems - Beijing China assert(dkinfo->dki_ctype == DKC_SCSI_CCS);
20697c478bd9Sstevel@tonic-gate dp = &disk->disk_dkinfo;
20707c478bd9Sstevel@tonic-gate if (dp->dki_ctype == dkinfo->dki_ctype &&
20717c478bd9Sstevel@tonic-gate dp->dki_cnum == dkinfo->dki_cnum &&
20727c478bd9Sstevel@tonic-gate dp->dki_unit == dkinfo->dki_unit &&
20737c478bd9Sstevel@tonic-gate strcmp(dp->dki_dname, dkinfo->dki_dname) == 0) {
20747c478bd9Sstevel@tonic-gate return (disk);
20757c478bd9Sstevel@tonic-gate }
20767c478bd9Sstevel@tonic-gate }
20777c478bd9Sstevel@tonic-gate
20787c478bd9Sstevel@tonic-gate impossible("No SCSI disk info instance\n");
2079052b6e8aSbg159949
2080052b6e8aSbg159949 return ((struct disk_info *)NULL);
20817c478bd9Sstevel@tonic-gate }
20827c478bd9Sstevel@tonic-gate
20837c478bd9Sstevel@tonic-gate
20847c478bd9Sstevel@tonic-gate static char *
20857c478bd9Sstevel@tonic-gate get_sun_disk_name(
20867c478bd9Sstevel@tonic-gate char *disk_name,
20877c478bd9Sstevel@tonic-gate struct scsi_inquiry *inquiry)
20887c478bd9Sstevel@tonic-gate {
20897c478bd9Sstevel@tonic-gate /*
20907c478bd9Sstevel@tonic-gate * Extract the sun name of the disk
20917c478bd9Sstevel@tonic-gate */
20927c478bd9Sstevel@tonic-gate (void) memset(disk_name, 0, DISK_NAME_MAX);
20937c478bd9Sstevel@tonic-gate (void) memcpy(disk_name, (char *)&inquiry->inq_pid[9], 7);
20947c478bd9Sstevel@tonic-gate
20957c478bd9Sstevel@tonic-gate return (disk_name);
20967c478bd9Sstevel@tonic-gate }
20977c478bd9Sstevel@tonic-gate
20987c478bd9Sstevel@tonic-gate
20991662a2f2SGary Mills char *
21007c478bd9Sstevel@tonic-gate get_generic_disk_name(
21017c478bd9Sstevel@tonic-gate char *disk_name,
21027c478bd9Sstevel@tonic-gate struct scsi_inquiry *inquiry)
21037c478bd9Sstevel@tonic-gate {
21047c478bd9Sstevel@tonic-gate char *p;
21057c478bd9Sstevel@tonic-gate
21067c478bd9Sstevel@tonic-gate (void) memset(disk_name, 0, DISK_NAME_MAX);
21077c478bd9Sstevel@tonic-gate p = strcopy(disk_name, inquiry->inq_vid,
21087c478bd9Sstevel@tonic-gate sizeof (inquiry->inq_vid));
21097c478bd9Sstevel@tonic-gate *p++ = '-';
21107c478bd9Sstevel@tonic-gate p = strcopy(p, inquiry->inq_pid, sizeof (inquiry->inq_pid));
21117c478bd9Sstevel@tonic-gate *p++ = '-';
21127c478bd9Sstevel@tonic-gate p = strcopy(p, inquiry->inq_revision,
21137c478bd9Sstevel@tonic-gate sizeof (inquiry->inq_revision));
21147c478bd9Sstevel@tonic-gate
21157c478bd9Sstevel@tonic-gate return (disk_name);
21167c478bd9Sstevel@tonic-gate }
21177c478bd9Sstevel@tonic-gate
21187c478bd9Sstevel@tonic-gate /*
21197c478bd9Sstevel@tonic-gate * Copy a string of characters from src to dst, for at
21207c478bd9Sstevel@tonic-gate * most n bytes. Strip all leading and trailing spaces,
21217c478bd9Sstevel@tonic-gate * and stop if there are any non-printable characters.
21227c478bd9Sstevel@tonic-gate * Return ptr to the next character to be filled.
21237c478bd9Sstevel@tonic-gate */
21247c478bd9Sstevel@tonic-gate static char *
21257c478bd9Sstevel@tonic-gate strcopy(
21267c478bd9Sstevel@tonic-gate char *dst,
21277c478bd9Sstevel@tonic-gate char *src,
21287c478bd9Sstevel@tonic-gate int n)
21297c478bd9Sstevel@tonic-gate {
21307c478bd9Sstevel@tonic-gate int i;
21317c478bd9Sstevel@tonic-gate
21327c478bd9Sstevel@tonic-gate while (*src == ' ' && n > 0) {
21337c478bd9Sstevel@tonic-gate src++;
21347c478bd9Sstevel@tonic-gate n--;
21357c478bd9Sstevel@tonic-gate }
21367c478bd9Sstevel@tonic-gate
21377c478bd9Sstevel@tonic-gate for (i = 0; n-- > 0 && isascii(*src) && isprint(*src); src++) {
21387c478bd9Sstevel@tonic-gate if (*src == ' ') {
21397c478bd9Sstevel@tonic-gate i++;
21407c478bd9Sstevel@tonic-gate } else {
21417c478bd9Sstevel@tonic-gate while (i-- > 0)
21427c478bd9Sstevel@tonic-gate *dst++ = ' ';
21437c478bd9Sstevel@tonic-gate *dst++ = *src;
21447c478bd9Sstevel@tonic-gate }
21457c478bd9Sstevel@tonic-gate }
21467c478bd9Sstevel@tonic-gate
21477c478bd9Sstevel@tonic-gate *dst = 0;
21487c478bd9Sstevel@tonic-gate return (dst);
21497c478bd9Sstevel@tonic-gate }
21507c478bd9Sstevel@tonic-gate
21517c478bd9Sstevel@tonic-gate /*
21527c478bd9Sstevel@tonic-gate * adjust disk geometry.
21537c478bd9Sstevel@tonic-gate * This is used when disk reports a disk geometry page having
21547c478bd9Sstevel@tonic-gate * no of physical cylinders is < 3 which is the minimum required
21557c478bd9Sstevel@tonic-gate * by Solaris (2 for storing labels and at least one as a data
21567c478bd9Sstevel@tonic-gate * cylinder )
21577c478bd9Sstevel@tonic-gate */
21587c478bd9Sstevel@tonic-gate int
2159342440ecSPrasad Singamsetty adjust_disk_geometry(diskaddr_t capacity, uint_t *cyl, uint_t *nhead,
2160342440ecSPrasad Singamsetty uint_t *nsect)
21617c478bd9Sstevel@tonic-gate {
2162342440ecSPrasad Singamsetty uint_t lcyl = *cyl;
2163342440ecSPrasad Singamsetty uint_t lnhead = *nhead;
2164342440ecSPrasad Singamsetty uint_t lnsect = *nsect;
21657c478bd9Sstevel@tonic-gate
21667c478bd9Sstevel@tonic-gate assert(lcyl < SUN_MIN_CYL);
21677c478bd9Sstevel@tonic-gate
21687c478bd9Sstevel@tonic-gate /*
21697c478bd9Sstevel@tonic-gate * reduce nsect by 2 for each iteration and re-calculate
21707c478bd9Sstevel@tonic-gate * the number of cylinders.
21717c478bd9Sstevel@tonic-gate */
21727c478bd9Sstevel@tonic-gate while (lnsect > MINIMUM_NO_SECTORS &&
21737c478bd9Sstevel@tonic-gate lcyl < MINIMUM_NO_CYLINDERS) {
21747c478bd9Sstevel@tonic-gate /*
21757c478bd9Sstevel@tonic-gate * make sure that we do not go below MINIMUM_NO_SECTORS.
21767c478bd9Sstevel@tonic-gate */
21777c478bd9Sstevel@tonic-gate lnsect = max(MINIMUM_NO_SECTORS, lnsect / 2);
21787c478bd9Sstevel@tonic-gate lcyl = (capacity) / (lnhead * lnsect);
21797c478bd9Sstevel@tonic-gate }
21807c478bd9Sstevel@tonic-gate /*
21817c478bd9Sstevel@tonic-gate * If the geometry still does not satisfy
21827c478bd9Sstevel@tonic-gate * MINIMUM_NO_CYLINDERS then try to reduce the
21837c478bd9Sstevel@tonic-gate * no of heads.
21847c478bd9Sstevel@tonic-gate */
21857c478bd9Sstevel@tonic-gate while (lnhead > MINIMUM_NO_HEADS &&
2186bc067c09Sqd208687 lcyl < MINIMUM_NO_CYLINDERS) {
21877c478bd9Sstevel@tonic-gate lnhead = max(MINIMUM_NO_HEADS, lnhead / 2);
21887c478bd9Sstevel@tonic-gate lcyl = (capacity) / (lnhead * lnsect);
21897c478bd9Sstevel@tonic-gate }
21907c478bd9Sstevel@tonic-gate /*
21917c478bd9Sstevel@tonic-gate * now we should have atleast SUN_MIN_CYL cylinders.
21927c478bd9Sstevel@tonic-gate * If we still do not get SUN_MIN_CYL with MINIMUM_NO_HEADS
21937c478bd9Sstevel@tonic-gate * and MINIMUM_NO_HEADS then return error.
21947c478bd9Sstevel@tonic-gate */
21957c478bd9Sstevel@tonic-gate if (lcyl < SUN_MIN_CYL)
21967c478bd9Sstevel@tonic-gate return (1);
21977c478bd9Sstevel@tonic-gate else {
21987c478bd9Sstevel@tonic-gate *cyl = lcyl;
21997c478bd9Sstevel@tonic-gate *nhead = lnhead;
22007c478bd9Sstevel@tonic-gate *nsect = lnsect;
22017c478bd9Sstevel@tonic-gate return (0);
22027c478bd9Sstevel@tonic-gate }
22037c478bd9Sstevel@tonic-gate }
22047c478bd9Sstevel@tonic-gate
22057c478bd9Sstevel@tonic-gate #if defined(_SUNOS_VTOC_8)
22067c478bd9Sstevel@tonic-gate /*
22077c478bd9Sstevel@tonic-gate * Reduce the size of one dimention below a specified
22087c478bd9Sstevel@tonic-gate * limit with a minimum loss of volume. Dimenstions are
22097c478bd9Sstevel@tonic-gate * assumed to be passed in form the largest value (the one
22107c478bd9Sstevel@tonic-gate * that needs to be reduced) to the smallest value. The
22117c478bd9Sstevel@tonic-gate * values will be twiddled until they are all less than or
22127c478bd9Sstevel@tonic-gate * equal to their limit. Returns the number in the new geometry.
22137c478bd9Sstevel@tonic-gate */
2214342440ecSPrasad Singamsetty static diskaddr_t
22157c478bd9Sstevel@tonic-gate square_box(
2216342440ecSPrasad Singamsetty diskaddr_t capacity,
2217342440ecSPrasad Singamsetty uint_t *dim1, uint_t lim1,
2218342440ecSPrasad Singamsetty uint_t *dim2, uint_t lim2,
2219342440ecSPrasad Singamsetty uint_t *dim3, uint_t lim3)
22207c478bd9Sstevel@tonic-gate {
2221342440ecSPrasad Singamsetty uint_t i;
22227c478bd9Sstevel@tonic-gate
22237c478bd9Sstevel@tonic-gate /*
22247c478bd9Sstevel@tonic-gate * Although the routine should work with any ordering of
22257c478bd9Sstevel@tonic-gate * parameters, it's most efficient if they are passed in
22267c478bd9Sstevel@tonic-gate * in decreasing magnitude.
22277c478bd9Sstevel@tonic-gate */
22287c478bd9Sstevel@tonic-gate assert(*dim1 >= *dim2);
22297c478bd9Sstevel@tonic-gate assert(*dim2 >= *dim3);
22307c478bd9Sstevel@tonic-gate
22317c478bd9Sstevel@tonic-gate /*
22327c478bd9Sstevel@tonic-gate * This is done in a very arbitrary manner. We could try to
22337c478bd9Sstevel@tonic-gate * find better values but I can't come up with a method that
22347c478bd9Sstevel@tonic-gate * would run in a reasonable amount of time. That could take
22357c478bd9Sstevel@tonic-gate * approximately 65535 * 65535 iterations of a dozen flops each
22367c478bd9Sstevel@tonic-gate * or well over 4G flops.
22377c478bd9Sstevel@tonic-gate *
22387c478bd9Sstevel@tonic-gate * First:
22397c478bd9Sstevel@tonic-gate *
22407c478bd9Sstevel@tonic-gate * Let's see how far we can go with bitshifts w/o losing
22417c478bd9Sstevel@tonic-gate * any blocks.
22427c478bd9Sstevel@tonic-gate */
22437c478bd9Sstevel@tonic-gate
224465908c77Syu, larry liu - Sun Microsystems - Beijing China for (i = 0; (((*dim1)>>i)&1) == 0 && ((*dim1)>>i) > lim1; i++)
224565908c77Syu, larry liu - Sun Microsystems - Beijing China ;
22467c478bd9Sstevel@tonic-gate if (i) {
22477c478bd9Sstevel@tonic-gate *dim1 = ((*dim1)>>i);
22487c478bd9Sstevel@tonic-gate *dim3 = ((*dim3)<<i);
22497c478bd9Sstevel@tonic-gate }
22507c478bd9Sstevel@tonic-gate
22517c478bd9Sstevel@tonic-gate if (((*dim1) > lim1) || ((*dim2) > lim2) || ((*dim3) > lim3)) {
22527c478bd9Sstevel@tonic-gate double d[4];
22537c478bd9Sstevel@tonic-gate
22547c478bd9Sstevel@tonic-gate /*
22557c478bd9Sstevel@tonic-gate * Second:
22567c478bd9Sstevel@tonic-gate *
22577c478bd9Sstevel@tonic-gate * Set the highest value at its limit then calculate errors,
22587c478bd9Sstevel@tonic-gate * adjusting the 2nd highest value (we get better resolution
22597c478bd9Sstevel@tonic-gate * that way).
22607c478bd9Sstevel@tonic-gate */
22617c478bd9Sstevel@tonic-gate d[1] = lim1;
22627c478bd9Sstevel@tonic-gate d[3] = *dim3;
22637c478bd9Sstevel@tonic-gate d[2] = (double)capacity/(d[1]*d[3]);
22647c478bd9Sstevel@tonic-gate
22657c478bd9Sstevel@tonic-gate /*
22667c478bd9Sstevel@tonic-gate * If we overflowed the middle term, set it to its limit and
22677c478bd9Sstevel@tonic-gate * chose a new low term.
22687c478bd9Sstevel@tonic-gate */
22697c478bd9Sstevel@tonic-gate if (d[2] > lim2) {
22707c478bd9Sstevel@tonic-gate d[2] = lim2;
22717c478bd9Sstevel@tonic-gate d[3] = (double)capacity/(d[1]*d[2]);
22727c478bd9Sstevel@tonic-gate }
22737c478bd9Sstevel@tonic-gate /*
22747c478bd9Sstevel@tonic-gate * Convert to integers.
22757c478bd9Sstevel@tonic-gate */
22767c478bd9Sstevel@tonic-gate *dim1 = (int)d[1];
22777c478bd9Sstevel@tonic-gate *dim2 = (int)d[2];
22787c478bd9Sstevel@tonic-gate *dim3 = (int)d[3];
22797c478bd9Sstevel@tonic-gate }
22807c478bd9Sstevel@tonic-gate /*
22817c478bd9Sstevel@tonic-gate * Fixup any other possible problems.
22827c478bd9Sstevel@tonic-gate * If this happens, we need a new disklabel format.
22837c478bd9Sstevel@tonic-gate */
22847c478bd9Sstevel@tonic-gate if (*dim1 > lim1) *dim1 = lim1;
22857c478bd9Sstevel@tonic-gate if (*dim2 > lim2) *dim2 = lim2;
22867c478bd9Sstevel@tonic-gate if (*dim3 > lim3) *dim3 = lim3;
22877c478bd9Sstevel@tonic-gate return (*dim1 * *dim2 * *dim3);
22887c478bd9Sstevel@tonic-gate }
22897c478bd9Sstevel@tonic-gate #endif /* defined(_SUNOS_VTOC_8) */
2290342440ecSPrasad Singamsetty
2291342440ecSPrasad Singamsetty /*
2292342440ecSPrasad Singamsetty * Calculate CHS values based on the capacity data.
2293342440ecSPrasad Singamsetty *
2294342440ecSPrasad Singamsetty * NOTE: This function is same as cmlb_convert_geomerty() function in
2295342440ecSPrasad Singamsetty * cmlb kernel module.
2296342440ecSPrasad Singamsetty */
2297342440ecSPrasad Singamsetty static void
2298342440ecSPrasad Singamsetty compute_chs_values(diskaddr_t total_capacity, diskaddr_t usable_capacity,
2299342440ecSPrasad Singamsetty uint_t *pcylp, uint_t *nheadp, uint_t *nsectp)
2300342440ecSPrasad Singamsetty {
2301342440ecSPrasad Singamsetty
2302342440ecSPrasad Singamsetty /* Unlabeled SCSI floppy device */
2303c31fac72SShidokht Yadegari if (total_capacity < 160) {
2304c31fac72SShidokht Yadegari /* Less than 80K */
2305c31fac72SShidokht Yadegari *nheadp = 1;
2306c31fac72SShidokht Yadegari *pcylp = total_capacity;
2307c31fac72SShidokht Yadegari *nsectp = 1;
2308c31fac72SShidokht Yadegari return;
2309c31fac72SShidokht Yadegari } else if (total_capacity <= 0x1000) {
2310342440ecSPrasad Singamsetty *nheadp = 2;
2311342440ecSPrasad Singamsetty *pcylp = 80;
2312342440ecSPrasad Singamsetty *nsectp = total_capacity / (80 * 2);
2313342440ecSPrasad Singamsetty return;
2314342440ecSPrasad Singamsetty }
2315342440ecSPrasad Singamsetty
2316342440ecSPrasad Singamsetty /*
2317342440ecSPrasad Singamsetty * For all devices we calculate cylinders using the heads and sectors
2318342440ecSPrasad Singamsetty * we assign based on capacity of the device. The algorithm is
2319342440ecSPrasad Singamsetty * designed to be compatible with the way other operating systems
2320342440ecSPrasad Singamsetty * lay out fdisk tables for X86 and to insure that the cylinders never
2321342440ecSPrasad Singamsetty * exceed 65535 to prevent problems with X86 ioctls that report
2322342440ecSPrasad Singamsetty * geometry.
2323342440ecSPrasad Singamsetty * For some smaller disk sizes we report geometry that matches those
2324342440ecSPrasad Singamsetty * used by X86 BIOS usage. For larger disks, we use SPT that are
2325342440ecSPrasad Singamsetty * multiples of 63, since other OSes that are not limited to 16-bits
2326342440ecSPrasad Singamsetty * for cylinders stop at 63 SPT we make do by using multiples of 63 SPT.
2327342440ecSPrasad Singamsetty *
2328342440ecSPrasad Singamsetty * The following table (in order) illustrates some end result
2329342440ecSPrasad Singamsetty * calculations:
2330342440ecSPrasad Singamsetty *
2331342440ecSPrasad Singamsetty * Maximum number of blocks nhead nsect
2332342440ecSPrasad Singamsetty *
2333342440ecSPrasad Singamsetty * 2097152 (1GB) 64 32
2334342440ecSPrasad Singamsetty * 16777216 (8GB) 128 32
2335342440ecSPrasad Singamsetty * 1052819775 (502.02GB) 255 63
2336342440ecSPrasad Singamsetty * 2105639550 (0.98TB) 255 126
2337342440ecSPrasad Singamsetty * 3158459325 (1.47TB) 255 189
2338342440ecSPrasad Singamsetty * 4211279100 (1.96TB) 255 252
2339342440ecSPrasad Singamsetty * 5264098875 (2.45TB) 255 315
2340342440ecSPrasad Singamsetty * ...
2341342440ecSPrasad Singamsetty */
2342342440ecSPrasad Singamsetty
2343342440ecSPrasad Singamsetty if (total_capacity <= 0x200000) {
2344342440ecSPrasad Singamsetty *nheadp = 64;
2345342440ecSPrasad Singamsetty *nsectp = 32;
2346342440ecSPrasad Singamsetty } else if (total_capacity <= 0x01000000) {
2347342440ecSPrasad Singamsetty *nheadp = 128;
2348342440ecSPrasad Singamsetty *nsectp = 32;
2349342440ecSPrasad Singamsetty } else {
2350342440ecSPrasad Singamsetty *nheadp = 255;
2351342440ecSPrasad Singamsetty
2352342440ecSPrasad Singamsetty /* make nsect be smallest multiple of 63 */
2353342440ecSPrasad Singamsetty *nsectp = ((total_capacity +
2354342440ecSPrasad Singamsetty (UINT16_MAX * 255 * 63) - 1) /
2355342440ecSPrasad Singamsetty (UINT16_MAX * 255 * 63)) * 63;
2356342440ecSPrasad Singamsetty
2357342440ecSPrasad Singamsetty if (*nsectp == 0)
2358342440ecSPrasad Singamsetty *nsectp = (UINT16_MAX / 63) * 63;
2359342440ecSPrasad Singamsetty }
2360342440ecSPrasad Singamsetty
2361342440ecSPrasad Singamsetty if (usable_capacity < total_capacity)
2362342440ecSPrasad Singamsetty *pcylp = usable_capacity / ((*nheadp) * (*nsectp));
2363342440ecSPrasad Singamsetty else
2364342440ecSPrasad Singamsetty *pcylp = total_capacity / ((*nheadp) * (*nsectp));
2365342440ecSPrasad Singamsetty }
2366