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