Home | History | Annotate | Download | only in io
      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 /*
     28  * This module provides support for labeling operations for target
     29  * drivers.
     30  */
     31 
     32 #include <sys/scsi/scsi.h>
     33 #include <sys/sunddi.h>
     34 #include <sys/dklabel.h>
     35 #include <sys/dkio.h>
     36 #include <sys/vtoc.h>
     37 #include <sys/dktp/fdisk.h>
     38 #include <sys/vtrace.h>
     39 #include <sys/efi_partition.h>
     40 #include <sys/cmlb.h>
     41 #include <sys/cmlb_impl.h>
     42 #include <sys/ddi_impldefs.h>
     43 
     44 /*
     45  * Driver minor node structure and data table
     46  */
     47 struct driver_minor_data {
     48 	char	*name;
     49 	minor_t	minor;
     50 	int	type;
     51 };
     52 
     53 static struct driver_minor_data dk_minor_data[] = {
     54 	{"a", 0, S_IFBLK},
     55 	{"b", 1, S_IFBLK},
     56 	{"c", 2, S_IFBLK},
     57 	{"d", 3, S_IFBLK},
     58 	{"e", 4, S_IFBLK},
     59 	{"f", 5, S_IFBLK},
     60 	{"g", 6, S_IFBLK},
     61 	{"h", 7, S_IFBLK},
     62 #if defined(_SUNOS_VTOC_16)
     63 	{"i", 8, S_IFBLK},
     64 	{"j", 9, S_IFBLK},
     65 	{"k", 10, S_IFBLK},
     66 	{"l", 11, S_IFBLK},
     67 	{"m", 12, S_IFBLK},
     68 	{"n", 13, S_IFBLK},
     69 	{"o", 14, S_IFBLK},
     70 	{"p", 15, S_IFBLK},
     71 #endif			/* defined(_SUNOS_VTOC_16) */
     72 #if defined(_FIRMWARE_NEEDS_FDISK)
     73 	{"q", 16, S_IFBLK},
     74 	{"r", 17, S_IFBLK},
     75 	{"s", 18, S_IFBLK},
     76 	{"t", 19, S_IFBLK},
     77 	{"u", 20, S_IFBLK},
     78 #endif			/* defined(_FIRMWARE_NEEDS_FDISK) */
     79 	{"a,raw", 0, S_IFCHR},
     80 	{"b,raw", 1, S_IFCHR},
     81 	{"c,raw", 2, S_IFCHR},
     82 	{"d,raw", 3, S_IFCHR},
     83 	{"e,raw", 4, S_IFCHR},
     84 	{"f,raw", 5, S_IFCHR},
     85 	{"g,raw", 6, S_IFCHR},
     86 	{"h,raw", 7, S_IFCHR},
     87 #if defined(_SUNOS_VTOC_16)
     88 	{"i,raw", 8, S_IFCHR},
     89 	{"j,raw", 9, S_IFCHR},
     90 	{"k,raw", 10, S_IFCHR},
     91 	{"l,raw", 11, S_IFCHR},
     92 	{"m,raw", 12, S_IFCHR},
     93 	{"n,raw", 13, S_IFCHR},
     94 	{"o,raw", 14, S_IFCHR},
     95 	{"p,raw", 15, S_IFCHR},
     96 #endif			/* defined(_SUNOS_VTOC_16) */
     97 #if defined(_FIRMWARE_NEEDS_FDISK)
     98 	{"q,raw", 16, S_IFCHR},
     99 	{"r,raw", 17, S_IFCHR},
    100 	{"s,raw", 18, S_IFCHR},
    101 	{"t,raw", 19, S_IFCHR},
    102 	{"u,raw", 20, S_IFCHR},
    103 #endif			/* defined(_FIRMWARE_NEEDS_FDISK) */
    104 	{0}
    105 };
    106 
    107 static struct driver_minor_data dk_minor_data_efi[] = {
    108 	{"a", 0, S_IFBLK},
    109 	{"b", 1, S_IFBLK},
    110 	{"c", 2, S_IFBLK},
    111 	{"d", 3, S_IFBLK},
    112 	{"e", 4, S_IFBLK},
    113 	{"f", 5, S_IFBLK},
    114 	{"g", 6, S_IFBLK},
    115 	{"wd", 7, S_IFBLK},
    116 #if defined(_FIRMWARE_NEEDS_FDISK)
    117 	{"q", 16, S_IFBLK},
    118 	{"r", 17, S_IFBLK},
    119 	{"s", 18, S_IFBLK},
    120 	{"t", 19, S_IFBLK},
    121 	{"u", 20, S_IFBLK},
    122 #endif			/* defined(_FIRMWARE_NEEDS_FDISK) */
    123 	{"a,raw", 0, S_IFCHR},
    124 	{"b,raw", 1, S_IFCHR},
    125 	{"c,raw", 2, S_IFCHR},
    126 	{"d,raw", 3, S_IFCHR},
    127 	{"e,raw", 4, S_IFCHR},
    128 	{"f,raw", 5, S_IFCHR},
    129 	{"g,raw", 6, S_IFCHR},
    130 	{"wd,raw", 7, S_IFCHR},
    131 #if defined(_FIRMWARE_NEEDS_FDISK)
    132 	{"q,raw", 16, S_IFCHR},
    133 	{"r,raw", 17, S_IFCHR},
    134 	{"s,raw", 18, S_IFCHR},
    135 	{"t,raw", 19, S_IFCHR},
    136 	{"u,raw", 20, S_IFCHR},
    137 #endif			/* defined(_FIRMWARE_NEEDS_FDISK) */
    138 	{0}
    139 };
    140 
    141 /*
    142  * Declare the dynamic properties implemented in prop_op(9E) implementation
    143  * that we want to have show up in a di_init(3DEVINFO) device tree snapshot
    144  * of drivers that call cmlb_attach().
    145  */
    146 static i_ddi_prop_dyn_t cmlb_prop_dyn[] = {
    147 	{"Nblocks",		DDI_PROP_TYPE_INT64,	S_IFBLK},
    148 	{"Size",		DDI_PROP_TYPE_INT64,	S_IFCHR},
    149 	{"device-nblocks",	DDI_PROP_TYPE_INT64},
    150 	{"device-blksize",	DDI_PROP_TYPE_INT},
    151 	{NULL}
    152 };
    153 
    154 /*
    155  * External kernel interfaces
    156  */
    157 extern struct mod_ops mod_miscops;
    158 
    159 extern int ddi_create_internal_pathname(dev_info_t *dip, char *name,
    160     int spec_type, minor_t minor_num);
    161 
    162 /*
    163  * Global buffer and mutex for debug logging
    164  */
    165 static char	cmlb_log_buffer[1024];
    166 static kmutex_t	cmlb_log_mutex;
    167 
    168 
    169 struct cmlb_lun *cmlb_debug_cl = NULL;
    170 uint_t cmlb_level_mask = 0x0;
    171 
    172 int cmlb_rot_delay = 4;	/* default rotational delay */
    173 
    174 static struct modlmisc modlmisc = {
    175 	&mod_miscops,   /* Type of module */
    176 	"Common Labeling module"
    177 };
    178 
    179 static struct modlinkage modlinkage = {
    180 	MODREV_1, (void *)&modlmisc, NULL
    181 };
    182 
    183 /* Local function prototypes */
    184 static dev_t cmlb_make_device(struct cmlb_lun *cl);
    185 static int cmlb_validate_geometry(struct cmlb_lun *cl, int forcerevalid,
    186     int flags, void *tg_cookie);
    187 static void cmlb_resync_geom_caches(struct cmlb_lun *cl, diskaddr_t capacity,
    188     void *tg_cookie);
    189 static int cmlb_read_fdisk(struct cmlb_lun *cl, diskaddr_t capacity,
    190     void *tg_cookie);
    191 static void cmlb_swap_efi_gpt(efi_gpt_t *e);
    192 static void cmlb_swap_efi_gpe(int nparts, efi_gpe_t *p);
    193 static int cmlb_validate_efi(efi_gpt_t *labp);
    194 static int cmlb_use_efi(struct cmlb_lun *cl, diskaddr_t capacity, int flags,
    195     void *tg_cookie);
    196 static void cmlb_build_default_label(struct cmlb_lun *cl, void *tg_cookie);
    197 static int  cmlb_uselabel(struct cmlb_lun *cl,  struct dk_label *l, int flags);
    198 #if defined(_SUNOS_VTOC_8)
    199 static void cmlb_build_user_vtoc(struct cmlb_lun *cl, struct vtoc *user_vtoc);
    200 #endif
    201 static int cmlb_build_label_vtoc(struct cmlb_lun *cl, struct vtoc *user_vtoc);
    202 static int cmlb_write_label(struct cmlb_lun *cl, void *tg_cookie);
    203 static int cmlb_set_vtoc(struct cmlb_lun *cl, struct dk_label *dkl,
    204     void *tg_cookie);
    205 static void cmlb_clear_efi(struct cmlb_lun *cl, void *tg_cookie);
    206 static void cmlb_clear_vtoc(struct cmlb_lun *cl, void *tg_cookie);
    207 static void cmlb_setup_default_geometry(struct cmlb_lun *cl, void *tg_cookie);
    208 static int cmlb_create_minor_nodes(struct cmlb_lun *cl);
    209 static int cmlb_check_update_blockcount(struct cmlb_lun *cl, void *tg_cookie);
    210 static int cmlb_check_efi_mbr(uchar_t *buf, int *is_mbr);
    211 
    212 #if defined(__i386) || defined(__amd64)
    213 static int cmlb_update_fdisk_and_vtoc(struct cmlb_lun *cl, void *tg_cookie);
    214 #endif
    215 
    216 #if defined(_FIRMWARE_NEEDS_FDISK)
    217 static int  cmlb_has_max_chs_vals(struct ipart *fdp);
    218 #endif
    219 
    220 #if defined(_SUNOS_VTOC_16)
    221 static void cmlb_convert_geometry(diskaddr_t capacity, struct dk_geom *cl_g);
    222 #endif
    223 
    224 static int cmlb_dkio_get_geometry(struct cmlb_lun *cl, caddr_t arg, int flag,
    225     void *tg_cookie);
    226 static int cmlb_dkio_set_geometry(struct cmlb_lun *cl, caddr_t arg, int flag);
    227 static int cmlb_dkio_get_partition(struct cmlb_lun *cl, caddr_t arg, int flag,
    228     void *tg_cookie);
    229 static int cmlb_dkio_set_partition(struct cmlb_lun *cl, caddr_t arg, int flag);
    230 static int cmlb_dkio_get_efi(struct cmlb_lun *cl, caddr_t arg, int flag,
    231     void *tg_cookie);
    232 static int cmlb_dkio_set_efi(struct cmlb_lun *cl, dev_t dev, caddr_t arg,
    233     int flag, void *tg_cookie);
    234 static int cmlb_dkio_get_vtoc(struct cmlb_lun *cl, caddr_t arg, int flag,
    235     void *tg_cookie);
    236 static int cmlb_dkio_get_extvtoc(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_set_extvtoc(struct cmlb_lun *cl, dev_t dev, caddr_t arg,
    241     int flag, void *tg_cookie);
    242 static int cmlb_dkio_get_mboot(struct cmlb_lun *cl, caddr_t arg, int flag,
    243     void *tg_cookie);
    244 static int cmlb_dkio_set_mboot(struct cmlb_lun *cl, caddr_t arg, int flag,
    245     void *tg_cookie);
    246 static int cmlb_dkio_partition(struct cmlb_lun *cl, caddr_t arg, int flag,
    247     void *tg_cookie);
    248 
    249 #if defined(__i386) || defined(__amd64)
    250 static int cmlb_dkio_get_virtgeom(struct cmlb_lun *cl, caddr_t arg, int flag);
    251 static int cmlb_dkio_get_phygeom(struct cmlb_lun *cl, caddr_t  arg, int flag);
    252 static int cmlb_dkio_partinfo(struct cmlb_lun *cl, dev_t dev, caddr_t arg,
    253     int flag);
    254 static int cmlb_dkio_extpartinfo(struct cmlb_lun *cl, dev_t dev, caddr_t arg,
    255     int flag);
    256 #endif
    257 
    258 static void cmlb_dbg(uint_t comp, struct cmlb_lun *cl, const char *fmt, ...);
    259 static void cmlb_v_log(dev_info_t *dev, char *label, uint_t level,
    260     const char *fmt, va_list ap);
    261 static void cmlb_log(dev_info_t *dev, char *label, uint_t level,
    262     const char *fmt, ...);
    263 
    264 int
    265 _init(void)
    266 {
    267 	mutex_init(&cmlb_log_mutex, NULL, MUTEX_DRIVER, NULL);
    268 	return (mod_install(&modlinkage));
    269 }
    270 
    271 int
    272 _info(struct modinfo *modinfop)
    273 {
    274 	return (mod_info(&modlinkage, modinfop));
    275 }
    276 
    277 int
    278 _fini(void)
    279 {
    280 	int err;
    281 
    282 	if ((err = mod_remove(&modlinkage)) != 0) {
    283 		return (err);
    284 	}
    285 
    286 	mutex_destroy(&cmlb_log_mutex);
    287 	return (err);
    288 }
    289 
    290 /*
    291  * cmlb_dbg is used for debugging to log additional info
    292  * Level of output is controlled via cmlb_level_mask setting.
    293  */
    294 static void
    295 cmlb_dbg(uint_t comp, struct cmlb_lun *cl, const char *fmt, ...)
    296 {
    297 	va_list		ap;
    298 	dev_info_t	*dev;
    299 	uint_t		level_mask = 0;
    300 
    301 	ASSERT(cl != NULL);
    302 	dev = CMLB_DEVINFO(cl);
    303 	ASSERT(dev != NULL);
    304 	/*
    305 	 * Filter messages based on the global component and level masks,
    306 	 * also print if cl matches the value of cmlb_debug_cl, or if
    307 	 * cmlb_debug_cl is set to NULL.
    308 	 */
    309 	if (comp & CMLB_TRACE)
    310 		level_mask |= CMLB_LOGMASK_TRACE;
    311 
    312 	if (comp & CMLB_INFO)
    313 		level_mask |= CMLB_LOGMASK_INFO;
    314 
    315 	if (comp & CMLB_ERROR)
    316 		level_mask |= CMLB_LOGMASK_ERROR;
    317 
    318 	if ((cmlb_level_mask & level_mask) &&
    319 	    ((cmlb_debug_cl == NULL) || (cmlb_debug_cl == cl))) {
    320 		va_start(ap, fmt);
    321 		cmlb_v_log(dev, CMLB_LABEL(cl), CE_CONT, fmt, ap);
    322 		va_end(ap);
    323 	}
    324 }
    325 
    326 /*
    327  * cmlb_log is basically a duplicate of scsi_log. It is redefined here
    328  * so that this module does not depend on scsi module.
    329  */
    330 static void
    331 cmlb_log(dev_info_t *dev, char *label, uint_t level, const char *fmt, ...)
    332 {
    333 	va_list		ap;
    334 
    335 	va_start(ap, fmt);
    336 	cmlb_v_log(dev, label, level, fmt, ap);
    337 	va_end(ap);
    338 }
    339 
    340 static void
    341 cmlb_v_log(dev_info_t *dev, char *label, uint_t level, const char *fmt,
    342     va_list ap)
    343 {
    344 	static char 	name[256];
    345 	int 		log_only = 0;
    346 	int 		boot_only = 0;
    347 	int 		console_only = 0;
    348 
    349 	mutex_enter(&cmlb_log_mutex);
    350 
    351 	if (dev) {
    352 		if (level == CE_PANIC || level == CE_WARN ||
    353 		    level == CE_NOTE) {
    354 			(void) sprintf(name, "%s (%s%d):\n",
    355 			    ddi_pathname(dev, cmlb_log_buffer),
    356 			    label, ddi_get_instance(dev));
    357 		} else {
    358 			name[0] = '\0';
    359 		}
    360 	} else {
    361 		(void) sprintf(name, "%s:", label);
    362 	}
    363 
    364 	(void) vsprintf(cmlb_log_buffer, fmt, ap);
    365 
    366 	switch (cmlb_log_buffer[0]) {
    367 	case '!':
    368 		log_only = 1;
    369 		break;
    370 	case '?':
    371 		boot_only = 1;
    372 		break;
    373 	case '^':
    374 		console_only = 1;
    375 		break;
    376 	}
    377 
    378 	switch (level) {
    379 	case CE_NOTE:
    380 		level = CE_CONT;
    381 		/* FALLTHROUGH */
    382 	case CE_CONT:
    383 	case CE_WARN:
    384 	case CE_PANIC:
    385 		if (boot_only) {
    386 			cmn_err(level, "?%s\t%s", name, &cmlb_log_buffer[1]);
    387 		} else if (console_only) {
    388 			cmn_err(level, "^%s\t%s", name, &cmlb_log_buffer[1]);
    389 		} else if (log_only) {
    390 			cmn_err(level, "!%s\t%s", name, &cmlb_log_buffer[1]);
    391 		} else {
    392 			cmn_err(level, "%s\t%s", name, cmlb_log_buffer);
    393 		}
    394 		break;
    395 	case CE_IGNORE:
    396 		break;
    397 	default:
    398 		cmn_err(CE_CONT, "^DEBUG: %s\t%s", name, cmlb_log_buffer);
    399 		break;
    400 	}
    401 	mutex_exit(&cmlb_log_mutex);
    402 }
    403 
    404 
    405 /*
    406  * cmlb_alloc_handle:
    407  *
    408  *	Allocates a handle.
    409  *
    410  * Arguments:
    411  *	cmlbhandlep	pointer to handle
    412  *
    413  * Notes:
    414  *	Allocates a handle and stores the allocated handle in the area
    415  *	pointed to by cmlbhandlep
    416  *
    417  * Context:
    418  *	Kernel thread only (can sleep).
    419  */
    420 void
    421 cmlb_alloc_handle(cmlb_handle_t *cmlbhandlep)
    422 {
    423 	struct cmlb_lun 	*cl;
    424 
    425 	cl = kmem_zalloc(sizeof (struct cmlb_lun), KM_SLEEP);
    426 	ASSERT(cmlbhandlep != NULL);
    427 
    428 	cl->cl_state = CMLB_INITED;
    429 	cl->cl_def_labeltype = CMLB_LABEL_UNDEF;
    430 	mutex_init(CMLB_MUTEX(cl), NULL, MUTEX_DRIVER, NULL);
    431 
    432 	*cmlbhandlep = (cmlb_handle_t)(cl);
    433 }
    434 
    435 /*
    436  * cmlb_free_handle
    437  *
    438  *	Frees handle.
    439  *
    440  * Arguments:
    441  *	cmlbhandlep	pointer to handle
    442  */
    443 void
    444 cmlb_free_handle(cmlb_handle_t *cmlbhandlep)
    445 {
    446 	struct cmlb_lun 	*cl;
    447 
    448 	cl = (struct cmlb_lun *)*cmlbhandlep;
    449 	if (cl != NULL) {
    450 		mutex_destroy(CMLB_MUTEX(cl));
    451 		kmem_free(cl, sizeof (struct cmlb_lun));
    452 	}
    453 
    454 }
    455 
    456 /*
    457  * cmlb_attach:
    458  *
    459  *	Attach handle to device, create minor nodes for device.
    460  *
    461  * Arguments:
    462  * 	devi		pointer to device's dev_info structure.
    463  * 	tgopsp		pointer to array of functions cmlb can use to callback
    464  *			to target driver.
    465  *
    466  *	device_type	Peripheral device type as defined in
    467  *			scsi/generic/inquiry.h
    468  *
    469  *	is_removable	whether or not device is removable.
    470  *			0 non-removable, 1 removable.
    471  *
    472  *	is_hotpluggable	whether or not device is hotpluggable.
    473  *			0 non-hotpluggable, 1 hotpluggable.
    474  *
    475  *	node_type	minor node type (as used by ddi_create_minor_node)
    476  *
    477  *	alter_behavior
    478  *			bit flags:
    479  *
    480  *			CMLB_CREATE_ALTSLICE_VTOC_16_DTYPE_DIRECT: create
    481  *			an alternate slice for the default label, if
    482  *			device type is DTYPE_DIRECT an architectures default
    483  *			label type is VTOC16.
    484  *			Otherwise alternate slice will no be created.
    485  *
    486  *
    487  *			CMLB_FAKE_GEOM_LABEL_IOCTLS_VTOC8: report a default
    488  *			geometry and label for DKIOCGGEOM and DKIOCGVTOC
    489  *			on architecture with VTOC8 label types.
    490  *
    491  * 			CMLB_OFF_BY_ONE: do the workaround for legacy off-by-
    492  *                      one bug in obtaining capacity (in sd):
    493  *			SCSI READ_CAPACITY command returns the LBA number of the
    494  *			last logical block, but sd once treated this number as
    495  *			disks' capacity on x86 platform. And LBAs are addressed
    496  *			based 0. So the last block was lost on x86 platform.
    497  *
    498  *			Now, we remove this workaround. In order for present sd
    499  *			driver to work with disks which are labeled/partitioned
    500  *			via previous sd, we add workaround as follows:
    501  *
    502  *			1) Locate backup EFI label: cmlb searches the next to
    503  *			   last
    504  *			   block for backup EFI label. If fails, it will
    505  *			   turn to the last block for backup EFI label;
    506  *
    507  *			2) Clear backup EFI label: cmlb first search the last
    508  *			   block for backup EFI label, and will search the
    509  *			   next to last block only if failed for the last
    510  *			   block.
    511  *
    512  *			3) Calculate geometry:refer to cmlb_convert_geometry()
    513  *			   If capacity increasing by 1 causes disks' capacity
    514  *			   to cross over the limits in geometry calculation,
    515  *			   geometry info will change. This will raise an issue:
    516  *			   In case that primary VTOC label is destroyed, format
    517  *			   commandline can restore it via backup VTOC labels.
    518  *			   And format locates backup VTOC labels by use of
    519  *			   geometry. So changing geometry will
    520  *			   prevent format from finding backup VTOC labels. To
    521  *			   eliminate this side effect for compatibility,
    522  *			   sd uses (capacity -1) to calculate geometry;
    523  *
    524  *			4) 1TB disks: some important data structures use
    525  *			   32-bit signed long/int (for example, daddr_t),
    526  *			   so that sd doesn't support a disk with capacity
    527  *			   larger than 1TB on 32-bit platform. However,
    528  *			   for exactly 1TB disk, it was treated as (1T - 512)B
    529  *			   in the past, and could have valid Solaris
    530  *			   partitions. To workaround this, if an exactly 1TB
    531  *			   disk has Solaris fdisk partition, it will be allowed
    532  *			   to work with sd.
    533  *
    534  *
    535  *
    536  *			CMLB_FAKE_LABEL_ONE_PARTITION: create s0 and s2 covering
    537  *			the entire disk, if there is no valid partition info.
    538  *			If there is a valid Solaris partition, s0 and s2 will
    539  *			only cover the entire Solaris partition.
    540  *
    541  *
    542  *	cmlbhandle	cmlb handle associated with device
    543  *
    544  *	tg_cookie	cookie from target driver to be passed back to target
    545  *			driver when we call back to it through tg_ops.
    546  *
    547  * Notes:
    548  *	Assumes a default label based on capacity for non-removable devices.
    549  *	If capacity > 1TB, EFI is assumed otherwise VTOC (default VTOC
    550  *	for the architecture).
    551  *
    552  *	For removable devices, default label type is assumed to be VTOC
    553  *	type. Create minor nodes based on a default label type.
    554  *	Label on the media is not validated.
    555  *	minor number consists of:
    556  *		if _SUNOS_VTOC_8 is defined
    557  *			lowest 3 bits is taken as partition number
    558  *			the rest is instance number
    559  *		if _SUNOS_VTOC_16 is defined
    560  *			lowest 6 bits is taken as partition number
    561  *			the rest is instance number
    562  *
    563  *
    564  * Return values:
    565  *	0 	Success
    566  * 	ENXIO 	creating minor nodes failed.
    567  *	EINVAL  invalid arg, unsupported tg_ops version
    568  */
    569 int
    570 cmlb_attach(dev_info_t *devi, cmlb_tg_ops_t *tgopsp, int device_type,
    571     int is_removable, int is_hotpluggable, char *node_type,
    572     int alter_behavior, cmlb_handle_t cmlbhandle, void *tg_cookie)
    573 {
    574 
    575 	struct cmlb_lun	*cl = (struct cmlb_lun *)cmlbhandle;
    576 	diskaddr_t	cap;
    577 	int		status;
    578 
    579 	if (tgopsp->tg_version < TG_DK_OPS_VERSION_1)
    580 		return (EINVAL);
    581 
    582 	mutex_enter(CMLB_MUTEX(cl));
    583 
    584 	CMLB_DEVINFO(cl) = devi;
    585 	cl->cmlb_tg_ops = tgopsp;
    586 	cl->cl_device_type = device_type;
    587 	cl->cl_is_removable = is_removable;
    588 	cl->cl_is_hotpluggable = is_hotpluggable;
    589 	cl->cl_node_type = node_type;
    590 	cl->cl_sys_blocksize = DEV_BSIZE;
    591 	cl->cl_f_geometry_is_valid = FALSE;
    592 	cl->cl_def_labeltype = CMLB_LABEL_VTOC;
    593 	cl->cl_alter_behavior = alter_behavior;
    594 	cl->cl_reserved = -1;
    595 	cl->cl_msglog_flag |= CMLB_ALLOW_2TB_WARN;
    596 
    597 	if (is_removable == 0) {
    598 		mutex_exit(CMLB_MUTEX(cl));
    599 		status = DK_TG_GETCAP(cl, &cap, tg_cookie);
    600 		mutex_enter(CMLB_MUTEX(cl));
    601 		if (status == 0 && cap > CMLB_EXTVTOC_LIMIT) {
    602 			/* set default EFI if > 2TB */
    603 			cl->cl_def_labeltype = CMLB_LABEL_EFI;
    604 		}
    605 	}
    606 
    607 	/* create minor nodes based on default label type */
    608 	cl->cl_last_labeltype = CMLB_LABEL_UNDEF;
    609 	cl->cl_cur_labeltype = CMLB_LABEL_UNDEF;
    610 
    611 	if (cmlb_create_minor_nodes(cl) != 0) {
    612 		mutex_exit(CMLB_MUTEX(cl));
    613 		return (ENXIO);
    614 	}
    615 
    616 	/* Define the dynamic properties for devinfo spapshots. */
    617 	i_ddi_prop_dyn_driver_set(CMLB_DEVINFO(cl), cmlb_prop_dyn);
    618 
    619 	cl->cl_state = CMLB_ATTACHED;
    620 
    621 	mutex_exit(CMLB_MUTEX(cl));
    622 	return (0);
    623 }
    624 
    625 /*
    626  * cmlb_detach:
    627  *
    628  * Invalidate in-core labeling data and remove all minor nodes for
    629  * the device associate with handle.
    630  *
    631  * Arguments:
    632  *	cmlbhandle	cmlb handle associated with device.
    633  *
    634  *	tg_cookie	cookie from target driver to be passed back to target
    635  *			driver when we call back to it through tg_ops.
    636  *
    637  */
    638 /*ARGSUSED1*/
    639 void
    640 cmlb_detach(cmlb_handle_t cmlbhandle, void *tg_cookie)
    641 {
    642 	struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle;
    643 
    644 	mutex_enter(CMLB_MUTEX(cl));
    645 	cl->cl_def_labeltype = CMLB_LABEL_UNDEF;
    646 	cl->cl_f_geometry_is_valid = FALSE;
    647 	ddi_remove_minor_node(CMLB_DEVINFO(cl), NULL);
    648 	i_ddi_prop_dyn_driver_set(CMLB_DEVINFO(cl), NULL);
    649 	cl->cl_state = CMLB_INITED;
    650 	mutex_exit(CMLB_MUTEX(cl));
    651 }
    652 
    653 /*
    654  * cmlb_validate:
    655  *
    656  *	Validates label.
    657  *
    658  * Arguments
    659  *	cmlbhandle	cmlb handle associated with device.
    660  *
    661  *	flags		operation flags. used for verbosity control
    662  *
    663  *	tg_cookie	cookie from target driver to be passed back to target
    664  *			driver when we call back to it through tg_ops.
    665  *
    666  *
    667  * Notes:
    668  *	If new label type is different from the current, adjust minor nodes
    669  *	accordingly.
    670  *
    671  * Return values:
    672  *	0		success
    673  *			Note: having fdisk but no solaris partition is assumed
    674  *			success.
    675  *
    676  *	ENOMEM		memory allocation failed
    677  *	EIO		i/o errors during read or get capacity
    678  * 	EACCESS		reservation conflicts
    679  * 	EINVAL		label was corrupt, or no default label was assumed
    680  *	ENXIO		invalid handle
    681  */
    682 int
    683 cmlb_validate(cmlb_handle_t cmlbhandle, int flags, void *tg_cookie)
    684 {
    685 	struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle;
    686 	int 		rval;
    687 	int  		ret = 0;
    688 
    689 	/*
    690 	 * Temp work-around checking cl for NULL since there is a bug
    691 	 * in sd_detach calling this routine from taskq_dispatch
    692 	 * inited function.
    693 	 */
    694 	if (cl == NULL)
    695 		return (ENXIO);
    696 
    697 	mutex_enter(CMLB_MUTEX(cl));
    698 	if (cl->cl_state < CMLB_ATTACHED) {
    699 		mutex_exit(CMLB_MUTEX(cl));
    700 		return (ENXIO);
    701 	}
    702 
    703 	rval = cmlb_validate_geometry((struct cmlb_lun *)cmlbhandle, 1,
    704 	    flags, tg_cookie);
    705 
    706 	if (rval == ENOTSUP) {
    707 		if (cl->cl_f_geometry_is_valid == TRUE) {
    708 			cl->cl_cur_labeltype = CMLB_LABEL_EFI;
    709 			ret = 0;
    710 		} else {
    711 			ret = EINVAL;
    712 		}
    713 	} else {
    714 		ret = rval;
    715 		if (ret == 0)
    716 			cl->cl_cur_labeltype = CMLB_LABEL_VTOC;
    717 	}
    718 
    719 	if (ret == 0)
    720 		(void) cmlb_create_minor_nodes(cl);
    721 
    722 	mutex_exit(CMLB_MUTEX(cl));
    723 	return (ret);
    724 }
    725 
    726 /*
    727  * cmlb_invalidate:
    728  *	Invalidate in core label data
    729  *
    730  * Arguments:
    731  *	cmlbhandle	cmlb handle associated with device.
    732  *	tg_cookie	cookie from target driver to be passed back to target
    733  *			driver when we call back to it through tg_ops.
    734  */
    735 /*ARGSUSED1*/
    736 void
    737 cmlb_invalidate(cmlb_handle_t cmlbhandle, void *tg_cookie)
    738 {
    739 	struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle;
    740 
    741 	if (cl == NULL)
    742 		return;
    743 
    744 	mutex_enter(CMLB_MUTEX(cl));
    745 	cl->cl_f_geometry_is_valid = FALSE;
    746 	mutex_exit(CMLB_MUTEX(cl));
    747 }
    748 
    749 /*
    750  * cmlb_is_valid
    751  * 	Get status on whether the incore label/geom data is valid
    752  *
    753  * Arguments:
    754  *	cmlbhandle      cmlb handle associated with device.
    755  *
    756  * Return values:
    757  *	TRUE if incore label/geom data is valid.
    758  *	FALSE otherwise.
    759  *
    760  */
    761 
    762 
    763 int
    764 cmlb_is_valid(cmlb_handle_t cmlbhandle)
    765 {
    766 	struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle;
    767 
    768 	if (cmlbhandle == NULL)
    769 		return (FALSE);
    770 
    771 	return (cl->cl_f_geometry_is_valid);
    772 
    773 }
    774 
    775 
    776 
    777 /*
    778  * cmlb_close:
    779  *
    780  * Close the device, revert to a default label minor node for the device,
    781  * if it is removable.
    782  *
    783  * Arguments:
    784  *	cmlbhandle	cmlb handle associated with device.
    785  *
    786  *	tg_cookie	cookie from target driver to be passed back to target
    787  *			driver when we call back to it through tg_ops.
    788  * Return values:
    789  *	0	Success
    790  * 	ENXIO	Re-creating minor node failed.
    791  */
    792 /*ARGSUSED1*/
    793 int
    794 cmlb_close(cmlb_handle_t cmlbhandle, void *tg_cookie)
    795 {
    796 	struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle;
    797 
    798 	mutex_enter(CMLB_MUTEX(cl));
    799 	cl->cl_f_geometry_is_valid = FALSE;
    800 
    801 	/* revert to default minor node for this device */
    802 	if (ISREMOVABLE(cl)) {
    803 		cl->cl_cur_labeltype = CMLB_LABEL_UNDEF;
    804 		(void) cmlb_create_minor_nodes(cl);
    805 	}
    806 
    807 	mutex_exit(CMLB_MUTEX(cl));
    808 	return (0);
    809 }
    810 
    811 /*
    812  * cmlb_get_devid_block:
    813  *	 get the block number where device id is stored.
    814  *
    815  * Arguments:
    816  *	cmlbhandle	cmlb handle associated with device.
    817  *	devidblockp	pointer to block number.
    818  *	tg_cookie	cookie from target driver to be passed back to target
    819  *			driver when we call back to it through tg_ops.
    820  *
    821  * Notes:
    822  *	It stores the block number of device id in the area pointed to
    823  *	by devidblockp.
    824  * 	with the block number of device id.
    825  *
    826  * Return values:
    827  *	0	success
    828  *	EINVAL 	device id does not apply to current label type.
    829  */
    830 /*ARGSUSED2*/
    831 int
    832 cmlb_get_devid_block(cmlb_handle_t cmlbhandle, diskaddr_t *devidblockp,
    833     void *tg_cookie)
    834 {
    835 	daddr_t			spc, blk, head, cyl;
    836 	struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle;
    837 
    838 	mutex_enter(CMLB_MUTEX(cl));
    839 	if (cl->cl_state < CMLB_ATTACHED) {
    840 		mutex_exit(CMLB_MUTEX(cl));
    841 		return (EINVAL);
    842 	}
    843 
    844 	if ((cl->cl_f_geometry_is_valid == FALSE) ||
    845 	    (cl->cl_solaris_size < DK_LABEL_LOC)) {
    846 		mutex_exit(CMLB_MUTEX(cl));
    847 		return (EINVAL);
    848 	}
    849 
    850 	if (cl->cl_cur_labeltype == CMLB_LABEL_EFI) {
    851 		if (cl->cl_reserved != -1) {
    852 			blk = cl->cl_map[cl->cl_reserved].dkl_cylno;
    853 		} else {
    854 			mutex_exit(CMLB_MUTEX(cl));
    855 			return (EINVAL);
    856 		}
    857 	} else {
    858 		/* if the disk is unlabeled, don't write a devid to it */
    859 		if (cl->cl_label_from_media != CMLB_LABEL_VTOC) {
    860 			mutex_exit(CMLB_MUTEX(cl));
    861 			return (EINVAL);
    862 		}
    863 
    864 		/* this geometry doesn't allow us to write a devid */
    865 		if (cl->cl_g.dkg_acyl < 2) {
    866 			mutex_exit(CMLB_MUTEX(cl));
    867 			return (EINVAL);
    868 		}
    869 
    870 		/*
    871 		 * Subtract 2 guarantees that the next to last cylinder
    872 		 * is used
    873 		 */
    874 		cyl  = cl->cl_g.dkg_ncyl  + cl->cl_g.dkg_acyl - 2;
    875 		spc  = cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect;
    876 		head = cl->cl_g.dkg_nhead - 1;
    877 		blk  = cl->cl_solaris_offset +
    878 		    (cyl * (spc - cl->cl_g.dkg_apc)) +
    879 		    (head * cl->cl_g.dkg_nsect) + 1;
    880 	}
    881 
    882 	*devidblockp = blk;
    883 	mutex_exit(CMLB_MUTEX(cl));
    884 	return (0);
    885 }
    886 
    887 /*
    888  * cmlb_partinfo:
    889  *	Get partition info for specified partition number.
    890  *
    891  * Arguments:
    892  *	cmlbhandle	cmlb handle associated with device.
    893  *	part		partition number
    894  *	nblocksp	pointer to number of blocks
    895  *	startblockp	pointer to starting block
    896  *	partnamep	pointer to name of partition
    897  *	tagp		pointer to tag info
    898  *	tg_cookie	cookie from target driver to be passed back to target
    899  *			driver when we call back to it through tg_ops.
    900  *
    901  *
    902  * Notes:
    903  *	If in-core label is not valid, this functions tries to revalidate
    904  *	the label. If label is valid, it stores the total number of blocks
    905  *	in this partition in the area pointed to by nblocksp, starting
    906  *	block number in area pointed to by startblockp,  pointer to partition
    907  *	name in area pointed to by partnamep, and tag value in area
    908  *	pointed by tagp.
    909  *	For EFI labels, tag value will be set to 0.
    910  *
    911  *	For all nblocksp, startblockp and partnamep, tagp, a value of NULL
    912  *	indicates the corresponding info is not requested.
    913  *
    914  *
    915  * Return values:
    916  *	0	success
    917  *	EINVAL  no valid label or requested partition number is invalid.
    918  *
    919  */
    920 int
    921 cmlb_partinfo(cmlb_handle_t cmlbhandle, int part, diskaddr_t *nblocksp,
    922     diskaddr_t *startblockp, char **partnamep, uint16_t *tagp, void *tg_cookie)
    923 {
    924 
    925 	struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle;
    926 	int rval;
    927 
    928 	ASSERT(cl != NULL);
    929 	mutex_enter(CMLB_MUTEX(cl));
    930 	if (cl->cl_state < CMLB_ATTACHED) {
    931 		mutex_exit(CMLB_MUTEX(cl));
    932 		return (EINVAL);
    933 	}
    934 
    935 	if (part  < 0 || part >= MAXPART) {
    936 		rval = EINVAL;
    937 	} else {
    938 		if (cl->cl_f_geometry_is_valid == FALSE)
    939 			(void) cmlb_validate_geometry((struct cmlb_lun *)cl, 0,
    940 			    0, tg_cookie);
    941 
    942 #if defined(_SUNOS_VTOC_16)
    943 		if (((cl->cl_f_geometry_is_valid == FALSE) ||
    944 		    (part < NDKMAP && cl->cl_solaris_size == 0)) &&
    945 		    (part != P0_RAW_DISK)) {
    946 #else
    947 		if ((cl->cl_f_geometry_is_valid == FALSE) ||
    948 		    (part < NDKMAP && cl->cl_solaris_size == 0)) {
    949 #endif
    950 			rval = EINVAL;
    951 		} else {
    952 			if (startblockp != NULL)
    953 				*startblockp = (diskaddr_t)cl->cl_offset[part];
    954 
    955 			if (nblocksp != NULL)
    956 				*nblocksp = (diskaddr_t)
    957 				    cl->cl_map[part].dkl_nblk;
    958 
    959 			if (tagp != NULL)
    960 				if (cl->cl_cur_labeltype == CMLB_LABEL_EFI)
    961 					*tagp = V_UNASSIGNED;
    962 				else
    963 					*tagp = cl->cl_vtoc.v_part[part].p_tag;
    964 			rval = 0;
    965 		}
    966 
    967 		/* consistent with behavior of sd for getting minor name */
    968 		if (partnamep != NULL)
    969 			*partnamep = dk_minor_data[part].name;
    970 
    971 	}
    972 
    973 	mutex_exit(CMLB_MUTEX(cl));
    974 	return (rval);
    975 }
    976 
    977 /*
    978  * cmlb_efi_label_capacity:
    979  *	Get capacity stored in EFI disk label.
    980  *
    981  * Arguments:
    982  *	cmlbhandle	cmlb handle associated with device.
    983  *	capacity	pointer to capacity stored in EFI disk label.
    984  *	tg_cookie	cookie from target driver to be passed back to target
    985  *			driver when we call back to it through tg_ops.
    986  *
    987  *
    988  * Notes:
    989  *	If in-core label is not valid, this functions tries to revalidate
    990  *	the label. If label is valid and is an EFI label, it stores the capacity
    991  *      in disk label in the area pointed to by capacity.
    992  *
    993  *
    994  * Return values:
    995  *	0	success
    996  *	EINVAL  no valid EFI label or capacity is NULL.
    997  *
    998  */
    999 int
   1000 cmlb_efi_label_capacity(cmlb_handle_t cmlbhandle, diskaddr_t *capacity,
   1001     void *tg_cookie)
   1002 {
   1003 	struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle;
   1004 	int rval;
   1005 
   1006 	ASSERT(cl != NULL);
   1007 	mutex_enter(CMLB_MUTEX(cl));
   1008 	if (cl->cl_state < CMLB_ATTACHED) {
   1009 		mutex_exit(CMLB_MUTEX(cl));
   1010 		return (EINVAL);
   1011 	}
   1012 
   1013 	if (cl->cl_f_geometry_is_valid == FALSE)
   1014 		(void) cmlb_validate_geometry((struct cmlb_lun *)cl, 0,
   1015 		    0, tg_cookie);
   1016 
   1017 	if ((cl->cl_f_geometry_is_valid == FALSE) || (capacity == NULL) ||
   1018 	    (cl->cl_cur_labeltype != CMLB_LABEL_EFI)) {
   1019 		rval = EINVAL;
   1020 	} else {
   1021 		*capacity = (diskaddr_t)cl->cl_map[WD_NODE].dkl_nblk;
   1022 		rval = 0;
   1023 	}
   1024 
   1025 	mutex_exit(CMLB_MUTEX(cl));
   1026 	return (rval);
   1027 }
   1028 
   1029 /* Caller should make sure Test Unit Ready succeeds before calling this. */
   1030 /*ARGSUSED*/
   1031 int
   1032 cmlb_ioctl(cmlb_handle_t cmlbhandle, dev_t dev, int cmd, intptr_t arg,
   1033     int flag, cred_t *cred_p, int *rval_p, void *tg_cookie)
   1034 {
   1035 
   1036 	int err;
   1037 	struct cmlb_lun *cl;
   1038 
   1039 	cl = (struct cmlb_lun *)cmlbhandle;
   1040 
   1041 	ASSERT(cl != NULL);
   1042 
   1043 	mutex_enter(CMLB_MUTEX(cl));
   1044 	if (cl->cl_state < CMLB_ATTACHED) {
   1045 		mutex_exit(CMLB_MUTEX(cl));
   1046 		return (EIO);
   1047 	}
   1048 
   1049 	switch (cmd) {
   1050 		case DKIOCSEXTVTOC:
   1051 		case DKIOCSGEOM:
   1052 		case DKIOCSETEFI:
   1053 		case DKIOCSMBOOT:
   1054 			break;
   1055 		case DKIOCSVTOC:
   1056 #if defined(__i386) || defined(__amd64)
   1057 		case DKIOCPARTINFO:
   1058 #endif
   1059 			if (cl->cl_blockcount > CMLB_OLDVTOC_LIMIT) {
   1060 				mutex_exit(CMLB_MUTEX(cl));
   1061 				return (EOVERFLOW);
   1062 			}
   1063 			break;
   1064 		default:
   1065 			(void) cmlb_validate_geometry(cl, 1, CMLB_SILENT,
   1066 			    tg_cookie);
   1067 
   1068 			switch (cmd) {
   1069 			case DKIOCGVTOC:
   1070 			case DKIOCGAPART:
   1071 			case DKIOCSAPART:
   1072 
   1073 				if (cl->cl_label_from_media == CMLB_LABEL_EFI) {
   1074 					/* GPT label on disk */
   1075 					mutex_exit(CMLB_MUTEX(cl));
   1076 					return (ENOTSUP);
   1077 				} else if
   1078 				    (cl->cl_blockcount > CMLB_OLDVTOC_LIMIT) {
   1079 					mutex_exit(CMLB_MUTEX(cl));
   1080 					return (EOVERFLOW);
   1081 				}
   1082 				break;
   1083 
   1084 			case DKIOCGGEOM:
   1085 				if (cl->cl_label_from_media == CMLB_LABEL_EFI) {
   1086 					/* GPT label on disk */
   1087 					mutex_exit(CMLB_MUTEX(cl));
   1088 					return (ENOTSUP);
   1089 				}
   1090 				break;
   1091 			default:
   1092 				break;
   1093 			}
   1094 	}
   1095 
   1096 	mutex_exit(CMLB_MUTEX(cl));
   1097 
   1098 	switch (cmd) {
   1099 	case DKIOCGGEOM:
   1100 		cmlb_dbg(CMLB_TRACE, cl, "DKIOCGGEOM\n");
   1101 		err = cmlb_dkio_get_geometry(cl, (caddr_t)arg, flag, tg_cookie);
   1102 		break;
   1103 
   1104 	case DKIOCSGEOM:
   1105 		cmlb_dbg(CMLB_TRACE, cl, "DKIOCSGEOM\n");
   1106 		err = cmlb_dkio_set_geometry(cl, (caddr_t)arg, flag);
   1107 		break;
   1108 
   1109 	case DKIOCGAPART:
   1110 		cmlb_dbg(CMLB_TRACE, cl, "DKIOCGAPART\n");
   1111 		err = cmlb_dkio_get_partition(cl, (caddr_t)arg,
   1112 		    flag, tg_cookie);
   1113 		break;
   1114 
   1115 	case DKIOCSAPART:
   1116 		cmlb_dbg(CMLB_TRACE, cl, "DKIOCSAPART\n");
   1117 		err = cmlb_dkio_set_partition(cl, (caddr_t)arg, flag);
   1118 		break;
   1119 
   1120 	case DKIOCGVTOC:
   1121 		cmlb_dbg(CMLB_TRACE, cl, "DKIOCGVTOC\n");
   1122 		err = cmlb_dkio_get_vtoc(cl, (caddr_t)arg, flag, tg_cookie);
   1123 		break;
   1124 
   1125 	case DKIOCGEXTVTOC:
   1126 		cmlb_dbg(CMLB_TRACE, cl, "DKIOCGVTOC\n");
   1127 		err = cmlb_dkio_get_extvtoc(cl, (caddr_t)arg, flag, tg_cookie);
   1128 		break;
   1129 
   1130 	case DKIOCGETEFI:
   1131 		cmlb_dbg(CMLB_TRACE, cl, "DKIOCGETEFI\n");
   1132 		err = cmlb_dkio_get_efi(cl, (caddr_t)ar