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