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