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