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 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * This module provides support for labeling operations for target 31 * drivers. 32 */ 33 34 #include <sys/scsi/scsi.h> 35 #include <sys/sunddi.h> 36 #include <sys/dklabel.h> 37 #include <sys/dkio.h> 38 #include <sys/vtoc.h> 39 #include <sys/dktp/fdisk.h> 40 #include <sys/vtrace.h> 41 #include <sys/efi_partition.h> 42 #include <sys/cmlb.h> 43 #include <sys/cmlb_impl.h> 44 #include <sys/ddi_impldefs.h> 45 46 /* 47 * Driver minor node structure and data table 48 */ 49 struct driver_minor_data { 50 char *name; 51 minor_t minor; 52 int type; 53 }; 54 55 static struct driver_minor_data dk_minor_data[] = { 56 {"a", 0, S_IFBLK}, 57 {"b", 1, S_IFBLK}, 58 {"c", 2, S_IFBLK}, 59 {"d", 3, S_IFBLK}, 60 {"e", 4, S_IFBLK}, 61 {"f", 5, S_IFBLK}, 62 {"g", 6, S_IFBLK}, 63 {"h", 7, S_IFBLK}, 64 #if defined(_SUNOS_VTOC_16) 65 {"i", 8, S_IFBLK}, 66 {"j", 9, S_IFBLK}, 67 {"k", 10, S_IFBLK}, 68 {"l", 11, S_IFBLK}, 69 {"m", 12, S_IFBLK}, 70 {"n", 13, S_IFBLK}, 71 {"o", 14, S_IFBLK}, 72 {"p", 15, S_IFBLK}, 73 #endif /* defined(_SUNOS_VTOC_16) */ 74 #if defined(_FIRMWARE_NEEDS_FDISK) 75 {"q", 16, S_IFBLK}, 76 {"r", 17, S_IFBLK}, 77 {"s", 18, S_IFBLK}, 78 {"t", 19, S_IFBLK}, 79 {"u", 20, S_IFBLK}, 80 #endif /* defined(_FIRMWARE_NEEDS_FDISK) */ 81 {"a,raw", 0, S_IFCHR}, 82 {"b,raw", 1, S_IFCHR}, 83 {"c,raw", 2, S_IFCHR}, 84 {"d,raw", 3, S_IFCHR}, 85 {"e,raw", 4, S_IFCHR}, 86 {"f,raw", 5, S_IFCHR}, 87 {"g,raw", 6, S_IFCHR}, 88 {"h,raw", 7, S_IFCHR}, 89 #if defined(_SUNOS_VTOC_16) 90 {"i,raw", 8, S_IFCHR}, 91 {"j,raw", 9, S_IFCHR}, 92 {"k,raw", 10, S_IFCHR}, 93 {"l,raw", 11, S_IFCHR}, 94 {"m,raw", 12, S_IFCHR}, 95 {"n,raw", 13, S_IFCHR}, 96 {"o,raw", 14, S_IFCHR}, 97 {"p,raw", 15, S_IFCHR}, 98 #endif /* defined(_SUNOS_VTOC_16) */ 99 #if defined(_FIRMWARE_NEEDS_FDISK) 100 {"q,raw", 16, S_IFCHR}, 101 {"r,raw", 17, S_IFCHR}, 102 {"s,raw", 18, S_IFCHR}, 103 {"t,raw", 19, S_IFCHR}, 104 {"u,raw", 20, S_IFCHR}, 105 #endif /* defined(_FIRMWARE_NEEDS_FDISK) */ 106 {0} 107 }; 108 109 static struct driver_minor_data dk_minor_data_efi[] = { 110 {"a", 0, S_IFBLK}, 111 {"b", 1, S_IFBLK}, 112 {"c", 2, S_IFBLK}, 113 {"d", 3, S_IFBLK}, 114 {"e", 4, S_IFBLK}, 115 {"f", 5, S_IFBLK}, 116 {"g", 6, S_IFBLK}, 117 {"wd", 7, S_IFBLK}, 118 #if defined(_FIRMWARE_NEEDS_FDISK) 119 {"q", 16, S_IFBLK}, 120 {"r", 17, S_IFBLK}, 121 {"s", 18, S_IFBLK}, 122 {"t", 19, S_IFBLK}, 123 {"u", 20, S_IFBLK}, 124 #endif /* defined(_FIRMWARE_NEEDS_FDISK) */ 125 {"a,raw", 0, S_IFCHR}, 126 {"b,raw", 1, S_IFCHR}, 127 {"c,raw", 2, S_IFCHR}, 128 {"d,raw", 3, S_IFCHR}, 129 {"e,raw", 4, S_IFCHR}, 130 {"f,raw", 5, S_IFCHR}, 131 {"g,raw", 6, S_IFCHR}, 132 {"wd,raw", 7, S_IFCHR}, 133 #if defined(_FIRMWARE_NEEDS_FDISK) 134 {"q,raw", 16, S_IFCHR}, 135 {"r,raw", 17, S_IFCHR}, 136 {"s,raw", 18, S_IFCHR}, 137 {"t,raw", 19, S_IFCHR}, 138 {"u,raw", 20, S_IFCHR}, 139 #endif /* defined(_FIRMWARE_NEEDS_FDISK) */ 140 {0} 141 }; 142 143 /* 144 * Declare the dynamic properties implemented in prop_op(9E) implementation 145 * that we want to have show up in a di_init(3DEVINFO) device tree snapshot 146 * of drivers that call cmlb_attach(). 147 */ 148 static i_ddi_prop_dyn_t cmlb_prop_dyn[] = { 149 {"Nblocks", DDI_PROP_TYPE_INT64, S_IFBLK}, 150 {"Size", DDI_PROP_TYPE_INT64, S_IFCHR}, 151 {"device-nblocks", DDI_PROP_TYPE_INT64}, 152 {"device-blksize", DDI_PROP_TYPE_INT}, 153 {NULL} 154 }; 155 156 /* 157 * External kernel interfaces 158 */ 159 extern struct mod_ops mod_miscops; 160 161 extern int ddi_create_internal_pathname(dev_info_t *dip, char *name, 162 int spec_type, minor_t minor_num); 163 164 /* 165 * Global buffer and mutex for debug logging 166 */ 167 static char cmlb_log_buffer[1024]; 168 static kmutex_t cmlb_log_mutex; 169 170 171 struct cmlb_lun *cmlb_debug_cl = NULL; 172 uint_t cmlb_level_mask = 0x0; 173 174 int cmlb_rot_delay = 4; /* default rotational delay */ 175 176 static struct modlmisc modlmisc = { 177 &mod_miscops, /* Type of module */ 178 "Common Labeling module %I%" 179 }; 180 181 static struct modlinkage modlinkage = { 182 MODREV_1, (void *)&modlmisc, NULL 183 }; 184 185 /* Local function prototypes */ 186 static dev_t cmlb_make_device(struct cmlb_lun *cl); 187 static int cmlb_validate_geometry(struct cmlb_lun *cl, int forcerevalid, 188 int flags, void *tg_cookie); 189 static void cmlb_resync_geom_caches(struct cmlb_lun *cl, diskaddr_t capacity, 190 void *tg_cookie); 191 static int cmlb_read_fdisk(struct cmlb_lun *cl, diskaddr_t capacity, 192 void *tg_cookie); 193 static void cmlb_swap_efi_gpt(efi_gpt_t *e); 194 static void cmlb_swap_efi_gpe(int nparts, efi_gpe_t *p); 195 static int cmlb_validate_efi(efi_gpt_t *labp); 196 static int cmlb_use_efi(struct cmlb_lun *cl, diskaddr_t capacity, int flags, 197 void *tg_cookie); 198 static void cmlb_build_default_label(struct cmlb_lun *cl, void *tg_cookie); 199 static int cmlb_uselabel(struct cmlb_lun *cl, struct dk_label *l, int flags); 200 #if defined(_SUNOS_VTOC_8) 201 static void cmlb_build_user_vtoc(struct cmlb_lun *cl, struct vtoc *user_vtoc); 202 #endif 203 static int cmlb_build_label_vtoc(struct cmlb_lun *cl, struct vtoc *user_vtoc); 204 static int cmlb_write_label(struct cmlb_lun *cl, void *tg_cookie); 205 static int cmlb_set_vtoc(struct cmlb_lun *cl, struct dk_label *dkl, 206 void *tg_cookie); 207 static void cmlb_clear_efi(struct cmlb_lun *cl, void *tg_cookie); 208 static void cmlb_clear_vtoc(struct cmlb_lun *cl, void *tg_cookie); 209 static void cmlb_setup_default_geometry(struct cmlb_lun *cl, void *tg_cookie); 210 static int cmlb_create_minor_nodes(struct cmlb_lun *cl); 211 static int cmlb_check_update_blockcount(struct cmlb_lun *cl, void *tg_cookie); 212 static int cmlb_check_efi_mbr(uchar_t *buf); 213 214 #if defined(__i386) || defined(__amd64) 215 static int cmlb_update_fdisk_and_vtoc(struct cmlb_lun *cl, void *tg_cookie); 216 #endif 217 218 #if defined(_FIRMWARE_NEEDS_FDISK) 219 static int cmlb_has_max_chs_vals(struct ipart *fdp); 220 #endif 221 222 #if defined(_SUNOS_VTOC_16) 223 static void cmlb_convert_geometry(diskaddr_t capacity, struct dk_geom *cl_g); 224 #endif 225 226 static int cmlb_dkio_get_geometry(struct cmlb_lun *cl, caddr_t arg, int flag, 227 void *tg_cookie); 228 static int cmlb_dkio_set_geometry(struct cmlb_lun *cl, caddr_t arg, int flag); 229 static int cmlb_dkio_get_partition(struct cmlb_lun *cl, caddr_t arg, int flag, 230 void *tg_cookie); 231 static int cmlb_dkio_set_partition(struct cmlb_lun *cl, caddr_t arg, int flag); 232 static int cmlb_dkio_get_efi(struct cmlb_lun *cl, caddr_t arg, int flag, 233 void *tg_cookie); 234 static int cmlb_dkio_set_efi(struct cmlb_lun *cl, dev_t dev, caddr_t arg, 235 int flag, void *tg_cookie); 236 static int cmlb_dkio_get_vtoc(struct cmlb_lun *cl, caddr_t arg, int flag, 237 void *tg_cookie); 238 static int cmlb_dkio_set_vtoc(struct cmlb_lun *cl, dev_t dev, caddr_t arg, 239 int flag, void *tg_cookie); 240 static int cmlb_dkio_get_mboot(struct cmlb_lun *cl, caddr_t arg, int flag, 241 void *tg_cookie); 242 static int cmlb_dkio_set_mboot(struct cmlb_lun *cl, caddr_t arg, int flag, 243 void *tg_cookie); 244 static int cmlb_dkio_partition(struct cmlb_lun *cl, caddr_t arg, int flag, 245 void *tg_cookie); 246 247 #if defined(__i386) || defined(__amd64) 248 static int cmlb_dkio_get_virtgeom(struct cmlb_lun *cl, caddr_t arg, int flag); 249 static int cmlb_dkio_get_phygeom(struct cmlb_lun *cl, caddr_t arg, int flag); 250 static int cmlb_dkio_partinfo(struct cmlb_lun *cl, dev_t dev, caddr_t arg, 251 int flag); 252 #endif 253 254 static void cmlb_dbg(uint_t comp, struct cmlb_lun *cl, const char *fmt, ...); 255 static void cmlb_v_log(dev_info_t *dev, char *label, uint_t level, 256 const char *fmt, va_list ap); 257 static void cmlb_log(dev_info_t *dev, char *label, uint_t level, 258 const char *fmt, ...); 259 260 int 261 _init(void) 262 { 263 mutex_init(&cmlb_log_mutex, NULL, MUTEX_DRIVER, NULL); 264 return (mod_install(&modlinkage)); 265 } 266 267 int 268 _info(struct modinfo *modinfop) 269 { 270 return (mod_info(&modlinkage, modinfop)); 271 } 272 273 int 274 _fini(void) 275 { 276 int err; 277 278 if ((err = mod_remove(&modlinkage)) != 0) { 279 return (err); 280 } 281 282 mutex_destroy(&cmlb_log_mutex); 283 return (err); 284 } 285 286 /* 287 * cmlb_dbg is used for debugging to log additional info 288 * Level of output is controlled via cmlb_level_mask setting. 289 */ 290 static void 291 cmlb_dbg(uint_t comp, struct cmlb_lun *cl, const char *fmt, ...) 292 { 293 va_list ap; 294 dev_info_t *dev; 295 uint_t level_mask = 0; 296 297 ASSERT(cl != NULL); 298 dev = CMLB_DEVINFO(cl); 299 ASSERT(dev != NULL); 300 /* 301 * Filter messages based on the global component and level masks, 302 * also print if cl matches the value of cmlb_debug_cl, or if 303 * cmlb_debug_cl is set to NULL. 304 */ 305 if (comp & CMLB_TRACE) 306 level_mask |= CMLB_LOGMASK_TRACE; 307 308 if (comp & CMLB_INFO) 309 level_mask |= CMLB_LOGMASK_INFO; 310 311 if (comp & CMLB_ERROR) 312 level_mask |= CMLB_LOGMASK_ERROR; 313 314 if ((cmlb_level_mask & level_mask) && 315 ((cmlb_debug_cl == NULL) || (cmlb_debug_cl == cl))) { 316 va_start(ap, fmt); 317 cmlb_v_log(dev, CMLB_LABEL(cl), CE_CONT, fmt, ap); 318 va_end(ap); 319 } 320 } 321 322 /* 323 * cmlb_log is basically a duplicate of scsi_log. It is redefined here 324 * so that this module does not depend on scsi module. 325 */ 326 static void 327 cmlb_log(dev_info_t *dev, char *label, uint_t level, const char *fmt, ...) 328 { 329 va_list ap; 330 331 va_start(ap, fmt); 332 cmlb_v_log(dev, label, level, fmt, ap); 333 va_end(ap); 334 } 335 336 static void 337 cmlb_v_log(dev_info_t *dev, char *label, uint_t level, const char *fmt, 338 va_list ap) 339 { 340 static char name[256]; 341 int log_only = 0; 342 int boot_only = 0; 343 int console_only = 0; 344 345 mutex_enter(&cmlb_log_mutex); 346 347 if (dev) { 348 if (level == CE_PANIC || level == CE_WARN || 349 level == CE_NOTE) { 350 (void) sprintf(name, "%s (%s%d):\n", 351 ddi_pathname(dev, cmlb_log_buffer), 352 label, ddi_get_instance(dev)); 353 } else { 354 name[0] = '\0'; 355 } 356 } else { 357 (void) sprintf(name, "%s:", label); 358 } 359 360 (void) vsprintf(cmlb_log_buffer, fmt, ap); 361 362 switch (cmlb_log_buffer[0]) { 363 case '!': 364 log_only = 1; 365 break; 366 case '?': 367 boot_only = 1; 368 break; 369 case '^': 370 console_only = 1; 371 break; 372 } 373 374 switch (level) { 375 case CE_NOTE: 376 level = CE_CONT; 377 /* FALLTHROUGH */ 378 case CE_CONT: 379 case CE_WARN: 380 case CE_PANIC: 381 if (boot_only) { 382 cmn_err(level, "?%s\t%s", name, &cmlb_log_buffer[1]); 383 } else if (console_only) { 384 cmn_err(level, "^%s\t%s", name, &cmlb_log_buffer[1]); 385 } else if (log_only) { 386 cmn_err(level, "!%s\t%s", name, &cmlb_log_buffer[1]); 387 } else { 388 cmn_err(level, "%s\t%s", name, cmlb_log_buffer); 389 } 390 break; 391 case CE_IGNORE: 392 break; 393 default: 394 cmn_err(CE_CONT, "^DEBUG: %s\t%s", name, cmlb_log_buffer); 395 break; 396 } 397 mutex_exit(&cmlb_log_mutex); 398 } 399 400 401 /* 402 * cmlb_alloc_handle: 403 * 404 * Allocates a handle. 405 * 406 * Arguments: 407 * cmlbhandlep pointer to handle 408 * 409 * Notes: 410 * Allocates a handle and stores the allocated handle in the area 411 * pointed to by cmlbhandlep 412 * 413 * Context: 414 * Kernel thread only (can sleep). 415 */ 416 void 417 cmlb_alloc_handle(cmlb_handle_t *cmlbhandlep) 418 { 419 struct cmlb_lun *cl; 420 421 cl = kmem_zalloc(sizeof (struct cmlb_lun), KM_SLEEP); 422 ASSERT(cmlbhandlep != NULL); 423 424 cl->cl_state = CMLB_INITED; 425 cl->cl_def_labeltype = CMLB_LABEL_UNDEF; 426 mutex_init(CMLB_MUTEX(cl), NULL, MUTEX_DRIVER, NULL); 427 428 *cmlbhandlep = (cmlb_handle_t)(cl); 429 } 430 431 /* 432 * cmlb_free_handle 433 * 434 * Frees handle. 435 * 436 * Arguments: 437 * cmlbhandlep pointer to handle 438 */ 439 void 440 cmlb_free_handle(cmlb_handle_t *cmlbhandlep) 441 { 442 struct cmlb_lun *cl; 443 444 cl = (struct cmlb_lun *)*cmlbhandlep; 445 if (cl != NULL) { 446 mutex_destroy(CMLB_MUTEX(cl)); 447 kmem_free(cl, sizeof (struct cmlb_lun)); 448 } 449 450 } 451 452 /* 453 * cmlb_attach: 454 * 455 * Attach handle to device, create minor nodes for device. 456 * 457 * Arguments: 458 * devi pointer to device's dev_info structure. 459 * tgopsp pointer to array of functions cmlb can use to callback 460 * to target driver. 461 * 462 * device_type Peripheral device type as defined in 463 * scsi/generic/inquiry.h 464 * 465 * is_removable whether or not device is removable. 466 * 0 non-removable, 1 removable. 467 * 468 * is_hotpluggable whether or not device is hotpluggable. 469 * 0 non-hotpluggable, 1 hotpluggable. 470 * 471 * node_type minor node type (as used by ddi_create_minor_node) 472 * 473 * alter_behavior 474 * bit flags: 475 * 476 * CMLB_CREATE_ALTSLICE_VTOC_16_DTYPE_DIRECT: create 477 * an alternate slice for the default label, if 478 * device type is DTYPE_DIRECT an architectures default 479 * label type is VTOC16. 480 * Otherwise alternate slice will no be created. 481 * 482 * 483 * CMLB_FAKE_GEOM_LABEL_IOCTLS_VTOC8: report a default 484 * geometry and label for DKIOCGGEOM and DKIOCGVTOC 485 * on architecture with VTOC8 label types. 486 * 487 * CMLB_OFF_BY_ONE: do the workaround for legacy off-by- 488 * one bug in obtaining capacity (in sd): 489 * SCSI READ_CAPACITY command returns the LBA number of the 490 * last logical block, but sd once treated this number as 491 * disks' capacity on x86 platform. And LBAs are addressed 492 * based 0. So the last block was lost on x86 platform. 493 * 494 * Now, we remove this workaround. In order for present sd 495 * driver to work with disks which are labeled/partitioned 496 * via previous sd, we add workaround as follows: 497 * 498 * 1) Locate backup EFI label: cmlb searches the next to 499 * last 500 * block for backup EFI label. If fails, it will 501 * turn to the last block for backup EFI label; 502 * 503 * 2) Clear backup EFI label: cmlb first search the last 504 * block for backup EFI label, and will search the 505 * next to last block only if failed for the last 506 * block. 507 * 508 * 3) Calculate geometry:refer to cmlb_convert_geometry() 509 * If capacity increasing by 1 causes disks' capacity 510 * to cross over the limits in table CHS_values, 511 * geometry info will change. This will raise an issue: 512 * In case that primary VTOC label is destroyed, format 513 * commandline can restore it via backup VTOC labels. 514 * And format locates backup VTOC labels by use of 515 * geometry. So changing geometry will 516 * prevent format from finding backup VTOC labels. To 517 * eliminate this side effect for compatibility, 518 * sd uses (capacity -1) to calculate geometry; 519 * 520 * 4) 1TB disks: some important data structures use 521 * 32-bit signed long/int (for example, daddr_t), 522 * so that sd doesn't support a disk with capacity 523 * larger than 1TB on 32-bit platform. However, 524 * for exactly 1TB disk, it was treated as (1T - 512)B 525 * in the past, and could have valid Solaris 526 * partitions. To workaround this, if an exactly 1TB 527 * disk has Solaris fdisk partition, it will be allowed 528 * to work with sd. 529 * 530 * 531 * 532 * CMLB_FAKE_LABEL_ONE_PARTITION: create s0 and s2 covering 533 * the entire disk, if there is no valid partition info. 534 * If there is a valid Solaris partition, s0 and s2 will 535 * only cover the entire Solaris partition. 536 * 537 * 538 * cmlbhandle cmlb handle associated with device 539 * 540 * tg_cookie cookie from target driver to be passed back to target 541 * driver when we call back to it through tg_ops. 542 * 543 * Notes: 544 * Assumes a default label based on capacity for non-removable devices. 545 * If capacity > 1TB, EFI is assumed otherwise VTOC (default VTOC 546 * for the architecture). 547 * 548 * For removable devices, default label type is assumed to be VTOC 549 * type. Create minor nodes based on a default label type. 550 * Label on the media is not validated. 551 * minor number consists of: 552 * if _SUNOS_VTOC_8 is defined 553 * lowest 3 bits is taken as partition number 554 * the rest is instance number 555 * if _SUNOS_VTOC_16 is defined 556 * lowest 6 bits is taken as partition number 557 * the rest is instance number 558 * 559 * 560 * Return values: 561 * 0 Success 562 * ENXIO creating minor nodes failed. 563 * EINVAL invalid arg, unsupported tg_ops version 564 */ 565 int 566 cmlb_attach(dev_info_t *devi, cmlb_tg_ops_t *tgopsp, int device_type, 567 int is_removable, int is_hotpluggable, char *node_type, 568 int alter_behavior, cmlb_handle_t cmlbhandle, void *tg_cookie) 569 { 570 571 struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle; 572 diskaddr_t cap; 573 int status; 574 575 if (tgopsp->tg_version < TG_DK_OPS_VERSION_1) 576 return (EINVAL); 577 578 mutex_enter(CMLB_MUTEX(cl)); 579 580 CMLB_DEVINFO(cl) = devi; 581 cl->cmlb_tg_ops = tgopsp; 582 cl->cl_device_type = device_type; 583 cl->cl_is_removable = is_removable; 584 cl->cl_is_hotpluggable = is_hotpluggable; 585 cl->cl_node_type = node_type; 586 cl->cl_sys_blocksize = DEV_BSIZE; 587 cl->cl_f_geometry_is_valid = FALSE; 588 cl->cl_def_labeltype = CMLB_LABEL_VTOC; 589 cl->cl_alter_behavior = alter_behavior; 590 cl->cl_reserved = -1; 591 592 if (is_removable != 0) { 593 mutex_exit(CMLB_MUTEX(cl)); 594 status = DK_TG_GETCAP(cl, &cap, tg_cookie); 595 mutex_enter(CMLB_MUTEX(cl)); 596 if (status == 0 && cap > DK_MAX_BLOCKS) { 597 /* set default EFI if > 1TB */ 598 cl->cl_def_labeltype = CMLB_LABEL_EFI; 599 } 600 } 601 602 /* create minor nodes based on default label type */ 603 cl->cl_last_labeltype = CMLB_LABEL_UNDEF; 604 cl->cl_cur_labeltype = CMLB_LABEL_UNDEF; 605 606 if (cmlb_create_minor_nodes(cl) != 0) { 607 mutex_exit(CMLB_MUTEX(cl)); 608 return (ENXIO); 609 } 610 611 /* Define the dynamic properties for devinfo spapshots. */ 612 i_ddi_prop_dyn_driver_set(CMLB_DEVINFO(cl), cmlb_prop_dyn); 613 614 cl->cl_state = CMLB_ATTACHED; 615 616 mutex_exit(CMLB_MUTEX(cl)); 617 return (0); 618 } 619 620 /* 621 * cmlb_detach: 622 * 623 * Invalidate in-core labeling data and remove all minor nodes for 624 * the device associate with handle. 625 * 626 * Arguments: 627 * cmlbhandle cmlb handle associated with device. 628 * 629 * tg_cookie cookie from target driver to be passed back to target 630 * driver when we call back to it through tg_ops. 631 * 632 */ 633 /*ARGSUSED1*/ 634 void 635 cmlb_detach(cmlb_handle_t cmlbhandle, void *tg_cookie) 636 { 637 struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle; 638 639 mutex_enter(CMLB_MUTEX(cl)); 640 cl->cl_def_labeltype = CMLB_LABEL_UNDEF; 641 cl->cl_f_geometry_is_valid = FALSE; 642 ddi_remove_minor_node(CMLB_DEVINFO(cl), NULL); 643 i_ddi_prop_dyn_driver_set(CMLB_DEVINFO(cl), NULL); 644 cl->cl_state = CMLB_INITED; 645 mutex_exit(CMLB_MUTEX(cl)); 646 } 647 648 /* 649 * cmlb_validate: 650 * 651 * Validates label. 652 * 653 * Arguments 654 * cmlbhandle cmlb handle associated with device. 655 * 656 * flags operation flags. used for verbosity control 657 * 658 * tg_cookie cookie from target driver to be passed back to target 659 * driver when we call back to it through tg_ops. 660 * 661 * 662 * Notes: 663 * If new label type is different from the current, adjust minor nodes 664 * accordingly. 665 * 666 * Return values: 667 * 0 success 668 * Note: having fdisk but no solaris partition is assumed 669 * success. 670 * 671 * ENOMEM memory allocation failed 672 * EIO i/o errors during read or get capacity 673 * EACCESS reservation conflicts 674 * EINVAL label was corrupt, or no default label was assumed 675 * ENXIO invalid handle 676 */ 677 int 678 cmlb_validate(cmlb_handle_t cmlbhandle, int flags, void *tg_cookie) 679 { 680 struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle; 681 int rval; 682 int ret = 0; 683 684 /* 685 * Temp work-around checking cl for NULL since there is a bug 686 * in sd_detach calling this routine from taskq_dispatch 687 * inited function. 688 */ 689 if (cl == NULL) 690 return (ENXIO); 691 692 mutex_enter(CMLB_MUTEX(cl)); 693 if (cl->cl_state < CMLB_ATTACHED) { 694 mutex_exit(CMLB_MUTEX(cl)); 695 return (ENXIO); 696 } 697 698 rval = cmlb_validate_geometry((struct cmlb_lun *)cmlbhandle, 1, 699 flags, tg_cookie); 700 701 if (rval == ENOTSUP) { 702 if (cl->cl_f_geometry_is_valid == TRUE) { 703 cl->cl_cur_labeltype = CMLB_LABEL_EFI; 704 ret = 0; 705 } else { 706 ret = EINVAL; 707 } 708 } else { 709 ret = rval; 710 if (ret == 0) 711 cl->cl_cur_labeltype = CMLB_LABEL_VTOC; 712 } 713 714 if (ret == 0) 715 (void) cmlb_create_minor_nodes(cl); 716 717 mutex_exit(CMLB_MUTEX(cl)); 718 return (ret); 719 } 720 721 /* 722 * cmlb_invalidate: 723 * Invalidate in core label data 724 * 725 * Arguments: 726 * cmlbhandle cmlb handle associated with device. 727 * tg_cookie cookie from target driver to be passed back to target 728 * driver when we call back to it through tg_ops. 729 */ 730 /*ARGSUSED1*/ 731 void 732 cmlb_invalidate(cmlb_handle_t cmlbhandle, void *tg_cookie) 733 { 734 struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle; 735 736 if (cl == NULL) 737 return; 738 739 mutex_enter(CMLB_MUTEX(cl)); 740 cl->cl_f_geometry_is_valid = FALSE; 741 mutex_exit(CMLB_MUTEX(cl)); 742 } 743 744 /* 745 * cmlb_is_valid 746 * Get status on whether the incore label/geom data is valid 747 * 748 * Arguments: 749 * cmlbhandle cmlb handle associated with device. 750 * 751 * Return values: 752 * TRUE if incore label/geom data is valid. 753 * FALSE otherwise. 754 * 755 */ 756 757 758 int 759 cmlb_is_valid(cmlb_handle_t cmlbhandle) 760 { 761 struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle; 762 763 if (cmlbhandle == NULL) 764 return (FALSE); 765 766 return (cl->cl_f_geometry_is_valid); 767 768 } 769 770 771 772 /* 773 * cmlb_close: 774 * 775 * Close the device, revert to a default label minor node for the device, 776 * if it is removable. 777 * 778 * Arguments: 779 * cmlbhandle cmlb handle associated with device. 780 * 781 * tg_cookie cookie from target driver to be passed back to target 782 * driver when we call back to it through tg_ops. 783 * Return values: 784 * 0 Success 785 * ENXIO Re-creating minor node failed. 786 */ 787 /*ARGSUSED1*/ 788 int 789 cmlb_close(cmlb_handle_t cmlbhandle, void *tg_cookie) 790 { 791 struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle; 792 793 mutex_enter(CMLB_MUTEX(cl)); 794 cl->cl_f_geometry_is_valid = FALSE; 795 796 /* revert to default minor node for this device */ 797 if (ISREMOVABLE(cl)) { 798 cl->cl_cur_labeltype = CMLB_LABEL_UNDEF; 799 (void) cmlb_create_minor_nodes(cl); 800 } 801 802 mutex_exit(CMLB_MUTEX(cl)); 803 return (0); 804 } 805 806 /* 807 * cmlb_get_devid_block: 808 * get the block number where device id is stored. 809 * 810 * Arguments: 811 * cmlbhandle cmlb handle associated with device. 812 * devidblockp pointer to block number. 813 * tg_cookie cookie from target driver to be passed back to target 814 * driver when we call back to it through tg_ops. 815 * 816 * Notes: 817 * It stores the block number of device id in the area pointed to 818 * by devidblockp. 819 * with the block number of device id. 820 * 821 * Return values: 822 * 0 success 823 * EINVAL device id does not apply to current label type. 824 */ 825 /*ARGSUSED2*/ 826 int 827 cmlb_get_devid_block(cmlb_handle_t cmlbhandle, diskaddr_t *devidblockp, 828 void *tg_cookie) 829 { 830 daddr_t spc, blk, head, cyl; 831 struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle; 832 833 mutex_enter(CMLB_MUTEX(cl)); 834 if (cl->cl_state < CMLB_ATTACHED) { 835 mutex_exit(CMLB_MUTEX(cl)); 836 return (EINVAL); 837 } 838 839 if ((cl->cl_f_geometry_is_valid == FALSE) || 840 (cl->cl_solaris_size < DK_LABEL_LOC)) { 841 mutex_exit(CMLB_MUTEX(cl)); 842 return (EINVAL); 843 } 844 845 if (cl->cl_cur_labeltype == CMLB_LABEL_EFI) { 846 if (cl->cl_reserved != -1) { 847 blk = cl->cl_map[cl->cl_reserved].dkl_cylno; 848 } else { 849 mutex_exit(CMLB_MUTEX(cl)); 850 return (EINVAL); 851 } 852 } else { 853 /* if the disk is unlabeled, don't write a devid to it */ 854 if (!cl->cl_vtoc_label_is_from_media) { 855 mutex_exit(CMLB_MUTEX(cl)); 856 return (EINVAL); 857 } 858 859 /* this geometry doesn't allow us to write a devid */ 860 if (cl->cl_g.dkg_acyl < 2) { 861 mutex_exit(CMLB_MUTEX(cl)); 862 return (EINVAL); 863 } 864 865 /* 866 * Subtract 2 guarantees that the next to last cylinder 867 * is used 868 */ 869 cyl = cl->cl_g.dkg_ncyl + cl->cl_g.dkg_acyl - 2; 870 spc = cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect; 871 head = cl->cl_g.dkg_nhead - 1; 872 blk = cl->cl_solaris_offset + 873 (cyl * (spc - cl->cl_g.dkg_apc)) + 874 (head * cl->cl_g.dkg_nsect) + 1; 875 } 876 877 *devidblockp = blk; 878 mutex_exit(CMLB_MUTEX(cl)); 879 return (0); 880 } 881 882 /* 883 * cmlb_partinfo: 884 * Get partition info for specified partition number. 885 * 886 * Arguments: 887 * cmlbhandle cmlb handle associated with device. 888 * part partition number 889 * nblocksp pointer to number of blocks 890 * startblockp pointer to starting block 891 * partnamep pointer to name of partition 892 * tagp pointer to tag info 893 * tg_cookie cookie from target driver to be passed back to target 894 * driver when we call back to it through tg_ops. 895 * 896 * 897 * Notes: 898 * If in-core label is not valid, this functions tries to revalidate 899 * the label. If label is valid, it stores the total number of blocks 900 * in this partition in the area pointed to by nblocksp, starting 901 * block number in area pointed to by startblockp, pointer to partition 902 * name in area pointed to by partnamep, and tag value in area 903 * pointed by tagp. 904 * For EFI labels, tag value will be set to 0. 905 * 906 * For all nblocksp, startblockp and partnamep, tagp, a value of NULL 907 * indicates the corresponding info is not requested. 908 * 909 * 910 * Return values: 911 * 0 success 912 * EINVAL no valid label or requested partition number is invalid. 913 * 914 */ 915 int 916 cmlb_partinfo(cmlb_handle_t cmlbhandle, int part, diskaddr_t *nblocksp, 917 diskaddr_t *startblockp, char **partnamep, uint16_t *tagp, void *tg_cookie) 918 { 919 920 struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle; 921 int rval; 922 923 ASSERT(cl != NULL); 924 mutex_enter(CMLB_MUTEX(cl)); 925 if (cl->cl_state < CMLB_ATTACHED) { 926 mutex_exit(CMLB_MUTEX(cl)); 927 return (EINVAL); 928 } 929 930 if (part < 0 || part >= MAXPART) { 931 rval = EINVAL; 932 } else { 933 if (cl->cl_f_geometry_is_valid == FALSE) 934 (void) cmlb_validate_geometry((struct cmlb_lun *)cl, 0, 935 0, tg_cookie); 936 937 if ((cl->cl_f_geometry_is_valid == FALSE) || 938 (part < NDKMAP && cl->cl_solaris_size == 0)) { 939 rval = EINVAL; 940 } else { 941 if (startblockp != NULL) 942 *startblockp = (diskaddr_t)cl->cl_offset[part]; 943 944 if (nblocksp != NULL) 945 *nblocksp = (diskaddr_t) 946 cl->cl_map[part].dkl_nblk; 947 948 if (tagp != NULL) 949 if (cl->cl_cur_labeltype == CMLB_LABEL_EFI) 950 *tagp = V_UNASSIGNED; 951 else 952 *tagp = cl->cl_vtoc.v_part[part].p_tag; 953 rval = 0; 954 } 955 956 /* consistent with behavior of sd for getting minor name */ 957 if (partnamep != NULL) 958 *partnamep = dk_minor_data[part].name; 959 960 } 961 962 mutex_exit(CMLB_MUTEX(cl)); 963 return (rval); 964 } 965 966 /* 967 * cmlb_efi_label_capacity: 968 * Get capacity stored in EFI disk label. 969 * 970 * Arguments: 971 * cmlbhandle cmlb handle associated with device. 972 * capacity pointer to capacity stored in EFI disk label. 973 * tg_cookie cookie from target driver to be passed back to target 974 * driver when we call back to it through tg_ops. 975 * 976 * 977 * Notes: 978 * If in-core label is not valid, this functions tries to revalidate 979 * the label. If label is valid and is an EFI label, it stores the capacity 980 * in disk label in the area pointed to by capacity. 981 * 982 * 983 * Return values: 984 * 0 success 985 * EINVAL no valid EFI label or capacity is NULL. 986 * 987 */ 988 int 989 cmlb_efi_label_capacity(cmlb_handle_t cmlbhandle, diskaddr_t *capacity, 990 void *tg_cookie) 991 { 992 struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle; 993 int rval; 994 995 ASSERT(cl != NULL); 996 mutex_enter(CMLB_MUTEX(cl)); 997 if (cl->cl_state < CMLB_ATTACHED) { 998 mutex_exit(CMLB_MUTEX(cl)); 999 return (EINVAL); 1000 } 1001 1002 if (cl->cl_f_geometry_is_valid == FALSE) 1003 (void) cmlb_validate_geometry((struct cmlb_lun *)cl, 0, 1004 0, tg_cookie); 1005 1006 if ((cl->cl_f_geometry_is_valid == FALSE) || (capacity == NULL) || 1007 (cl->cl_cur_labeltype != CMLB_LABEL_EFI)) { 1008 rval = EINVAL; 1009 } else { 1010 *capacity = (diskaddr_t)cl->cl_map[WD_NODE].dkl_nblk; 1011 rval = 0; 1012 } 1013 1014 mutex_exit(CMLB_MUTEX(cl)); 1015 return (rval); 1016 } 1017 1018 /* Caller should make sure Test Unit Ready succeeds before calling this. */ 1019 /*ARGSUSED*/ 1020 int 1021 cmlb_ioctl(cmlb_handle_t cmlbhandle, dev_t dev, int cmd, intptr_t arg, 1022 int flag, cred_t *cred_p, int *rval_p, void *tg_cookie) 1023 { 1024 1025 int err; 1026 struct cmlb_lun *cl; 1027 int status; 1028 1029 cl = (struct cmlb_lun *)cmlbhandle; 1030 1031 ASSERT(cl != NULL); 1032 1033 mutex_enter(CMLB_MUTEX(cl)); 1034 if (cl->cl_state < CMLB_ATTACHED) { 1035 mutex_exit(CMLB_MUTEX(cl)); 1036 return (EIO); 1037 } 1038 1039 switch (cmd) { 1040 case DKIOCSVTOC: 1041 case DKIOCSGEOM: 1042 case DKIOCSETEFI: 1043 case DKIOCSMBOOT: 1044 break; 1045 default: 1046 status = cmlb_validate_geometry(cl, 1, CMLB_SILENT, 1047 tg_cookie); 1048 1049 /* 1050 * VTOC related ioctls except SVTOC/SGEOM should 1051 * fail if > 1TB disk and there is not already a VTOC 1052 * on the disk.i.e either EFI or blank 1053 * 1054 * PHYGEOM AND VIRTGEOM succeeds when disk is 1055 * EFI labeled but <1TB 1056 */ 1057 1058 if (status == ENOTSUP && 1059 cl->cl_f_geometry_is_valid == FALSE) { 1060 switch (cmd) { 1061 case DKIOCGAPART: 1062 case DKIOCGGEOM: 1063 case DKIOCGVTOC: 1064 case DKIOCSAPART: 1065 case DKIOCG_PHYGEOM: 1066 case DKIOCG_VIRTGEOM: 1067 1068 mutex_exit(CMLB_MUTEX(cl)); 1069 return (ENOTSUP); 1070 } 1071 } else { 1072 if ((cl->cl_f_geometry_is_valid == TRUE) && 1073 (cl->cl_solaris_size > 0)) { 1074 if (cl->cl_vtoc.v_sanity != VTOC_SANE) { 1075 /* 1076 * it is EFI, so return ENOTSUP for 1077 * these 1078 */ 1079 switch (cmd) { 1080 case DKIOCGAPART: 1081 case DKIOCGGEOM: 1082 case DKIOCGVTOC: 1083 case DKIOCSVTOC: 1084 case DKIOCSAPART: 1085 1086 mutex_exit(CMLB_MUTEX(cl)); 1087 return (ENOTSUP); 1088 } 1089 } 1090 } 1091 } 1092 } 1093 1094 mutex_exit(CMLB_MUTEX(cl)); 1095 1096 switch (cmd) { 1097 case DKIOCGGEOM: 1098 cmlb_dbg(CMLB_TRACE, cl, "DKIOCGGEOM\n"); 1099 err = cmlb_dkio_get_geometry(cl, (caddr_t)arg, flag, tg_cookie); 1100 break; 1101 1102 case DKIOCSGEOM: 1103 cmlb_dbg(CMLB_TRACE, cl, "DKIOCSGEOM\n"); 1104 err = cmlb_dkio_set_geometry(cl, (caddr_t)arg, flag); 1105 break; 1106 1107 case DKIOCGAPART: 1108 cmlb_dbg(CMLB_TRACE, cl, "DKIOCGAPART\n"); 1109 err = cmlb_dkio_get_partition(cl, (caddr_t)arg, 1110 flag, tg_cookie); 1111 break; 1112 1113 case DKIOCSAPART: 1114 cmlb_dbg(CMLB_TRACE, cl, "DKIOCSAPART\n"); 1115 err = cmlb_dkio_set_partition(cl, (caddr_t)arg, flag); 1116 break; 1117 1118 case DKIOCGVTOC: 1119 cmlb_dbg(CMLB_TRACE, cl, "DKIOCGVTOC\n"); 1120 err = cmlb_dkio_get_vtoc(cl, (caddr_t)arg, flag, tg_cookie); 1121 break; 1122 1123 case DKIOCGETEFI: 1124 cmlb_dbg(CMLB_TRACE, cl, "DKIOCGETEFI\n"); 1125 err = cmlb_dkio_get_efi(cl, (caddr_t)arg, flag, tg_cookie); 1126 break; 1127 1128 case DKIOCPARTITION: 1129 cmlb_dbg(CMLB_TRACE, cl, "DKIOCPARTITION\n"); 1130 err = cmlb_dkio_partition(cl, (caddr_t)arg, flag, tg_cookie); 1131 break; 1132 1133 case DKIOCSVTOC: 1134 cmlb_dbg(CMLB_TRACE, cl, "DKIOCSVTOC\n"); 1135 err = cmlb_dkio_set_vtoc(cl, dev, (caddr_t)arg, flag, 1136 tg_cookie); 1137 break; 1138 1139 case DKIOCSETEFI: 1140 cmlb_dbg(CMLB_TRACE, cl, "DKIOCSETEFI\n"); 1141 err = cmlb_dkio_set_efi(cl, dev, (caddr_t)arg, flag, tg_cookie); 1142 break; 1143 1144 case DKIOCGMBOOT: 1145 cmlb_dbg(CMLB_TRACE, cl, "DKIOCGMBOOT\n"); 1146 err = cmlb_dkio_get_mboot(cl, (caddr_t)arg, flag, tg_cookie); 1147 break; 1148 1149 case DKIOCSMBOOT: 1150 cmlb_dbg(CMLB_TRACE, cl, "DKIOCSMBOOT\n"); 1151 err = cmlb_dkio_set_mboot(cl, (caddr_t)arg, flag, tg_cookie); 1152 break; 1153 case DKIOCG_PHYGEOM: 1154 cmlb_dbg(CMLB_TRACE, cl, "DKIOCG_PHYGEOM\n"); 1155 #if defined(__i386) || defined(__amd64) 1156 err = cmlb_dkio_get_phygeom(cl, (caddr_t)arg, flag); 1157 #else 1158 err = ENOTTY; 1159 #endif 1160 break; 1161 case DKIOCG_VIRTGEOM: 1162 cmlb_dbg(CMLB_TRACE, cl, "DKIOCG_VIRTGEOM\n"); 1163 #if defined(__i386) || defined(__amd64) 1164 err = cmlb_dkio_get_virtgeom(cl, (caddr_t)arg, flag); 1165 #else 1166 err = ENOTTY; 1167 #endif 1168 break; 1169 case DKIOCPARTINFO: 1170 cmlb_dbg(CMLB_TRACE, cl, "DKIOCPARTINFO"); 1171 #if defined(__i386) || defined(__amd64) 1172 err = cmlb_dkio_partinfo(cl, dev, (caddr_t)arg, flag); 1173 #else 1174 err = ENOTTY; 1175 #endif 1176 break; 1177 1178 default: 1179 err = ENOTTY; 1180 1181 } 1182 1183 /* 1184 * An ioctl that succeeds and changed ('set') size(9P) information 1185 * needs to invalidate the cached devinfo snapshot to avoid having 1186 * old information being returned in a snapshots. 1187 * 1188 * NB: When available, call ddi_change_minor_node() to clear 1189 * SSIZEVALID in specfs vnodes via spec_size_invalidate(). 1190 */ 1191 if (err == 0) { 1192 switch (cmd) { 1193 case DKIOCSGEOM: 1194 case DKIOCSAPART: 1195 case DKIOCSVTOC: 1196 case DKIOCSETEFI: 1197 i_ddi_prop_dyn_cache_invalidate(CMLB_DEVINFO(cl), 1198 i_ddi_prop_dyn_driver_get(CMLB_DEVINFO(cl))); 1199 } 1200 } 1201 return (err); 1202 } 1203 1204 dev_t 1205 cmlb_make_device(struct cmlb_lun *cl) 1206 { 1207 return (makedevice(ddi_name_to_major(ddi_get_name(CMLB_DEVINFO(cl))), 1208 ddi_get_instance(CMLB_DEVINFO(cl)) << CMLBUNIT_SHIFT)); 1209 } 1210 1211 /* 1212 * Function: cmlb_check_update_blockcount 1213 * 1214 * Description: If current capacity value is invalid, obtains the 1215 * current capacity from target driver. 1216 * 1217 * Return Code: 0 success 1218 * EIO failure 1219 */ 1220 static int 1221 cmlb_check_update_blockcount(struct cmlb_lun *cl, void *tg_cookie) 1222 { 1223 int status; 1224 diskaddr_t capacity; 1225 uint32_t lbasize; 1226 1227 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 1228 1229 if (cl->cl_f_geometry_is_valid == FALSE) { 1230 mutex_exit(CMLB_MUTEX(cl)); 1231 status = DK_TG_GETCAP(cl, &capacity, tg_cookie); 1232 if (status != 0) { 1233 mutex_enter(CMLB_MUTEX(cl)); 1234 return (EIO); 1235 } 1236 1237 status = DK_TG_GETBLOCKSIZE(cl, &lbasize, tg_cookie); 1238 mutex_enter(CMLB_MUTEX(cl)); 1239 if (status != 0) 1240 return (EIO); 1241 1242 if ((capacity != 0) && (lbasize != 0)) { 1243 cl->cl_blockcount = capacity; 1244 cl->cl_tgt_blocksize = lbasize; 1245 return (0); 1246 } else 1247 return (EIO); 1248 } else 1249 return (0); 1250 } 1251 1252 static int 1253 cmlb_create_minor(dev_info_t *dip, char *name, int spec_type, 1254 minor_t minor_num, char *node_type, int flag, boolean_t internal) 1255 { 1256 if (internal) 1257 return (ddi_create_internal_pathname(dip, 1258 name, spec_type, minor_num)); 1259 else 1260 return (ddi_create_minor_node(dip, 1261 name, spec_type, minor_num, node_type, flag)); 1262 } 1263 1264 /* 1265 * Function: cmlb_create_minor_nodes 1266 * 1267 * Description: Create or adjust the minor device nodes for the instance. 1268 * Minor nodes are created based on default label type, 1269 * current label type and last label type we created 1270 * minor nodes based on. 1271 * 1272 * 1273 * Arguments: cl - driver soft state (unit) structure 1274 * 1275 * Return Code: 0 success 1276 * ENXIO failure. 1277 * 1278 * Context: Kernel thread context 1279 */ 1280 static int 1281 cmlb_create_minor_nodes(struct cmlb_lun *cl) 1282 { 1283 struct driver_minor_data *dmdp; 1284 int instance; 1285 char name[48]; 1286 cmlb_label_t newlabeltype; 1287 boolean_t internal; 1288 1289 ASSERT(cl != NULL); 1290 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 1291 1292 internal = ((cl->cl_alter_behavior & (CMLB_INTERNAL_MINOR_NODES)) != 0); 1293 1294 /* check the most common case */ 1295 if (cl->cl_cur_labeltype != CMLB_LABEL_UNDEF && 1296 cl->cl_last_labeltype == cl->cl_cur_labeltype) { 1297 /* do nothing */ 1298 return (0); 1299 } 1300 1301 if (cl->cl_def_labeltype == CMLB_LABEL_UNDEF) { 1302 /* we should never get here */ 1303 return (ENXIO); 1304 } 1305 1306 if (cl->cl_last_labeltype == CMLB_LABEL_UNDEF) { 1307 /* first time during attach */ 1308 newlabeltype = cl->cl_def_labeltype; 1309 1310 instance = ddi_get_instance(CMLB_DEVINFO(cl)); 1311 1312 /* Create all the minor nodes for this target. */ 1313 dmdp = (newlabeltype == CMLB_LABEL_EFI) ? dk_minor_data_efi : 1314 dk_minor_data; 1315 while (dmdp->name != NULL) { 1316 1317 (void) sprintf(name, "%s", dmdp->name); 1318 1319 if (cmlb_create_minor(CMLB_DEVINFO(cl), name, 1320 dmdp->type, 1321 (instance << CMLBUNIT_SHIFT) | dmdp->minor, 1322 cl->cl_node_type, NULL, internal) == DDI_FAILURE) { 1323 /* 1324 * Clean up any nodes that may have been 1325 * created, in case this fails in the middle 1326 * of the loop. 1327 */ 1328 ddi_remove_minor_node(CMLB_DEVINFO(cl), NULL); 1329 return (ENXIO); 1330 } 1331 dmdp++; 1332 } 1333 cl->cl_last_labeltype = newlabeltype; 1334 return (0); 1335 } 1336 1337 /* Not first time */ 1338 if (cl->cl_cur_labeltype == CMLB_LABEL_UNDEF) { 1339 if (cl->cl_last_labeltype != cl->cl_def_labeltype) { 1340 /* close time, revert to default. */ 1341 newlabeltype = cl->cl_def_labeltype; 1342 } else { 1343 /* 1344 * do nothing since the type for which we last created 1345 * nodes matches the default 1346 */ 1347 return (0); 1348 } 1349 } else { 1350 if (cl->cl_cur_labeltype != cl->cl_last_labeltype) { 1351 /* We are not closing, use current label type */ 1352 newlabeltype = cl->cl_cur_labeltype; 1353 } else { 1354 /* 1355 * do nothing since the type for which we last created 1356 * nodes matches the current label type 1357 */ 1358 return (0); 1359 } 1360 } 1361 1362 instance = ddi_get_instance(CMLB_DEVINFO(cl)); 1363 1364 /* 1365 * Currently we only fix up the s7 node when we are switching 1366 * label types from or to EFI. This is consistent with 1367 * current behavior of sd. 1368 */ 1369 if (newlabeltype == CMLB_LABEL_EFI && 1370 cl->cl_last_labeltype != CMLB_LABEL_EFI) { 1371 /* from vtoc to EFI */ 1372 ddi_remove_minor_node(CMLB_DEVINFO(cl), "h"); 1373 ddi_remove_minor_node(CMLB_DEVINFO(cl), "h,raw"); 1374 (void) cmlb_create_minor(CMLB_DEVINFO(cl), "wd", 1375 S_IFBLK, (instance << CMLBUNIT_SHIFT) | WD_NODE, 1376 cl->cl_node_type, NULL, internal); 1377 (void) cmlb_create_minor(CMLB_DEVINFO(cl), "wd,raw", 1378 S_IFCHR, (instance << CMLBUNIT_SHIFT) | WD_NODE, 1379 cl->cl_node_type, NULL, internal); 1380 } else { 1381 /* from efi to vtoc */ 1382 ddi_remove_minor_node(CMLB_DEVINFO(cl), "wd"); 1383 ddi_remove_minor_node(CMLB_DEVINFO(cl), "wd,raw"); 1384 (void) cmlb_create_minor(CMLB_DEVINFO(cl), "h", 1385 S_IFBLK, (instance << CMLBUNIT_SHIFT) | WD_NODE, 1386 cl->cl_node_type, NULL, internal); 1387 (void) cmlb_create_minor(CMLB_DEVINFO(cl), "h,raw", 1388 S_IFCHR, (instance << CMLBUNIT_SHIFT) | WD_NODE, 1389 cl->cl_node_type, NULL, internal); 1390 } 1391 1392 cl->cl_last_labeltype = newlabeltype; 1393 return (0); 1394 } 1395 1396 /* 1397 * Function: cmlb_validate_geometry 1398 * 1399 * Description: Read the label from the disk (if present). Update the unit's 1400 * geometry and vtoc information from the data in the label. 1401 * Verify that the label is valid. 1402 * 1403 * Arguments: 1404 * cl driver soft state (unit) structure 1405 * 1406 * forcerevalid force revalidation even if we are already valid. 1407 * flags operation flags from target driver. Used for verbosity 1408 * control at this time. 1409 * tg_cookie cookie from target driver to be passed back to target 1410 * driver when we call back to it through tg_ops. 1411 * 1412 * Return Code: 0 - Successful completion 1413 * EINVAL - Invalid value in cl->cl_tgt_blocksize or 1414 * cl->cl_blockcount; or label on disk is corrupted 1415 * or unreadable. 1416 * EACCES - Reservation conflict at the device. 1417 * ENOMEM - Resource allocation error 1418 * ENOTSUP - geometry not applicable 1419 * 1420 * Context: Kernel thread only (can sleep). 1421 */ 1422 static int 1423 cmlb_validate_geometry(struct cmlb_lun *cl, int forcerevalid, int flags, 1424 void *tg_cookie) 1425 { 1426 int label_error = 0; 1427 diskaddr_t capacity; 1428 int count; 1429 #if defined(__i386) || defined(__amd64) 1430 int forced_under_1t = 0; 1431 #endif 1432 1433 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 1434 1435 if ((cl->cl_f_geometry_is_valid == TRUE) && (forcerevalid == 0)) { 1436 if (cl->cl_cur_labeltype == CMLB_LABEL_EFI) 1437 return (ENOTSUP); 1438 return (0); 1439 } 1440 1441 if (cmlb_check_update_blockcount(cl, tg_cookie) != 0) 1442 return (EIO); 1443 1444 capacity = cl->cl_blockcount; 1445 1446 #if defined(_SUNOS_VTOC_16) 1447 /* 1448 * Set up the "whole disk" fdisk partition; this should always 1449 * exist, regardless of whether the disk contains an fdisk table 1450 * or vtoc. 1451 */ 1452 cl->cl_map[P0_RAW_DISK].dkl_cylno = 0; 1453 /* 1454 * note if capacity > uint32_max we should be using efi, 1455 * and not use p0, so the truncation does not matter. 1456 */ 1457 cl->cl_map[P0_RAW_DISK].dkl_nblk = capacity; 1458 #endif 1459 /* 1460 * Refresh the logical and physical geometry caches. 1461 * (data from MODE SENSE format/rigid disk geometry pages, 1462 * and scsi_ifgetcap("geometry"). 1463 */ 1464 cmlb_resync_geom_caches(cl, capacity, tg_cookie); 1465 1466 label_error = cmlb_use_efi(cl, capacity, flags, tg_cookie); 1467 if (label_error == 0) { 1468 1469 /* found a valid EFI label */ 1470 cmlb_dbg(CMLB_TRACE, cl, 1471 "cmlb_validate_geometry: found EFI label\n"); 1472 /* 1473 * solaris_size and geometry_is_valid are set in 1474 * cmlb_use_efi 1475 */ 1476 return (ENOTSUP); 1477 } 1478 1479 /* NO EFI label found */ 1480 1481 if (capacity > DK_MAX_BLOCKS) { 1482 if (label_error == ESRCH) { 1483 /* 1484 * they've configured a LUN over 1TB, but used 1485 * format.dat to restrict format's view of the 1486 * capacity to be under 1TB 1487 */ 1488 /* i.e > 1Tb with a VTOC < 1TB */ 1489 if (!(flags & CMLB_SILENT)) { 1490 cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl), 1491 CE_WARN, "is >1TB and has a VTOC label: " 1492 "use format(1M) to either decrease the"); 1493 1494 cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl), 1495 CE_NOTE, "size to be < 1TB or relabel the " 1496 "disk with an EFI label"); 1497 #if defined(__i386) || defined(__amd64) 1498 forced_under_1t = 1; 1499 #endif 1500 } 1501 } else { 1502 /* unlabeled disk over 1TB */ 1503 #if defined(__i386) || defined(__amd64) 1504 1505 /* 1506 * Refer to comments on off-by-1 at the head of the file 1507 * A 1TB disk was treated as (1T - 512)B in the past, 1508 * thus, it might have valid solaris partition. We 1509 * will return ENOTSUP later only if this disk has no 1510 * valid solaris partition. 1511 */ 1512 if (!(cl->cl_alter_behavior & CMLB_OFF_BY_ONE) || 1513 (cl->cl_sys_blocksize != cl->cl_tgt_blocksize) || 1514 (capacity - 1 > DK_MAX_BLOCKS)) 1515 #endif 1516 return (ENOTSUP); 1517 } 1518 } 1519 1520 label_error = 0; 1521 1522 /* 1523 * at this point it is either labeled with a VTOC or it is 1524 * under 1TB (<= 1TB actually for off-by-1) 1525 */ 1526 1527 /* 1528 * Only DIRECT ACCESS devices will have Scl labels. 1529 * CD's supposedly have a Scl label, too 1530 */ 1531 if (cl->cl_device_type == DTYPE_DIRECT || ISREMOVABLE(cl)) { 1532 struct dk_label *dkl; 1533 offset_t label_addr; 1534 int rval; 1535 size_t buffer_size; 1536 1537 /* 1538 * Note: This will set up cl->cl_solaris_size and 1539 * cl->cl_solaris_offset. 1540 */ 1541 rval = cmlb_read_fdisk(cl, capacity, tg_cookie); 1542 if ((rval != 0) && !ISCD(cl)) { 1543 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 1544 return (rval); 1545 } 1546 1547 if (cl->cl_solaris_size <= DK_LABEL_LOC) { 1548 1549 #if defined(__i386) || defined(__amd64) 1550 /* 1551 * Refer to comments on off-by-1 at the head of the file 1552 * This is for 1TB disk only. Since that there is no 1553 * solaris partitions, return ENOTSUP as we do for 1554 * >1TB disk. 1555 */ 1556 if (cl->cl_blockcount > DK_MAX_BLOCKS) 1557 return (ENOTSUP); 1558 #endif 1559 /* 1560 * Found fdisk table but no Solaris partition entry, 1561 * so don't call cmlb_uselabel() and don't create 1562 * a default label. 1563 */ 1564 label_error = 0; 1565 cl->cl_f_geometry_is_valid = TRUE; 1566 goto no_solaris_partition; 1567 } 1568 1569 label_addr = (daddr_t)(cl->cl_solaris_offset + DK_LABEL_LOC); 1570 1571 #if defined(__i386) || defined(__amd64) 1572 /* 1573 * Refer to comments on off-by-1 at the head of the file 1574 * Now, this 1TB disk has valid solaris partition. It 1575 * must be created by previous sd driver, we have to 1576 * treat it as (1T-512)B. 1577 */ 1578 if ((cl->cl_blockcount > DK_MAX_BLOCKS) && 1579 (forced_under_1t != 1)) { 1580 /* 1581 * Refer to cmlb_read_fdisk, when there is no 1582 * fdisk partition table, cl_solaris_size is 1583 * set to disk's capacity. In this case, we 1584 * need to adjust it 1585 */ 1586 if (cl->cl_solaris_size > DK_MAX_BLOCKS) 1587 cl->cl_solaris_size = DK_MAX_BLOCKS; 1588 cmlb_resync_geom_caches(cl, DK_MAX_BLOCKS, tg_cookie); 1589 } 1590 #endif 1591 1592 buffer_size = sizeof (struct dk_label); 1593 1594 cmlb_dbg(CMLB_TRACE, cl, "cmlb_validate_geometry: " 1595 "label_addr: 0x%x allocation size: 0x%x\n", 1596 label_addr, buffer_size); 1597 1598 if ((dkl = kmem_zalloc(buffer_size, KM_NOSLEEP)) == NULL) 1599 return (ENOMEM); 1600 1601 mutex_exit(CMLB_MUTEX(cl)); 1602 rval = DK_TG_READ(cl, dkl, label_addr, buffer_size, tg_cookie); 1603 mutex_enter(CMLB_MUTEX(cl)); 1604 1605 switch (rval) { 1606 case 0: 1607 /* 1608 * cmlb_uselabel will establish that the geometry 1609 * is valid. 1610 */ 1611 if (cmlb_uselabel(cl, 1612 (struct dk_label *)(uintptr_t)dkl, flags) != 1613 CMLB_LABEL_IS_VALID) { 1614 label_error = EINVAL; 1615 } else 1616 cl->cl_vtoc_label_is_from_media = 1; 1617 break; 1618 case EACCES: 1619 label_error = EACCES; 1620 break; 1621 default: 1622 label_error = EINVAL; 1623 break; 1624 } 1625 1626 kmem_free(dkl, buffer_size); 1627 } 1628 1629 /* 1630 * If a valid label was not found, AND if no reservation conflict 1631 * was detected, then go ahead and create a default label (4069506). 1632 * 1633 * Note: currently, for VTOC_8 devices, the default label is created 1634 * for removables and hotpluggables only. For VTOC_16 devices, the 1635 * default label will be created for all devices. 1636 * (see cmlb_build_default_label) 1637 */ 1638 #if defined(_SUNOS_VTOC_8) 1639 if ((ISREMOVABLE(cl) || ISHOTPLUGGABLE(cl)) && 1640 (label_error != EACCES)) { 1641 #elif defined(_SUNOS_VTOC_16) 1642 if (label_error != EACCES) { 1643 #endif 1644 if (cl->cl_f_geometry_is_valid == FALSE) { 1645 cmlb_build_default_label(cl, tg_cookie); 1646 } 1647 label_error = 0; 1648 } 1649 1650 no_solaris_partition: 1651 1652 #if defined(_SUNOS_VTOC_16) 1653 /* 1654 * If we have valid geometry, set up the remaining fdisk partitions. 1655 * Note that dkl_cylno is not used for the fdisk map entries, so 1656 * we set it to an entirely bogus value. 1657 */ 1658 for (count = 0; count < FD_NUMPART; count++) { 1659 cl->cl_map[FDISK_P1 + count].dkl_cylno = -1; 1660 cl->cl_map[FDISK_P1 + count].dkl_nblk = 1661 cl->cl_fmap[count].fmap_nblk; 1662 1663 cl->cl_offset[FDISK_P1 + count] = 1664 cl->cl_fmap[count].fmap_start; 1665 } 1666 #endif 1667 1668 for (count = 0; count < NDKMAP; count++) { 1669 #if defined(_SUNOS_VTOC_8) 1670 struct dk_map *lp = &cl->cl_map[count]; 1671 cl->cl_offset[count] = 1672 cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect * lp->dkl_cylno; 1673 #elif defined(_SUNOS_VTOC_16) 1674 struct dkl_partition *vp = &cl->cl_vtoc.v_part[count]; 1675 1676 cl->cl_offset[count] = vp->p_start + cl->cl_solaris_offset; 1677 #else 1678 #error "No VTOC format defined." 1679 #endif 1680 } 1681 1682 return (label_error); 1683 } 1684 1685 #if defined(_SUNOS_VTOC_16) 1686 /* 1687 * Macro: MAX_BLKS 1688 * 1689 * This macro is used for table entries where we need to have the largest 1690 * possible sector value for that head & SPT (sectors per track) 1691 * combination. Other entries for some smaller disk sizes are set by 1692 * convention to match those used by X86 BIOS usage. 1693 */ 1694 #define MAX_BLKS(heads, spt) UINT16_MAX * heads * spt, heads, spt 1695 1696 /* 1697 * Function: cmlb_convert_geometry 1698 * 1699 * Description: Convert physical geometry into a dk_geom structure. In 1700 * other words, make sure we don't wrap 16-bit values. 1701 * e.g. converting from geom_cache to dk_geom 1702 * 1703 * Context: Kernel thread only 1704 */ 1705 static void 1706 cmlb_convert_geometry(diskaddr_t capacity, struct dk_geom *cl_g) 1707 { 1708 int i; 1709 static const struct chs_values { 1710 uint_t max_cap; /* Max Capacity for this HS. */ 1711 uint_t nhead; /* Heads to use. */ 1712 uint_t nsect; /* SPT to use. */ 1713 } CHS_values[] = { 1714 {0x00200000, 64, 32}, /* 1GB or smaller disk. */ 1715 {0x01000000, 128, 32}, /* 8GB or smaller disk. */ 1716 {MAX_BLKS(255, 63)}, /* 502.02GB or smaller disk. */ 1717 {MAX_BLKS(255, 126)}, /* .98TB or smaller disk. */ 1718 {DK_MAX_BLOCKS, 255, 189} /* Max size is just under 1TB */ 1719 }; 1720 1721 /* Unlabeled SCSI floppy device */ 1722 if (capacity <= 0x1000) { 1723 cl_g->dkg_nhead = 2; 1724 cl_g->dkg_ncyl = 80; 1725 cl_g->dkg_nsect = capacity / (cl_g->dkg_nhead * cl_g->dkg_ncyl); 1726 return; 1727 } 1728 1729 /* 1730 * For all devices we calculate cylinders using the 1731 * heads and sectors we assign based on capacity of the 1732 * device. The table is designed to be compatible with the 1733 * way other operating systems lay out fdisk tables for X86 1734 * and to insure that the cylinders never exceed 65535 to 1735 * prevent problems with X86 ioctls that report geometry. 1736 * We use SPT that are multiples of 63, since other OSes that 1737 * are not limited to 16-bits for cylinders stop at 63 SPT 1738 * we make do by using multiples of 63 SPT. 1739 * 1740 * Note than capacities greater than or equal to 1TB will simply 1741 * get the largest geometry from the table. This should be okay 1742 * since disks this large shouldn't be using CHS values anyway. 1743 */ 1744 for (i = 0; CHS_values[i].max_cap < capacity && 1745 CHS_values[i].max_cap != DK_MAX_BLOCKS; i++) 1746 ; 1747 1748 cl_g->dkg_nhead = CHS_values[i].nhead; 1749 cl_g->dkg_nsect = CHS_values[i].nsect; 1750 } 1751 #endif 1752 1753 /* 1754 * Function: cmlb_resync_geom_caches 1755 * 1756 * Description: (Re)initialize both geometry caches: the virtual geometry 1757 * information is extracted from the HBA (the "geometry" 1758 * capability), and the physical geometry cache data is 1759 * generated by issuing MODE SENSE commands. 1760 * 1761 * Arguments: 1762 * cl driver soft state (unit) structure 1763 * capacity disk capacity in #blocks 1764 * tg_cookie cookie from target driver to be passed back to target 1765 * driver when we call back to it through tg_ops. 1766 * 1767 * Context: Kernel thread only (can sleep). 1768 */ 1769 static void 1770 cmlb_resync_geom_caches(struct cmlb_lun *cl, diskaddr_t capacity, 1771 void *tg_cookie) 1772 { 1773 struct cmlb_geom pgeom; 1774 struct cmlb_geom lgeom; 1775 struct cmlb_geom *pgeomp = &pgeom; 1776 unsigned short nhead; 1777 unsigned short nsect; 1778 int spc; 1779 int ret; 1780 1781 ASSERT(cl != NULL); 1782 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 1783 1784 /* 1785 * Ask the controller for its logical geometry. 1786 * Note: if the HBA does not support scsi_ifgetcap("geometry"), 1787 * then the lgeom cache will be invalid. 1788 */ 1789 mutex_exit(CMLB_MUTEX(cl)); 1790 bzero(&lgeom, sizeof (struct cmlb_geom)); 1791 ret = DK_TG_GETVIRTGEOM(cl, &lgeom, tg_cookie); 1792 mutex_enter(CMLB_MUTEX(cl)); 1793 1794 bcopy(&lgeom, &cl->cl_lgeom, sizeof (cl->cl_lgeom)); 1795 1796 /* 1797 * Initialize the pgeom cache from lgeom, so that if MODE SENSE 1798 * doesn't work, DKIOCG_PHYSGEOM can return reasonable values. 1799 */ 1800 if (ret != 0 || cl->cl_lgeom.g_nsect == 0 || 1801 cl->cl_lgeom.g_nhead == 0) { 1802 /* 1803 * Note: Perhaps this needs to be more adaptive? The rationale 1804 * is that, if there's no HBA geometry from the HBA driver, any 1805 * guess is good, since this is the physical geometry. If MODE 1806 * SENSE fails this gives a max cylinder size for non-LBA access 1807 */ 1808 nhead = 255; 1809 nsect = 63; 1810 } else { 1811 nhead = cl->cl_lgeom.g_nhead; 1812 nsect = cl->cl_lgeom.g_nsect; 1813 } 1814 1815 if (ISCD(cl)) { 1816 pgeomp->g_nhead = 1; 1817 pgeomp->g_nsect = nsect * nhead; 1818 } else { 1819 pgeomp->g_nhead = nhead; 1820 pgeomp->g_nsect = nsect; 1821 } 1822 1823 spc = pgeomp->g_nhead * pgeomp->g_nsect; 1824 pgeomp->g_capacity = capacity; 1825 pgeomp->g_ncyl = pgeomp->g_capacity / spc; 1826 pgeomp->g_acyl = 0; 1827 1828 /* 1829 * Retrieve fresh geometry data from the hardware, stash it 1830 * here temporarily before we rebuild the incore label. 1831 * 1832 * We want to use the MODE SENSE commands to derive the 1833 * physical geometry of the device, but if either command 1834 * fails, the logical geometry is used as the fallback for 1835 * disk label geometry. 1836 */ 1837 1838 mutex_exit(CMLB_MUTEX(cl)); 1839 (void) DK_TG_GETPHYGEOM(cl, pgeomp, tg_cookie); 1840 mutex_enter(CMLB_MUTEX(cl)); 1841 1842 /* 1843 * Now update the real copy while holding the mutex. This 1844 * way the global copy is never in an inconsistent state. 1845 */ 1846 bcopy(pgeomp, &cl->cl_pgeom, sizeof (cl->cl_pgeom)); 1847 1848 cmlb_dbg(CMLB_INFO, cl, "cmlb_resync_geom_caches: " 1849 "(cached from lgeom)\n"); 1850 cmlb_dbg(CMLB_INFO, cl, 1851 " ncyl: %ld; acyl: %d; nhead: %d; nsect: %d\n", 1852 cl->cl_pgeom.g_ncyl, cl->cl_pgeom.g_acyl, 1853 cl->cl_pgeom.g_nhead, cl->cl_pgeom.g_nsect); 1854 cmlb_dbg(CMLB_INFO, cl, " lbasize: %d; capacity: %ld; " 1855 "intrlv: %d; rpm: %d\n", cl->cl_pgeom.g_secsize, 1856 cl->cl_pgeom.g_capacity, cl->cl_pgeom.g_intrlv, 1857 cl->cl_pgeom.g_rpm); 1858 } 1859 1860 1861 /* 1862 * Function: cmlb_read_fdisk 1863 * 1864 * Description: utility routine to read the fdisk table. 1865 * 1866 * Arguments: 1867 * cl driver soft state (unit) structure 1868 * capacity disk capacity in #blocks 1869 * tg_cookie cookie from target driver to be passed back to target 1870 * driver when we call back to it through tg_ops. 1871 * 1872 * Return Code: 0 for success (includes not reading for no_fdisk_present case 1873 * errnos from tg_rw if failed to read the first block. 1874 * 1875 * Context: Kernel thread only (can sleep). 1876 */ 1877 /*ARGSUSED*/ 1878 static int 1879 cmlb_read_fdisk(struct cmlb_lun *cl, diskaddr_t capacity, void *tg_cookie) 1880 { 1881 #if defined(_NO_FDISK_PRESENT) 1882 1883 cl->cl_solaris_offset = 0; 1884 cl->cl_solaris_size = capacity; 1885 bzero(cl->cl_fmap, sizeof (struct fmap) * FD_NUMPART); 1886 return (0); 1887 1888 #elif defined(_FIRMWARE_NEEDS_FDISK) 1889 1890 struct ipart *fdp; 1891 struct mboot *mbp; 1892 struct ipart fdisk[FD_NUMPART]; 1893 int i; 1894 char sigbuf[2]; 1895 caddr_t bufp; 1896 int uidx; 1897 int rval; 1898 int lba = 0; 1899 uint_t solaris_offset; /* offset to solaris part. */ 1900 daddr_t solaris_size; /* size of solaris partition */ 1901 uint32_t blocksize; 1902 1903 ASSERT(cl != NULL); 1904 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 1905 1906 /* 1907 * Start off assuming no fdisk table 1908 */ 1909 solaris_offset = 0; 1910 solaris_size = capacity; 1911 1912 blocksize = cl->cl_tgt_blocksize; 1913 1914 bufp = kmem_zalloc(blocksize, KM_SLEEP); 1915 1916 mutex_exit(CMLB_MUTEX(cl)); 1917 rval = DK_TG_READ(cl, bufp, 0, blocksize, tg_cookie); 1918 mutex_enter(CMLB_MUTEX(cl)); 1919 1920 if (rval != 0) { 1921 cmlb_dbg(CMLB_ERROR, cl, 1922 "cmlb_read_fdisk: fdisk read err\n"); 1923 bzero(cl->cl_fmap, sizeof (struct fmap) * FD_NUMPART); 1924 goto done; 1925 } 1926 1927 mbp = (struct mboot *)bufp; 1928 1929 /* 1930 * The fdisk table does not begin on a 4-byte boundary within the 1931 * master boot record, so we copy it to an aligned structure to avoid 1932 * alignment exceptions on some processors. 1933 */ 1934 bcopy(&mbp->parts[0], fdisk, sizeof (fdisk)); 1935 1936 /* 1937 * Check for lba support before verifying sig; sig might not be 1938 * there, say on a blank disk, but the max_chs mark may still 1939 * be present. 1940 * 1941 * Note: LBA support and BEFs are an x86-only concept but this 1942 * code should work OK on SPARC as well. 1943 */ 1944 1945 /* 1946 * First, check for lba-access-ok on root node (or prom root node) 1947 * if present there, don't need to search fdisk table. 1948 */ 1949 if (ddi_getprop(DDI_DEV_T_ANY, ddi_root_node(), 0, 1950 "lba-access-ok", 0) != 0) { 1951 /* All drives do LBA; don't search fdisk table */ 1952 lba = 1; 1953 } else { 1954 /* Okay, look for mark in fdisk table */ 1955 for (fdp = fdisk, i = 0; i < FD_NUMPART; i++, fdp++) { 1956 /* accumulate "lba" value from all partitions */ 1957 lba = (lba || cmlb_has_max_chs_vals(fdp)); 1958 } 1959 } 1960 1961 if (lba != 0) { 1962 dev_t dev = cmlb_make_device(cl); 1963 1964 if (ddi_getprop(dev, CMLB_DEVINFO(cl), DDI_PROP_DONTPASS, 1965 "lba-access-ok", 0) == 0) { 1966 /* not found; create it */ 1967 if (ddi_prop_create(dev, CMLB_DEVINFO(cl), 0, 1968 "lba-access-ok", (caddr_t)NULL, 0) != 1969 DDI_PROP_SUCCESS) { 1970 cmlb_dbg(CMLB_ERROR, cl, 1971 "cmlb_read_fdisk: Can't create lba " 1972 "property for instance %d\n", 1973 ddi_get_instance(CMLB_DEVINFO(cl))); 1974 } 1975 } 1976 } 1977 1978 bcopy(&mbp->signature, sigbuf, sizeof (sigbuf)); 1979 1980 /* 1981 * Endian-independent signature check 1982 */ 1983 if (((sigbuf[1] & 0xFF) != ((MBB_MAGIC >> 8) & 0xFF)) || 1984 (sigbuf[0] != (MBB_MAGIC & 0xFF))) { 1985 cmlb_dbg(CMLB_ERROR, cl, 1986 "cmlb_read_fdisk: no fdisk\n"); 1987 bzero(cl->cl_fmap, sizeof (struct fmap) * FD_NUMPART); 1988 goto done; 1989 } 1990 1991 #ifdef CMLBDEBUG 1992 if (cmlb_level_mask & CMLB_LOGMASK_INFO) { 1993 fdp = fdisk; 1994 cmlb_dbg(CMLB_INFO, cl, "cmlb_read_fdisk:\n"); 1995 cmlb_dbg(CMLB_INFO, cl, " relsect " 1996 "numsect sysid bootid\n"); 1997 for (i = 0; i < FD_NUMPART; i++, fdp++) { 1998 cmlb_dbg(CMLB_INFO, cl, 1999 " %d: %8d %8d 0x%08x 0x%08x\n", 2000 i, fdp->relsect, fdp->numsect, 2001 fdp->systid, fdp->bootid); 2002 } 2003 } 2004 #endif 2005 2006 /* 2007 * Try to find the unix partition 2008 */ 2009 uidx = -1; 2010 solaris_offset = 0; 2011 solaris_size = 0; 2012 2013 for (fdp = fdisk, i = 0; i < FD_NUMPART; i++, fdp++) { 2014 int relsect; 2015 int numsect; 2016 2017 if (fdp->numsect == 0) { 2018 cl->cl_fmap[i].fmap_start = 0; 2019 cl->cl_fmap[i].fmap_nblk = 0; 2020 continue; 2021 } 2022 2023 /* 2024 * Data in the fdisk table is little-endian. 2025 */ 2026 relsect = LE_32(fdp->relsect); 2027 numsect = LE_32(fdp->numsect); 2028 2029 cl->cl_fmap[i].fmap_start = relsect; 2030 cl->cl_fmap[i].fmap_nblk = numsect; 2031 2032 if (fdp->systid != SUNIXOS && 2033 fdp->systid != SUNIXOS2 && 2034 fdp->systid != EFI_PMBR) { 2035 continue; 2036 } 2037 2038 /* 2039 * use the last active solaris partition id found 2040 * (there should only be 1 active partition id) 2041 * 2042 * if there are no active solaris partition id 2043 * then use the first inactive solaris partition id 2044 */ 2045 if ((uidx == -1) || (fdp->bootid == ACTIVE)) { 2046 uidx = i; 2047 solaris_offset = relsect; 2048 solaris_size = numsect; 2049 } 2050 } 2051 2052 cmlb_dbg(CMLB_INFO, cl, "fdisk 0x%x 0x%lx", 2053 cl->cl_solaris_offset, cl->cl_solaris_size); 2054 done: 2055 2056 /* 2057 * Clear the VTOC info, only if the Solaris partition entry 2058 * has moved, changed size, been deleted, or if the size of 2059 * the partition is too small to even fit the label sector. 2060 */ 2061 if ((cl->cl_solaris_offset != solaris_offset) || 2062 (cl->cl_solaris_size != solaris_size) || 2063 solaris_size <= DK_LABEL_LOC) { 2064 cmlb_dbg(CMLB_INFO, cl, "fdisk moved 0x%x 0x%lx", 2065 solaris_offset, solaris_size); 2066 bzero(&cl->cl_g, sizeof (struct dk_geom)); 2067 bzero(&cl->cl_vtoc, sizeof (struct dk_vtoc)); 2068 bzero(&cl->cl_map, NDKMAP * (sizeof (struct dk_map))); 2069 cl->cl_f_geometry_is_valid = FALSE; 2070 } 2071 cl->cl_solaris_offset = solaris_offset; 2072 cl->cl_solaris_size = solaris_size; 2073 kmem_free(bufp, blocksize); 2074 return (rval); 2075 2076 #else /* #elif defined(_FIRMWARE_NEEDS_FDISK) */ 2077 #error "fdisk table presence undetermined for this platform." 2078 #endif /* #if defined(_NO_FDISK_PRESENT) */ 2079 } 2080 2081 static void 2082 cmlb_swap_efi_gpt(efi_gpt_t *e) 2083 { 2084 _NOTE(ASSUMING_PROTECTED(*e)) 2085 e->efi_gpt_Signature = LE_64(e->efi_gpt_Signature); 2086 e->efi_gpt_Revision = LE_32(e->efi_gpt_Revision); 2087 e->efi_gpt_HeaderSize = LE_32(e->efi_gpt_HeaderSize); 2088 e->efi_gpt_HeaderCRC32 = LE_32(e->efi_gpt_HeaderCRC32); 2089 e->efi_gpt_MyLBA = LE_64(e->efi_gpt_MyLBA); 2090 e->efi_gpt_AlternateLBA = LE_64(e->efi_gpt_AlternateLBA); 2091 e->efi_gpt_FirstUsableLBA = LE_64(e->efi_gpt_FirstUsableLBA); 2092 e->efi_gpt_LastUsableLBA = LE_64(e->efi_gpt_LastUsableLBA); 2093 UUID_LE_CONVERT(e->efi_gpt_DiskGUID, e->efi_gpt_DiskGUID); 2094 e->efi_gpt_PartitionEntryLBA = LE_64(e->efi_gpt_PartitionEntryLBA); 2095 e->efi_gpt_NumberOfPartitionEntries = 2096 LE_32(e->efi_gpt_NumberOfPartitionEntries); 2097 e->efi_gpt_SizeOfPartitionEntry = 2098 LE_32(e->efi_gpt_SizeOfPartitionEntry); 2099 e->efi_gpt_PartitionEntryArrayCRC32 = 2100 LE_32(e->efi_gpt_PartitionEntryArrayCRC32); 2101 } 2102 2103 static void 2104 cmlb_swap_efi_gpe(int nparts, efi_gpe_t *p) 2105 { 2106 int i; 2107 2108 _NOTE(ASSUMING_PROTECTED(*p)) 2109 for (i = 0; i < nparts; i++) { 2110 UUID_LE_CONVERT(p[i].efi_gpe_PartitionTypeGUID, 2111 p[i].efi_gpe_PartitionTypeGUID); 2112 p[i].efi_gpe_StartingLBA = LE_64(p[i].efi_gpe_StartingLBA); 2113 p[i].efi_gpe_EndingLBA = LE_64(p[i].efi_gpe_EndingLBA); 2114 /* PartitionAttrs */ 2115 } 2116 } 2117 2118 static int 2119 cmlb_validate_efi(efi_gpt_t *labp) 2120 { 2121 if (labp->efi_gpt_Signature != EFI_SIGNATURE) 2122 return (EINVAL); 2123 /* at least 96 bytes in this version of the spec. */ 2124 if (sizeof (efi_gpt_t) - sizeof (labp->efi_gpt_Reserved2) > 2125 labp->efi_gpt_HeaderSize) 2126 return (EINVAL); 2127 /* this should be 128 bytes */ 2128 if (labp->efi_gpt_SizeOfPartitionEntry != sizeof (efi_gpe_t)) 2129 return (EINVAL); 2130 return (0); 2131 } 2132 2133 /* 2134 * This function returns FALSE if there is a valid MBR signature and no 2135 * partition table entries of type EFI_PMBR (0xEE). Otherwise it returns TRUE. 2136 * 2137 * The EFI spec (1.10 and later) requires having a Protective MBR (PMBR) to 2138 * recognize the disk as GPT partitioned. However, some other OS creates an MBR 2139 * where a PMBR entry is not the only one. Also, if the first block has been 2140 * corrupted, currently best attempt to allow data access would be to try to 2141 * check for GPT headers. Hence in case of more than one partition entry, but 2142 * at least one EFI_PMBR partition type or no valid magic number, the function 2143 * returns TRUE to continue with looking for GPT header. 2144 */ 2145 2146 static int 2147 cmlb_check_efi_mbr(uchar_t *buf) 2148 { 2149 struct ipart *fdp; 2150 struct mboot *mbp = (struct mboot *)buf; 2151 struct ipart fdisk[FD_NUMPART]; 2152 int i; 2153 2154 if (LE_16(mbp->signature) != MBB_MAGIC) 2155 return (TRUE); 2156 2157 bcopy(&mbp->parts[0], fdisk, sizeof (fdisk)); 2158 2159 for (fdp = fdisk, i = 0; i < FD_NUMPART; i++, fdp++) { 2160 if (fdp->systid == EFI_PMBR) 2161 return (TRUE); 2162 } 2163 2164 return (FALSE); 2165 } 2166 2167 static int 2168 cmlb_use_efi(struct cmlb_lun *cl, diskaddr_t capacity, int flags, 2169 void *tg_cookie) 2170 { 2171 int i; 2172 int rval = 0; 2173 efi_gpe_t *partitions; 2174 uchar_t *buf; 2175 uint_t lbasize; /* is really how much to read */ 2176 diskaddr_t cap = 0; 2177 uint_t nparts; 2178 diskaddr_t gpe_lba; 2179 diskaddr_t alternate_lba; 2180 int iofailed = 0; 2181 struct uuid uuid_type_reserved = EFI_RESERVED; 2182 2183 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 2184 2185 if (cl->cl_tgt_blocksize != cl->cl_sys_blocksize) { 2186 rval = EINVAL; 2187 goto done_err1; 2188 } 2189 2190 2191 lbasize = cl->cl_sys_blocksize; 2192 2193 cl->cl_reserved = -1; 2194 mutex_exit(CMLB_MUTEX(cl)); 2195 2196 buf = kmem_zalloc(EFI_MIN_ARRAY_SIZE, KM_SLEEP); 2197 2198 rval = DK_TG_READ(cl, buf, 0, lbasize, tg_cookie); 2199 if (rval) { 2200 iofailed = 1; 2201 goto done_err; 2202 } 2203 if (((struct dk_label *)buf)->dkl_magic == DKL_MAGIC) { 2204 /* not ours */ 2205 rval = ESRCH; 2206 goto done_err; 2207 } 2208 2209 if (cmlb_check_efi_mbr(buf) == FALSE) { 2210 rval = EINVAL; 2211 goto done_err; 2212 } 2213 2214 rval = DK_TG_READ(cl, buf, 1, lbasize, tg_cookie); 2215 if (rval) { 2216 iofailed = 1; 2217 goto done_err; 2218 } 2219 cmlb_swap_efi_gpt((efi_gpt_t *)buf); 2220 2221 if ((rval = cmlb_validate_efi((efi_gpt_t *)buf)) != 0) { 2222 /* 2223 * Couldn't read the primary, try the backup. Our 2224 * capacity at this point could be based on CHS, so 2225 * check what the device reports. 2226 */ 2227 rval = DK_TG_GETCAP(cl, &cap, tg_cookie); 2228 if (rval) { 2229 iofailed = 1; 2230 goto done_err; 2231 } 2232 2233 /* 2234 * CMLB_OFF_BY_ONE case, we check the next to last block first 2235 * for backup GPT header, otherwise check the last block. 2236 */ 2237 2238 if ((rval = DK_TG_READ(cl, buf, 2239 cap - ((cl->cl_alter_behavior & CMLB_OFF_BY_ONE) ? 2 : 1), 2240 lbasize, tg_cookie)) 2241 != 0) { 2242 iofailed = 1; 2243 goto done_err; 2244 } 2245 cmlb_swap_efi_gpt((efi_gpt_t *)buf); 2246 2247 if ((rval = cmlb_validate_efi((efi_gpt_t *)buf)) != 0) { 2248 2249 if (!(cl->cl_alter_behavior & CMLB_OFF_BY_ONE)) 2250 goto done_err; 2251 if ((rval = DK_TG_READ(cl, buf, cap - 1, lbasize, 2252 tg_cookie)) != 0) 2253 goto done_err; 2254 cmlb_swap_efi_gpt((efi_gpt_t *)buf); 2255 if ((rval = cmlb_validate_efi((efi_gpt_t *)buf)) != 0) 2256 goto done_err; 2257 } 2258 if (!(flags & CMLB_SILENT)) 2259 cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl), CE_WARN, 2260 "primary label corrupt; using backup\n"); 2261 } 2262 2263 nparts = ((efi_gpt_t *)buf)->efi_gpt_NumberOfPartitionEntries; 2264 gpe_lba = ((efi_gpt_t *)buf)->efi_gpt_PartitionEntryLBA; 2265 alternate_lba = ((efi_gpt_t *)buf)->efi_gpt_AlternateLBA; 2266 2267 rval = DK_TG_READ(cl, buf, gpe_lba, EFI_MIN_ARRAY_SIZE, tg_cookie); 2268 if (rval) { 2269 iofailed = 1; 2270 goto done_err; 2271 } 2272 partitions = (efi_gpe_t *)buf; 2273 2274 if (nparts > MAXPART) { 2275 nparts = MAXPART; 2276 } 2277 cmlb_swap_efi_gpe(nparts, partitions); 2278 2279 mutex_enter(CMLB_MUTEX(cl)); 2280 2281 /* Fill in partition table. */ 2282 for (i = 0; i < nparts; i++) { 2283 if (partitions->efi_gpe_StartingLBA != 0 || 2284 partitions->efi_gpe_EndingLBA != 0) { 2285 cl->cl_map[i].dkl_cylno = 2286 partitions->efi_gpe_StartingLBA; 2287 cl->cl_map[i].dkl_nblk = 2288 partitions->efi_gpe_EndingLBA - 2289 partitions->efi_gpe_StartingLBA + 1; 2290 cl->cl_offset[i] = 2291 partitions->efi_gpe_StartingLBA; 2292 } 2293 2294 if (cl->cl_reserved == -1) { 2295 if (bcmp(&partitions->efi_gpe_PartitionTypeGUID, 2296 &uuid_type_reserved, sizeof (struct uuid)) == 0) { 2297 cl->cl_reserved = i; 2298 } 2299 } 2300 if (i == WD_NODE) { 2301 /* 2302 * minor number 7 corresponds to the whole disk 2303 * if the disk capacity is expanded after disk is 2304 * labeled, minor number 7 represents the capacity 2305 * indicated by the disk label. 2306 */ 2307 cl->cl_map[i].dkl_cylno = 0; 2308 if (alternate_lba == 1) { 2309 /* 2310 * We are using backup label. Since we can 2311 * find a valid label at the end of disk, 2312 * the disk capacity is not expanded. 2313 */ 2314 cl->cl_map[i].dkl_nblk = capacity; 2315 } else { 2316 cl->cl_map[i].dkl_nblk = alternate_lba + 1; 2317 } 2318 cl->cl_offset[i] = 0; 2319 } 2320 partitions++; 2321 } 2322 cl->cl_solaris_offset = 0; 2323 cl->cl_solaris_size = capacity; 2324 cl->cl_f_geometry_is_valid = TRUE; 2325 2326 /* clear the vtoc label */ 2327 bzero(&cl->cl_vtoc, sizeof (struct dk_vtoc)); 2328 2329 kmem_free(buf, EFI_MIN_ARRAY_SIZE); 2330 return (0); 2331 2332 done_err: 2333 kmem_free(buf, EFI_MIN_ARRAY_SIZE); 2334 mutex_enter(CMLB_MUTEX(cl)); 2335 done_err1: 2336 /* 2337 * if we didn't find something that could look like a VTOC 2338 * and the disk is over 1TB, we know there isn't a valid label. 2339 * Otherwise let cmlb_uselabel decide what to do. We only 2340 * want to invalidate this if we're certain the label isn't 2341 * valid because cmlb_prop_op will now fail, which in turn 2342 * causes things like opens and stats on the partition to fail. 2343 */ 2344 if ((capacity > DK_MAX_BLOCKS) && (rval != ESRCH) && !iofailed) { 2345 cl->cl_f_geometry_is_valid = FALSE; 2346 } 2347 return (rval); 2348 } 2349 2350 2351 /* 2352 * Function: cmlb_uselabel 2353 * 2354 * Description: Validate the disk label and update the relevant data (geometry, 2355 * partition, vtoc, and capacity data) in the cmlb_lun struct. 2356 * Marks the geometry of the unit as being valid. 2357 * 2358 * Arguments: cl: unit struct. 2359 * dk_label: disk label 2360 * 2361 * Return Code: CMLB_LABEL_IS_VALID: Label read from disk is OK; geometry, 2362 * partition, vtoc, and capacity data are good. 2363 * 2364 * CMLB_LABEL_IS_INVALID: Magic number or checksum error in the 2365 * label; or computed capacity does not jibe with capacity 2366 * reported from the READ CAPACITY command. 2367 * 2368 * Context: Kernel thread only (can sleep). 2369 */ 2370 static int 2371 cmlb_uselabel(struct cmlb_lun *cl, struct dk_label *labp, int flags) 2372 { 2373 short *sp; 2374 short sum; 2375 short count; 2376 int label_error = CMLB_LABEL_IS_VALID; 2377 int i; 2378 diskaddr_t label_capacity; 2379 int part_end; 2380 diskaddr_t track_capacity; 2381 #if defined(_SUNOS_VTOC_16) 2382 struct dkl_partition *vpartp; 2383 #endif 2384 ASSERT(cl != NULL); 2385 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 2386 2387 /* Validate the magic number of the label. */ 2388 if (labp->dkl_magic != DKL_MAGIC) { 2389 #if defined(__sparc) 2390 if (!ISREMOVABLE(cl) && !ISHOTPLUGGABLE(cl)) { 2391 if (!(flags & CMLB_SILENT)) 2392 cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl), 2393 CE_WARN, 2394 "Corrupt label; wrong magic number\n"); 2395 } 2396 #endif 2397 return (CMLB_LABEL_IS_INVALID); 2398 } 2399 2400 /* Validate the checksum of the label. */ 2401 sp = (short *)labp; 2402 sum = 0; 2403 count = sizeof (struct dk_label) / sizeof (short); 2404 while (count--) { 2405 sum ^= *sp++; 2406 } 2407 2408 if (sum != 0) { 2409 #if defined(_SUNOS_VTOC_16) 2410 if (!ISCD(cl)) { 2411 #elif defined(_SUNOS_VTOC_8) 2412 if (!ISREMOVABLE(cl) && !ISHOTPLUGGABLE(cl)) { 2413 #endif 2414 if (!(flags & CMLB_SILENT)) 2415 cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl), 2416 CE_WARN, 2417 "Corrupt label - label checksum failed\n"); 2418 } 2419 return (CMLB_LABEL_IS_INVALID); 2420 } 2421 2422 2423 /* 2424 * Fill in geometry structure with data from label. 2425 */ 2426 bzero(&cl->cl_g, sizeof (struct dk_geom)); 2427 cl->cl_g.dkg_ncyl = labp->dkl_ncyl; 2428 cl->cl_g.dkg_acyl = labp->dkl_acyl; 2429 cl->cl_g.dkg_bcyl = 0; 2430 cl->cl_g.dkg_nhead = labp->dkl_nhead; 2431 cl->cl_g.dkg_nsect = labp->dkl_nsect; 2432 cl->cl_g.dkg_intrlv = labp->dkl_intrlv; 2433 2434 #if defined(_SUNOS_VTOC_8) 2435 cl->cl_g.dkg_gap1 = labp->dkl_gap1; 2436 cl->cl_g.dkg_gap2 = labp->dkl_gap2; 2437 cl->cl_g.dkg_bhead = labp->dkl_bhead; 2438 #endif 2439 #if defined(_SUNOS_VTOC_16) 2440 cl->cl_dkg_skew = labp->dkl_skew; 2441 #endif 2442 2443 #if defined(__i386) || defined(__amd64) 2444 cl->cl_g.dkg_apc = labp->dkl_apc; 2445 #endif 2446 2447 /* 2448 * Currently we rely on the values in the label being accurate. If 2449 * dkl_rpm or dkl_pcly are zero in the label, use a default value. 2450 * 2451 * Note: In the future a MODE SENSE may be used to retrieve this data, 2452 * although this command is optional in SCSI-2. 2453 */ 2454 cl->cl_g.dkg_rpm = (labp->dkl_rpm != 0) ? labp->dkl_rpm : 3600; 2455 cl->cl_g.dkg_pcyl = (labp->dkl_pcyl != 0) ? labp->dkl_pcyl : 2456 (cl->cl_g.dkg_ncyl + cl->cl_g.dkg_acyl); 2457 2458 /* 2459 * The Read and Write reinstruct values may not be valid 2460 * for older disks. 2461 */ 2462 cl->cl_g.dkg_read_reinstruct = labp->dkl_read_reinstruct; 2463 cl->cl_g.dkg_write_reinstruct = labp->dkl_write_reinstruct; 2464 2465 /* Fill in partition table. */ 2466 #if defined(_SUNOS_VTOC_8) 2467 for (i = 0; i < NDKMAP; i++) { 2468 cl->cl_map[i].dkl_cylno = labp->dkl_map[i].dkl_cylno; 2469 cl->cl_map[i].dkl_nblk = labp->dkl_map[i].dkl_nblk; 2470 } 2471 #endif 2472 #if defined(_SUNOS_VTOC_16) 2473 vpartp = labp->dkl_vtoc.v_part; 2474 track_capacity = labp->dkl_nhead * labp->dkl_nsect; 2475 2476 /* Prevent divide by zero */ 2477 if (track_capacity == 0) { 2478 if (!(flags & CMLB_SILENT)) 2479 cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl), CE_WARN, 2480 "Corrupt label - zero nhead or nsect value\n"); 2481 2482 return (CMLB_LABEL_IS_INVALID); 2483 } 2484 2485 for (i = 0; i < NDKMAP; i++, vpartp++) { 2486 cl->cl_map[i].dkl_cylno = vpartp->p_start / track_capacity; 2487 cl->cl_map[i].dkl_nblk = vpartp->p_size; 2488 } 2489 #endif 2490 2491 /* Fill in VTOC Structure. */ 2492 bcopy(&labp->dkl_vtoc, &cl->cl_vtoc, sizeof (struct dk_vtoc)); 2493 #if defined(_SUNOS_VTOC_8) 2494 /* 2495 * The 8-slice vtoc does not include the ascii label; save it into 2496 * the device's soft state structure here. 2497 */ 2498 bcopy(labp->dkl_asciilabel, cl->cl_asciilabel, LEN_DKL_ASCII); 2499 #endif 2500 2501 /* Now look for a valid capacity. */ 2502 track_capacity = (cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect); 2503 label_capacity = (cl->cl_g.dkg_ncyl * track_capacity); 2504 2505 if (cl->cl_g.dkg_acyl) { 2506 #if defined(__i386) || defined(__amd64) 2507 /* we may have > 1 alts cylinder */ 2508 label_capacity += (track_capacity * cl->cl_g.dkg_acyl); 2509 #else 2510 label_capacity += track_capacity; 2511 #endif 2512 } 2513 2514 /* 2515 * Force check here to ensure the computed capacity is valid. 2516 * If capacity is zero, it indicates an invalid label and 2517 * we should abort updating the relevant data then. 2518 */ 2519 if (label_capacity == 0) { 2520 if (!(flags & CMLB_SILENT)) 2521 cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl), CE_WARN, 2522 "Corrupt label - no valid capacity could be " 2523 "retrieved\n"); 2524 2525 return (CMLB_LABEL_IS_INVALID); 2526 } 2527 2528 /* Mark the geometry as valid. */ 2529 cl->cl_f_geometry_is_valid = TRUE; 2530 2531 /* 2532 * if we got invalidated when mutex exit and entered again, 2533 * if blockcount different than when we came in, need to 2534 * retry from beginning of cmlb_validate_geometry. 2535 * revisit this on next phase of utilizing this for 2536 * sd. 2537 */ 2538 2539 if (label_capacity <= cl->cl_blockcount) { 2540 #if defined(_SUNOS_VTOC_8) 2541 /* 2542 * We can't let this happen on drives that are subdivided 2543 * into logical disks (i.e., that have an fdisk table). 2544 * The cl_blockcount field should always hold the full media 2545 * size in sectors, period. This code would overwrite 2546 * cl_blockcount with the size of the Solaris fdisk partition. 2547 */ 2548 cmlb_dbg(CMLB_ERROR, cl, 2549 "cmlb_uselabel: Label %d blocks; Drive %d blocks\n", 2550 label_capacity, cl->cl_blockcount); 2551 cl->cl_solaris_size = label_capacity; 2552 2553 #endif /* defined(_SUNOS_VTOC_8) */ 2554 goto done; 2555 } 2556 2557 if (ISCD(cl)) { 2558 /* For CDROMs, we trust that the data in the label is OK. */ 2559 #if defined(_SUNOS_VTOC_8) 2560 for (i = 0; i < NDKMAP; i++) { 2561 part_end = labp->dkl_nhead * labp->dkl_nsect * 2562 labp->dkl_map[i].dkl_cylno + 2563 labp->dkl_map[i].dkl_nblk - 1; 2564 2565 if ((labp->dkl_map[i].dkl_nblk) && 2566 (part_end > cl->cl_blockcount)) { 2567 cl->cl_f_geometry_is_valid = FALSE; 2568 break; 2569 } 2570 } 2571 #endif 2572 #if defined(_SUNOS_VTOC_16) 2573 vpartp = &(labp->dkl_vtoc.v_part[0]); 2574 for (i = 0; i < NDKMAP; i++, vpartp++) { 2575 part_end = vpartp->p_start + vpartp->p_size; 2576 if ((vpartp->p_size > 0) && 2577 (part_end > cl->cl_blockcount)) { 2578 cl->cl_f_geometry_is_valid = FALSE; 2579 break; 2580 } 2581 } 2582 #endif 2583 } else { 2584 /* label_capacity > cl->cl_blockcount */ 2585 if (!(flags & CMLB_SILENT)) { 2586 cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl), CE_WARN, 2587 "Corrupt label - bad geometry\n"); 2588 cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl), CE_CONT, 2589 "Label says %llu blocks; Drive says %llu blocks\n", 2590 label_capacity, cl->cl_blockcount); 2591 } 2592 cl->cl_f_geometry_is_valid = FALSE; 2593 label_error = CMLB_LABEL_IS_INVALID; 2594 } 2595 2596 done: 2597 2598 cmlb_dbg(CMLB_INFO, cl, "cmlb_uselabel: (label geometry)\n"); 2599 cmlb_dbg(CMLB_INFO, cl, 2600 " ncyl: %d; acyl: %d; nhead: %d; nsect: %d\n", 2601 cl->cl_g.dkg_ncyl, cl->cl_g.dkg_acyl, 2602 cl->cl_g.dkg_nhead, cl->cl_g.dkg_nsect); 2603 2604 cmlb_dbg(CMLB_INFO, cl, 2605 " label_capacity: %d; intrlv: %d; rpm: %d\n", 2606 cl->cl_blockcount, cl->cl_g.dkg_intrlv, cl->cl_g.dkg_rpm); 2607 cmlb_dbg(CMLB_INFO, cl, " wrt_reinstr: %d; rd_reinstr: %d\n", 2608 cl->cl_g.dkg_write_reinstruct, cl->cl_g.dkg_read_reinstruct); 2609 2610 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 2611 2612 return (label_error); 2613 } 2614 2615 2616 /* 2617 * Function: cmlb_build_default_label 2618 * 2619 * Description: Generate a default label for those devices that do not have 2620 * one, e.g., new media, removable cartridges, etc.. 2621 * 2622 * Context: Kernel thread only 2623 */ 2624 /*ARGSUSED*/ 2625 static void 2626 cmlb_build_default_label(struct cmlb_lun *cl, void *tg_cookie) 2627 { 2628 #if defined(_SUNOS_VTOC_16) 2629 uint_t phys_spc; 2630 uint_t disksize; 2631 struct dk_geom cl_g; 2632 diskaddr_t capacity; 2633 #endif 2634 2635 ASSERT(cl != NULL); 2636 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 2637 2638 #if defined(_SUNOS_VTOC_8) 2639 /* 2640 * Note: This is a legacy check for non-removable devices on VTOC_8 2641 * only. This may be a valid check for VTOC_16 as well. 2642 * Once we understand why there is this difference between SPARC and 2643 * x86 platform, we could remove this legacy check. 2644 */ 2645 if (!ISREMOVABLE(cl) && !ISHOTPLUGGABLE(cl)) { 2646 return; 2647 } 2648 #endif 2649 2650 bzero(&cl->cl_g, sizeof (struct dk_geom)); 2651 bzero(&cl->cl_vtoc, sizeof (struct dk_vtoc)); 2652 bzero(&cl->cl_map, NDKMAP * (sizeof (struct dk_map))); 2653 2654 #if defined(_SUNOS_VTOC_8) 2655 2656 /* 2657 * It's a REMOVABLE media, therefore no label (on sparc, anyway). 2658 * But it is still necessary to set up various geometry information, 2659 * and we are doing this here. 2660 */ 2661 2662 /* 2663 * For the rpm, we use the minimum for the disk. For the head, cyl, 2664 * and number of sector per track, if the capacity <= 1GB, head = 64, 2665 * sect = 32. else head = 255, sect 63 Note: the capacity should be 2666 * equal to C*H*S values. This will cause some truncation of size due 2667 * to round off errors. For CD-ROMs, this truncation can have adverse 2668 * side effects, so returning ncyl and nhead as 1. The nsect will 2669 * overflow for most of CD-ROMs as nsect is of type ushort. (4190569) 2670 */ 2671 cl->cl_solaris_size = cl->cl_blockcount; 2672 if (ISCD(cl)) { 2673 tg_attribute_t tgattribute; 2674 int is_writable; 2675 /* 2676 * Preserve the old behavior for non-writable 2677 * medias. Since dkg_nsect is a ushort, it 2678 * will lose bits as cdroms have more than 2679 * 65536 sectors. So if we recalculate 2680 * capacity, it will become much shorter. 2681 * But the dkg_* information is not 2682 * used for CDROMs so it is OK. But for 2683 * Writable CDs we need this information 2684 * to be valid (for newfs say). So we 2685 * make nsect and nhead > 1 that way 2686 * nsect can still stay within ushort limit 2687 * without losing any bits. 2688 */ 2689 2690 bzero(&tgattribute, sizeof (tg_attribute_t)); 2691 2692 mutex_exit(CMLB_MUTEX(cl)); 2693 is_writable = 2694 (DK_TG_GETATTRIBUTE(cl, &tgattribute, tg_cookie) == 0) ? 2695 tgattribute.media_is_writable : 1; 2696 mutex_enter(CMLB_MUTEX(cl)); 2697 2698 if (is_writable) { 2699 cl->cl_g.dkg_nhead = 64; 2700 cl->cl_g.dkg_nsect = 32; 2701 cl->cl_g.dkg_ncyl = cl->cl_blockcount / (64 * 32); 2702 cl->cl_solaris_size = cl->cl_g.dkg_ncyl * 2703 cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect; 2704 } else { 2705 cl->cl_g.dkg_ncyl = 1; 2706 cl->cl_g.dkg_nhead = 1; 2707 cl->cl_g.dkg_nsect = cl->cl_blockcount; 2708 } 2709 } else { 2710 if (cl->cl_blockcount <= 0x1000) { 2711 /* unlabeled SCSI floppy device */ 2712 cl->cl_g.dkg_nhead = 2; 2713 cl->cl_g.dkg_ncyl = 80; 2714 cl->cl_g.dkg_nsect = cl->cl_blockcount / (2 * 80); 2715 } else if (cl->cl_blockcount <= 0x200000) { 2716 cl->cl_g.dkg_nhead = 64; 2717 cl->cl_g.dkg_nsect = 32; 2718 cl->cl_g.dkg_ncyl = cl->cl_blockcount / (64 * 32); 2719 } else { 2720 cl->cl_g.dkg_nhead = 255; 2721 2722 cl->cl_g.dkg_nsect = ((cl->cl_blockcount + 2723 (UINT16_MAX * 255 * 63) - 1) / 2724 (UINT16_MAX * 255 * 63)) * 63; 2725 2726 if (cl->cl_g.dkg_nsect == 0) 2727 cl->cl_g.dkg_nsect = (UINT16_MAX / 63) * 63; 2728 2729 cl->cl_g.dkg_ncyl = cl->cl_blockcount / 2730 (255 * cl->cl_g.dkg_nsect); 2731 } 2732 2733 cl->cl_solaris_size = 2734 cl->cl_g.dkg_ncyl * cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect; 2735 2736 } 2737 2738 cl->cl_g.dkg_acyl = 0; 2739 cl->cl_g.dkg_bcyl = 0; 2740 cl->cl_g.dkg_rpm = 200; 2741 cl->cl_asciilabel[0] = '\0'; 2742 cl->cl_g.dkg_pcyl = cl->cl_g.dkg_ncyl; 2743 2744 cl->cl_map[0].dkl_cylno = 0; 2745 cl->cl_map[0].dkl_nblk = cl->cl_solaris_size; 2746 2747 cl->cl_map[2].dkl_cylno = 0; 2748 cl->cl_map[2].dkl_nblk = cl->cl_solaris_size; 2749 2750 #elif defined(_SUNOS_VTOC_16) 2751 2752 if (cl->cl_solaris_size == 0) { 2753 /* 2754 * Got fdisk table but no solaris entry therefore 2755 * don't create a default label 2756 */ 2757 cl->cl_f_geometry_is_valid = TRUE; 2758 return; 2759 } 2760 2761 /* 2762 * For CDs we continue to use the physical geometry to calculate 2763 * number of cylinders. All other devices must convert the 2764 * physical geometry (cmlb_geom) to values that will fit 2765 * in a dk_geom structure. 2766 */ 2767 if (ISCD(cl)) { 2768 phys_spc = cl->cl_pgeom.g_nhead * cl->cl_pgeom.g_nsect; 2769 } else { 2770 /* Convert physical geometry to disk geometry */ 2771 bzero(&cl_g, sizeof (struct dk_geom)); 2772 2773 /* 2774 * Refer to comments related to off-by-1 at the 2775 * header of this file. 2776 * Before calculating geometry, capacity should be 2777 * decreased by 1. 2778 */ 2779 2780 if (cl->cl_alter_behavior & CMLB_OFF_BY_ONE) 2781 capacity = cl->cl_blockcount - 1; 2782 else 2783 capacity = cl->cl_blockcount; 2784 2785 2786 cmlb_convert_geometry(capacity, &cl_g); 2787 bcopy(&cl_g, &cl->cl_g, sizeof (cl->cl_g)); 2788 phys_spc = cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect; 2789 } 2790 2791 ASSERT(phys_spc != 0); 2792 cl->cl_g.dkg_pcyl = cl->cl_solaris_size / phys_spc; 2793 if (cl->cl_alter_behavior & CMLB_FAKE_LABEL_ONE_PARTITION) { 2794 /* disable devid */ 2795 cl->cl_g.dkg_ncyl = cl->cl_g.dkg_pcyl; 2796 disksize = cl->cl_solaris_size; 2797 } else { 2798 cl->cl_g.dkg_acyl = DK_ACYL; 2799 cl->cl_g.dkg_ncyl = cl->cl_g.dkg_pcyl - DK_ACYL; 2800 disksize = cl->cl_g.dkg_ncyl * phys_spc; 2801 } 2802 2803 if (ISCD(cl)) { 2804 /* 2805 * CD's don't use the "heads * sectors * cyls"-type of 2806 * geometry, but instead use the entire capacity of the media. 2807 */ 2808 disksize = cl->cl_solaris_size; 2809 cl->cl_g.dkg_nhead = 1; 2810 cl->cl_g.dkg_nsect = 1; 2811 cl->cl_g.dkg_rpm = 2812 (cl->cl_pgeom.g_rpm == 0) ? 200 : cl->cl_pgeom.g_rpm; 2813 2814 cl->cl_vtoc.v_part[0].p_start = 0; 2815 cl->cl_vtoc.v_part[0].p_size = disksize; 2816 cl->cl_vtoc.v_part[0].p_tag = V_BACKUP; 2817 cl->cl_vtoc.v_part[0].p_flag = V_UNMNT; 2818 2819 cl->cl_map[0].dkl_cylno = 0; 2820 cl->cl_map[0].dkl_nblk = disksize; 2821 cl->cl_offset[0] = 0; 2822 2823 } else { 2824 /* 2825 * Hard disks and removable media cartridges 2826 */ 2827 cl->cl_g.dkg_rpm = 2828 (cl->cl_pgeom.g_rpm == 0) ? 3600: cl->cl_pgeom.g_rpm; 2829 cl->cl_vtoc.v_sectorsz = cl->cl_sys_blocksize; 2830 2831 /* Add boot slice */ 2832 cl->cl_vtoc.v_part[8].p_start = 0; 2833 cl->cl_vtoc.v_part[8].p_size = phys_spc; 2834 cl->cl_vtoc.v_part[8].p_tag = V_BOOT; 2835 cl->cl_vtoc.v_part[8].p_flag = V_UNMNT; 2836 2837 cl->cl_map[8].dkl_cylno = 0; 2838 cl->cl_map[8].dkl_nblk = phys_spc; 2839 cl->cl_offset[8] = 0; 2840 2841 if ((cl->cl_alter_behavior & 2842 CMLB_CREATE_ALTSLICE_VTOC_16_DTYPE_DIRECT) && 2843 cl->cl_device_type == DTYPE_DIRECT) { 2844 cl->cl_vtoc.v_part[9].p_start = phys_spc; 2845 cl->cl_vtoc.v_part[9].p_size = 2 * phys_spc; 2846 cl->cl_vtoc.v_part[9].p_tag = V_ALTSCTR; 2847 cl->cl_vtoc.v_part[9].p_flag = 0; 2848 2849 cl->cl_map[9].dkl_cylno = 1; 2850 cl->cl_map[9].dkl_nblk = 2 * phys_spc; 2851 cl->cl_offset[9] = phys_spc; 2852 } 2853 } 2854 2855 cl->cl_g.dkg_apc = 0; 2856 cl->cl_vtoc.v_nparts = V_NUMPAR; 2857 cl->cl_vtoc.v_version = V_VERSION; 2858 2859 /* Add backup slice */ 2860 cl->cl_vtoc.v_part[2].p_start = 0; 2861 cl->cl_vtoc.v_part[2].p_size = disksize; 2862 cl->cl_vtoc.v_part[2].p_tag = V_BACKUP; 2863 cl->cl_vtoc.v_part[2].p_flag = V_UNMNT; 2864 2865 cl->cl_map[2].dkl_cylno = 0; 2866 cl->cl_map[2].dkl_nblk = disksize; 2867 cl->cl_offset[2] = 0; 2868 2869 /* 2870 * single slice (s0) covering the entire disk 2871 */ 2872 if (cl->cl_alter_behavior & CMLB_FAKE_LABEL_ONE_PARTITION) { 2873 cl->cl_vtoc.v_part[0].p_start = 0; 2874 cl->cl_vtoc.v_part[0].p_tag = V_UNASSIGNED; 2875 cl->cl_vtoc.v_part[0].p_flag = 0; 2876 cl->cl_vtoc.v_part[0].p_size = disksize; 2877 cl->cl_map[0].dkl_cylno = 0; 2878 cl->cl_map[0].dkl_nblk = disksize; 2879 cl->cl_offset[0] = 0; 2880 } 2881 2882 (void) sprintf(cl->cl_vtoc.v_asciilabel, "DEFAULT cyl %d alt %d" 2883 " hd %d sec %d", cl->cl_g.dkg_ncyl, cl->cl_g.dkg_acyl, 2884 cl->cl_g.dkg_nhead, cl->cl_g.dkg_nsect); 2885 2886 #else 2887 #error "No VTOC format defined." 2888 #endif 2889 2890 cl->cl_g.dkg_read_reinstruct = 0; 2891 cl->cl_g.dkg_write_reinstruct = 0; 2892 2893 cl->cl_g.dkg_intrlv = 1; 2894 2895 cl->cl_vtoc.v_sanity = VTOC_SANE; 2896 2897 cl->cl_f_geometry_is_valid = TRUE; 2898 cl->cl_vtoc_label_is_from_media = 0; 2899 2900 cmlb_dbg(CMLB_INFO, cl, 2901 "cmlb_build_default_label: Default label created: " 2902 "cyl: %d\tacyl: %d\tnhead: %d\tnsect: %d\tcap: %d\n", 2903 cl->cl_g.dkg_ncyl, cl->cl_g.dkg_acyl, cl->cl_g.dkg_nhead, 2904 cl->cl_g.dkg_nsect, cl->cl_blockcount); 2905 } 2906 2907 2908 #if defined(_FIRMWARE_NEEDS_FDISK) 2909 /* 2910 * Max CHS values, as they are encoded into bytes, for 1022/254/63 2911 */ 2912 #define LBA_MAX_SECT (63 | ((1022 & 0x300) >> 2)) 2913 #define LBA_MAX_CYL (1022 & 0xFF) 2914 #define LBA_MAX_HEAD (254) 2915 2916 2917 /* 2918 * Function: cmlb_has_max_chs_vals 2919 * 2920 * Description: Return TRUE if Cylinder-Head-Sector values are all at maximum. 2921 * 2922 * Arguments: fdp - ptr to CHS info 2923 * 2924 * Return Code: True or false 2925 * 2926 * Context: Any. 2927 */ 2928 static int 2929 cmlb_has_max_chs_vals(struct ipart *fdp) 2930 { 2931 return ((fdp->begcyl == LBA_MAX_CYL) && 2932 (fdp->beghead == LBA_MAX_HEAD) && 2933 (fdp->begsect == LBA_MAX_SECT) && 2934 (fdp->endcyl == LBA_MAX_CYL) && 2935 (fdp->endhead == LBA_MAX_HEAD) && 2936 (fdp->endsect == LBA_MAX_SECT)); 2937 } 2938 #endif 2939 2940 /* 2941 * Function: cmlb_dkio_get_geometry 2942 * 2943 * Description: This routine is the driver entry point for handling user 2944 * requests to get the device geometry (DKIOCGGEOM). 2945 * 2946 * Arguments: 2947 * arg pointer to user provided dk_geom structure specifying 2948 * the controller's notion of the current geometry. 2949 * 2950 * flag this argument is a pass through to ddi_copyxxx() 2951 * directly from the mode argument of ioctl(). 2952 * 2953 * tg_cookie cookie from target driver to be passed back to target 2954 * driver when we call back to it through tg_ops. 2955 * 2956 * Return Code: 0 2957 * EFAULT 2958 * ENXIO 2959 * EIO 2960 */ 2961 static int 2962 cmlb_dkio_get_geometry(struct cmlb_lun *cl, caddr_t arg, int flag, 2963 void *tg_cookie) 2964 { 2965 struct dk_geom *tmp_geom = NULL; 2966 int rval = 0; 2967 2968 /* 2969 * cmlb_validate_geometry does not spin a disk up 2970 * if it was spcl down. We need to make sure it 2971 * is ready. 2972 */ 2973 mutex_enter(CMLB_MUTEX(cl)); 2974 rval = cmlb_validate_geometry(cl, 1, 0, tg_cookie); 2975 #if defined(_SUNOS_VTOC_8) 2976 if (rval == EINVAL && 2977 cl->cl_alter_behavior & CMLB_FAKE_GEOM_LABEL_IOCTLS_VTOC8) { 2978 /* 2979 * This is to return a default label geometry even when we 2980 * do not really assume a default label for the device. 2981 * dad driver utilizes this. 2982 */ 2983 if (cl->cl_blockcount <= DK_MAX_BLOCKS) { 2984 cmlb_setup_default_geometry(cl, tg_cookie); 2985 rval = 0; 2986 } 2987 } 2988 #endif 2989 if (rval) { 2990 mutex_exit(CMLB_MUTEX(cl)); 2991 return (rval); 2992 } 2993 2994 #if defined(__i386) || defined(__amd64) 2995 if (cl->cl_solaris_size == 0) { 2996 mutex_exit(CMLB_MUTEX(cl)); 2997 return (EIO); 2998 } 2999 #endif 3000 3001 /* 3002 * Make a local copy of the soft state geometry to avoid some potential 3003 * race conditions associated with holding the mutex and updating the 3004 * write_reinstruct value 3005 */ 3006 tmp_geom = kmem_zalloc(sizeof (struct dk_geom), KM_SLEEP); 3007 bcopy(&cl->cl_g, tmp_geom, sizeof (struct dk_geom)); 3008 3009 if (tmp_geom->dkg_write_reinstruct == 0) { 3010 tmp_geom->dkg_write_reinstruct = 3011 (int)((int)(tmp_geom->dkg_nsect * tmp_geom->dkg_rpm * 3012 cmlb_rot_delay) / (int)60000); 3013 } 3014 mutex_exit(CMLB_MUTEX(cl)); 3015 3016 rval = ddi_copyout(tmp_geom, (void *)arg, sizeof (struct dk_geom), 3017 flag); 3018 if (rval != 0) { 3019 rval = EFAULT; 3020 } 3021 3022 kmem_free(tmp_geom, sizeof (struct dk_geom)); 3023 return (rval); 3024 3025 } 3026 3027 3028 /* 3029 * Function: cmlb_dkio_set_geometry 3030 * 3031 * Description: This routine is the driver entry point for handling user 3032 * requests to set the device geometry (DKIOCSGEOM). The actual 3033 * device geometry is not updated, just the driver "notion" of it. 3034 * 3035 * Arguments: 3036 * arg pointer to user provided dk_geom structure used to set 3037 * the controller's notion of the current geometry. 3038 * 3039 * flag this argument is a pass through to ddi_copyxxx() 3040 * directly from the mode argument of ioctl(). 3041 * 3042 * tg_cookie cookie from target driver to be passed back to target 3043 * driver when we call back to it through tg_ops. 3044 * 3045 * Return Code: 0 3046 * EFAULT 3047 * ENXIO 3048 * EIO 3049 */ 3050 static int 3051 cmlb_dkio_set_geometry(struct cmlb_lun *cl, caddr_t arg, int flag) 3052 { 3053 struct dk_geom *tmp_geom; 3054 struct dk_map *lp; 3055 int rval = 0; 3056 int i; 3057 3058 3059 #if defined(__i386) || defined(__amd64) 3060 if (cl->cl_solaris_size == 0) { 3061 return (EIO); 3062 } 3063 #endif 3064 /* 3065 * We need to copy the user specified geometry into local 3066 * storage and then update the softstate. We don't want to hold 3067 * the mutex and copyin directly from the user to the soft state 3068 */ 3069 tmp_geom = (struct dk_geom *) 3070 kmem_zalloc(sizeof (struct dk_geom), KM_SLEEP); 3071 rval = ddi_copyin(arg, tmp_geom, sizeof (struct dk_geom), flag); 3072 if (rval != 0) { 3073 kmem_free(tmp_geom, sizeof (struct dk_geom)); 3074 return (EFAULT); 3075 } 3076 3077 mutex_enter(CMLB_MUTEX(cl)); 3078 bcopy(tmp_geom, &cl->cl_g, sizeof (struct dk_geom)); 3079 for (i = 0; i < NDKMAP; i++) { 3080 lp = &cl->cl_map[i]; 3081 cl->cl_offset[i] = 3082 cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect * lp->dkl_cylno; 3083 #if defined(__i386) || defined(__amd64) 3084 cl->cl_offset[i] += cl->cl_solaris_offset; 3085 #endif 3086 } 3087 cl->cl_f_geometry_is_valid = FALSE; 3088 mutex_exit(CMLB_MUTEX(cl)); 3089 kmem_free(tmp_geom, sizeof (struct dk_geom)); 3090 3091 return (rval); 3092 } 3093 3094 /* 3095 * Function: cmlb_dkio_get_partition 3096 * 3097 * Description: This routine is the driver entry point for handling user 3098 * requests to get the partition table (DKIOCGAPART). 3099 * 3100 * Arguments: 3101 * arg pointer to user provided dk_allmap structure specifying 3102 * the controller's notion of the current partition table. 3103 * 3104 * flag this argument is a pass through to ddi_copyxxx() 3105 * directly from the mode argument of ioctl(). 3106 * 3107 * tg_cookie cookie from target driver to be passed back to target 3108 * driver when we call back to it through tg_ops. 3109 * 3110 * Return Code: 0 3111 * EFAULT 3112 * ENXIO 3113 * EIO 3114 */ 3115 static int 3116 cmlb_dkio_get_partition(struct cmlb_lun *cl, caddr_t arg, int flag, 3117 void *tg_cookie) 3118 { 3119 int rval = 0; 3120 int size; 3121 3122 /* 3123 * Make sure the geometry is valid before getting the partition 3124 * information. 3125 */ 3126 mutex_enter(CMLB_MUTEX(cl)); 3127 if ((rval = cmlb_validate_geometry(cl, 1, 0, tg_cookie)) != 0) { 3128 mutex_exit(CMLB_MUTEX(cl)); 3129 return (rval); 3130 } 3131 mutex_exit(CMLB_MUTEX(cl)); 3132 3133 #if defined(__i386) || defined(__amd64) 3134 if (cl->cl_solaris_size == 0) { 3135 return (EIO); 3136 } 3137 #endif 3138 3139 #ifdef _MULTI_DATAMODEL 3140 switch (ddi_model_convert_from(flag & FMODELS)) { 3141 case DDI_MODEL_ILP32: { 3142 struct dk_map32 dk_map32[NDKMAP]; 3143 int i; 3144 3145 for (i = 0; i < NDKMAP; i++) { 3146 dk_map32[i].dkl_cylno = cl->cl_map[i].dkl_cylno; 3147 dk_map32[i].dkl_nblk = cl->cl_map[i].dkl_nblk; 3148 } 3149 size = NDKMAP * sizeof (struct dk_map32); 3150 rval = ddi_copyout(dk_map32, (void *)arg, size, flag); 3151 if (rval != 0) { 3152 rval = EFAULT; 3153 } 3154 break; 3155 } 3156 case DDI_MODEL_NONE: 3157 size = NDKMAP * sizeof (struct dk_map); 3158 rval = ddi_copyout(cl->cl_map, (void *)arg, size, flag); 3159 if (rval != 0) { 3160 rval = EFAULT; 3161 } 3162 break; 3163 } 3164 #else /* ! _MULTI_DATAMODEL */ 3165 size = NDKMAP * sizeof (struct dk_map); 3166 rval = ddi_copyout(cl->cl_map, (void *)arg, size, flag); 3167 if (rval != 0) { 3168 rval = EFAULT; 3169 } 3170 #endif /* _MULTI_DATAMODEL */ 3171 return (rval); 3172 } 3173 3174 /* 3175 * Function: cmlb_dkio_set_partition 3176 * 3177 * Description: This routine is the driver entry point for handling user 3178 * requests to set the partition table (DKIOCSAPART). The actual 3179 * device partition is not updated. 3180 * 3181 * Arguments: 3182 * arg - pointer to user provided dk_allmap structure used to set 3183 * the controller's notion of the partition table. 3184 * flag - this argument is a pass through to ddi_copyxxx() 3185 * directly from the mode argument of ioctl(). 3186 * 3187 * Return Code: 0 3188 * EINVAL 3189 * EFAULT 3190 * ENXIO 3191 * EIO 3192 */ 3193 static int 3194 cmlb_dkio_set_partition(struct cmlb_lun *cl, caddr_t arg, int flag) 3195 { 3196 struct dk_map dk_map[NDKMAP]; 3197 struct dk_map *lp; 3198 int rval = 0; 3199 int size; 3200 int i; 3201 #if defined(_SUNOS_VTOC_16) 3202 struct dkl_partition *vp; 3203 #endif 3204 3205 /* 3206 * Set the map for all logical partitions. We lock 3207 * the priority just to make sure an interrupt doesn't 3208 * come in while the map is half updated. 3209 */ 3210 _NOTE(DATA_READABLE_WITHOUT_LOCK(cmlb_lun::cl_solaris_size)) 3211 mutex_enter(CMLB_MUTEX(cl)); 3212 3213 if (cl->cl_blockcount > DK_MAX_BLOCKS) { 3214 mutex_exit(CMLB_MUTEX(cl)); 3215 return (ENOTSUP); 3216 } 3217 mutex_exit(CMLB_MUTEX(cl)); 3218 if (cl->cl_solaris_size == 0) { 3219 return (EIO); 3220 } 3221 3222 #ifdef _MULTI_DATAMODEL 3223 switch (ddi_model_convert_from(flag & FMODELS)) { 3224 case DDI_MODEL_ILP32: { 3225 struct dk_map32 dk_map32[NDKMAP]; 3226 3227 size = NDKMAP * sizeof (struct dk_map32); 3228 rval = ddi_copyin((void *)arg, dk_map32, size, flag); 3229 if (rval != 0) { 3230 return (EFAULT); 3231 } 3232 for (i = 0; i < NDKMAP; i++) { 3233 dk_map[i].dkl_cylno = dk_map32[i].dkl_cylno; 3234 dk_map[i].dkl_nblk = dk_map32[i].dkl_nblk; 3235 } 3236 break; 3237 } 3238 case DDI_MODEL_NONE: 3239 size = NDKMAP * sizeof (struct dk_map); 3240 rval = ddi_copyin((void *)arg, dk_map, size, flag); 3241 if (rval != 0) { 3242 return (EFAULT); 3243 } 3244 break; 3245 } 3246 #else /* ! _MULTI_DATAMODEL */ 3247 size = NDKMAP * sizeof (struct dk_map); 3248 rval = ddi_copyin((void *)arg, dk_map, size, flag); 3249 if (rval != 0) { 3250 return (EFAULT); 3251 } 3252 #endif /* _MULTI_DATAMODEL */ 3253 3254 mutex_enter(CMLB_MUTEX(cl)); 3255 /* Note: The size used in this bcopy is set based upon the data model */ 3256 bcopy(dk_map, cl->cl_map, size); 3257 #if defined(_SUNOS_VTOC_16) 3258 vp = (struct dkl_partition *)&(cl->cl_vtoc); 3259 #endif /* defined(_SUNOS_VTOC_16) */ 3260 for (i = 0; i < NDKMAP; i++) { 3261 lp = &cl->cl_map[i]; 3262 cl->cl_offset[i] = 3263 cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect * lp->dkl_cylno; 3264 #if defined(_SUNOS_VTOC_16) 3265 vp->p_start = cl->cl_offset[i]; 3266 vp->p_size = lp->dkl_nblk; 3267 vp++; 3268 #endif /* defined(_SUNOS_VTOC_16) */ 3269 #if defined(__i386) || defined(__amd64) 3270 cl->cl_offset[i] += cl->cl_solaris_offset; 3271 #endif 3272 } 3273 mutex_exit(CMLB_MUTEX(cl)); 3274 return (rval); 3275 } 3276 3277 3278 /* 3279 * Function: cmlb_dkio_get_vtoc 3280 * 3281 * Description: This routine is the driver entry point for handling user 3282 * requests to get the current volume table of contents 3283 * (DKIOCGVTOC). 3284 * 3285 * Arguments: 3286 * arg pointer to user provided vtoc structure specifying 3287 * the current vtoc. 3288 * 3289 * flag this argument is a pass through to ddi_copyxxx() 3290 * directly from the mode argument of ioctl(). 3291 * 3292 * tg_cookie cookie from target driver to be passed back to target 3293 * driver when we call back to it through tg_ops. 3294 * 3295 * Return Code: 0 3296 * EFAULT 3297 * ENXIO 3298 * EIO 3299 */ 3300 static int 3301 cmlb_dkio_get_vtoc(struct cmlb_lun *cl, caddr_t arg, int flag, void *tg_cookie) 3302 { 3303 #if defined(_SUNOS_VTOC_8) 3304 struct vtoc user_vtoc; 3305 #endif /* defined(_SUNOS_VTOC_8) */ 3306 int rval = 0; 3307 3308 mutex_enter(CMLB_MUTEX(cl)); 3309 rval = cmlb_validate_geometry(cl, 1, 0, tg_cookie); 3310 3311 #if defined(_SUNOS_VTOC_8) 3312 if (rval == EINVAL && 3313 (cl->cl_alter_behavior & CMLB_FAKE_GEOM_LABEL_IOCTLS_VTOC8)) { 3314 /* 3315 * This is to return a default label even when we do not 3316 * really assume a default label for the device. 3317 * dad driver utilizes this. 3318 */ 3319 if (cl->cl_blockcount <= DK_MAX_BLOCKS) { 3320 cmlb_setup_default_geometry(cl, tg_cookie); 3321 rval = 0; 3322 } 3323 } 3324 #endif 3325 if (rval) { 3326 mutex_exit(CMLB_MUTEX(cl)); 3327 return (rval); 3328 } 3329 3330 #if defined(_SUNOS_VTOC_8) 3331 cmlb_build_user_vtoc(cl, &user_vtoc); 3332 mutex_exit(CMLB_MUTEX(cl)); 3333 3334 #ifdef _MULTI_DATAMODEL 3335 switch (ddi_model_convert_from(flag & FMODELS)) { 3336 case DDI_MODEL_ILP32: { 3337 struct vtoc32 user_vtoc32; 3338 3339 vtoctovtoc32(user_vtoc, user_vtoc32); 3340 if (ddi_copyout(&user_vtoc32, (void *)arg, 3341 sizeof (struct vtoc32), flag)) { 3342 return (EFAULT); 3343 } 3344 break; 3345 } 3346 3347 case DDI_MODEL_NONE: 3348 if (ddi_copyout(&user_vtoc, (void *)arg, 3349 sizeof (struct vtoc), flag)) { 3350 return (EFAULT); 3351 } 3352 break; 3353 } 3354 #else /* ! _MULTI_DATAMODEL */ 3355 if (ddi_copyout(&user_vtoc, (void *)arg, sizeof (struct vtoc), flag)) { 3356 return (EFAULT); 3357 } 3358 #endif /* _MULTI_DATAMODEL */ 3359 3360 #elif defined(_SUNOS_VTOC_16) 3361 mutex_exit(CMLB_MUTEX(cl)); 3362 3363 #ifdef _MULTI_DATAMODEL 3364 /* 3365 * The cl_vtoc structure is a "struct dk_vtoc" which is always 3366 * 32-bit to maintain compatibility with existing on-disk 3367 * structures. Thus, we need to convert the structure when copying 3368 * it out to a datamodel-dependent "struct vtoc" in a 64-bit 3369 * program. If the target is a 32-bit program, then no conversion 3370 * is necessary. 3371 */ 3372 /* LINTED: logical expression always true: op "||" */ 3373 ASSERT(sizeof (cl->cl_vtoc) == sizeof (struct vtoc32)); 3374 switch (ddi_model_convert_from(flag & FMODELS)) { 3375 case DDI_MODEL_ILP32: 3376 if (ddi_copyout(&(cl->cl_vtoc), (void *)arg, 3377 sizeof (cl->cl_vtoc), flag)) { 3378 return (EFAULT); 3379 } 3380 break; 3381 3382 case DDI_MODEL_NONE: { 3383 struct vtoc user_vtoc; 3384 3385 vtoc32tovtoc(cl->cl_vtoc, user_vtoc); 3386 if (ddi_copyout(&user_vtoc, (void *)arg, 3387 sizeof (struct vtoc), flag)) { 3388 return (EFAULT); 3389 } 3390 break; 3391 } 3392 } 3393 #else /* ! _MULTI_DATAMODEL */ 3394 if (ddi_copyout(&(cl->cl_vtoc), (void *)arg, sizeof (cl->cl_vtoc), 3395 flag)) { 3396 return (EFAULT); 3397 } 3398 #endif /* _MULTI_DATAMODEL */ 3399 #else 3400 #error "No VTOC format defined." 3401 #endif 3402 3403 return (rval); 3404 } 3405 3406 static int 3407 cmlb_dkio_get_efi(struct cmlb_lun *cl, caddr_t arg, int flag, void *tg_cookie) 3408 { 3409 dk_efi_t user_efi; 3410 int rval = 0; 3411 void *buffer; 3412 diskaddr_t tgt_lba; 3413 3414 if (ddi_copyin(arg, &user_efi, sizeof (dk_efi_t), flag)) 3415 return (EFAULT); 3416 3417 user_efi.dki_data = (void *)(uintptr_t)user_efi.dki_data_64; 3418 3419 tgt_lba = user_efi.dki_lba; 3420 3421 mutex_enter(CMLB_MUTEX(cl)); 3422 if ((cmlb_check_update_blockcount(cl, tg_cookie) != 0) || 3423 (cl->cl_tgt_blocksize == 0)) { 3424 mutex_exit(CMLB_MUTEX(cl)); 3425 return (EINVAL); 3426 } 3427 if (cl->cl_tgt_blocksize != cl->cl_sys_blocksize) 3428 tgt_lba = tgt_lba * cl->cl_tgt_blocksize / 3429 cl->cl_sys_blocksize; 3430 mutex_exit(CMLB_MUTEX(cl)); 3431 3432 buffer = kmem_alloc(user_efi.dki_length, KM_SLEEP); 3433 rval = DK_TG_READ(cl, buffer, tgt_lba, user_efi.dki_length, tg_cookie); 3434 if (rval == 0 && ddi_copyout(buffer, user_efi.dki_data, 3435 user_efi.dki_length, flag) != 0) 3436 rval = EFAULT; 3437 3438 kmem_free(buffer, user_efi.dki_length); 3439 return (rval); 3440 } 3441 3442 #if defined(_SUNOS_VTOC_8) 3443 /* 3444 * Function: cmlb_build_user_vtoc 3445 * 3446 * Description: This routine populates a pass by reference variable with the 3447 * current volume table of contents. 3448 * 3449 * Arguments: cl - driver soft state (unit) structure 3450 * user_vtoc - pointer to vtoc structure to be populated 3451 */ 3452 static void 3453 cmlb_build_user_vtoc(struct cmlb_lun *cl, struct vtoc *user_vtoc) 3454 { 3455 struct dk_map2 *lpart; 3456 struct dk_map *lmap; 3457 struct partition *vpart; 3458 int nblks; 3459 int i; 3460 3461 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 3462 3463 /* 3464 * Return vtoc structure fields in the provided VTOC area, addressed 3465 * by *vtoc. 3466 */ 3467 bzero(user_vtoc, sizeof (struct vtoc)); 3468 user_vtoc->v_bootinfo[0] = cl->cl_vtoc.v_bootinfo[0]; 3469 user_vtoc->v_bootinfo[1] = cl->cl_vtoc.v_bootinfo[1]; 3470 user_vtoc->v_bootinfo[2] = cl->cl_vtoc.v_bootinfo[2]; 3471 user_vtoc->v_sanity = VTOC_SANE; 3472 user_vtoc->v_version = cl->cl_vtoc.v_version; 3473 bcopy(cl->cl_vtoc.v_volume, user_vtoc->v_volume, LEN_DKL_VVOL); 3474 user_vtoc->v_sectorsz = cl->cl_sys_blocksize; 3475 user_vtoc->v_nparts = cl->cl_vtoc.v_nparts; 3476 3477 for (i = 0; i < 10; i++) 3478 user_vtoc->v_reserved[i] = cl->cl_vtoc.v_reserved[i]; 3479 3480 /* 3481 * Convert partitioning information. 3482 * 3483 * Note the conversion from starting cylinder number 3484 * to starting sector number. 3485 */ 3486 lmap = cl->cl_map; 3487 lpart = (struct dk_map2 *)cl->cl_vtoc.v_part; 3488 vpart = user_vtoc->v_part; 3489 3490 nblks = cl->cl_g.dkg_nsect * cl->cl_g.dkg_nhead; 3491 3492 for (i = 0; i < V_NUMPAR; i++) { 3493 vpart->p_tag = lpart->p_tag; 3494 vpart->p_flag = lpart->p_flag; 3495 vpart->p_start = lmap->dkl_cylno * nblks; 3496 vpart->p_size = lmap->dkl_nblk; 3497 lmap++; 3498 lpart++; 3499 vpart++; 3500 3501 /* (4364927) */ 3502 user_vtoc->timestamp[i] = (time_t)cl->cl_vtoc.v_timestamp[i]; 3503 } 3504 3505 bcopy(cl->cl_asciilabel, user_vtoc->v_asciilabel, LEN_DKL_ASCII); 3506 } 3507 #endif 3508 3509 static int 3510 cmlb_dkio_partition(struct cmlb_lun *cl, caddr_t arg, int flag, 3511 void *tg_cookie) 3512 { 3513 struct partition64 p64; 3514 int rval = 0; 3515 uint_t nparts; 3516 efi_gpe_t *partitions; 3517 efi_gpt_t *buffer; 3518 diskaddr_t gpe_lba; 3519 3520 if (ddi_copyin((const void *)arg, &p64, 3521 sizeof (struct partition64), flag)) { 3522 return (EFAULT); 3523 } 3524 3525 buffer = kmem_alloc(EFI_MIN_ARRAY_SIZE, KM_SLEEP); 3526 rval = DK_TG_READ(cl, buffer, 1, DEV_BSIZE, tg_cookie); 3527 if (rval != 0) 3528 goto done_error; 3529 3530 cmlb_swap_efi_gpt(buffer); 3531 3532 if ((rval = cmlb_validate_efi(buffer)) != 0) 3533 goto done_error; 3534 3535 nparts = buffer->efi_gpt_NumberOfPartitionEntries; 3536 gpe_lba = buffer->efi_gpt_PartitionEntryLBA; 3537 if (p64.p_partno > nparts) { 3538 /* couldn't find it */ 3539 rval = ESRCH; 3540 goto done_error; 3541 } 3542 /* 3543 * if we're dealing with a partition that's out of the normal 3544 * 16K block, adjust accordingly 3545 */ 3546 gpe_lba += p64.p_partno / sizeof (efi_gpe_t); 3547 rval = DK_TG_READ(cl, buffer, gpe_lba, EFI_MIN_ARRAY_SIZE, tg_cookie); 3548 3549 if (rval) { 3550 goto done_error; 3551 } 3552 partitions = (efi_gpe_t *)buffer; 3553 3554 cmlb_swap_efi_gpe(nparts, partitions); 3555 3556 partitions += p64.p_partno; 3557 bcopy(&partitions->efi_gpe_PartitionTypeGUID, &p64.p_type, 3558 sizeof (struct uuid)); 3559 p64.p_start = partitions->efi_gpe_StartingLBA; 3560 p64.p_size = partitions->efi_gpe_EndingLBA - 3561 p64.p_start + 1; 3562 3563 if (ddi_copyout(&p64, (void *)arg, sizeof (struct partition64), flag)) 3564 rval = EFAULT; 3565 3566 done_error: 3567 kmem_free(buffer, EFI_MIN_ARRAY_SIZE); 3568 return (rval); 3569 } 3570 3571 3572 /* 3573 * Function: cmlb_dkio_set_vtoc 3574 * 3575 * Description: This routine is the driver entry point for handling user 3576 * requests to set the current volume table of contents 3577 * (DKIOCSVTOC). 3578 * 3579 * Arguments: 3580 * dev the device number 3581 * arg pointer to user provided vtoc structure used to set the 3582 * current vtoc. 3583 * 3584 * flag this argument is a pass through to ddi_copyxxx() 3585 * directly from the mode argument of ioctl(). 3586 * 3587 * tg_cookie cookie from target driver to be passed back to target 3588 * driver when we call back to it through tg_ops. 3589 * 3590 * Return Code: 0 3591 * EFAULT 3592 * ENXIO 3593 * EINVAL 3594 * ENOTSUP 3595 */ 3596 static int 3597 cmlb_dkio_set_vtoc(struct cmlb_lun *cl, dev_t dev, caddr_t arg, int flag, 3598 void *tg_cookie) 3599 { 3600 struct vtoc user_vtoc; 3601 int rval = 0; 3602 boolean_t internal; 3603 3604 internal = ((cl->cl_alter_behavior & (CMLB_INTERNAL_MINOR_NODES)) != 0); 3605 3606 #ifdef _MULTI_DATAMODEL 3607 switch (ddi_model_convert_from(flag & FMODELS)) { 3608 case DDI_MODEL_ILP32: { 3609 struct vtoc32 user_vtoc32; 3610 3611 if (ddi_copyin((const void *)arg, &user_vtoc32, 3612 sizeof (struct vtoc32), flag)) { 3613 return (EFAULT); 3614 } 3615 vtoc32tovtoc(user_vtoc32, user_vtoc); 3616 break; 3617 } 3618 3619 case DDI_MODEL_NONE: 3620 if (ddi_copyin((const void *)arg, &user_vtoc, 3621 sizeof (struct vtoc), flag)) { 3622 return (EFAULT); 3623 } 3624 break; 3625 } 3626 #else /* ! _MULTI_DATAMODEL */ 3627 if (ddi_copyin((const void *)arg, &user_vtoc, 3628 sizeof (struct vtoc), flag)) { 3629 return (EFAULT); 3630 } 3631 #endif /* _MULTI_DATAMODEL */ 3632 3633 mutex_enter(CMLB_MUTEX(cl)); 3634 if (cl->cl_blockcount > DK_MAX_BLOCKS) { 3635 mutex_exit(CMLB_MUTEX(cl)); 3636 return (ENOTSUP); 3637 } 3638 3639 #if defined(__i386) || defined(__amd64) 3640 if (cl->cl_tgt_blocksize != cl->cl_sys_blocksize) { 3641 mutex_exit(CMLB_MUTEX(cl)); 3642 return (EINVAL); 3643 } 3644 #endif 3645 3646 if (cl->cl_g.dkg_ncyl == 0) { 3647 mutex_exit(CMLB_MUTEX(cl)); 3648 return (EINVAL); 3649 } 3650 3651 mutex_exit(CMLB_MUTEX(cl)); 3652 cmlb_clear_efi(cl, tg_cookie); 3653 ddi_remove_minor_node(CMLB_DEVINFO(cl), "wd"); 3654 ddi_remove_minor_node(CMLB_DEVINFO(cl), "wd,raw"); 3655 (void) cmlb_create_minor(CMLB_DEVINFO(cl), "h", 3656 S_IFBLK, (CMLBUNIT(dev) << CMLBUNIT_SHIFT) | WD_NODE, 3657 cl->cl_node_type, NULL, internal); 3658 (void) cmlb_create_minor(CMLB_DEVINFO(cl), "h,raw", 3659 S_IFCHR, (CMLBUNIT(dev) << CMLBUNIT_SHIFT) | WD_NODE, 3660 cl->cl_node_type, NULL, internal); 3661 mutex_enter(CMLB_MUTEX(cl)); 3662 3663 if ((rval = cmlb_build_label_vtoc(cl, &user_vtoc)) == 0) { 3664 if ((rval = cmlb_write_label(cl, tg_cookie)) == 0) { 3665 if (cmlb_validate_geometry(cl, 1, 0, tg_cookie) != 0) { 3666 cmlb_dbg(CMLB_ERROR, cl, 3667 "cmlb_dkio_set_vtoc: " 3668 "Failed validate geometry\n"); 3669 } 3670 } 3671 } 3672 mutex_exit(CMLB_MUTEX(cl)); 3673 return (rval); 3674 } 3675 3676 3677 /* 3678 * Function: cmlb_build_label_vtoc 3679 * 3680 * Description: This routine updates the driver soft state current volume table 3681 * of contents based on a user specified vtoc. 3682 * 3683 * Arguments: cl - driver soft state (unit) structure 3684 * user_vtoc - pointer to vtoc structure specifying vtoc to be used 3685 * to update the driver soft state. 3686 * 3687 * Return Code: 0 3688 * EINVAL 3689 */ 3690 static int 3691 cmlb_build_label_vtoc(struct cmlb_lun *cl, struct vtoc *user_vtoc) 3692 { 3693 struct dk_map *lmap; 3694 struct partition *vpart; 3695 int nblks; 3696 #if defined(_SUNOS_VTOC_8) 3697 int ncyl; 3698 struct dk_map2 *lpart; 3699 #endif /* defined(_SUNOS_VTOC_8) */ 3700 int i; 3701 3702 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 3703 3704 /* Sanity-check the vtoc */ 3705 if (user_vtoc->v_sanity != VTOC_SANE || 3706 user_vtoc->v_sectorsz != cl->cl_sys_blocksize || 3707 user_vtoc->v_nparts != V_NUMPAR) { 3708 cmlb_dbg(CMLB_INFO, cl, 3709 "cmlb_build_label_vtoc: vtoc not valid\n"); 3710 return (EINVAL); 3711 } 3712 3713 nblks = cl->cl_g.dkg_nsect * cl->cl_g.dkg_nhead; 3714 if (nblks == 0) { 3715 cmlb_dbg(CMLB_INFO, cl, 3716 "cmlb_build_label_vtoc: geom nblks is 0\n"); 3717 return (EINVAL); 3718 } 3719 3720 #if defined(_SUNOS_VTOC_8) 3721 vpart = user_vtoc->v_part; 3722 for (i = 0; i < V_NUMPAR; i++) { 3723 if ((vpart->p_start % nblks) != 0) { 3724 cmlb_dbg(CMLB_INFO, cl, 3725 "cmlb_build_label_vtoc: p_start not multiply of" 3726 "nblks part %d p_start %d nblks %d\n", i, 3727 vpart->p_start, nblks); 3728 return (EINVAL); 3729 } 3730 ncyl = vpart->p_start / nblks; 3731 ncyl += vpart->p_size / nblks; 3732 if ((vpart->p_size % nblks) != 0) { 3733 ncyl++; 3734 } 3735 if (ncyl > (int)cl->cl_g.dkg_ncyl) { 3736 cmlb_dbg(CMLB_INFO, cl, 3737 "cmlb_build_label_vtoc: ncyl %d > dkg_ncyl %d" 3738 "p_size %ld p_start %ld nblks %d part number %d" 3739 "tag %d\n", 3740 ncyl, cl->cl_g.dkg_ncyl, vpart->p_size, 3741 vpart->p_start, nblks, 3742 i, vpart->p_tag); 3743 3744 return (EINVAL); 3745 } 3746 vpart++; 3747 } 3748 #endif /* defined(_SUNOS_VTOC_8) */ 3749 3750 /* Put appropriate vtoc structure fields into the disk label */ 3751 #if defined(_SUNOS_VTOC_16) 3752 /* 3753 * The vtoc is always a 32bit data structure to maintain the 3754 * on-disk format. Convert "in place" instead of doing bcopy. 3755 */ 3756 vtoctovtoc32((*user_vtoc), (*((struct vtoc32 *)&(cl->cl_vtoc)))); 3757 3758 /* 3759 * in the 16-slice vtoc, starting sectors are expressed in 3760 * numbers *relative* to the start of the Solaris fdisk partition. 3761 */ 3762 lmap = cl->cl_map; 3763 vpart = user_vtoc->v_part; 3764 3765 for (i = 0; i < (int)user_vtoc->v_nparts; i++, lmap++, vpart++) { 3766 lmap->dkl_cylno = vpart->p_start / nblks; 3767 lmap->dkl_nblk = vpart->p_size; 3768 } 3769 3770 #elif defined(_SUNOS_VTOC_8) 3771 3772 cl->cl_vtoc.v_bootinfo[0] = (uint32_t)user_vtoc->v_bootinfo[0]; 3773 cl->cl_vtoc.v_bootinfo[1] = (uint32_t)user_vtoc->v_bootinfo[1]; 3774 cl->cl_vtoc.v_bootinfo[2] = (uint32_t)user_vtoc->v_bootinfo[2]; 3775 3776 cl->cl_vtoc.v_sanity = (uint32_t)user_vtoc->v_sanity; 3777 cl->cl_vtoc.v_version = (uint32_t)user_vtoc->v_version; 3778 3779 bcopy(user_vtoc->v_volume, cl->cl_vtoc.v_volume, LEN_DKL_VVOL); 3780 3781 cl->cl_vtoc.v_nparts = user_vtoc->v_nparts; 3782 3783 for (i = 0; i < 10; i++) 3784 cl->cl_vtoc.v_reserved[i] = user_vtoc->v_reserved[i]; 3785 3786 /* 3787 * Note the conversion from starting sector number 3788 * to starting cylinder number. 3789 * Return error if division results in a remainder. 3790 */ 3791 lmap = cl->cl_map; 3792 lpart = cl->cl_vtoc.v_part; 3793 vpart = user_vtoc->v_part; 3794 3795 for (i = 0; i < (int)user_vtoc->v_nparts; i++) { 3796 lpart->p_tag = vpart->p_tag; 3797 lpart->p_flag = vpart->p_flag; 3798 lmap->dkl_cylno = vpart->p_start / nblks; 3799 lmap->dkl_nblk = vpart->p_size; 3800 3801 lmap++; 3802 lpart++; 3803 vpart++; 3804 3805 /* (4387723) */ 3806 #ifdef _LP64 3807 if (user_vtoc->timestamp[i] > TIME32_MAX) { 3808 cl->cl_vtoc.v_timestamp[i] = TIME32_MAX; 3809 } else { 3810 cl->cl_vtoc.v_timestamp[i] = user_vtoc->timestamp[i]; 3811 } 3812 #else 3813 cl->cl_vtoc.v_timestamp[i] = user_vtoc->timestamp[i]; 3814 #endif 3815 } 3816 3817 bcopy(user_vtoc->v_asciilabel, cl->cl_asciilabel, LEN_DKL_ASCII); 3818 #else 3819 #error "No VTOC format defined." 3820 #endif 3821 return (0); 3822 } 3823 3824 /* 3825 * Function: cmlb_clear_efi 3826 * 3827 * Description: This routine clears all EFI labels. 3828 * 3829 * Arguments: 3830 * cl driver soft state (unit) structure 3831 * 3832 * tg_cookie cookie from target driver to be passed back to target 3833 * driver when we call back to it through tg_ops. 3834 * Return Code: void 3835 */ 3836 static void 3837 cmlb_clear_efi(struct cmlb_lun *cl, void *tg_cookie) 3838 { 3839 efi_gpt_t *gpt; 3840 diskaddr_t cap; 3841 int rval; 3842 3843 ASSERT(!mutex_owned(CMLB_MUTEX(cl))); 3844 3845 mutex_enter(CMLB_MUTEX(cl)); 3846 cl->cl_reserved = -1; 3847 mutex_exit(CMLB_MUTEX(cl)); 3848 3849 gpt = kmem_alloc(sizeof (efi_gpt_t), KM_SLEEP); 3850 3851 if (DK_TG_READ(cl, gpt, 1, DEV_BSIZE, tg_cookie) != 0) { 3852 goto done; 3853 } 3854 3855 cmlb_swap_efi_gpt(gpt); 3856 rval = cmlb_validate_efi(gpt); 3857 if (rval == 0) { 3858 /* clear primary */ 3859 bzero(gpt, sizeof (efi_gpt_t)); 3860 if (rval = DK_TG_WRITE(cl, gpt, 1, EFI_LABEL_SIZE, tg_cookie)) { 3861 cmlb_dbg(CMLB_INFO, cl, 3862 "cmlb_clear_efi: clear primary label failed\n"); 3863 } 3864 } 3865 /* the backup */ 3866 rval = DK_TG_GETCAP(cl, &cap, tg_cookie); 3867 if (rval) { 3868 goto done; 3869 } 3870 3871 if ((rval = DK_TG_READ(cl, gpt, cap - 1, EFI_LABEL_SIZE, tg_cookie)) 3872 != 0) { 3873 goto done; 3874 } 3875 cmlb_swap_efi_gpt(gpt); 3876 rval = cmlb_validate_efi(gpt); 3877 if (rval == 0) { 3878 /* clear backup */ 3879 cmlb_dbg(CMLB_TRACE, cl, 3880 "cmlb_clear_efi clear backup@%lu\n", cap - 1); 3881 bzero(gpt, sizeof (efi_gpt_t)); 3882 if ((rval = DK_TG_WRITE(cl, gpt, cap - 1, EFI_LABEL_SIZE, 3883 tg_cookie))) { 3884 cmlb_dbg(CMLB_INFO, cl, 3885 "cmlb_clear_efi: clear backup label failed\n"); 3886 } 3887 } else { 3888 /* 3889 * Refer to comments related to off-by-1 at the 3890 * header of this file 3891 */ 3892 if ((rval = DK_TG_READ(cl, gpt, cap - 2, 3893 EFI_LABEL_SIZE, tg_cookie)) != 0) { 3894 goto done; 3895 } 3896 cmlb_swap_efi_gpt(gpt); 3897 rval = cmlb_validate_efi(gpt); 3898 if (rval == 0) { 3899 /* clear legacy backup EFI label */ 3900 cmlb_dbg(CMLB_TRACE, cl, 3901 "cmlb_clear_efi clear legacy backup@%lu\n", 3902 cap - 2); 3903 bzero(gpt, sizeof (efi_gpt_t)); 3904 if ((rval = DK_TG_WRITE(cl, gpt, cap - 2, 3905 EFI_LABEL_SIZE, tg_cookie))) { 3906 cmlb_dbg(CMLB_INFO, cl, 3907 "cmlb_clear_efi: clear legacy backup label " 3908 "failed\n"); 3909 } 3910 } 3911 } 3912 3913 done: 3914 kmem_free(gpt, sizeof (efi_gpt_t)); 3915 } 3916 3917 /* 3918 * Function: cmlb_set_vtoc 3919 * 3920 * Description: This routine writes data to the appropriate positions 3921 * 3922 * Arguments: 3923 * cl driver soft state (unit) structure 3924 * 3925 * dkl the data to be written 3926 * 3927 * tg_cookie cookie from target driver to be passed back to target 3928 * driver when we call back to it through tg_ops. 3929 * 3930 * Return: void 3931 */ 3932 static int 3933 cmlb_set_vtoc(struct cmlb_lun *cl, struct dk_label *dkl, void *tg_cookie) 3934 { 3935 uint_t label_addr; 3936 int sec; 3937 int blk; 3938 int head; 3939 int cyl; 3940 int rval; 3941 3942 #if defined(__i386) || defined(__amd64) 3943 label_addr = cl->cl_solaris_offset + DK_LABEL_LOC; 3944 #else 3945 /* Write the primary label at block 0 of the solaris partition. */ 3946 label_addr = 0; 3947 #endif 3948 3949 rval = DK_TG_WRITE(cl, dkl, label_addr, cl->cl_sys_blocksize, 3950 tg_cookie); 3951 3952 if (rval != 0) { 3953 return (rval); 3954 } 3955 3956 /* 3957 * Calculate where the backup labels go. They are always on 3958 * the last alternate cylinder, but some older drives put them 3959 * on head 2 instead of the last head. They are always on the 3960 * first 5 odd sectors of the appropriate track. 3961 * 3962 * We have no choice at this point, but to believe that the 3963 * disk label is valid. Use the geometry of the disk 3964 * as described in the label. 3965 */ 3966 cyl = dkl->dkl_ncyl + dkl->dkl_acyl - 1; 3967 head = dkl->dkl_nhead - 1; 3968 3969 /* 3970 * Write and verify the backup labels. Make sure we don't try to 3971 * write past the last cylinder. 3972 */ 3973 for (sec = 1; ((sec < 5 * 2 + 1) && (sec < dkl->dkl_nsect)); sec += 2) { 3974 blk = (daddr_t)( 3975 (cyl * ((dkl->dkl_nhead * dkl->dkl_nsect) - dkl->dkl_apc)) + 3976 (head * dkl->dkl_nsect) + sec); 3977 #if defined(__i386) || defined(__amd64) 3978 blk += cl->cl_solaris_offset; 3979 #endif 3980 rval = DK_TG_WRITE(cl, dkl, blk, cl->cl_sys_blocksize, 3981 tg_cookie); 3982 cmlb_dbg(CMLB_INFO, cl, 3983 "cmlb_set_vtoc: wrote backup label %d\n", blk); 3984 if (rval != 0) { 3985 goto exit; 3986 } 3987 } 3988 exit: 3989 return (rval); 3990 } 3991 3992 /* 3993 * Function: cmlb_clear_vtoc 3994 * 3995 * Description: This routine clears out the VTOC labels. 3996 * 3997 * Arguments: 3998 * cl driver soft state (unit) structure 3999 * 4000 * tg_cookie cookie from target driver to be passed back to target 4001 * driver when we call back to it through tg_ops. 4002 * 4003 * Return: void 4004 */ 4005 static void 4006 cmlb_clear_vtoc(struct cmlb_lun *cl, void *tg_cookie) 4007 { 4008 struct dk_label *dkl; 4009 4010 mutex_exit(CMLB_MUTEX(cl)); 4011 dkl = kmem_zalloc(sizeof (struct dk_label), KM_SLEEP); 4012 mutex_enter(CMLB_MUTEX(cl)); 4013 /* 4014 * cmlb_set_vtoc uses these fields in order to figure out 4015 * where to overwrite the backup labels 4016 */ 4017 dkl->dkl_apc = cl->cl_g.dkg_apc; 4018 dkl->dkl_ncyl = cl->cl_g.dkg_ncyl; 4019 dkl->dkl_acyl = cl->cl_g.dkg_acyl; 4020 dkl->dkl_nhead = cl->cl_g.dkg_nhead; 4021 dkl->dkl_nsect = cl->cl_g.dkg_nsect; 4022 mutex_exit(CMLB_MUTEX(cl)); 4023 (void) cmlb_set_vtoc(cl, dkl, tg_cookie); 4024 kmem_free(dkl, sizeof (struct dk_label)); 4025 4026 mutex_enter(CMLB_MUTEX(cl)); 4027 } 4028 4029 /* 4030 * Function: cmlb_write_label 4031 * 4032 * Description: This routine will validate and write the driver soft state vtoc 4033 * contents to the device. 4034 * 4035 * Arguments: 4036 * cl cmlb handle 4037 * 4038 * tg_cookie cookie from target driver to be passed back to target 4039 * driver when we call back to it through tg_ops. 4040 * 4041 * 4042 * Return Code: the code returned by cmlb_send_scsi_cmd() 4043 * 0 4044 * EINVAL 4045 * ENXIO 4046 * ENOMEM 4047 */ 4048 static int 4049 cmlb_write_label(struct cmlb_lun *cl, void *tg_cookie) 4050 { 4051 struct dk_label *dkl; 4052 short sum; 4053 short *sp; 4054 int i; 4055 int rval; 4056 4057 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 4058 mutex_exit(CMLB_MUTEX(cl)); 4059 dkl = kmem_zalloc(sizeof (struct dk_label), KM_SLEEP); 4060 mutex_enter(CMLB_MUTEX(cl)); 4061 4062 bcopy(&cl->cl_vtoc, &dkl->dkl_vtoc, sizeof (struct dk_vtoc)); 4063 dkl->dkl_rpm = cl->cl_g.dkg_rpm; 4064 dkl->dkl_pcyl = cl->cl_g.dkg_pcyl; 4065 dkl->dkl_apc = cl->cl_g.dkg_apc; 4066 dkl->dkl_intrlv = cl->cl_g.dkg_intrlv; 4067 dkl->dkl_ncyl = cl->cl_g.dkg_ncyl; 4068 dkl->dkl_acyl = cl->cl_g.dkg_acyl; 4069 dkl->dkl_nhead = cl->cl_g.dkg_nhead; 4070 dkl->dkl_nsect = cl->cl_g.dkg_nsect; 4071 4072 #if defined(_SUNOS_VTOC_8) 4073 dkl->dkl_obs1 = cl->cl_g.dkg_obs1; 4074 dkl->dkl_obs2 = cl->cl_g.dkg_obs2; 4075 dkl->dkl_obs3 = cl->cl_g.dkg_obs3; 4076 for (i = 0; i < NDKMAP; i++) { 4077 dkl->dkl_map[i].dkl_cylno = cl->cl_map[i].dkl_cylno; 4078 dkl->dkl_map[i].dkl_nblk = cl->cl_map[i].dkl_nblk; 4079 } 4080 bcopy(cl->cl_asciilabel, dkl->dkl_asciilabel, LEN_DKL_ASCII); 4081 #elif defined(_SUNOS_VTOC_16) 4082 dkl->dkl_skew = cl->cl_dkg_skew; 4083 #else 4084 #error "No VTOC format defined." 4085 #endif 4086 4087 dkl->dkl_magic = DKL_MAGIC; 4088 dkl->dkl_write_reinstruct = cl->cl_g.dkg_write_reinstruct; 4089 dkl->dkl_read_reinstruct = cl->cl_g.dkg_read_reinstruct; 4090 4091 /* Construct checksum for the new disk label */ 4092 sum = 0; 4093 sp = (short *)dkl; 4094 i = sizeof (struct dk_label) / sizeof (short); 4095 while (i--) { 4096 sum ^= *sp++; 4097 } 4098 dkl->dkl_cksum = sum; 4099 4100 mutex_exit(CMLB_MUTEX(cl)); 4101 4102 rval = cmlb_set_vtoc(cl, dkl, tg_cookie); 4103 exit: 4104 kmem_free(dkl, sizeof (struct dk_label)); 4105 mutex_enter(CMLB_MUTEX(cl)); 4106 return (rval); 4107 } 4108 4109 static int 4110 cmlb_dkio_set_efi(struct cmlb_lun *cl, dev_t dev, caddr_t arg, int flag, 4111 void *tg_cookie) 4112 { 4113 dk_efi_t user_efi; 4114 int rval = 0; 4115 void *buffer; 4116 diskaddr_t tgt_lba; 4117 boolean_t internal; 4118 4119 if (ddi_copyin(arg, &user_efi, sizeof (dk_efi_t), flag)) 4120 return (EFAULT); 4121 4122 internal = ((cl->cl_alter_behavior & (CMLB_INTERNAL_MINOR_NODES)) != 0); 4123 4124 user_efi.dki_data = (void *)(uintptr_t)user_efi.dki_data_64; 4125 4126 buffer = kmem_alloc(user_efi.dki_length, KM_SLEEP); 4127 if (ddi_copyin(user_efi.dki_data, buffer, user_efi.dki_length, flag)) { 4128 rval = EFAULT; 4129 } else { 4130 /* 4131 * let's clear the vtoc labels and clear the softstate 4132 * vtoc. 4133 */ 4134 mutex_enter(CMLB_MUTEX(cl)); 4135 if (cl->cl_vtoc.v_sanity == VTOC_SANE) { 4136 cmlb_dbg(CMLB_TRACE, cl, 4137 "cmlb_dkio_set_efi: CLEAR VTOC\n"); 4138 if (cl->cl_vtoc_label_is_from_media) 4139 cmlb_clear_vtoc(cl, tg_cookie); 4140 bzero(&cl->cl_vtoc, sizeof (struct dk_vtoc)); 4141 mutex_exit(CMLB_MUTEX(cl)); 4142 ddi_remove_minor_node(CMLB_DEVINFO(cl), "h"); 4143 ddi_remove_minor_node(CMLB_DEVINFO(cl), "h,raw"); 4144 (void) cmlb_create_minor(CMLB_DEVINFO(cl), "wd", 4145 S_IFBLK, 4146 (CMLBUNIT(dev) << CMLBUNIT_SHIFT) | WD_NODE, 4147 cl->cl_node_type, NULL, internal); 4148 (void) cmlb_create_minor(CMLB_DEVINFO(cl), "wd,raw", 4149 S_IFCHR, 4150 (CMLBUNIT(dev) << CMLBUNIT_SHIFT) | WD_NODE, 4151 cl->cl_node_type, NULL, internal); 4152 } else 4153 mutex_exit(CMLB_MUTEX(cl)); 4154 4155 tgt_lba = user_efi.dki_lba; 4156 4157 mutex_enter(CMLB_MUTEX(cl)); 4158 if ((cmlb_check_update_blockcount(cl, tg_cookie) != 0) || 4159 (cl->cl_tgt_blocksize == 0)) { 4160 kmem_free(buffer, user_efi.dki_length); 4161 mutex_exit(CMLB_MUTEX(cl)); 4162 return (EINVAL); 4163 } 4164 if (cl->cl_tgt_blocksize != cl->cl_sys_blocksize) 4165 tgt_lba = tgt_lba * 4166 cl->cl_tgt_blocksize / cl->cl_sys_blocksize; 4167 4168 mutex_exit(CMLB_MUTEX(cl)); 4169 rval = DK_TG_WRITE(cl, buffer, tgt_lba, user_efi.dki_length, 4170 tg_cookie); 4171 4172 if (rval == 0) { 4173 mutex_enter(CMLB_MUTEX(cl)); 4174 cl->cl_f_geometry_is_valid = FALSE; 4175 mutex_exit(CMLB_MUTEX(cl)); 4176 } 4177 } 4178 kmem_free(buffer, user_efi.dki_length); 4179 return (rval); 4180 } 4181 4182 /* 4183 * Function: cmlb_dkio_get_mboot 4184 * 4185 * Description: This routine is the driver entry point for handling user 4186 * requests to get the current device mboot (DKIOCGMBOOT) 4187 * 4188 * Arguments: 4189 * arg pointer to user provided mboot structure specifying 4190 * the current mboot. 4191 * 4192 * flag this argument is a pass through to ddi_copyxxx() 4193 * directly from the mode argument of ioctl(). 4194 * 4195 * tg_cookie cookie from target driver to be passed back to target 4196 * driver when we call back to it through tg_ops. 4197 * 4198 * Return Code: 0 4199 * EINVAL 4200 * EFAULT 4201 * ENXIO 4202 */ 4203 static int 4204 cmlb_dkio_get_mboot(struct cmlb_lun *cl, caddr_t arg, int flag, void *tg_cookie) 4205 { 4206 struct mboot *mboot; 4207 int rval; 4208 size_t buffer_size; 4209 4210 4211 #if defined(_SUNOS_VTOC_8) 4212 if ((!ISREMOVABLE(cl) && !ISHOTPLUGGABLE(cl)) || (arg == NULL)) { 4213 #elif defined(_SUNOS_VTOC_16) 4214 if (arg == NULL) { 4215 #endif 4216 return (EINVAL); 4217 } 4218 4219 /* 4220 * Read the mboot block, located at absolute block 0 on the target. 4221 */ 4222 buffer_size = sizeof (struct mboot); 4223 4224 cmlb_dbg(CMLB_TRACE, cl, 4225 "cmlb_dkio_get_mboot: allocation size: 0x%x\n", buffer_size); 4226 4227 mboot = kmem_zalloc(buffer_size, KM_SLEEP); 4228 if ((rval = DK_TG_READ(cl, mboot, 0, buffer_size, tg_cookie)) == 0) { 4229 if (ddi_copyout(mboot, (void *)arg, 4230 sizeof (struct mboot), flag) != 0) { 4231 rval = EFAULT; 4232 } 4233 } 4234 kmem_free(mboot, buffer_size); 4235 return (rval); 4236 } 4237 4238 4239 /* 4240 * Function: cmlb_dkio_set_mboot 4241 * 4242 * Description: This routine is the driver entry point for handling user 4243 * requests to validate and set the device master boot 4244 * (DKIOCSMBOOT). 4245 * 4246 * Arguments: 4247 * arg pointer to user provided mboot structure used to set the 4248 * master boot. 4249 * 4250 * flag this argument is a pass through to ddi_copyxxx() 4251 * directly from the mode argument of ioctl(). 4252 * 4253 * tg_cookie cookie from target driver to be passed back to target 4254 * driver when we call back to it through tg_ops. 4255 * 4256 * Return Code: 0 4257 * EINVAL 4258 * EFAULT 4259 * ENXIO 4260 */ 4261 static int 4262 cmlb_dkio_set_mboot(struct cmlb_lun *cl, caddr_t arg, int flag, void *tg_cookie) 4263 { 4264 struct mboot *mboot = NULL; 4265 int rval; 4266 ushort_t magic; 4267 4268 4269 ASSERT(!mutex_owned(CMLB_MUTEX(cl))); 4270 4271 #if defined(_SUNOS_VTOC_8) 4272 if (!ISREMOVABLE(cl) && !ISHOTPLUGGABLE(cl)) { 4273 return (EINVAL); 4274 } 4275 #endif 4276 4277 if (arg == NULL) { 4278 return (EINVAL); 4279 } 4280 4281 mboot = kmem_zalloc(sizeof (struct mboot), KM_SLEEP); 4282 4283 if (ddi_copyin((const void *)arg, mboot, 4284 sizeof (struct mboot), flag) != 0) { 4285 kmem_free(mboot, (size_t)(sizeof (struct mboot))); 4286 return (EFAULT); 4287 } 4288 4289 /* Is this really a master boot record? */ 4290 magic = LE_16(mboot->signature); 4291 if (magic != MBB_MAGIC) { 4292 kmem_free(mboot, (size_t)(sizeof (struct mboot))); 4293 return (EINVAL); 4294 } 4295 4296 rval = DK_TG_WRITE(cl, mboot, 0, cl->cl_sys_blocksize, tg_cookie); 4297 4298 mutex_enter(CMLB_MUTEX(cl)); 4299 #if defined(__i386) || defined(__amd64) 4300 if (rval == 0) { 4301 /* 4302 * mboot has been written successfully. 4303 * update the fdisk and vtoc tables in memory 4304 */ 4305 rval = cmlb_update_fdisk_and_vtoc(cl, tg_cookie); 4306 if ((cl->cl_f_geometry_is_valid == FALSE) || (rval != 0)) { 4307 mutex_exit(CMLB_MUTEX(cl)); 4308 kmem_free(mboot, (size_t)(sizeof (struct mboot))); 4309 return (rval); 4310 } 4311 } 4312 4313 #ifdef __lock_lint 4314 cmlb_setup_default_geometry(cl, tg_cookie); 4315 #endif 4316 4317 #else 4318 if (rval == 0) { 4319 /* 4320 * mboot has been written successfully. 4321 * set up the default geometry and VTOC 4322 */ 4323 if (cl->cl_blockcount <= DK_MAX_BLOCKS) 4324 cmlb_setup_default_geometry(cl, tg_cookie); 4325 } 4326 #endif 4327 mutex_exit(CMLB_MUTEX(cl)); 4328 kmem_free(mboot, (size_t)(sizeof (struct mboot))); 4329 return (rval); 4330 } 4331 4332 4333 /* 4334 * Function: cmlb_setup_default_geometry 4335 * 4336 * Description: This local utility routine sets the default geometry as part of 4337 * setting the device mboot. 4338 * 4339 * Arguments: 4340 * cl driver soft state (unit) structure 4341 * 4342 * tg_cookie cookie from target driver to be passed back to target 4343 * driver when we call back to it through tg_ops. 4344 * 4345 * 4346 * Note: This may be redundant with cmlb_build_default_label. 4347 */ 4348 static void 4349 cmlb_setup_default_geometry(struct cmlb_lun *cl, void *tg_cookie) 4350 { 4351 struct cmlb_geom pgeom; 4352 struct cmlb_geom *pgeomp = &pgeom; 4353 int ret; 4354 int geom_base_cap = 1; 4355 4356 4357 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 4358 4359 /* zero out the soft state geometry and partition table. */ 4360 bzero(&cl->cl_g, sizeof (struct dk_geom)); 4361 bzero(&cl->cl_vtoc, sizeof (struct dk_vtoc)); 4362 bzero(cl->cl_map, NDKMAP * (sizeof (struct dk_map))); 4363 4364 /* 4365 * For the rpm, we use the minimum for the disk. 4366 * For the head, cyl and number of sector per track, 4367 * if the capacity <= 1GB, head = 64, sect = 32. 4368 * else head = 255, sect 63 4369 * Note: the capacity should be equal to C*H*S values. 4370 * This will cause some truncation of size due to 4371 * round off errors. For CD-ROMs, this truncation can 4372 * have adverse side effects, so returning ncyl and 4373 * nhead as 1. The nsect will overflow for most of 4374 * CD-ROMs as nsect is of type ushort. 4375 */ 4376 if (cl->cl_alter_behavior & CMLB_FAKE_GEOM_LABEL_IOCTLS_VTOC8) { 4377 /* 4378 * newfs currently can not handle 255 ntracks for SPARC 4379 * so get the geometry from target driver instead of coming up 4380 * with one based on capacity. 4381 */ 4382 mutex_exit(CMLB_MUTEX(cl)); 4383 ret = DK_TG_GETPHYGEOM(cl, pgeomp, tg_cookie); 4384 mutex_enter(CMLB_MUTEX(cl)); 4385 4386 if (ret == 0) { 4387 geom_base_cap = 0; 4388 } else { 4389 cmlb_dbg(CMLB_ERROR, cl, 4390 "cmlb_setup_default_geometry: " 4391 "tg_getphygeom failed %d\n", ret); 4392 4393 /* do default setting, geometry based on capacity */ 4394 } 4395 } 4396 4397 if (geom_base_cap) { 4398 if (ISCD(cl)) { 4399 cl->cl_g.dkg_ncyl = 1; 4400 cl->cl_g.dkg_nhead = 1; 4401 cl->cl_g.dkg_nsect = cl->cl_blockcount; 4402 } else if (cl->cl_blockcount <= 0x1000) { 4403 /* Needed for unlabeled SCSI floppies. */ 4404 cl->cl_g.dkg_nhead = 2; 4405 cl->cl_g.dkg_ncyl = 80; 4406 cl->cl_g.dkg_pcyl = 80; 4407 cl->cl_g.dkg_nsect = cl->cl_blockcount / (2 * 80); 4408 } else if (cl->cl_blockcount <= 0x200000) { 4409 cl->cl_g.dkg_nhead = 64; 4410 cl->cl_g.dkg_nsect = 32; 4411 cl->cl_g.dkg_ncyl = cl->cl_blockcount / (64 * 32); 4412 } else { 4413 cl->cl_g.dkg_nhead = 255; 4414 4415 cl->cl_g.dkg_nsect = ((cl->cl_blockcount + 4416 (UINT16_MAX * 255 * 63) - 1) / 4417 (UINT16_MAX * 255 * 63)) * 63; 4418 4419 if (cl->cl_g.dkg_nsect == 0) 4420 cl->cl_g.dkg_nsect = (UINT16_MAX / 63) * 63; 4421 4422 cl->cl_g.dkg_ncyl = cl->cl_blockcount / 4423 (255 * cl->cl_g.dkg_nsect); 4424 } 4425 4426 cl->cl_g.dkg_acyl = 0; 4427 cl->cl_g.dkg_bcyl = 0; 4428 cl->cl_g.dkg_intrlv = 1; 4429 cl->cl_g.dkg_rpm = 200; 4430 if (cl->cl_g.dkg_pcyl == 0) 4431 cl->cl_g.dkg_pcyl = cl->cl_g.dkg_ncyl + 4432 cl->cl_g.dkg_acyl; 4433 } else { 4434 cl->cl_g.dkg_ncyl = (short)pgeomp->g_ncyl; 4435 cl->cl_g.dkg_acyl = pgeomp->g_acyl; 4436 cl->cl_g.dkg_nhead = pgeomp->g_nhead; 4437 cl->cl_g.dkg_nsect = pgeomp->g_nsect; 4438 cl->cl_g.dkg_intrlv = pgeomp->g_intrlv; 4439 cl->cl_g.dkg_rpm = pgeomp->g_rpm; 4440 cl->cl_g.dkg_pcyl = cl->cl_g.dkg_ncyl + cl->cl_g.dkg_acyl; 4441 } 4442 4443 cl->cl_g.dkg_read_reinstruct = 0; 4444 cl->cl_g.dkg_write_reinstruct = 0; 4445 cl->cl_solaris_size = cl->cl_g.dkg_ncyl * 4446 cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect; 4447 4448 cl->cl_map['a'-'a'].dkl_cylno = 0; 4449 cl->cl_map['a'-'a'].dkl_nblk = cl->cl_solaris_size; 4450 4451 cl->cl_map['c'-'a'].dkl_cylno = 0; 4452 cl->cl_map['c'-'a'].dkl_nblk = cl->cl_solaris_size; 4453 4454 cl->cl_vtoc.v_part[2].p_tag = V_BACKUP; 4455 cl->cl_vtoc.v_part[2].p_flag = V_UNMNT; 4456 cl->cl_vtoc.v_nparts = V_NUMPAR; 4457 cl->cl_vtoc.v_version = V_VERSION; 4458 (void) sprintf((char *)cl->cl_asciilabel, "DEFAULT cyl %d alt %d" 4459 " hd %d sec %d", cl->cl_g.dkg_ncyl, cl->cl_g.dkg_acyl, 4460 cl->cl_g.dkg_nhead, cl->cl_g.dkg_nsect); 4461 4462 cl->cl_f_geometry_is_valid = FALSE; 4463 } 4464 4465 4466 #if defined(__i386) || defined(__amd64) 4467 /* 4468 * Function: cmlb_update_fdisk_and_vtoc 4469 * 4470 * Description: This local utility routine updates the device fdisk and vtoc 4471 * as part of setting the device mboot. 4472 * 4473 * Arguments: 4474 * cl driver soft state (unit) structure 4475 * 4476 * tg_cookie cookie from target driver to be passed back to target 4477 * driver when we call back to it through tg_ops. 4478 * 4479 * 4480 * Return Code: 0 for success or errno-type return code. 4481 * 4482 * Note:x86: This looks like a duplicate of cmlb_validate_geometry(), but 4483 * these did exist separately in x86 sd.c. 4484 */ 4485 static int 4486 cmlb_update_fdisk_and_vtoc(struct cmlb_lun *cl, void *tg_cookie) 4487 { 4488 int count; 4489 int label_rc = 0; 4490 int fdisk_rval; 4491 diskaddr_t capacity; 4492 4493 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 4494 4495 if (cmlb_check_update_blockcount(cl, tg_cookie) != 0) 4496 return (EINVAL); 4497 4498 #if defined(_SUNOS_VTOC_16) 4499 /* 4500 * Set up the "whole disk" fdisk partition; this should always 4501 * exist, regardless of whether the disk contains an fdisk table 4502 * or vtoc. 4503 */ 4504 cl->cl_map[P0_RAW_DISK].dkl_cylno = 0; 4505 cl->cl_map[P0_RAW_DISK].dkl_nblk = cl->cl_blockcount; 4506 #endif /* defined(_SUNOS_VTOC_16) */ 4507 4508 /* 4509 * copy the lbasize and capacity so that if they're 4510 * reset while we're not holding the CMLB_MUTEX(cl), we will 4511 * continue to use valid values after the CMLB_MUTEX(cl) is 4512 * reacquired. 4513 */ 4514 capacity = cl->cl_blockcount; 4515 4516 /* 4517 * refresh the logical and physical geometry caches. 4518 * (data from mode sense format/rigid disk geometry pages, 4519 * and scsi_ifgetcap("geometry"). 4520 */ 4521 cmlb_resync_geom_caches(cl, capacity, tg_cookie); 4522 4523 /* 4524 * Only DIRECT ACCESS devices will have Scl labels. 4525 * CD's supposedly have a Scl label, too 4526 */ 4527 if (cl->cl_device_type == DTYPE_DIRECT || ISREMOVABLE(cl)) { 4528 fdisk_rval = cmlb_read_fdisk(cl, capacity, tg_cookie); 4529 if (fdisk_rval != 0) { 4530 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 4531 return (fdisk_rval); 4532 } 4533 4534 if (cl->cl_solaris_size <= DK_LABEL_LOC) { 4535 /* 4536 * Found fdisk table but no Solaris partition entry, 4537 * so don't call cmlb_uselabel() and don't create 4538 * a default label. 4539 */ 4540 label_rc = 0; 4541 cl->cl_f_geometry_is_valid = TRUE; 4542 goto no_solaris_partition; 4543 } 4544 } else if (capacity < 0) { 4545 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 4546 return (EINVAL); 4547 } 4548 4549 /* 4550 * For Removable media We reach here if we have found a 4551 * SOLARIS PARTITION. 4552 * If cl_f_geometry_is_valid is FALSE it indicates that the SOLARIS 4553 * PARTITION has changed from the previous one, hence we will setup a 4554 * default VTOC in this case. 4555 */ 4556 if (cl->cl_f_geometry_is_valid == FALSE) { 4557 /* if we get here it is writable */ 4558 /* we are called from SMBOOT, and after a write of fdisk */ 4559 cmlb_build_default_label(cl, tg_cookie); 4560 label_rc = 0; 4561 } 4562 4563 no_solaris_partition: 4564 4565 #if defined(_SUNOS_VTOC_16) 4566 /* 4567 * If we have valid geometry, set up the remaining fdisk partitions. 4568 * Note that dkl_cylno is not used for the fdisk map entries, so 4569 * we set it to an entirely bogus value. 4570 */ 4571 for (count = 0; count < FD_NUMPART; count++) { 4572 cl->cl_map[FDISK_P1 + count].dkl_cylno = -1; 4573 cl->cl_map[FDISK_P1 + count].dkl_nblk = 4574 cl->cl_fmap[count].fmap_nblk; 4575 cl->cl_offset[FDISK_P1 + count] = 4576 cl->cl_fmap[count].fmap_start; 4577 } 4578 #endif 4579 4580 for (count = 0; count < NDKMAP; count++) { 4581 #if defined(_SUNOS_VTOC_8) 4582 struct dk_map *lp = &cl->cl_map[count]; 4583 cl->cl_offset[count] = 4584 cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect * lp->dkl_cylno; 4585 #elif defined(_SUNOS_VTOC_16) 4586 struct dkl_partition *vp = &cl->cl_vtoc.v_part[count]; 4587 cl->cl_offset[count] = vp->p_start + cl->cl_solaris_offset; 4588 #else 4589 #error "No VTOC format defined." 4590 #endif 4591 } 4592 4593 ASSERT(mutex_owned(CMLB_MUTEX(cl))); 4594 return (label_rc); 4595 } 4596 #endif 4597 4598 #if defined(__i386) || defined(__amd64) 4599 static int 4600 cmlb_dkio_get_virtgeom(struct cmlb_lun *cl, caddr_t arg, int flag) 4601 { 4602 int err = 0; 4603 4604 /* Return the driver's notion of the media's logical geometry */ 4605 struct dk_geom disk_geom; 4606 struct dk_geom *dkgp = &disk_geom; 4607 4608 mutex_enter(CMLB_MUTEX(cl)); 4609 /* 4610 * If there is no HBA geometry available, or 4611 * if the HBA returned us something that doesn't 4612 * really fit into an Int 13/function 8 geometry 4613 * result, just fail the ioctl. See PSARC 1998/313. 4614 */ 4615 if (cl->cl_lgeom.g_nhead == 0 || 4616 cl->cl_lgeom.g_nsect == 0 || 4617 cl->cl_lgeom.g_ncyl > 1024) { 4618 mutex_exit(CMLB_MUTEX(cl)); 4619 err = EINVAL; 4620 } else { 4621 dkgp->dkg_ncyl = cl->cl_lgeom.g_ncyl; 4622 dkgp->dkg_acyl = cl->cl_lgeom.g_acyl; 4623 dkgp->dkg_pcyl = dkgp->dkg_ncyl + dkgp->dkg_acyl; 4624 dkgp->dkg_nhead = cl->cl_lgeom.g_nhead; 4625 dkgp->dkg_nsect = cl->cl_lgeom.g_nsect; 4626 4627 mutex_exit(CMLB_MUTEX(cl)); 4628 if (ddi_copyout(dkgp, (void *)arg, 4629 sizeof (struct dk_geom), flag)) { 4630 err = EFAULT; 4631 } else { 4632 err = 0; 4633 } 4634 } 4635 return (err); 4636 } 4637 #endif 4638 4639 #if defined(__i386) || defined(__amd64) 4640 static int 4641 cmlb_dkio_get_phygeom(struct cmlb_lun *cl, caddr_t arg, int flag) 4642 { 4643 int err = 0; 4644 diskaddr_t capacity; 4645 4646 4647 /* Return the driver's notion of the media physical geometry */ 4648 struct dk_geom disk_geom; 4649 struct dk_geom *dkgp = &disk_geom; 4650 4651 mutex_enter(CMLB_MUTEX(cl)); 4652 4653 if (cl->cl_g.dkg_nhead != 0 && 4654 cl->cl_g.dkg_nsect != 0) { 4655 /* 4656 * We succeeded in getting a geometry, but 4657 * right now it is being reported as just the 4658 * Solaris fdisk partition, just like for 4659 * DKIOCGGEOM. We need to change that to be 4660 * correct for the entire disk now. 4661 */ 4662 bcopy(&cl->cl_g, dkgp, sizeof (*dkgp)); 4663 dkgp->dkg_acyl = 0; 4664 dkgp->dkg_ncyl = cl->cl_blockcount / 4665 (dkgp->dkg_nhead * dkgp->dkg_nsect); 4666 } else { 4667 bzero(dkgp, sizeof (struct dk_geom)); 4668 /* 4669 * This disk does not have a Solaris VTOC 4670 * so we must present a physical geometry 4671 * that will remain consistent regardless 4672 * of how the disk is used. This will ensure 4673 * that the geometry does not change regardless 4674 * of the fdisk partition type (ie. EFI, FAT32, 4675 * Solaris, etc). 4676 */ 4677 if (ISCD(cl)) { 4678 dkgp->dkg_nhead = cl->cl_pgeom.g_nhead; 4679 dkgp->dkg_nsect = cl->cl_pgeom.g_nsect; 4680 dkgp->dkg_ncyl = cl->cl_pgeom.g_ncyl; 4681 dkgp->dkg_acyl = cl->cl_pgeom.g_acyl; 4682 } else { 4683 /* 4684 * Invalid cl_blockcount can generate invalid 4685 * dk_geom and may result in division by zero 4686 * system failure. Should make sure blockcount 4687 * is valid before using it here. 4688 */ 4689 if (cl->cl_blockcount == 0) { 4690 mutex_exit(CMLB_MUTEX(cl)); 4691 err = EIO; 4692 return (err); 4693 } 4694 /* 4695 * Refer to comments related to off-by-1 at the 4696 * header of this file 4697 */ 4698 if (cl->cl_alter_behavior & CMLB_OFF_BY_ONE) 4699 capacity = cl->cl_blockcount - 1; 4700 else 4701 capacity = cl->cl_blockcount; 4702 4703 cmlb_convert_geometry(capacity, dkgp); 4704 dkgp->dkg_acyl = 0; 4705 dkgp->dkg_ncyl = capacity / 4706 (dkgp->dkg_nhead * dkgp->dkg_nsect); 4707 } 4708 } 4709 dkgp->dkg_pcyl = dkgp->dkg_ncyl + dkgp->dkg_acyl; 4710 4711 mutex_exit(CMLB_MUTEX(cl)); 4712 if (ddi_copyout(dkgp, (void *)arg, sizeof (struct dk_geom), flag)) 4713 err = EFAULT; 4714 4715 return (err); 4716 } 4717 #endif 4718 4719 #if defined(__i386) || defined(__amd64) 4720 static int 4721 cmlb_dkio_partinfo(struct cmlb_lun *cl, dev_t dev, caddr_t arg, int flag) 4722 { 4723 int err = 0; 4724 4725 /* 4726 * Return parameters describing the selected disk slice. 4727 * Note: this ioctl is for the intel platform only 4728 */ 4729 int part; 4730 4731 part = CMLBPART(dev); 4732 4733 mutex_enter(CMLB_MUTEX(cl)); 4734 /* don't check cl_solaris_size for pN */ 4735 if (part < P0_RAW_DISK && cl->cl_solaris_size == 0) { 4736 err = EIO; 4737 mutex_exit(CMLB_MUTEX(cl)); 4738 } else { 4739 struct part_info p; 4740 4741 p.p_start = (daddr_t)cl->cl_offset[part]; 4742 p.p_length = (int)cl->cl_map[part].dkl_nblk; 4743 mutex_exit(CMLB_MUTEX(cl)); 4744 #ifdef _MULTI_DATAMODEL 4745 switch (ddi_model_convert_from(flag & FMODELS)) { 4746 case DDI_MODEL_ILP32: 4747 { 4748 struct part_info32 p32; 4749 4750 p32.p_start = (daddr32_t)p.p_start; 4751 p32.p_length = p.p_length; 4752 if (ddi_copyout(&p32, (void *)arg, 4753 sizeof (p32), flag)) 4754 err = EFAULT; 4755 break; 4756 } 4757 4758 case DDI_MODEL_NONE: 4759 { 4760 if (ddi_copyout(&p, (void *)arg, sizeof (p), 4761 flag)) 4762 err = EFAULT; 4763 break; 4764 } 4765 } 4766 #else /* ! _MULTI_DATAMODEL */ 4767 if (ddi_copyout(&p, (void *)arg, sizeof (p), flag)) 4768 err = EFAULT; 4769 #endif /* _MULTI_DATAMODEL */ 4770 } 4771 return (err); 4772 } 4773 #endif 4774 4775 int 4776 cmlb_prop_op(cmlb_handle_t cmlbhandle, 4777 dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags, 4778 char *name, caddr_t valuep, int *lengthp, int part, void *tg_cookie) 4779 { 4780 struct cmlb_lun *cl; 4781 diskaddr_t capacity; 4782 uint32_t lbasize; 4783 enum dp { DP_NBLOCKS, DP_BLKSIZE } dp; 4784 int callers_length; 4785 caddr_t buffer; 4786 uint64_t nblocks64; 4787 uint_t dblk; 4788 4789 /* Always fallback to ddi_prop_op... */ 4790 cl = (struct cmlb_lun *)cmlbhandle; 4791 if (cl == NULL) { 4792 fallback: return (ddi_prop_op(dev, dip, prop_op, mod_flags, 4793 name, valuep, lengthp)); 4794 } 4795 4796 /* Pick up capacity and blocksize information. */ 4797 capacity = cl->cl_blockcount; 4798 if (capacity == 0) 4799 goto fallback; 4800 lbasize = cl->cl_tgt_blocksize; 4801 if (lbasize == 0) 4802 lbasize = DEV_BSIZE; /* 0 -> DEV_BSIZE units */ 4803 4804 /* Check for dynamic property of whole device. */ 4805 if (dev == DDI_DEV_T_ANY) { 4806 /* Fallback to ddi_prop_op if we don't understand. */ 4807 if (strcmp(name, "device-nblocks") == 0) 4808 dp = DP_NBLOCKS; 4809 else if (strcmp(name, "device-blksize") == 0) 4810 dp = DP_BLKSIZE; 4811 else 4812 goto fallback; 4813 4814 /* get callers length, establish length of our dynamic prop */ 4815 callers_length = *lengthp; 4816 if (dp == DP_NBLOCKS) 4817 *lengthp = sizeof (uint64_t); 4818 else if (dp == DP_BLKSIZE) 4819 *lengthp = sizeof (uint32_t); 4820 4821 /* service request for the length of the property */ 4822 if (prop_op == PROP_LEN) 4823 return (DDI_PROP_SUCCESS); 4824 4825 switch (prop_op) { 4826 case PROP_LEN_AND_VAL_ALLOC: 4827 if ((buffer = kmem_alloc(*lengthp, 4828 (mod_flags & DDI_PROP_CANSLEEP) ? 4829 KM_SLEEP : KM_NOSLEEP)) == NULL) 4830 return (DDI_PROP_NO_MEMORY); 4831 *(caddr_t *)valuep = buffer; /* set callers buf */ 4832 break; 4833 4834 case PROP_LEN_AND_VAL_BUF: 4835 /* the length of the prop and the request must match */ 4836 if (callers_length != *lengthp) 4837 return (DDI_PROP_INVAL_ARG); 4838 buffer = valuep; /* get callers buf */ 4839 break; 4840 4841 default: 4842 return (DDI_PROP_INVAL_ARG); 4843 } 4844 4845 /* transfer the value into the buffer */ 4846 if (dp == DP_NBLOCKS) 4847 *((uint64_t *)buffer) = capacity; 4848 else if (dp == DP_BLKSIZE) 4849 *((uint32_t *)buffer) = lbasize; 4850 4851 return (DDI_PROP_SUCCESS); 4852 } 4853 4854 /* 4855 * Support dynamic size oriented properties of partition. Requests 4856 * issued under conditions where size is valid are passed to 4857 * ddi_prop_op_nblocks with the size information, otherwise the 4858 * request is passed to ddi_prop_op. Size depends on valid geometry. 4859 */ 4860 if (!cmlb_is_valid(cmlbhandle)) 4861 goto fallback; 4862 4863 /* Get partition nblocks value. */ 4864 (void) cmlb_partinfo(cmlbhandle, part, 4865 (diskaddr_t *)&nblocks64, NULL, NULL, NULL, tg_cookie); 4866 4867 /* 4868 * Assume partition information is in DEV_BSIZE units, compute 4869 * divisor for size(9P) property representation. 4870 */ 4871 dblk = lbasize / DEV_BSIZE; 4872 4873 /* Now let ddi_prop_op_nblocks_blksize() handle the request. */ 4874 return (ddi_prop_op_nblocks_blksize(dev, dip, prop_op, mod_flags, 4875 name, valuep, lengthp, nblocks64 / dblk, lbasize)); 4876 } 4877