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