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