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