Home | History | Annotate | Download | only in io
      1    786      lclee /*
      2    786      lclee  * CDDL HEADER START
      3    786      lclee  *
      4    786      lclee  * The contents of this file are subject to the terms of the
      5   3525   shidokht  * Common Development and Distribution License (the "License").
      6   3525   shidokht  * You may not use this file except in compliance with the License.
      7    786      lclee  *
      8    786      lclee  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9    786      lclee  * or http://www.opensolaris.org/os/licensing.
     10    786      lclee  * See the License for the specific language governing permissions
     11    786      lclee  * and limitations under the License.
     12    786      lclee  *
     13    786      lclee  * When distributing Covered Code, include this CDDL HEADER in each
     14    786      lclee  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15    786      lclee  * If applicable, add the following below this CDDL HEADER, with the
     16    786      lclee  * fields enclosed by brackets "[]" replaced with your own identifying
     17    786      lclee  * information: Portions Copyright [yyyy] [name of copyright owner]
     18    786      lclee  *
     19    786      lclee  * CDDL HEADER END
     20    786      lclee  */
     21    786      lclee 
     22    786      lclee /*
     23   8570     Sriram  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24    786      lclee  * Use is subject to license terms.
     25    786      lclee  */
     26    786      lclee 
     27    786      lclee /*
     28    786      lclee  * This module provides support for labeling operations for target
     29    786      lclee  * drivers.
     30    786      lclee  */
     31    786      lclee 
     32    786      lclee #include <sys/scsi/scsi.h>
     33    786      lclee #include <sys/sunddi.h>
     34    786      lclee #include <sys/dklabel.h>
     35    786      lclee #include <sys/dkio.h>
     36    786      lclee #include <sys/vtoc.h>
     37    786      lclee #include <sys/dktp/fdisk.h>
     38    786      lclee #include <sys/vtrace.h>
     39    786      lclee #include <sys/efi_partition.h>
     40    786      lclee #include <sys/cmlb.h>
     41    786      lclee #include <sys/cmlb_impl.h>
     42  10021  Sheshadri #if defined(__i386) || defined(__amd64)
     43  10021  Sheshadri #include <sys/fs/dv_node.h>
     44  10021  Sheshadri #endif
     45   7224        cth #include <sys/ddi_impldefs.h>
     46    786      lclee 
     47    786      lclee /*
     48    786      lclee  * Driver minor node structure and data table
     49    786      lclee  */
     50    786      lclee struct driver_minor_data {
     51    786      lclee 	char	*name;
     52    786      lclee 	minor_t	minor;
     53    786      lclee 	int	type;
     54    786      lclee };
     55    786      lclee 
     56    786      lclee static struct driver_minor_data dk_minor_data[] = {
     57    786      lclee 	{"a", 0, S_IFBLK},
     58    786      lclee 	{"b", 1, S_IFBLK},
     59    786      lclee 	{"c", 2, S_IFBLK},
     60    786      lclee 	{"d", 3, S_IFBLK},
     61    786      lclee 	{"e", 4, S_IFBLK},
     62    786      lclee 	{"f", 5, S_IFBLK},
     63    786      lclee 	{"g", 6, S_IFBLK},
     64    786      lclee 	{"h", 7, S_IFBLK},
     65    786      lclee #if defined(_SUNOS_VTOC_16)
     66    786      lclee 	{"i", 8, S_IFBLK},
     67    786      lclee 	{"j", 9, S_IFBLK},
     68    786      lclee 	{"k", 10, S_IFBLK},
     69    786      lclee 	{"l", 11, S_IFBLK},
     70    786      lclee 	{"m", 12, S_IFBLK},
     71    786      lclee 	{"n", 13, S_IFBLK},
     72    786      lclee 	{"o", 14, S_IFBLK},
     73    786      lclee 	{"p", 15, S_IFBLK},
     74    786      lclee #endif			/* defined(_SUNOS_VTOC_16) */
     75    786      lclee #if defined(_FIRMWARE_NEEDS_FDISK)
     76    786      lclee 	{"q", 16, S_IFBLK},
     77    786      lclee 	{"r", 17, S_IFBLK},
     78    786      lclee 	{"s", 18, S_IFBLK},
     79    786      lclee 	{"t", 19, S_IFBLK},
     80    786      lclee 	{"u", 20, S_IFBLK},
     81    786      lclee #endif			/* defined(_FIRMWARE_NEEDS_FDISK) */
     82    786      lclee 	{"a,raw", 0, S_IFCHR},
     83    786      lclee 	{"b,raw", 1, S_IFCHR},
     84    786      lclee 	{"c,raw", 2, S_IFCHR},
     85    786      lclee 	{"d,raw", 3, S_IFCHR},
     86    786      lclee 	{"e,raw", 4, S_IFCHR},
     87    786      lclee 	{"f,raw", 5, S_IFCHR},
     88    786      lclee 	{"g,raw", 6, S_IFCHR},
     89    786      lclee 	{"h,raw", 7, S_IFCHR},
     90    786      lclee #if defined(_SUNOS_VTOC_16)
     91    786      lclee 	{"i,raw", 8, S_IFCHR},
     92    786      lclee 	{"j,raw", 9, S_IFCHR},
     93    786      lclee 	{"k,raw", 10, S_IFCHR},
     94    786      lclee 	{"l,raw", 11, S_IFCHR},
     95    786      lclee 	{"m,raw", 12, S_IFCHR},
     96    786      lclee 	{"n,raw", 13, S_IFCHR},
     97    786      lclee 	{"o,raw", 14, S_IFCHR},
     98    786      lclee 	{"p,raw", 15, S_IFCHR},
     99    786      lclee #endif			/* defined(_SUNOS_VTOC_16) */
    100    786      lclee #if defined(_FIRMWARE_NEEDS_FDISK)
    101    786      lclee 	{"q,raw", 16, S_IFCHR},
    102    786      lclee 	{"r,raw", 17, S_IFCHR},
    103    786      lclee 	{"s,raw", 18, S_IFCHR},
    104    786      lclee 	{"t,raw", 19, S_IFCHR},
    105    786      lclee 	{"u,raw", 20, S_IFCHR},
    106    786      lclee #endif			/* defined(_FIRMWARE_NEEDS_FDISK) */
    107    786      lclee 	{0}
    108    786      lclee };
    109    786      lclee 
    110  10021  Sheshadri #if defined(__i386) || defined(__amd64)
    111  10021  Sheshadri #if defined(_FIRMWARE_NEEDS_FDISK)
    112  10021  Sheshadri static struct driver_minor_data dk_ext_minor_data[] = {
    113  10021  Sheshadri 	{"p5", 21, S_IFBLK},
    114  10021  Sheshadri 	{"p6", 22, S_IFBLK},
    115  10021  Sheshadri 	{"p7", 23, S_IFBLK},
    116  10021  Sheshadri 	{"p8", 24, S_IFBLK},
    117  10021  Sheshadri 	{"p9", 25, S_IFBLK},
    118  10021  Sheshadri 	{"p10", 26, S_IFBLK},
    119  10021  Sheshadri 	{"p11", 27, S_IFBLK},
    120  10021  Sheshadri 	{"p12", 28, S_IFBLK},
    121  10021  Sheshadri 	{"p13", 29, S_IFBLK},
    122  10021  Sheshadri 	{"p14", 30, S_IFBLK},
    123  10021  Sheshadri 	{"p15", 31, S_IFBLK},
    124  10021  Sheshadri 	{"p16", 32, S_IFBLK},
    125  10021  Sheshadri 	{"p17", 33, S_IFBLK},
    126  10021  Sheshadri 	{"p18", 34, S_IFBLK},
    127  10021  Sheshadri 	{"p19", 35, S_IFBLK},
    128  10021  Sheshadri 	{"p20", 36, S_IFBLK},
    129  10021  Sheshadri 	{"p21", 37, S_IFBLK},
    130  10021  Sheshadri 	{"p22", 38, S_IFBLK},
    131  10021  Sheshadri 	{"p23", 39, S_IFBLK},
    132  10021  Sheshadri 	{"p24", 40, S_IFBLK},
    133  10021  Sheshadri 	{"p25", 41, S_IFBLK},
    134  10021  Sheshadri 	{"p26", 42, S_IFBLK},
    135  10021  Sheshadri 	{"p27", 43, S_IFBLK},
    136  10021  Sheshadri 	{"p28", 44, S_IFBLK},
    137  10021  Sheshadri 	{"p29", 45, S_IFBLK},
    138  10021  Sheshadri 	{"p30", 46, S_IFBLK},
    139  10021  Sheshadri 	{"p31", 47, S_IFBLK},
    140  10021  Sheshadri 	{"p32", 48, S_IFBLK},
    141  10021  Sheshadri 	{"p33", 49, S_IFBLK},
    142  10021  Sheshadri 	{"p34", 50, S_IFBLK},
    143  10021  Sheshadri 	{"p35", 51, S_IFBLK},
    144  10021  Sheshadri 	{"p36", 52, S_IFBLK},
    145  10021  Sheshadri 	{"p5,raw", 21, S_IFCHR},
    146  10021  Sheshadri 	{"p6,raw", 22, S_IFCHR},
    147  10021  Sheshadri 	{"p7,raw", 23, S_IFCHR},
    148  10021  Sheshadri 	{"p8,raw", 24, S_IFCHR},
    149  10021  Sheshadri 	{"p9,raw", 25, S_IFCHR},
    150  10021  Sheshadri 	{"p10,raw", 26, S_IFCHR},
    151  10021  Sheshadri 	{"p11,raw", 27, S_IFCHR},
    152  10021  Sheshadri 	{"p12,raw", 28, S_IFCHR},
    153  10021  Sheshadri 	{"p13,raw", 29, S_IFCHR},
    154  10021  Sheshadri 	{"p14,raw", 30, S_IFCHR},
    155  10021  Sheshadri 	{"p15,raw", 31, S_IFCHR},
    156  10021  Sheshadri 	{"p16,raw", 32, S_IFCHR},
    157  10021  Sheshadri 	{"p17,raw", 33, S_IFCHR},
    158  10021  Sheshadri 	{"p18,raw", 34, S_IFCHR},
    159  10021  Sheshadri 	{"p19,raw", 35, S_IFCHR},
    160  10021  Sheshadri 	{"p20,raw", 36, S_IFCHR},
    161  10021  Sheshadri 	{"p21,raw", 37, S_IFCHR},
    162  10021  Sheshadri 	{"p22,raw", 38, S_IFCHR},
    163  10021  Sheshadri 	{"p23,raw", 39, S_IFCHR},
    164  10021  Sheshadri 	{"p24,raw", 40, S_IFCHR},
    165  10021  Sheshadri 	{"p25,raw", 41, S_IFCHR},
    166  10021  Sheshadri 	{"p26,raw", 42, S_IFCHR},
    167  10021  Sheshadri 	{"p27,raw", 43, S_IFCHR},
    168  10021  Sheshadri 	{"p28,raw", 44, S_IFCHR},
    169  10021  Sheshadri 	{"p29,raw", 45, S_IFCHR},
    170  10021  Sheshadri 	{"p30,raw", 46, S_IFCHR},
    171  10021  Sheshadri 	{"p31,raw", 47, S_IFCHR},
    172  10021  Sheshadri 	{"p32,raw", 48, S_IFCHR},
    173  10021  Sheshadri 	{"p33,raw", 49, S_IFCHR},
    174  10021  Sheshadri 	{"p34,raw", 50, S_IFCHR},
    175  10021  Sheshadri 	{"p35,raw", 51, S_IFCHR},
    176  10021  Sheshadri 	{"p36,raw", 52, S_IFCHR},
    177  10021  Sheshadri 	{0}
    178  10021  Sheshadri };
    179  10021  Sheshadri #endif			/* defined(_FIRMWARE_NEEDS_FDISK) */
    180  10021  Sheshadri #endif			/* if defined(__i386) || defined(__amd64) */
    181  10021  Sheshadri 
    182    786      lclee static struct driver_minor_data dk_minor_data_efi[] = {
    183    786      lclee 	{"a", 0, S_IFBLK},
    184    786      lclee 	{"b", 1, S_IFBLK},
    185    786      lclee 	{"c", 2, S_IFBLK},
    186    786      lclee 	{"d", 3, S_IFBLK},
    187    786      lclee 	{"e", 4, S_IFBLK},
    188    786      lclee 	{"f", 5, S_IFBLK},
    189    786      lclee 	{"g", 6, S_IFBLK},
    190    786      lclee 	{"wd", 7, S_IFBLK},
    191   8749   Shidokht #if defined(_SUNOS_VTOC_16)
    192   8749   Shidokht 	{"i", 8, S_IFBLK},
    193   8749   Shidokht 	{"j", 9, S_IFBLK},
    194   8749   Shidokht 	{"k", 10, S_IFBLK},
    195   8749   Shidokht 	{"l", 11, S_IFBLK},
    196   8749   Shidokht 	{"m", 12, S_IFBLK},
    197   8749   Shidokht 	{"n", 13, S_IFBLK},
    198   8749   Shidokht 	{"o", 14, S_IFBLK},
    199   8749   Shidokht 	{"p", 15, S_IFBLK},
    200   8749   Shidokht #endif			/* defined(_SUNOS_VTOC_16) */
    201    786      lclee #if defined(_FIRMWARE_NEEDS_FDISK)
    202    786      lclee 	{"q", 16, S_IFBLK},
    203    786      lclee 	{"r", 17, S_IFBLK},
    204    786      lclee 	{"s", 18, S_IFBLK},
    205    786      lclee 	{"t", 19, S_IFBLK},
    206    786      lclee 	{"u", 20, S_IFBLK},
    207    786      lclee #endif			/* defined(_FIRMWARE_NEEDS_FDISK) */
    208    786      lclee 	{"a,raw", 0, S_IFCHR},
    209    786      lclee 	{"b,raw", 1, S_IFCHR},
    210    786      lclee 	{"c,raw", 2, S_IFCHR},
    211    786      lclee 	{"d,raw", 3, S_IFCHR},
    212    786      lclee 	{"e,raw", 4, S_IFCHR},
    213    786      lclee 	{"f,raw", 5, S_IFCHR},
    214    786      lclee 	{"g,raw", 6, S_IFCHR},
    215    786      lclee 	{"wd,raw", 7, S_IFCHR},
    216   8749   Shidokht #if defined(_SUNOS_VTOC_16)
    217   8749   Shidokht 	{"i,raw", 8, S_IFCHR},
    218   8749   Shidokht 	{"j,raw", 9, S_IFCHR},
    219   8749   Shidokht 	{"k,raw", 10, S_IFCHR},
    220   8749   Shidokht 	{"l,raw", 11, S_IFCHR},
    221   8749   Shidokht 	{"m,raw", 12, S_IFCHR},
    222   8749   Shidokht 	{"n,raw", 13, S_IFCHR},
    223   8749   Shidokht 	{"o,raw", 14, S_IFCHR},
    224   8749   Shidokht 	{"p,raw", 15, S_IFCHR},
    225   8749   Shidokht #endif			/* defined(_SUNOS_VTOC_16) */
    226    786      lclee #if defined(_FIRMWARE_NEEDS_FDISK)
    227    786      lclee 	{"q,raw", 16, S_IFCHR},
    228    786      lclee 	{"r,raw", 17, S_IFCHR},
    229    786      lclee 	{"s,raw", 18, S_IFCHR},
    230    786      lclee 	{"t,raw", 19, S_IFCHR},
    231    786      lclee 	{"u,raw", 20, S_IFCHR},
    232    786      lclee #endif			/* defined(_FIRMWARE_NEEDS_FDISK) */
    233    786      lclee 	{0}
    234    786      lclee };
    235    786      lclee 
    236   7224        cth /*
    237   7224        cth  * Declare the dynamic properties implemented in prop_op(9E) implementation
    238   7224        cth  * that we want to have show up in a di_init(3DEVINFO) device tree snapshot
    239   7224        cth  * of drivers that call cmlb_attach().
    240   7224        cth  */
    241   7224        cth static i_ddi_prop_dyn_t cmlb_prop_dyn[] = {
    242   7224        cth 	{"Nblocks",		DDI_PROP_TYPE_INT64,	S_IFBLK},
    243   7224        cth 	{"Size",		DDI_PROP_TYPE_INT64,	S_IFCHR},
    244   7224        cth 	{"device-nblocks",	DDI_PROP_TYPE_INT64},
    245   7224        cth 	{"device-blksize",	DDI_PROP_TYPE_INT},
    246   7224        cth 	{NULL}
    247   7224        cth };
    248    786      lclee 
    249   6318        edp /*
    250   6318        edp  * External kernel interfaces
    251   6318        edp  */
    252    786      lclee extern struct mod_ops mod_miscops;
    253   6318        edp 
    254   6318        edp extern int ddi_create_internal_pathname(dev_info_t *dip, char *name,
    255   6318        edp     int spec_type, minor_t minor_num);
    256    786      lclee 
    257    786      lclee /*
    258    786      lclee  * Global buffer and mutex for debug logging
    259    786      lclee  */
    260    786      lclee static char	cmlb_log_buffer[1024];
    261    786      lclee static kmutex_t	cmlb_log_mutex;
    262    786      lclee 
    263    786      lclee 
    264   3525   shidokht struct cmlb_lun *cmlb_debug_cl = NULL;
    265    786      lclee uint_t cmlb_level_mask = 0x0;
    266    786      lclee 
    267    786      lclee int cmlb_rot_delay = 4;	/* default rotational delay */
    268    786      lclee 
    269    786      lclee static struct modlmisc modlmisc = {
    270    786      lclee 	&mod_miscops,   /* Type of module */
    271   7563     Prasad 	"Common Labeling module"
    272    786      lclee };
    273    786      lclee 
    274    786      lclee static struct modlinkage modlinkage = {
    275    786      lclee 	MODREV_1, (void *)&modlmisc, NULL
    276    786      lclee };
    277    786      lclee 
    278    786      lclee /* Local function prototypes */
    279   3525   shidokht static dev_t cmlb_make_device(struct cmlb_lun *cl);
    280   8863     Edward static int cmlb_validate_geometry(struct cmlb_lun *cl, boolean_t forcerevalid,
    281   3525   shidokht     int flags, void *tg_cookie);
    282   3525   shidokht static void cmlb_resync_geom_caches(struct cmlb_lun *cl, diskaddr_t capacity,
    283   3525   shidokht     void *tg_cookie);
    284   3525   shidokht static int cmlb_read_fdisk(struct cmlb_lun *cl, diskaddr_t capacity,
    285   3525   shidokht     void *tg_cookie);
    286    786      lclee static void cmlb_swap_efi_gpt(efi_gpt_t *e);
    287    786      lclee static void cmlb_swap_efi_gpe(int nparts, efi_gpe_t *p);
    288    786      lclee static int cmlb_validate_efi(efi_gpt_t *labp);
    289   3525   shidokht static int cmlb_use_efi(struct cmlb_lun *cl, diskaddr_t capacity, int flags,
    290   3525   shidokht     void *tg_cookie);
    291   3525   shidokht static void cmlb_build_default_label(struct cmlb_lun *cl, void *tg_cookie);
    292   3525   shidokht static int  cmlb_uselabel(struct cmlb_lun *cl,  struct dk_label *l, int flags);
    293   3525   shidokht #if defined(_SUNOS_VTOC_8)
    294   3525   shidokht static void cmlb_build_user_vtoc(struct cmlb_lun *cl, struct vtoc *user_vtoc);
    295   3525   shidokht #endif
    296   3525   shidokht static int cmlb_build_label_vtoc(struct cmlb_lun *cl, struct vtoc *user_vtoc);
    297   3525   shidokht static int cmlb_write_label(struct cmlb_lun *cl, void *tg_cookie);
    298   3525   shidokht static int cmlb_set_vtoc(struct cmlb_lun *cl, struct dk_label *dkl,
    299   3525   shidokht     void *tg_cookie);
    300   3525   shidokht static void cmlb_clear_efi(struct cmlb_lun *cl, void *tg_cookie);
    301   3525   shidokht static void cmlb_clear_vtoc(struct cmlb_lun *cl, void *tg_cookie);
    302   3525   shidokht static void cmlb_setup_default_geometry(struct cmlb_lun *cl, void *tg_cookie);
    303   3525   shidokht static int cmlb_create_minor_nodes(struct cmlb_lun *cl);
    304   3525   shidokht static int cmlb_check_update_blockcount(struct cmlb_lun *cl, void *tg_cookie);
    305   8863     Edward static boolean_t cmlb_check_efi_mbr(uchar_t *buf, boolean_t *is_mbr);
    306   3525   shidokht 
    307   3525   shidokht #if defined(__i386) || defined(__amd64)
    308   3525   shidokht static int cmlb_update_fdisk_and_vtoc(struct cmlb_lun *cl, void *tg_cookie);
    309    786      lclee #endif
    310    786      lclee 
    311    786      lclee #if defined(_FIRMWARE_NEEDS_FDISK)
    312   8863     Edward static boolean_t  cmlb_has_max_chs_vals(struct ipart *fdp);
    313    786      lclee #endif
    314    786      lclee 
    315    786      lclee #if defined(_SUNOS_VTOC_16)
    316  10320      Larry static void cmlb_convert_geometry(struct cmlb_lun *cl, diskaddr_t capacity,
    317  10320      Larry     struct dk_geom *cl_g, void *tg_cookie);
    318   3525   shidokht #endif
    319   3525   shidokht 
    320   3525   shidokht static int cmlb_dkio_get_geometry(struct cmlb_lun *cl, caddr_t arg, int flag,
    321   3525   shidokht     void *tg_cookie);
    322   3525   shidokht static int cmlb_dkio_set_geometry(struct cmlb_lun *cl, caddr_t arg, int flag);
    323   3525   shidokht static int cmlb_dkio_get_partition(struct cmlb_lun *cl, caddr_t arg, int flag,
    324   3525   shidokht     void *tg_cookie);
    325   3525   shidokht static int cmlb_dkio_set_partition(struct cmlb_lun *cl, caddr_t arg, int flag);
    326   3525   shidokht static int cmlb_dkio_get_efi(struct cmlb_lun *cl, caddr_t arg, int flag,
    327   3525   shidokht     void *tg_cookie);
    328   3525   shidokht static int cmlb_dkio_set_efi(struct cmlb_lun *cl, dev_t dev, caddr_t arg,
    329   3525   shidokht     int flag, void *tg_cookie);
    330   3525   shidokht static int cmlb_dkio_get_vtoc(struct cmlb_lun *cl, caddr_t arg, int flag,
    331   3525   shidokht     void *tg_cookie);
    332   7563     Prasad static int cmlb_dkio_get_extvtoc(struct cmlb_lun *cl, caddr_t arg, int flag,
    333   7563     Prasad     void *tg_cookie);
    334   3525   shidokht static int cmlb_dkio_set_vtoc(struct cmlb_lun *cl, dev_t dev, caddr_t arg,
    335   7563     Prasad     int flag, void *tg_cookie);
    336   7563     Prasad static int cmlb_dkio_set_extvtoc(struct cmlb_lun *cl, dev_t dev, caddr_t arg,
    337   3525   shidokht     int flag, void *tg_cookie);
    338   3525   shidokht static int cmlb_dkio_get_mboot(struct cmlb_lun *cl, caddr_t arg, int flag,
    339   3525   shidokht     void *tg_cookie);
    340   3525   shidokht static int cmlb_dkio_set_mboot(struct cmlb_lun *cl, caddr_t arg, int flag,
    341   3525   shidokht     void *tg_cookie);
    342   3525   shidokht static int cmlb_dkio_partition(struct cmlb_lun *cl, caddr_t arg, int flag,
    343   3525   shidokht     void *tg_cookie);
    344   3525   shidokht 
    345   3525   shidokht #if defined(__i386) || defined(__amd64)
    346  10021  Sheshadri static int cmlb_dkio_set_ext_part(struct cmlb_lun *cl, caddr_t arg, int flag,
    347  10021  Sheshadri     void *tg_cookie);
    348  10021  Sheshadri static int cmlb_validate_ext_part(struct cmlb_lun *cl, int part, int epart,
    349  10021  Sheshadri     uint32_t start, uint32_t size);
    350  10021  Sheshadri static int cmlb_is_linux_swap(struct cmlb_lun *cl, uint32_t part_start,
    351  10021  Sheshadri     void *tg_cookie);
    352   3525   shidokht static int cmlb_dkio_get_virtgeom(struct cmlb_lun *cl, caddr_t arg, int flag);
    353  10320      Larry static int cmlb_dkio_get_phygeom(struct cmlb_lun *cl, caddr_t  arg, int flag,
    354  10320      Larry     void *tg_cookie);
    355   3525   shidokht static int cmlb_dkio_partinfo(struct cmlb_lun *cl, dev_t dev, caddr_t arg,
    356   7563     Prasad     int flag);
    357   7563     Prasad static int cmlb_dkio_extpartinfo(struct cmlb_lun *cl, dev_t dev, caddr_t arg,
    358    786      lclee     int flag);
    359   3525   shidokht #endif
    360   3525   shidokht 
    361   3525   shidokht static void cmlb_dbg(uint_t comp, struct cmlb_lun *cl, const char *fmt, ...);
    362    786      lclee static void cmlb_v_log(dev_info_t *dev, char *label, uint_t level,
    363    786      lclee     const char *fmt, va_list ap);
    364    786      lclee static void cmlb_log(dev_info_t *dev, char *label, uint_t level,
    365    786      lclee     const char *fmt, ...);
    366    786      lclee 
    367    786      lclee int
    368    786      lclee _init(void)
    369    786      lclee {
    370    786      lclee 	mutex_init(&cmlb_log_mutex, NULL, MUTEX_DRIVER, NULL);
    371    786      lclee 	return (mod_install(&modlinkage));
    372    786      lclee }
    373    786      lclee 
    374    786      lclee int
    375    786      lclee _info(struct modinfo *modinfop)
    376    786      lclee {
    377    786      lclee 	return (mod_info(&modlinkage, modinfop));
    378    786      lclee }
    379    786      lclee 
    380    786      lclee int
    381    786      lclee _fini(void)
    382    786      lclee {
    383    786      lclee 	int err;
    384    786      lclee 
    385    786      lclee 	if ((err = mod_remove(&modlinkage)) != 0) {
    386    786      lclee 		return (err);
    387    786      lclee 	}
    388    786      lclee 
    389    786      lclee 	mutex_destroy(&cmlb_log_mutex);
    390    786      lclee 	return (err);
    391    786      lclee }
    392    786      lclee 
    393    786      lclee /*
    394    786      lclee  * cmlb_dbg is used for debugging to log additional info
    395    786      lclee  * Level of output is controlled via cmlb_level_mask setting.
    396    786      lclee  */
    397    786      lclee static void
    398   3525   shidokht cmlb_dbg(uint_t comp, struct cmlb_lun *cl, const char *fmt, ...)
    399    786      lclee {
    400    786      lclee 	va_list		ap;
    401    786      lclee 	dev_info_t	*dev;
    402    786      lclee 	uint_t		level_mask = 0;
    403    786      lclee 
    404   3525   shidokht 	ASSERT(cl != NULL);
    405   3525   shidokht 	dev = CMLB_DEVINFO(cl);
    406    786      lclee 	ASSERT(dev != NULL);
    407    786      lclee 	/*
    408    786      lclee 	 * Filter messages based on the global component and level masks,
    409   3525   shidokht 	 * also print if cl matches the value of cmlb_debug_cl, or if
    410   3525   shidokht 	 * cmlb_debug_cl is set to NULL.
    411    786      lclee 	 */
    412    786      lclee 	if (comp & CMLB_TRACE)
    413    786      lclee 		level_mask |= CMLB_LOGMASK_TRACE;
    414    786      lclee 
    415    786      lclee 	if (comp & CMLB_INFO)
    416    786      lclee 		level_mask |= CMLB_LOGMASK_INFO;
    417    786      lclee 
    418    786      lclee 	if (comp & CMLB_ERROR)
    419    786      lclee 		level_mask |= CMLB_LOGMASK_ERROR;
    420    786      lclee 
    421    786      lclee 	if ((cmlb_level_mask & level_mask) &&
    422   3525   shidokht 	    ((cmlb_debug_cl == NULL) || (cmlb_debug_cl == cl))) {
    423    786      lclee 		va_start(ap, fmt);
    424   3525   shidokht 		cmlb_v_log(dev, CMLB_LABEL(cl), CE_CONT, fmt, ap);
    425    786      lclee 		va_end(ap);
    426    786      lclee 	}
    427    786      lclee }
    428    786      lclee 
    429    786      lclee /*
    430    786      lclee  * cmlb_log is basically a duplicate of scsi_log. It is redefined here
    431    786      lclee  * so that this module does not depend on scsi module.
    432    786      lclee  */
    433    786      lclee static void
    434    786      lclee cmlb_log(dev_info_t *dev, char *label, uint_t level, const char *fmt, ...)
    435    786      lclee {
    436    786      lclee 	va_list		ap;
    437    786      lclee 
    438    786      lclee 	va_start(ap, fmt);
    439    786      lclee 	cmlb_v_log(dev, label, level, fmt, ap);
    440    786      lclee 	va_end(ap);
    441    786      lclee }
    442    786      lclee 
    443    786      lclee static void
    444    786      lclee cmlb_v_log(dev_info_t *dev, char *label, uint_t level, const char *fmt,
    445    786      lclee     va_list ap)
    446    786      lclee {
    447    786      lclee 	static char 	name[256];
    448    786      lclee 	int 		log_only = 0;
    449    786      lclee 	int 		boot_only = 0;
    450    786      lclee 	int 		console_only = 0;
    451    786      lclee 
    452    786      lclee 	mutex_enter(&cmlb_log_mutex);
    453    786      lclee 
    454    786      lclee 	if (dev) {
    455    786      lclee 		if (level == CE_PANIC || level == CE_WARN ||
    456    786      lclee 		    level == CE_NOTE) {
    457    786      lclee 			(void) sprintf(name, "%s (%s%d):\n",
    458    786      lclee 			    ddi_pathname(dev, cmlb_log_buffer),
    459    786      lclee 			    label, ddi_get_instance(dev));
    460    786      lclee 		} else {
    461    786      lclee 			name[0] = '\0';
    462    786      lclee 		}
    463    786      lclee 	} else {
    464    786      lclee 		(void) sprintf(name, "%s:", label);
    465    786      lclee 	}
    466    786      lclee 
    467    786      lclee 	(void) vsprintf(cmlb_log_buffer, fmt, ap);
    468    786      lclee 
    469    786      lclee 	switch (cmlb_log_buffer[0]) {
    470    786      lclee 	case '!':
    471    786      lclee 		log_only = 1;
    472    786      lclee 		break;
    473    786      lclee 	case '?':
    474    786      lclee 		boot_only = 1;
    475    786      lclee 		break;
    476    786      lclee 	case '^':
    477    786      lclee 		console_only = 1;
    478    786      lclee 		break;
    479    786      lclee 	}
    480    786      lclee 
    481    786      lclee 	switch (level) {
    482    786      lclee 	case CE_NOTE:
    483    786      lclee 		level = CE_CONT;
    484    786      lclee 		/* FALLTHROUGH */
    485    786      lclee 	case CE_CONT:
    486    786      lclee 	case CE_WARN:
    487    786      lclee 	case CE_PANIC:
    488    786      lclee 		if (boot_only) {
    489    786      lclee 			cmn_err(level, "?%s\t%s", name, &cmlb_log_buffer[1]);
    490    786      lclee 		} else if (console_only) {
    491    786      lclee 			cmn_err(level, "^%s\t%s", name, &cmlb_log_buffer[1]);
    492    786      lclee 		} else if (log_only) {
    493    786      lclee 			cmn_err(level, "!%s\t%s", name, &cmlb_log_buffer[1]);
    494    786      lclee 		} else {
    495    786      lclee 			cmn_err(level, "%s\t%s", name, cmlb_log_buffer);
    496    786      lclee 		}
    497    786      lclee 		break;
    498    786      lclee 	case CE_IGNORE:
    499    786      lclee 		break;
    500    786      lclee 	default:
    501    786      lclee 		cmn_err(CE_CONT, "^DEBUG: %s\t%s", name, cmlb_log_buffer);
    502    786      lclee 		break;
    503    786      lclee 	}
    504    786      lclee 	mutex_exit(&cmlb_log_mutex);
    505    786      lclee }
    506    786      lclee 
    507    786      lclee 
    508    786      lclee /*
    509    786      lclee  * cmlb_alloc_handle:
    510    786      lclee  *
    511    786      lclee  *	Allocates a handle.
    512    786      lclee  *
    513    786      lclee  * Arguments:
    514    786      lclee  *	cmlbhandlep	pointer to handle
    515    786      lclee  *
    516    786      lclee  * Notes:
    517    786      lclee  *	Allocates a handle and stores the allocated handle in the area
    518    786      lclee  *	pointed to by cmlbhandlep
    519    786      lclee  *
    520    786      lclee  * Context:
    521    786      lclee  *	Kernel thread only (can sleep).
    522    786      lclee  */
    523    786      lclee void
    524    786      lclee cmlb_alloc_handle(cmlb_handle_t *cmlbhandlep)
    525    786      lclee {
    526   3525   shidokht 	struct cmlb_lun 	*cl;
    527   3525   shidokht 
    528   3525   shidokht 	cl = kmem_zalloc(sizeof (struct cmlb_lun), KM_SLEEP);
    529    786      lclee 	ASSERT(cmlbhandlep != NULL);
    530    786      lclee 
    531   3525   shidokht 	cl->cl_state = CMLB_INITED;
    532   3525   shidokht 	cl->cl_def_labeltype = CMLB_LABEL_UNDEF;
    533   3525   shidokht 	mutex_init(CMLB_MUTEX(cl), NULL, MUTEX_DRIVER, NULL);
    534   3525   shidokht 
    535   3525   shidokht 	*cmlbhandlep = (cmlb_handle_t)(cl);
    536    786      lclee }
    537    786      lclee 
    538    786      lclee /*
    539    786      lclee  * cmlb_free_handle
    540    786      lclee  *
    541    786      lclee  *	Frees handle.
    542    786      lclee  *
    543    786      lclee  * Arguments:
    544    786      lclee  *	cmlbhandlep	pointer to handle
    545    786      lclee  */
    546    786      lclee void
    547    786      lclee cmlb_free_handle(cmlb_handle_t *cmlbhandlep)
    548    786      lclee {
    549   3525   shidokht 	struct cmlb_lun 	*cl;
    550   3525   shidokht 
    551   3525   shidokht 	cl = (struct cmlb_lun *)*cmlbhandlep;
    552   3525   shidokht 	if (cl != NULL) {
    553   3525   shidokht 		mutex_destroy(CMLB_MUTEX(cl));
    554   3525   shidokht 		kmem_free(cl, sizeof (struct cmlb_lun));
    555    786      lclee 	}
    556    786      lclee 
    557    786      lclee }
    558    786      lclee 
    559    786      lclee /*
    560    786      lclee  * cmlb_attach:
    561    786      lclee  *
    562    786      lclee  *	Attach handle to device, create minor nodes for device.
    563    786      lclee  *
    564    786      lclee  * Arguments:
    565    786      lclee  * 	devi		pointer to device's dev_info structure.
    566    786      lclee  * 	tgopsp		pointer to array of functions cmlb can use to callback
    567    786      lclee  *			to target driver.
    568    786      lclee  *
    569    786      lclee  *	device_type	Peripheral device type as defined in
    570    786      lclee  *			scsi/generic/inquiry.h
    571    786      lclee  *
    572    786      lclee  *	is_removable	whether or not device is removable.
    573   3525   shidokht  *
    574   3525   shidokht  *	is_hotpluggable	whether or not device is hotpluggable.
    575    786      lclee  *
    576    786      lclee  *	node_type	minor node type (as used by ddi_create_minor_node)
    577    786      lclee  *
    578    786      lclee  *	alter_behavior
    579    786      lclee  *			bit flags:
    580    786      lclee  *
    581    786      lclee  *			CMLB_CREATE_ALTSLICE_VTOC_16_DTYPE_DIRECT: create
    582    786      lclee  *			an alternate slice for the default label, if
    583    786      lclee  *			device type is DTYPE_DIRECT an architectures default
    584    786      lclee  *			label type is VTOC16.
    585    786      lclee  *			Otherwise alternate slice will no be created.
    586    786      lclee  *
    587    786      lclee  *
    588    786      lclee  *			CMLB_FAKE_GEOM_LABEL_IOCTLS_VTOC8: report a default
    589    786      lclee  *			geometry and label for DKIOCGGEOM and DKIOCGVTOC
    590    786      lclee  *			on architecture with VTOC8 label types.
    591    786      lclee  *
    592   3525   shidokht  * 			CMLB_OFF_BY_ONE: do the workaround for legacy off-by-
    593   3525   shidokht  *                      one bug in obtaining capacity (in sd):
    594   3525   shidokht  *			SCSI READ_CAPACITY command returns the LBA number of the
    595   3525   shidokht  *			last logical block, but sd once treated this number as
    596   3525   shidokht  *			disks' capacity on x86 platform. And LBAs are addressed
    597   3525   shidokht  *			based 0. So the last block was lost on x86 platform.
    598   3525   shidokht  *
    599   3525   shidokht  *			Now, we remove this workaround. In order for present sd
    600   3525   shidokht  *			driver to work with disks which are labeled/partitioned
    601   3525   shidokht  *			via previous sd, we add workaround as follows:
    602   3525   shidokht  *
    603   3525   shidokht  *			1) Locate backup EFI label: cmlb searches the next to
    604   3525   shidokht  *			   last
    605   3525   shidokht  *			   block for backup EFI label. If fails, it will
    606   3525   shidokht  *			   turn to the last block for backup EFI label;
    607   3525   shidokht  *
    608   3525   shidokht  *			2) Clear backup EFI label: cmlb first search the last
    609   3525   shidokht  *			   block for backup EFI label, and will search the
    610   3525   shidokht  *			   next to last block only if failed for the last
    611   3525   shidokht  *			   block.
    612   3525   shidokht  *
    613   3525   shidokht  *			3) Calculate geometry:refer to cmlb_convert_geometry()
    614   3525   shidokht  *			   If capacity increasing by 1 causes disks' capacity
    615   7563     Prasad  *			   to cross over the limits in geometry calculation,
    616   3525   shidokht  *			   geometry info will change. This will raise an issue:
    617   3525   shidokht  *			   In case that primary VTOC label is destroyed, format
    618   3525   shidokht  *			   commandline can restore it via backup VTOC labels.
    619   3525   shidokht  *			   And format locates backup VTOC labels by use of
    620   3525   shidokht  *			   geometry. So changing geometry will
    621   3525   shidokht  *			   prevent format from finding backup VTOC labels. To
    622   3525   shidokht  *			   eliminate this side effect for compatibility,
    623   3525   shidokht  *			   sd uses (capacity -1) to calculate geometry;
    624   3525   shidokht  *
    625   3525   shidokht  *			4) 1TB disks: some important data structures use
    626   3525   shidokht  *			   32-bit signed long/int (for example, daddr_t),
    627   3525   shidokht  *			   so that sd doesn't support a disk with capacity
    628   3525   shidokht  *			   larger than 1TB on 32-bit platform. However,
    629   3525   shidokht  *			   for exactly 1TB disk, it was treated as (1T - 512)B
    630   3525   shidokht  *			   in the past, and could have valid Solaris
    631   3525   shidokht  *			   partitions. To workaround this, if an exactly 1TB
    632   3525   shidokht  *			   disk has Solaris fdisk partition, it will be allowed
    633   3525   shidokht  *			   to work with sd.
    634   3525   shidokht  *
    635   5084    johnlev  *
    636   5084    johnlev  *
    637   5084    johnlev  *			CMLB_FAKE_LABEL_ONE_PARTITION: create s0 and s2 covering
    638   5084    johnlev  *			the entire disk, if there is no valid partition info.
    639   5084    johnlev  *			If there is a valid Solaris partition, s0 and s2 will
    640   5084    johnlev  *			only cover the entire Solaris partition.
    641   3525   shidokht  *
    642    786      lclee  *
    643    786      lclee  *	cmlbhandle	cmlb handle associated with device
    644   3525   shidokht  *
    645   3525   shidokht  *	tg_cookie	cookie from target driver to be passed back to target
    646   3525   shidokht  *			driver when we call back to it through tg_ops.
    647    786      lclee  *
    648    786      lclee  * Notes:
    649    786      lclee  *	Assumes a default label based on capacity for non-removable devices.
    650    786      lclee  *	If capacity > 1TB, EFI is assumed otherwise VTOC (default VTOC
    651    786      lclee  *	for the architecture).
    652    786      lclee  *
    653    786      lclee  *	For removable devices, default label type is assumed to be VTOC
    654    786      lclee  *	type. Create minor nodes based on a default label type.
    655    786      lclee  *	Label on the media is not validated.
    656    786      lclee  *	minor number consists of:
    657    786      lclee  *		if _SUNOS_VTOC_8 is defined
    658    786      lclee  *			lowest 3 bits is taken as partition number
    659    786      lclee  *			the rest is instance number
    660    786      lclee  *		if _SUNOS_VTOC_16 is defined
    661    786      lclee  *			lowest 6 bits is taken as partition number
    662    786      lclee  *			the rest is instance number
    663    786      lclee  *
    664    786      lclee  *
    665    786      lclee  * Return values:
    666    786      lclee  *	0 	Success
    667    786      lclee  * 	ENXIO 	creating minor nodes failed.
    668   3525   shidokht  *	EINVAL  invalid arg, unsupported tg_ops version
    669    786      lclee  */
    670    786      lclee int
    671    786      lclee cmlb_attach(dev_info_t *devi, cmlb_tg_ops_t *tgopsp, int device_type,
    672   8863     Edward     boolean_t is_removable, boolean_t is_hotpluggable, char *node_type,
    673   3525   shidokht     int alter_behavior, cmlb_handle_t cmlbhandle, void *tg_cookie)
    674   3525   shidokht {
    675   3525   shidokht 
    676   3525   shidokht 	struct cmlb_lun	*cl = (struct cmlb_lun *)cmlbhandle;
    677    786      lclee 	diskaddr_t	cap;
    678    786      lclee 	int		status;
    679   8863     Edward 
    680   8863     Edward 	ASSERT(VALID_BOOLEAN(is_removable));
    681   8863     Edward 	ASSERT(VALID_BOOLEAN(is_hotpluggable));
    682    786      lclee 
    683   3525   shidokht 	if (tgopsp->tg_version < TG_DK_OPS_VERSION_1)
    684   3525   shidokht 		return (EINVAL);
    685   3525   shidokht 
    686   3525   shidokht 	mutex_enter(CMLB_MUTEX(cl));
    687   3525   shidokht 
    688   3525   shidokht 	CMLB_DEVINFO(cl) = devi;
    689   3525   shidokht 	cl->cmlb_tg_ops = tgopsp;
    690   3525   shidokht 	cl->cl_device_type = device_type;
    691   3525   shidokht 	cl->cl_is_removable = is_removable;
    692   3525   shidokht 	cl->cl_is_hotpluggable = is_hotpluggable;
    693   3525   shidokht 	cl->cl_node_type = node_type;
    694   3525   shidokht 	cl->cl_sys_blocksize = DEV_BSIZE;
    695   8863     Edward 	cl->cl_f_geometry_is_valid = B_FALSE;
    696   3525   shidokht 	cl->cl_def_labeltype = CMLB_LABEL_VTOC;
    697   3525   shidokht 	cl->cl_alter_behavior = alter_behavior;
    698   3525   shidokht 	cl->cl_reserved = -1;
    699   7563     Prasad 	cl->cl_msglog_flag |= CMLB_ALLOW_2TB_WARN;
    700  10021  Sheshadri #if defined(__i386) || defined(__amd64)
    701  10021  Sheshadri 	cl->cl_logical_drive_count = 0;
    702  10021  Sheshadri #endif
    703   7563     Prasad 
    704   8863     Edward 	if (!is_removable) {
    705   3525   shidokht 		mutex_exit(CMLB_MUTEX(cl));
    706   3525   shidokht 		status = DK_TG_GETCAP(cl, &cap, tg_cookie);
    707   3525   shidokht 		mutex_enter(CMLB_MUTEX(cl));
    708   7563     Prasad 		if (status == 0 && cap > CMLB_EXTVTOC_LIMIT) {
    709   7563     Prasad 			/* set default EFI if > 2TB */
    710   3525   shidokht 			cl->cl_def_labeltype = CMLB_LABEL_EFI;
    711    786      lclee 		}
    712    786      lclee 	}
    713    786      lclee 
    714    786      lclee 	/* create minor nodes based on default label type */
    715   3525   shidokht 	cl->cl_last_labeltype = CMLB_LABEL_UNDEF;
    716   3525   shidokht 	cl->cl_cur_labeltype = CMLB_LABEL_UNDEF;
    717   3525   shidokht 
    718   3525   shidokht 	if (cmlb_create_minor_nodes(cl) != 0) {
    719   3525   shidokht 		mutex_exit(CMLB_MUTEX(cl));
    720    786      lclee 		return (ENXIO);
    721    786      lclee 	}
    722    786      lclee 
    723   7224        cth 	/* Define the dynamic properties for devinfo spapshots. */
    724   7224        cth 	i_ddi_prop_dyn_driver_set(CMLB_DEVINFO(cl), cmlb_prop_dyn);
    725   7224        cth 
    726   3525   shidokht 	cl->cl_state = CMLB_ATTACHED;
    727   3525   shidokht 
    728   3525   shidokht 	mutex_exit(CMLB_MUTEX(cl));
    729    786      lclee 	return (0);
    730    786      lclee }
    731    786      lclee 
    732    786      lclee /*
    733    786      lclee  * cmlb_detach:
    734    786      lclee  *
    735    786      lclee  * Invalidate in-core labeling data and remove all minor nodes for
    736    786      lclee  * the device associate with handle.
    737    786      lclee  *
    738    786      lclee  * Arguments:
    739    786      lclee  *	cmlbhandle	cmlb handle associated with device.
    740    786      lclee  *
    741   3525   shidokht  *	tg_cookie	cookie from target driver to be passed back to target
    742   3525   shidokht  *			driver when we call back to it through tg_ops.
    743   3525   shidokht  *
    744   3525   shidokht  */
    745   3525   shidokht /*ARGSUSED1*/
    746    786      lclee void
    747   3525   shidokht cmlb_detach(cmlb_handle_t cmlbhandle, void *tg_cookie)
    748   3525   shidokht {
    749   3525   shidokht 	struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle;
    750   3525   shidokht 
    751   3525   shidokht 	mutex_enter(CMLB_MUTEX(cl));
    752   3525   shidokht 	cl->cl_def_labeltype = CMLB_LABEL_UNDEF;
    753   8863     Edward 	cl->cl_f_geometry_is_valid = B_FALSE;
    754   3525   shidokht 	ddi_remove_minor_node(CMLB_DEVINFO(cl), NULL);
    755   7224        cth 	i_ddi_prop_dyn_driver_set(CMLB_DEVINFO(cl), NULL);
    756   3525   shidokht 	cl->cl_state = CMLB_INITED;
    757   3525   shidokht 	mutex_exit(CMLB_MUTEX(cl));
    758    786      lclee }
    759    786      lclee 
    760    786      lclee /*
    761    786      lclee  * cmlb_validate:
    762    786      lclee  *
    763    786      lclee  *	Validates label.
    764    786      lclee  *
    765    786      lclee  * Arguments
    766    786      lclee  *	cmlbhandle	cmlb handle associated with device.
    767   3525   shidokht  *
    768   3525   shidokht  *	flags		operation flags. used for verbosity control
    769   3525   shidokht  *
    770   3525   shidokht  *	tg_cookie	cookie from target driver to be passed back to target
    771   3525   shidokht  *			driver when we call back to it through tg_ops.
    772   3525   shidokht  *
    773    786      lclee  *
    774    786      lclee  * Notes:
    775    786      lclee  *	If new label type is different from the current, adjust minor nodes
    776    786      lclee  *	accordingly.
    777    786      lclee  *
    778    786      lclee  * Return values:
    779    786      lclee  *	0		success
    780    786      lclee  *			Note: having fdisk but no solaris partition is assumed
    781    786      lclee  *			success.
    782    786      lclee  *
    783    786      lclee  *	ENOMEM		memory allocation failed
    784    786      lclee  *	EIO		i/o errors during read or get capacity
    785    786      lclee  * 	EACCESS		reservation conflicts
    786    786      lclee  * 	EINVAL		label was corrupt, or no default label was assumed
    787    786      lclee  *	ENXIO		invalid handle
    788    786      lclee  */
    789    786      lclee int
    790   3525   shidokht cmlb_validate(cmlb_handle_t cmlbhandle, int flags, void *tg_cookie)
    791   3525   shidokht {
    792   3525   shidokht 	struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle;
    793    786      lclee 	int 		rval;
    794    786      lclee 	int  		ret = 0;
    795    786      lclee 
    796    786      lclee 	/*
    797   3525   shidokht 	 * Temp work-around checking cl for NULL since there is a bug
    798    786      lclee 	 * in sd_detach calling this routine from taskq_dispatch
    799    786      lclee 	 * inited function.
    800    786      lclee 	 */
    801   3525   shidokht 	if (cl == NULL)
    802    786      lclee 		return (ENXIO);
    803    786      lclee 
    804   3525   shidokht 	mutex_enter(CMLB_MUTEX(cl));
    805   3525   shidokht 	if (cl->cl_state < CMLB_ATTACHED) {
    806   3525   shidokht 		mutex_exit(CMLB_MUTEX(cl));
    807    786      lclee 		return (ENXIO);
    808    786      lclee 	}
    809    786      lclee 
    810   8863     Edward 	rval = cmlb_validate_geometry((struct cmlb_lun *)cmlbhandle, B_TRUE,
    811   3525   shidokht 	    flags, tg_cookie);
    812    786      lclee 
    813    786      lclee 	if (rval == ENOTSUP) {
    814   8863     Edward 		if (cl->cl_f_geometry_is_valid) {
    815   3525   shidokht 			cl->cl_cur_labeltype = CMLB_LABEL_EFI;
    816    786      lclee 			ret = 0;
    817    786      lclee 		} else {
    818    786      lclee 			ret = EINVAL;
    819    786      lclee 		}
    820    786      lclee 	} else {
    821    786      lclee 		ret = rval;
    822    786      lclee 		if (ret == 0)
    823   3525   shidokht 			cl->cl_cur_labeltype = CMLB_LABEL_VTOC;
    824    786      lclee 	}
    825    786      lclee 
    826    786      lclee 	if (ret == 0)
    827   3525   shidokht 		(void) cmlb_create_minor_nodes(cl);
    828   3525   shidokht 
    829   3525   shidokht 	mutex_exit(CMLB_MUTEX(cl));
    830    786      lclee 	return (ret);
    831    786      lclee }
    832    786      lclee 
    833    786      lclee /*
    834    786      lclee  * cmlb_invalidate:
    835    786      lclee  *	Invalidate in core label data
    836    786      lclee  *
    837    786      lclee  * Arguments:
    838    786      lclee  *	cmlbhandle	cmlb handle associated with device.
    839   3525   shidokht  *	tg_cookie	cookie from target driver to be passed back to target
    840   3525   shidokht  *			driver when we call back to it through tg_ops.
    841   3525   shidokht  */
    842   3525   shidokht /*ARGSUSED1*/
    843    786      lclee void
    844   3525   shidokht cmlb_invalidate(cmlb_handle_t cmlbhandle, void *tg_cookie)
    845   3525   shidokht {
    846   3525   shidokht 	struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle;
    847   3525   shidokht 
    848   3525   shidokht 	if (cl == NULL)
    849    786      lclee 		return;
    850    786      lclee 
    851   3525   shidokht 	mutex_enter(CMLB_MUTEX(cl));
    852   8863     Edward 	cl->cl_f_geometry_is_valid = B_FALSE;
    853   3525   shidokht 	mutex_exit(CMLB_MUTEX(cl));
    854   3525   shidokht }
    855   3525   shidokht 
    856   3525   shidokht /*
    857   3525   shidokht  * cmlb_is_valid
    858   3525   shidokht  * 	Get status on whether the incore label/geom data is valid
    859   3525   shidokht  *
    860   3525   shidokht  * Arguments:
    861   3525   shidokht  *	cmlbhandle      cmlb handle associated with device.
    862   3525   shidokht  *
    863   3525   shidokht  * Return values:
    864   8863     Edward  *	B_TRUE if incore label/geom data is valid.
    865   8863     Edward  *	B_FALSE otherwise.
    866   8863     Edward  *
    867   8863     Edward  */
    868   8863     Edward 
    869   8863     Edward 
    870   8863     Edward boolean_t
    871   3525   shidokht cmlb_is_valid(cmlb_handle_t cmlbhandle)
    872   3525   shidokht {
    873   3525   shidokht 	struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle;
    874   3525   shidokht 
    875   3525   shidokht 	if (cmlbhandle == NULL)
    876   8863     Edward 		return (B_FALSE);
    877   3525   shidokht 
    878   3525   shidokht 	return (cl->cl_f_geometry_is_valid);
    879   3525   shidokht 
    880   3525   shidokht }
    881   3525   shidokht 
    882   3525   shidokht 
    883    786      lclee 
    884    786      lclee /*
    885    786      lclee  * cmlb_close:
    886    786      lclee  *
    887    786      lclee  * Close the device, revert to a default label minor node for the device,
    888    786      lclee  * if it is removable.
    889    786      lclee  *
    890    786      lclee  * Arguments:
    891    786      lclee  *	cmlbhandle	cmlb handle associated with device.
    892    786      lclee  *
    893   3525   shidokht  *	tg_cookie	cookie from target driver to be passed back to target
    894   3525   shidokht  *			driver when we call back to it through tg_ops.
    895    786      lclee  * Return values:
    896    786      lclee  *	0	Success
    897    786      lclee  * 	ENXIO	Re-creating minor node failed.
    898    786      lclee  */
    899   3525   shidokht /*ARGSUSED1*/
    900   3525   shidokht int
    901   3525   shidokht cmlb_close(cmlb_handle_t cmlbhandle, void *tg_cookie)
    902   3525   shidokht {
    903   3525   shidokht 	struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle;
    904   3525   shidokht 
    905   3525   shidokht 	mutex_enter(CMLB_MUTEX(cl));
    906   8863     Edward 	cl->cl_f_geometry_is_valid = B_FALSE;
    907    786      lclee 
    908    786      lclee 	/* revert to default minor node for this device */
    909   3525   shidokht 	if (ISREMOVABLE(cl)) {
    910   3525   shidokht 		cl->cl_cur_labeltype = CMLB_LABEL_UNDEF;
    911   3525   shidokht 		(void) cmlb_create_minor_nodes(cl);
    912   3525   shidokht 	}
    913   3525   shidokht 
    914   3525   shidokht 	mutex_exit(CMLB_MUTEX(cl));
    915    786      lclee 	return (0);
    916    786      lclee }
    917    786      lclee 
    918    786      lclee /*
    919    786      lclee  * cmlb_get_devid_block:
    920    786      lclee  *	 get the block number where device id is stored.
    921    786      lclee  *
    922    786      lclee  * Arguments:
    923    786      lclee  *	cmlbhandle	cmlb handle associated with device.
    924    786      lclee  *	devidblockp	pointer to block number.
    925   3525   shidokht  *	tg_cookie	cookie from target driver to be passed back to target
    926   3525   shidokht  *			driver when we call back to it through tg_ops.
    927    786      lclee  *
    928    786      lclee  * Notes:
    929    786      lclee  *	It stores the block number of device id in the area pointed to
    930    786      lclee  *	by devidblockp.
    931    786      lclee  * 	with the block number of device id.
    932    786      lclee  *
    933    786      lclee  * Return values:
    934    786      lclee  *	0	success
    935    786      lclee  *	EINVAL 	device id does not apply to current label type.
    936    786      lclee  */
    937   3525   shidokht /*ARGSUSED2*/
    938   3525   shidokht int
    939   3525   shidokht cmlb_get_devid_block(cmlb_handle_t cmlbhandle, diskaddr_t *devidblockp,
    940   3525   shidokht     void *tg_cookie)
    941    786      lclee {
    942    786      lclee 	daddr_t			spc, blk, head, cyl;
    943   3525   shidokht 	struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle;
    944   3525   shidokht 
    945   3525   shidokht 	mutex_enter(CMLB_MUTEX(cl));
    946   3525   shidokht 	if (cl->cl_state < CMLB_ATTACHED) {
    947   3525   shidokht 		mutex_exit(CMLB_MUTEX(cl));
    948   3525   shidokht 		return (EINVAL);
    949   3525   shidokht 	}
    950   3525   shidokht 
    951   8863     Edward 	if ((!cl->cl_f_geometry_is_valid) ||
    952   3525   shidokht 	    (cl->cl_solaris_size < DK_LABEL_LOC)) {
    953   3525   shidokht 		mutex_exit(CMLB_MUTEX(cl));
    954   3525   shidokht 		return (EINVAL);
    955   3525   shidokht 	}
    956   3525   shidokht 
    957   3525   shidokht 	if (cl->cl_cur_labeltype == CMLB_LABEL_EFI) {
    958   3525   shidokht 		if (cl->cl_reserved != -1) {
    959   3525   shidokht 			blk = cl->cl_map[cl->cl_reserved].dkl_cylno;
    960   3525   shidokht 		} else {
    961   3525   shidokht 			mutex_exit(CMLB_MUTEX(cl));
    962   3525   shidokht 			return (EINVAL);
    963   3525   shidokht 		}
    964   3525   shidokht 	} else {
    965   6513    ml40262 		/* if the disk is unlabeled, don't write a devid to it */
    966   7563     Prasad 		if (cl->cl_label_from_media != CMLB_LABEL_VTOC) {
    967   6513    ml40262 			mutex_exit(CMLB_MUTEX(cl));
    968   6513    ml40262 			return (EINVAL);
    969   6513    ml40262 		}
    970   6513    ml40262 
    971    786      lclee 		/* this geometry doesn't allow us to write a devid */
    972   3525   shidokht 		if (cl->cl_g.dkg_acyl < 2) {
    973   3525   shidokht 			mutex_exit(CMLB_MUTEX(cl));
    974    786      lclee 			return (EINVAL);
    975    786      lclee 		}
    976    786      lclee 
    977    786      lclee 		/*
    978    786      lclee 		 * Subtract 2 guarantees that the next to last cylinder
    979    786      lclee 		 * is used
    980    786      lclee 		 */
    981   3525   shidokht 		cyl  = cl->cl_g.dkg_ncyl  + cl->cl_g.dkg_acyl - 2;
    982   3525   shidokht 		spc  = cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect;
    983   3525   shidokht 		head = cl->cl_g.dkg_nhead - 1;
    984   6513    ml40262 		blk  = cl->cl_solaris_offset +
    985   6513    ml40262 		    (cyl * (spc - cl->cl_g.dkg_apc)) +
    986   3525   shidokht 		    (head * cl->cl_g.dkg_nsect) + 1;
    987   3525   shidokht 	}
    988   3525   shidokht 
    989    786      lclee 	*devidblockp = blk;
    990   3525   shidokht 	mutex_exit(CMLB_MUTEX(cl));
    991    786      lclee 	return (0);
    992    786      lclee }
    993    786      lclee 
    994    786      lclee /*
    995    786      lclee  * cmlb_partinfo:
    996    786      lclee  *	Get partition info for specified partition number.
    997    786      lclee  *
    998    786      lclee  * Arguments:
    999    786      lclee  *	cmlbhandle	cmlb handle associated with device.
   1000    786      lclee  *	part		partition number
   1001    786      lclee  *	nblocksp	pointer to number of blocks
   1002    786      lclee  *	startblockp	pointer to starting block
   1003    786      lclee  *	partnamep	pointer to name of partition
   1004    786      lclee  *	tagp		pointer to tag info
   1005   3525   shidokht  *	tg_cookie	cookie from target driver to be passed back to target
   1006   3525   shidokht  *			driver when we call back to it through tg_ops.
   1007    786      lclee  *
   1008    786      lclee  *
   1009    786      lclee  * Notes:
   1010    786      lclee  *	If in-core label is not valid, this functions tries to revalidate
   1011    786      lclee  *	the label. If label is valid, it stores the total number of blocks
   1012    786      lclee  *	in this partition in the area pointed to by nblocksp, starting
   1013    786      lclee  *	block number in area pointed to by startblockp,  pointer to partition
   1014    786      lclee  *	name in area pointed to by partnamep, and tag value in area
   1015    786      lclee  *	pointed by tagp.
   1016    786      lclee  *	For EFI labels, tag value will be set to 0.
   1017    786      lclee  *
   1018    786      lclee  *	For all nblocksp, startblockp and partnamep, tagp, a value of NULL
   1019    786      lclee  *	indicates the corresponding info is not requested.
   1020    786      lclee  *
   1021    786      lclee  *
   1022    786      lclee  * Return values:
   1023    786      lclee  *	0	success
   1024    786      lclee  *	EINVAL  no valid label or requested partition number is invalid.
   1025    786      lclee  *
   1026    786      lclee  */
   1027    786      lclee int
   1028    786      lclee cmlb_partinfo(cmlb_handle_t cmlbhandle, int part, diskaddr_t *nblocksp,
   1029   3525   shidokht     diskaddr_t *startblockp, char **partnamep, uint16_t *tagp, void *tg_cookie)
   1030   3525   shidokht {
   1031   3525   shidokht 
   1032   3525   shidokht 	struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle;
   1033    786      lclee 	int rval;
   1034  10021  Sheshadri #if defined(__i386) || defined(__amd64)
   1035  10021  Sheshadri 	int ext_part;
   1036  10021  Sheshadri #endif
   1037    786      lclee 
   1038   3525   shidokht 	ASSERT(cl != NULL);
   1039   3525   shidokht 	mutex_enter(CMLB_MUTEX(cl));
   1040   3525   shidokht 	if (cl->cl_state < CMLB_ATTACHED) {
   1041   3525   shidokht 		mutex_exit(CMLB_MUTEX(cl));
   1042    786      lclee 		return (EINVAL);
   1043    786      lclee 	}
   1044    786      lclee 
   1045    786      lclee 	if (part  < 0 || part >= MAXPART) {
   1046    786      lclee 		rval = EINVAL;
   1047    786      lclee 	} else {
   1048   8863     Edward 		if (!cl->cl_f_geometry_is_valid)
   1049   8863     Edward 			(void) cmlb_validate_geometry((struct cmlb_lun *)cl,
   1050   8863     Edward 			    B_FALSE, 0, tg_cookie);
   1051   8863     Edward 
   1052   8863     Edward #if defined(_SUNOS_VTOC_16)
   1053   8863     Edward 		if (((!cl->cl_f_geometry_is_valid) ||
   1054   7563     Prasad 		    (part < NDKMAP && cl->cl_solaris_size == 0)) &&
   1055   7563     Prasad 		    (part != P0_RAW_DISK)) {
   1056   7563     Prasad #else
   1057   8863     Edward 		if ((!cl->cl_f_geometry_is_valid) ||
   1058   3525   shidokht 		    (part < NDKMAP && cl->cl_solaris_size == 0)) {
   1059   7563     Prasad #endif
   1060    786      lclee 			rval = EINVAL;
   1061    786      lclee 		} else {
   1062    786      lclee 			if (startblockp != NULL)
   1063   3525   shidokht 				*startblockp = (diskaddr_t)cl->cl_offset[part];
   1064    786      lclee 
   1065    786      lclee 			if (nblocksp != NULL)
   1066    786      lclee 				*nblocksp = (diskaddr_t)
   1067   3525   shidokht 				    cl->cl_map[part].dkl_nblk;
   1068    786      lclee 
   1069    786      lclee 			if (tagp != NULL)
   1070   3525   shidokht 				if (cl->cl_cur_labeltype == CMLB_LABEL_EFI)
   1071    786      lclee 					*tagp = V_UNASSIGNED;
   1072    786      lclee 				else
   1073   3525   shidokht 					*tagp = cl->cl_vtoc.v_part[part].p_tag;
   1074    786      lclee 			rval = 0;
   1075    786      lclee 		}
   1076    786      lclee 
   1077    786      lclee 		/* consistent with behavior of sd for getting minor name */
   1078  10021  Sheshadri 		if (partnamep != NULL) {
   1079  10021  Sheshadri #if defined(__i386) || defined(__amd64)
   1080  10021  Sheshadri #if defined(_FIRMWARE_NEEDS_FDISK)
   1081  10021  Sheshadri 		if (part > FDISK_P4) {
   1082  10021  Sheshadri 			ext_part = part-FDISK_P4-1;
   1083  10021  Sheshadri 			*partnamep = dk_ext_minor_data[ext_part].name;
   1084  10021  Sheshadri 		} else
   1085  10021  Sheshadri #endif
   1086  10021  Sheshadri #endif
   1087    786      lclee 			*partnamep = dk_minor_data[part].name;
   1088  10021  Sheshadri 		}
   1089    786      lclee 
   1090   6590   yl194034 	}
   1091   6590   yl194034 
   1092   6590   yl194034 	mutex_exit(CMLB_MUTEX(cl));
   1093   6590   yl194034 	return (rval);
   1094   6590   yl194034 }
   1095   6590   yl194034 
   1096   6590   yl194034 /*
   1097   6590   yl194034  * cmlb_efi_label_capacity:
   1098   6590   yl194034  *	Get capacity stored in EFI disk label.
   1099   6590   yl194034  *
   1100   6590   yl194034  * Arguments:
   1101   6590   yl194034  *	cmlbhandle	cmlb handle associated with device.
   1102   6590   yl194034  *	capacity	pointer to capacity stored in EFI disk label.
   1103   6590   yl194034  *	tg_cookie	cookie from target driver to be passed back to target
   1104   6590   yl194034  *			driver when we call back to it through tg_ops.
   1105   6590   yl194034  *
   1106   6590   yl194034  *
   1107   6590   yl194034  * Notes:
   1108   6590   yl194034  *	If in-core label is not valid, this functions tries to revalidate
   1109   6590   yl194034  *	the label. If label is valid and is an EFI label, it stores the capacity
   1110   6590   yl194034  *      in disk label in the area pointed to by capacity.
   1111   6590   yl194034  *
   1112   6590   yl194034  *
   1113   6590   yl194034  * Return values:
   1114   6590   yl194034  *	0	success
   1115   6590   yl194034  *	EINVAL  no valid EFI label or capacity is NULL.
   1116   6590   yl194034  *
   1117   6590   yl194034  */
   1118   6590   yl194034 int
   1119   6590   yl194034 cmlb_efi_label_capacity(cmlb_handle_t cmlbhandle, diskaddr_t *capacity,
   1120   6590   yl194034     void *tg_cookie)
   1121   6590   yl194034 {
   1122   6590   yl194034 	struct cmlb_lun *cl = (struct cmlb_lun *)cmlbhandle;
   1123   6590   yl194034 	int rval;
   1124   6590   yl194034 
   1125   6590   yl194034 	ASSERT(cl != NULL);
   1126   6590   yl194034 	mutex_enter(CMLB_MUTEX(cl));
   1127   6590   yl194034 	if (cl->cl_state < CMLB_ATTACHED) {
   1128   6590   yl194034 		mutex_exit(CMLB_MUTEX(cl));
   1129   6590   yl194034 		return (EINVAL);
   1130   6590   yl194034 	}
   1131   6590   yl194034 
   1132   8863     Edward 	if (!cl->cl_f_geometry_is_valid)
   1133   8863     Edward 		(void) cmlb_validate_geometry((struct cmlb_lun *)cl, B_FALSE,
   1134   6590   yl194034 		    0, tg_cookie);
   1135   6590   yl194034 
   1136   8863     Edward 	if ((!cl->cl_f_geometry_is_valid) || (capacity == NULL) ||
   1137   6590   yl194034 	    (cl->cl_cur_labeltype != CMLB_LABEL_EFI)) {
   1138   6590   yl194034 		rval = EINVAL;
   1139   6590   yl194034 	} else {
   1140   6590   yl194034 		*capacity = (diskaddr_t)cl->cl_map[WD_NODE].dkl_nblk;
   1141   6590   yl194034 		rval = 0;
   1142    786      lclee 	}
   1143    786      lclee 
   1144   3525   shidokht 	mutex_exit(CMLB_MUTEX(cl));
   1145   3525   shidokht 	return (rval);
   1146   3525   shidokht }
   1147   3525   shidokht 
   1148   3525   shidokht /* Caller should make sure Test Unit Ready succeeds before calling this. */
   1149   3525   shidokht /*ARGSUSED*/
   1150    786      lclee int
   1151    786      lclee cmlb_ioctl(cmlb_handle_t cmlbhandle, dev_t dev, int cmd, intptr_t arg,
   1152   3525   shidokht     int flag, cred_t *cred_p, int *rval_p, void *tg_cookie)
   1153    786      lclee {
   1154    786      lclee 
   1155    786      lclee 	int err;
   1156   3525   shidokht 	struct cmlb_lun *cl;
   1157   3525   shidokht 
   1158   3525   shidokht 	cl = (struct cmlb_lun *)cmlbhandle;
   1159   3525   shidokht 
   1160   3525   shidokht 	ASSERT(cl != NULL);
   1161   3525   shidokht 
   1162   3525   shidokht 	mutex_enter(CMLB_MUTEX(cl));
   1163   3525   shidokht 	if (cl->cl_state < CMLB_ATTACHED) {
   1164   3525   shidokht 		mutex_exit(CMLB_MUTEX(cl));
   1165   3525   shidokht 		return (EIO);
   1166    786      lclee 	}
   1167    786      lclee 
   1168    786      lclee 	switch (cmd) {
   1169   7563     Prasad 		case DKIOCSEXTVTOC:
   1170   3525   shidokht 		case DKIOCSGEOM:
   1171    786      lclee 		case DKIOCSETEFI:
   1172    786      lclee 		case DKIOCSMBOOT:
   1173  10021  Sheshadri #if defined(__i386) || defined(__amd64)
   1174  10021  Sheshadri 		case DKIOCSETEXTPART:
   1175  10021  Sheshadri #endif
   1176    786      lclee 			break;
   1177   7563     Prasad 		case DKIOCSVTOC:
   1178   7563     Prasad #if defined(__i386) || defined(__amd64)
   1179   7563     Prasad 		case DKIOCPARTINFO:
   1180   7563     Prasad #endif
   1181   7563     Prasad 			if (cl->cl_blockcount > CMLB_OLDVTOC_LIMIT) {
   1182   7563     Prasad 				mutex_exit(CMLB_MUTEX(cl));
   1183   7563     Prasad 				return (EOVERFLOW);
   1184   7563     Prasad 			}
   1185   7563     Prasad 			break;
   1186    786      lclee 		default:
   1187   7563     Prasad 			(void) cmlb_validate_geometry(cl, 1, CMLB_SILENT,
   1188   3903   shidokht 			    tg_cookie);
   1189   3525   shidokht 
   1190   7563     Prasad 			switch (cmd) {
   1191   7563     Prasad 			case DKIOCGVTOC:
   1192   7563     Prasad 			case DKIOCGAPART:
   1193   7563     Prasad 			case DKIOCSAPART:
   1194   7563     Prasad 
   1195   7563     Prasad 				if (cl->cl_label_from_media == CMLB_LABEL_EFI) {
   1196   7563     Prasad 					/* GPT label on disk */
   1197   7563     Prasad 					mutex_exit(CMLB_MUTEX(cl));
   1198   7563     Prasad 					return (ENOTSUP);
   1199   7563     Prasad 				} else if
   1200   7563     Prasad 				    (cl->cl_blockcount > CMLB_OLDVTOC_LIMIT) {
   1201   7563     Prasad 					mutex_exit(CMLB_MUTEX(cl));
   1202   7563     Prasad 					return (EOVERFLOW);
   1203   7563     Prasad 				}
   1204   7563     Prasad 				break;
   1205   7563     Prasad 
   1206   7563     Prasad 			case DKIOCGGEOM:
   1207   7563     Prasad 				if (cl->cl_label_from_media == CMLB_LABEL_EFI) {
   1208   7563     Prasad 					/* GPT label on disk */
   1209   3525   shidokht 					mutex_exit(CMLB_MUTEX(cl));
   1210    786      lclee 					return (ENOTSUP);
   1211    786      lclee 				}
   1212   7563     Prasad 				break;
   1213   7563     Prasad 			default:
   1214   7563     Prasad 				break;
   1215   7563     Prasad 			}
   1216   3525   shidokht 	}
   1217   3525   shidokht 
   1218   3525   shidokht 	mutex_exit(CMLB_MUTEX(cl));
   1219    786      lclee 
   1220    786      lclee 	switch (cmd) {
   1221    786      lclee 	case DKIOCGGEOM:
   1222   3525   shidokht 		cmlb_dbg(CMLB_TRACE, cl, "DKIOCGGEOM\n");
   1223   3525   shidokht 		err = cmlb_dkio_get_geometry(cl, (caddr_t)arg, flag, tg_cookie);
   1224    786      lclee 		break;
   1225    786      lclee 
   1226    786      lclee 	case DKIOCSGEOM:
   1227   3525   shidokht 		cmlb_dbg(CMLB_TRACE, cl, "DKIOCSGEOM\n");
   1228   3525   shidokht 		err = cmlb_dkio_set_geometry(cl, (caddr_t)arg, flag);
   1229    786      lclee 		break;
   1230    786      lclee 
   1231    786      lclee 	case DKIOCGAPART:
   1232   3525   shidokht 		cmlb_dbg(CMLB_TRACE, cl, "DKIOCGAPART\n");
   1233   3525   shidokht 		err = cmlb_dkio_get_partition(cl, (caddr_t)arg,
   1234   3525   shidokht 		    flag, tg_cookie);
   1235    786      lclee 		break;
   1236    786      lclee 
   1237    786      lclee 	case DKIOCSAPART:
   1238   3525   shidokht 		cmlb_dbg(CMLB_TRACE, cl, "DKIOCSAPART\n");
   1239   3525   shidokht 		err = cmlb_dkio_set_partition(cl, (caddr_t)arg, flag);
   1240    786      lclee 		break;
   1241    786      lclee 
   1242    786      lclee 	case DKIOCGVTOC:
   1243   3525   shidokht 		cmlb_dbg(CMLB_TRACE, cl, "DKIOCGVTOC\n");
   1244   3525   shidokht 		err = cmlb_dkio_get_vtoc(cl, (caddr_t)arg, flag, tg_cookie);
   1245    786      lclee 		break;
   1246    786      lclee 
   1247   7563     Prasad 	case DKIOCGEXTVTOC:
   1248   7563     Prasad 		cmlb_dbg(CMLB_TRACE, cl, "DKIOCGVTOC\n");
   1249   7563     Prasad 		err = cmlb_dkio_get_extvtoc(cl, (caddr_t)arg, flag, tg_cookie);
   1250   7563     Prasad 		break;
   1251   7563     Prasad 
   1252    786      lclee 	case DKIOCGETEFI:
   1253   3525   shidokht 		cmlb_dbg(CMLB_TRACE, cl, "DKIOCGETEFI\n");
   1254   3525   shidokht 		err = cmlb_dkio_get_efi(cl, (caddr_t)arg, flag, tg_cookie);
   1255    786      lclee 		break;
   1256    786      lclee 
   1257    786      lclee 	case DKIOCPARTITION:
   1258   3525   shidokht 		cmlb_dbg(CMLB_TRACE, cl, "DKIOCPARTITION\n");
   1259   3525   shidokht 		err = cmlb_dkio_partition(cl, (caddr_t)arg, flag, tg_cookie);
   1260    786      lclee 		break;
   1261    786      lclee 
   1262    786      lclee 	case DKIOCSVTOC:
   1263   3525   shidokht 		cmlb_dbg(CMLB_TRACE, cl, "DKIOCSVTOC\n");
   1264   3525   shidokht 		err = cmlb_dkio_set_vtoc(cl, dev, (caddr_t)arg, flag,
   1265   3525   shidokht 		    tg_cookie);
   1266    786      lclee 		break;
   1267    786      lclee 
   1268   7563     Prasad 	case DKIOCSEXTVTOC:
   1269   7563     Prasad 		cmlb_dbg(CMLB_TRACE, cl, "DKIOCSVTOC\n");
   1270   7563     Prasad 		err = cmlb_dkio_set_extvtoc(cl, dev, (caddr_t)arg, flag,
   1271   7563     Prasad 		    tg_cookie);
   1272   7563     Prasad 		break;
   1273   7563     Prasad 
   1274    786      lclee 	case DKIOCSETEFI:
   1275   3525   shidokht 		cmlb_dbg(CMLB_TRACE, cl, "DKIOCSETEFI\n");
   1276   3525   shidokht 		err = cmlb_dkio_set_efi(cl, dev, (caddr_t)arg, flag, tg_cookie);
   1277    786      lclee 		break;
   1278    786      lclee 
   1279    786      lclee 	case DKIOCGMBOOT:
   1280   3525   shidokht 		cmlb_dbg(CMLB_TRACE, cl, "DKIOCGMBOOT\n");
   1281   3525   shidokht 		err = cmlb_dkio_get_mboot(cl, (caddr_t)arg, flag, tg_cookie);
   1282    786      lclee 		break;
   1283    786      lclee 
   1284    786      lclee 	case DKIOCSMBOOT:
   1285   3525   shidokht 		cmlb_dbg(CMLB_TRACE, cl, "DKIOCSMBOOT\n");
   1286   3525   shidokht 		err = cmlb_dkio_set_mboot(cl, (caddr_t)arg, flag, tg_cookie);
   1287    786      lclee 		break;
   1288    786      lclee 	case DKIOCG_PHYGEOM:
   1289   3525   shidokht 		cmlb_dbg(CMLB_TRACE, cl, "DKIOCG_PHYGEOM\n");
   1290   3525   shidokht #if defined(__i386) || defined(__amd64)
   1291  10320      Larry 		err = cmlb_dkio_get_phygeom(cl, (caddr_t)arg, flag, tg_cookie);
   1292    786      lclee #else
   1293    786      lclee 		err = ENOTTY;
   1294    786      lclee #endif
   1295    786      lclee 		break;
   1296    786      lclee 	case DKIOCG_VIRTGEOM:
   1297   3525   shidokht 		cmlb_dbg(CMLB_TRACE, cl, "DKIOCG_VIRTGEOM\n");
   1298   3525   shidokht #if defined(__i386) || defined(__amd64)
   1299   3525   shidokht 		err = cmlb_dkio_get_virtgeom(cl, (caddr_t)arg, flag);
   1300    786      lclee #else
   1301    786      lclee 		err = ENOTTY;
   1302    786      lclee #endif
   1303    786      lclee 		break;
   1304    786      lclee 	case DKIOCPARTINFO:
   1305   3525   shidokht 		cmlb_dbg(CMLB_TRACE, cl, "DKIOCPARTINFO");
   1306   3525   shidokht #if defined(__i386) || defined(__amd64)
   1307   3525   shidokht 		err = cmlb_dkio_partinfo(cl, dev, (caddr_t)arg, flag);
   1308   7563     Prasad #else
   1309   7563     Prasad 		err = ENOTTY;
   1310   7563     Prasad #endif
   1311   7563     Prasad 		break;
   1312   7563     Prasad 	case DKIOCEXTPARTINFO:
   1313   7563     Prasad 		cmlb_dbg(CMLB_TRACE, cl, "DKIOCPARTINFO");
   1314   7563     Prasad #if defined(__i386) || defined(__amd64)
   1315   7563     Prasad 		err = cmlb_dkio_extpartinfo(cl, dev, (caddr_t)arg, flag);
   1316    786      lclee #else
   1317    786      lclee 		err = ENOTTY;
   1318    786      lclee #endif
   1319    786      lclee 		break;
   1320  10021  Sheshadri #if defined(__i386) || defined(__amd64)
   1321  10021  Sheshadri 	case DKIOCSETEXTPART:
   1322  10021  Sheshadri 		cmlb_dbg(CMLB_TRACE, cl, "DKIOCSETEXTPART");
   1323  10021  Sheshadri 		err = cmlb_dkio_set_ext_part(cl, (caddr_t)arg, flag, tg_cookie);
   1324  10021  Sheshadri 		break;
   1325  10021  Sheshadri #endif
   1326    786      lclee 	default:
   1327    786      lclee 		err = ENOTTY;
   1328    786      lclee 
   1329    786      lclee 	}
   1330   7224        cth 
   1331   7224        cth 	/*
   1332   7224        cth 	 * An ioctl that succeeds and changed ('set') size(9P) information
   1333   7224        cth 	 * needs to invalidate the cached devinfo snapshot to avoid having
   1334   7224        cth 	 * old information being returned in a snapshots.
   1335   7224        cth 	 *
   1336   7224        cth 	 * NB: When available, call ddi_change_minor_node() to clear
   1337   7224        cth 	 * SSIZEVALID in specfs vnodes via spec_size_invalidate().
   1338   7224        cth 	 */
   1339   7224        cth 	if (err == 0) {
   1340   7224        cth 		switch (cmd) {
   1341   7224        cth 		case DKIOCSGEOM:
   1342   7224        cth 		case DKIOCSAPART:
   1343   7224        cth 		case DKIOCSVTOC:
   1344   7563     Prasad 		case DKIOCSEXTVTOC:
   1345   7224        cth 		case DKIOCSETEFI:
   1346   7224        cth 			i_ddi_prop_dyn_cache_invalidate(CMLB_DEVINFO(cl),
   1347   7224        cth 			    i_ddi_prop_dyn_driver_get(CMLB_DEVINFO(cl)));
   1348   7224        cth 		}
   1349   7224        cth 	}
   1350    786      lclee 	return (err);
   1351    786      lclee }
   1352    786      lclee 
   1353    786      lclee dev_t
   1354   3525   shidokht cmlb_make_device(struct cmlb_lun *cl)
   1355   3525   shidokht {
   1356   8459      Jerry 	return (makedevice(ddi_driver_major(CMLB_DEVINFO(cl)),
   1357   3525   shidokht 	    ddi_get_instance(CMLB_DEVINFO(cl)) << CMLBUNIT_SHIFT));
   1358    786      lclee }
   1359    786      lclee 
   1360    786      lclee /*
   1361    786      lclee  * Function: cmlb_check_update_blockcount
   1362    786      lclee  *
   1363    786      lclee  * Description: If current capacity value is invalid, obtains the
   1364    786      lclee  *		current capacity from target driver.
   1365    786      lclee  *
   1366    786      lclee  * Return Code: 0	success
   1367    786      lclee  *		EIO	failure
   1368    786      lclee  */
   1369    786      lclee static int
   1370   3525   shidokht cmlb_check_update_blockcount(struct cmlb_lun *cl, void *tg_cookie)
   1371    786      lclee {
   1372    786      lclee 	int status;
   1373    786      lclee 	diskaddr_t capacity;
   1374   3525   shidokht 	uint32_t lbasize;
   1375   3525   shidokht 
   1376   3525   shidokht 	ASSERT(mutex_owned(CMLB_MUTEX(cl)));
   1377   3525   shidokht 
   1378   8863     Edward 	if (cl->cl_f_geometry_is_valid)
   1379    786      lclee 		return (0);
   1380   8863     Edward 
   1381   8863     Edward 	mutex_exit(CMLB_MUTEX(cl));
   1382   8863     Edward 	status = DK_TG_GETCAP(cl, &capacity, tg_cookie);
   1383   8863     Edward 	if (status != 0) {
   1384   8863     Edward 		mutex_enter(CMLB_MUTEX(cl));
   1385   8863     Edward 		return (EIO);
   1386   8863     Edward 	}
   1387   8863     Edward 
   1388   8863     Edward 	status = DK_TG_GETBLOCKSIZE(cl, &lbasize, tg_cookie);
   1389   8863     Edward 	mutex_enter(CMLB_MUTEX(cl));
   1390   8863     Edward 	if (status != 0)
   1391   8863     Edward 		return (EIO);
   1392   8863     Edward 
   1393   8863     Edward 	if ((capacity != 0) && (lbasize != 0)) {
   1394   8863     Edward 		cl->cl_blockcount = capacity;
   1395   8863     Edward 		cl->cl_tgt_blocksize = lbasize;
   1396   9889      Larry 		if (!cl->cl_is_removable) {
   1397   9889      Larry 			cl->cl_sys_blocksize = lbasize;
   1398   9889      Larry 		}
   1399   8863     Edward 		return (0);
   1400   8863     Edward 	} else {
   1401   8863     Edward 		return (EIO);
   1402   8863     Edward 	}
   1403    786      lclee }
   1404    786      lclee 
   1405   6318        edp static int
   1406   6318        edp cmlb_create_minor(dev_info_t *dip, char *name, int spec_type,
   1407   6318        edp     minor_t minor_num, char *node_type, int flag, boolean_t internal)
   1408   6318        edp {
   1409   8863     Edward 	ASSERT(VALID_BOOLEAN(internal));
   1410   8863     Edward 
   1411   6318        edp 	if (internal)
   1412   6318        edp 		return (ddi_create_internal_pathname(dip,
   1413   6318        edp 		    name, spec_type, minor_num));
   1414   6318        edp 	else
   1415   6318        edp 		return (ddi_create_minor_node(dip,
   1416   6318        edp 		    name, spec_type, minor_num, node_type, flag));
   1417   6318        edp }
   1418   6318        edp 
   1419    786      lclee /*
   1420    786      lclee  *    Function: cmlb_create_minor_nodes
   1421    786      lclee  *
   1422    786      lclee  * Description: Create or adjust the minor device nodes for the instance.
   1423    786      lclee  * 		Minor nodes are created based on default label type,
   1424    786      lclee  *		current label type and last label type we created
   1425    786      lclee  *		minor nodes based on.
   1426    786      lclee  *
   1427    786      lclee  *
   1428   3525   shidokht  *   Arguments: cl - driver soft state (unit) structure
   1429    786      lclee  *
   1430    786      lclee  * Return Code: 0 success
   1431    786      lclee  *		ENXIO	failure.
   1432    786      lclee  *
   1433    786      lclee  *     Context: Kernel thread context
   1434    786      lclee  */
   1435    786      lclee static int
   1436   3525   shidokht cmlb_create_minor_nodes(struct cmlb_lun *cl)
   1437    786      lclee {
   1438    786      lclee 	struct driver_minor_data	*dmdp;
   1439    786      lclee 	int				instance;
   1440    786      lclee 	char				name[48];
   1441    786      lclee 	cmlb_label_t			newlabeltype;
   1442   6318        edp 	boolean_t			internal;
   1443   6318        edp 
   1444   6318        edp 	ASSERT(cl != NULL);
   1445   6318        edp 	ASSERT(mutex_owned(CMLB_MUTEX(cl)));
   1446   6318        edp 
   1447   8863     Edward 	internal = VOID2BOOLEAN(
   1448   8863     Edward 	    (cl->cl_alter_behavior & (CMLB_INTERNAL_MINOR_NODES)) != 0);
   1449    786      lclee 
   1450    786      lclee 	/* check the most common case */
   1451   3525   shidokht 	if (cl->cl_cur_labeltype != CMLB_LABEL_UNDEF &&
   1452   3525   shidokht 	    cl->cl_last_labeltype == cl->cl_cur_labeltype) {
   1453    786      lclee 		/* do nothing */
   1454    786      lclee 		return (0);
   1455    786      lclee 	}
   1456    786      lclee 
   1457   3525   shidokht 	if (cl->cl_def_labeltype == CMLB_LABEL_UNDEF) {
   1458    786      lclee 		/* we should never get here */
   1459    786      lclee 		return (ENXIO);
   1460    786      lclee 	}
   1461    786      lclee 
   1462   3525   shidokht 	if (cl->cl_last_labeltype == CMLB_LABEL_UNDEF) {
   1463    786      lclee 		/* first time during attach */
   1464   3525   shidokht 		newlabeltype = cl->cl_def_labeltype;
   1465   3525   shidokht 
   1466   3525   shidokht 		instance = ddi_get_instance(CMLB_DEVINFO(cl));
   1467    786      lclee 
   1468    786      lclee 		/* Create all the minor nodes for this target. */
   1469    786      lclee 		dmdp = (newlabeltype == CMLB_LABEL_EFI) ? dk_minor_data_efi :
   1470    786      lclee 		    dk_minor_data;
   1471    786      lclee 		while (dmdp->name != NULL) {
   1472    786      lclee 
   1473    786      lclee 			(void) sprintf(name, "%s", dmdp->name);
   1474    786      lclee 
   1475   6318        edp 			if (cmlb_create_minor(CMLB_DEVINFO(cl), name,
   1476    786      lclee 			    dmdp->type,
   1477    786      lclee 			    (instance << CMLBUNIT_SHIFT) | dmdp->minor,
   1478   6318        edp 			    cl->cl_node_type, NULL, internal) == DDI_FAILURE) {
   1479    786      lclee 				/*
   1480    786      lclee 				 * Clean up any nodes that may have been
   1481    786      lclee 				 * created, in case this fails in the middle
   1482    786      lclee 				 * of the loop.
   1483    786      lclee 				 */
   1484   3525   shidokht 				ddi_remove_minor_node(CMLB_DEVINFO(cl), NULL);
   1485    786      lclee 				return (ENXIO);
   1486    786      lclee 			}
   1487    786      lclee 			dmdp++;
   1488    786      lclee 		}
   1489   3525   shidokht 		cl->cl_last_labeltype = newlabeltype;
   1490    786      lclee 		return (0);
   1491    786      lclee 	}
   1492    786      lclee 
   1493    786      lclee 	/* Not first time  */
   1494   3525   shidokht 	if (cl->cl_cur_labeltype == CMLB_LABEL_UNDEF) {
   1495   3525   shidokht 		if (cl->cl_last_labeltype != cl->cl_def_labeltype) {
   1496    786      lclee 			/* close time, revert to default. */
   1497   3525   shidokht 			newlabeltype = cl->cl_def_labeltype;
   1498    786      lclee 		} else {
   1499    786      lclee 			/*
   1500    786      lclee 			 * do nothing since the type for which we last created
   1501    786      lclee 			 * nodes matches the default
   1502    786      lclee 			 */
   1503    786      lclee 			return (0);
   1504    786      lclee 		}
   1505    786      lclee 	} else {
   1506   3525   shidokht 		if (cl->cl_cur_labeltype != cl->cl_last_labeltype) {
   1507    786      lclee 			/* We are not closing, use current label type */
   1508   3525   shidokht 			newlabeltype = cl->cl_cur_labeltype;
   1509    786      lclee 		} else {
   1510    786      lclee 			/*
   1511    786      lclee 			 * do nothing since the type for which we last created
   1512    786      lclee 			 * nodes matches the current label type
   1513    786      lclee 			 */
   1514    786      lclee 			return (0);
   1515    786      lclee 		}
   1516    786      lclee 	}
   1517    786      lclee 
   1518   3525   shidokht 	instance = ddi_get_instance(CMLB_DEVINFO(cl));
   1519    786      lclee 
   1520    786      lclee 	/*
   1521    786      lclee 	 * Currently we only fix up the s7 node when we are switching
   1522    786      lclee 	 * label types from or to EFI. This is consistent with
   1523    786      lclee 	 * current behavior of sd.
   1524    786      lclee 	 */
   1525    786      lclee 	if (newlabeltype == CMLB_LABEL_EFI &&
   1526   3525   shidokht 	    cl->cl_last_labeltype != CMLB_LABEL_EFI) {
   1527    786      lclee 		/* from vtoc to EFI */
   1528   3525   shidokht 		ddi_remove_minor_node(CMLB_DEVINFO(cl), "h");
   1529   3525   shidokht 		ddi_remove_minor_node(CMLB_DEVINFO(cl), "h,raw");
   1530   6318        edp 		(void) cmlb_create_minor(CMLB_DEVINFO(cl), "wd",
   1531    786      lclee 		    S_IFBLK, (instance << CMLBUNIT_SHIFT) | WD_NODE,
   1532   6318        edp 		    cl->cl_node_type, NULL, internal);
   1533   6318        edp 		(void) cmlb_create_minor(CMLB_DEVINFO(cl), "wd,raw",
   1534    786      lclee 		    S_IFCHR, (instance << CMLBUNIT_SHIFT) | WD_NODE,
   1535   6318        edp 		    cl->cl_node_type, NULL, internal);
   1536    786      lclee 	} else {
   1537    786      lclee 		/* from efi to vtoc */
   1538   3525   shidokht 		ddi_remove_minor_node(CMLB_DEVINFO(cl), "wd");
   1539   3525   shidokht 		ddi_remove_minor_node(CMLB_DEVINFO(cl), "wd,raw");
   1540   6318        edp 		(void) cmlb_create_minor(CMLB_DEVINFO(cl), "h",
   1541    786      lclee 		    S_IFBLK, (instance << CMLBUNIT_SHIFT) | WD_NODE,
   1542   6318        edp 		    cl->cl_node_type, NULL, internal);
   1543   6318        edp 		(void) cmlb_create_minor(CMLB_DEVINFO(cl), "h,raw",
   1544    786      lclee 		    S_IFCHR, (instance << CMLBUNIT_SHIFT) | WD_NODE,
   1545   6318        edp 		    cl->cl_node_type, NULL, internal);
   1546   3525   shidokht 	}
   1547   3525   shidokht 
   1548   3525   shidokht 	cl->cl_last_labeltype = newlabeltype;
   1549    786      lclee 	return (0);
   1550    786      lclee }
   1551    786      lclee 
   1552    786      lclee /*
   1553    786      lclee  *    Function: cmlb_validate_geometry
   1554    786      lclee  *
   1555    786      lclee  * Description: Read the label from the disk (if present). Update the unit's
   1556    786      lclee  *		geometry and vtoc information from the data in the label.
   1557    786      lclee  *		Verify that the label is valid.
   1558    786      lclee  *
   1559   3525   shidokht  *   Arguments:
   1560   3525   shidokht  *	cl		driver soft state (unit) structure
   1561   3525   shidokht  *
   1562   3525   shidokht  *	forcerevalid	force revalidation even if we are already valid.
   1563   3525   shidokht  *	flags		operation flags from target driver. Used for verbosity
   1564   3525   shidokht  *			control	at this time.
   1565   3525   shidokht  *	tg_cookie	cookie from target driver to be passed back to target
   1566   3525   shidokht  *			driver when we call back to it through tg_ops.
   1567    786      lclee  *
   1568    786      lclee  * Return Code: 0 - Successful completion
   1569   3525   shidokht  *		EINVAL  - Invalid value in cl->cl_tgt_blocksize or
   1570   3525   shidokht  *			  cl->cl_blockcount; or label on disk is corrupted
   1571    786      lclee  *			  or unreadable.
   1572    786      lclee  *		EACCES  - Reservation conflict at the device.
   1573    786      lclee  *		ENOMEM  - Resource allocation error
   1574    786      lclee  *		ENOTSUP - geometry not applicable
   1575    786      lclee  *
   1576    786      lclee  *     Context: Kernel thread only (can sleep).
   1577    786      lclee  */
   1578    786      lclee static int
   1579   8863     Edward cmlb_validate_geometry(struct cmlb_lun *cl, boolean_t forcerevalid, int flags,
   1580   3525   shidokht     void *tg_cookie)
   1581    786      lclee {
   1582    786      lclee 	int		label_error = 0;
   1583    786      lclee 	diskaddr_t	capacity;
   1584    786      lclee 	int		count;
   1585   3525   shidokht 
   1586   3525   shidokht 	ASSERT(mutex_owned(CMLB_MUTEX(cl)));
   1587   8863     Edward 	ASSERT(VALID_BOOLEAN(forcerevalid));
   1588   8863     Edward 
   1589   8863     Edward 	if ((cl->cl_f_geometry_is_valid) && (!forcerevalid)) {
   1590   3525   shidokht 		if (cl->cl_cur_labeltype == CMLB_LABEL_EFI)
   1591    786      lclee 			return (ENOTSUP);
   1592    786      lclee 		return (0);
   1593    786      lclee 	}
   1594    786      lclee 
   1595   3525   shidokht 	if (cmlb_check_update_blockcount(cl, tg_cookie) != 0)
   1596   3525   shidokht 		return (EIO);
   1597   3525   shidokht 
   1598   3525   shidokht 	capacity = cl->cl_blockcount;
   1599    786      lclee 
   1600    786      lclee #if defined(_SUNOS_VTOC_16)
   1601    786      lclee 	/*
   1602    786      lclee 	 * Set up the "whole disk" fdisk partition; this should always
   1603    786      lclee 	 * exist, regardless of whether the disk contains an fdisk table
   1604    786      lclee 	 * or vtoc.
   1605    786      lclee 	 */
   1606   3525   shidokht 	cl->cl_map[P0_RAW_DISK].dkl_cylno = 0;
   1607   7563     Prasad 	cl->cl_offset[P0_RAW_DISK] = 0;
   1608   7563     Prasad 	/*
   1609   7563     Prasad 	 * note if capacity > int32_max(1TB) we are in 64bit environment
   1610   7563     Prasad 	 * so no truncation happens
   1611    786      lclee 	 */
   1612   3525   shidokht 	cl->cl_map[P0_RAW_DISK].dkl_nblk  = capacity;
   1613    786      lclee #endif
   1614    786      lclee 	/*
   1615    786      lclee 	 * Refresh the logical and physical geometry caches.
   1616    786      lclee 	 * (data from MODE SENSE format/rigid disk geometry pages,
   1617    786      lclee 	 * and scsi_ifgetcap("geometry").
   1618    786      lclee 	 */
   1619   3525   shidokht 	cmlb_resync_geom_caches(cl, capacity, tg_cookie);
   1620   3525   shidokht 
   1621   7563     Prasad 	cl->cl_label_from_media = CMLB_LABEL_UNDEF;
   1622   3525   shidokht 	label_error = cmlb_use_efi(cl, capacity, flags, tg_cookie);
   1623    786      lclee 	if (label_error == 0) {
   1624    786      lclee 
   1625    786      lclee 		/* found a valid EFI label */
   1626   3525   shidokht 		cmlb_dbg(CMLB_TRACE, cl,
   1627    786      lclee 		    "cmlb_validate_geometry: found EFI label\n");
   1628    786      lclee 		/*
   1629    786      lclee 		 * solaris_size and geometry_is_valid are set in
   1630    786      lclee 		 * cmlb_use_efi
   1631    786      lclee 		 */
   1632    786      lclee 		return (ENOTSUP);
   1633    786      lclee 	}
   1634    786      lclee 
   1635    786      lclee 	/* NO EFI label found */
   1636    786      lclee 
   1637   7563     Prasad 	if (capacity > CMLB_EXTVTOC_LIMIT) {
   1638    786      lclee 		if (label_error == ESRCH) {
   1639    786      lclee 			/*
   1640   7563     Prasad 			 * they've configured a LUN over 2TB, but used
   1641    786      lclee 			 * format.dat to restrict format's view of the
   1642   7563     Prasad 			 * capacity to be under 2TB in some earlier Solaris
   1643   7563     Prasad 			 * release.
   1644   7563     Prasad 			 */
   1645   7563     Prasad 			/* i.e > 2TB with a VTOC < 2TB */
   1646   7563     Prasad 			if (!(flags & CMLB_SILENT) &&
   1647   7563     Prasad 			    (cl->cl_msglog_flag & CMLB_ALLOW_2TB_WARN)) {
   1648   7563     Prasad 
   1649   3525   shidokht 				cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl),
   1650   7563     Prasad 				    CE_NOTE, "!Disk (%s%d) is limited to 2 TB "
   1651   7563     Prasad 				    "due to VTOC label. To use the full "
   1652   7563     Prasad 				    "capacity of the disk, use format(1M) to "
   1653   7563     Prasad 				    "relabel the disk with EFI/GPT label.\n",
   1654   7563     Prasad 				    CMLB_LABEL(cl),
   1655   7563     Prasad 				    ddi_get_instance(CMLB_DEVINFO(cl)));
   1656   7563     Prasad 
   1657   7563     Prasad 				cl->cl_msglog_flag &= ~CMLB_ALLOW_2TB_WARN;
   1658   7563     Prasad 			}
   1659   7563     Prasad 		} else {
   1660   3525   shidokht 				return (ENOTSUP);
   1661    786      lclee 		}
   1662    786      lclee 	}
   1663    786      lclee 
   1664    786      lclee 	label_error = 0;
   1665    786      lclee 
   1666    786      lclee 	/*
   1667    786      lclee 	 * at this point it is either labeled with a VTOC or it is
   1668   3525   shidokht 	 * under 1TB (<= 1TB actually for off-by-1)
   1669   3525   shidokht 	 */
   1670   3525   shidokht 
   1671   3525   shidokht 	/*
   1672   3525   shidokht 	 * Only DIRECT ACCESS devices will have Scl labels.
   1673   3525   shidokht 	 * CD's supposedly have a Scl label, too
   1674   3525   shidokht 	 */
   1675   3525   shidokht 	if (cl->cl_device_type == DTYPE_DIRECT || ISREMOVABLE(cl)) {
   1676    786      lclee 		struct	dk_label *dkl;
   1677    786      lclee 		offset_t label_addr;
   1678    786      lclee 		int	rval;
   1679    786      lclee 		size_t	buffer_size;
   1680    786      lclee 
   1681    786      lclee 		/*
   1682   3525   shidokht 		 * Note: This will set up cl->cl_solaris_size and
   1683   3525   shidokht 		 * cl->cl_solaris_offset.
   1684   3525   shidokht 		 */
   1685   3525   shidokht 		rval = cmlb_read_fdisk(cl, capacity, tg_cookie);
   1686   3525   shidokht 		if ((rval != 0) && !ISCD(cl)) {
   1687   3525   shidokht 			ASSERT(mutex_owned(CMLB_MUTEX(cl)));
   1688    786      lclee 			return (rval);
   1689    786      lclee 		}
   1690    786      lclee 
   1691   3525   shidokht 		if (cl->cl_solaris_size <= DK_LABEL_LOC) {
   1692    786      lclee 			/*
   1693    786      lclee 			 * Found fdisk table but no Solaris partition entry,
   1694    786      lclee 			 * so don't call cmlb_uselabel() and don't create
   1695    786      lclee 			 * a default label.
   1696    786      lclee 			 */
   1697    786      lclee 			label_error = 0;
   1698   8863     Edward 			cl->cl_f_geometry_is_valid = B_TRUE;
   1699    786      lclee 			goto no_solaris_partition;
   1700    786      lclee 		}
   1701    786      lclee 
   1702   3525   shidokht 		label_addr = (daddr_t)(cl->cl_solaris_offset + DK_LABEL_LOC);
   1703    786      lclee 
   1704   9889      Larry 		buffer_size = cl->cl_sys_blocksize;
   1705    786      lclee 
   1706   3525   shidokht 		cmlb_dbg(CMLB_TRACE, cl, "cmlb_validate_geometry: "
   1707    786      lclee 		    "label_addr: 0x%x allocation size: 0x%x\n",
   1708    786      lclee 		    label_addr, buffer_size);
   1709    786      lclee 
   1710    786      lclee 		if ((dkl = kmem_zalloc(buffer_size, KM_NOSLEEP)) == NULL)
   1711    786      lclee 			return (ENOMEM);
   1712    786      lclee 
   1713   3525   shidokht 		mutex_exit(CMLB_MUTEX(cl));
   1714   3525   shidokht 		rval = DK_TG_READ(cl, dkl, label_addr, buffer_size, tg_cookie);
   1715   3525   shidokht 		mutex_enter(CMLB_MUTEX(cl));
   1716    786      lclee 
   1717    786      lclee 		switch (rval) {
   1718    786      lclee 		case 0:
   1719    786      lclee 			/*
   1720    786      lclee 			 * cmlb_uselabel will establish that the geometry
   1721    786      lclee 			 * is valid.
   1722    786      lclee 			 */
   1723   3525   shidokht 			if (cmlb_uselabel(cl,
   1724   3525   shidokht 			    (struct dk_label *)(uintptr_t)dkl, flags) !=
   1725    786      lclee 			    CMLB_LABEL_IS_VALID) {
   1726    786      lclee 				label_error = EINVAL;
   1727    786      lclee 			} else
   1728   7563     Prasad 				cl->cl_label_from_media = CMLB_LABEL_VTOC;
   1729    786      lclee 			break;
   1730    786      lclee 		case EACCES:
   1731    786      lclee 			label_error = EACCES;
   1732    786      lclee 			break;
   1733    786      lclee 		default:
   1734    786      lclee 			label_error = EINVAL;
   1735    786      lclee 			break;
   1736    786      lclee 		}
   1737    786      lclee 
   1738    786      lclee 		kmem_free(dkl, buffer_size);
   1739    786      lclee 	}
   1740    786      lclee 
   1741    786      lclee 	/*
   1742    786      lclee 	 * If a valid label was not found, AND if no reservation conflict
   1743    786      lclee 	 * was detected, then go ahead and create a default label (4069506).
   1744    786      lclee 	 *
   1745    786      lclee 	 * Note: currently, for VTOC_8 devices, the default label is created
   1746   3525   shidokht 	 * for removables and hotpluggables only.  For VTOC_16 devices, the
   1747   3525   shidokht 	 * default label will be created for all devices.
   1748    786      lclee 	 * (see cmlb_build_default_label)
   1749    786      lclee 	 */
   1750    786      lclee #if defined(_SUNOS_VTOC_8)
   1751   3525   shidokht 	if ((ISREMOVABLE(cl) || ISHOTPLUGGABLE(cl)) &&
   1752   3525   shidokht 	    (label_error != EACCES)) {
   1753    786      lclee #elif defined(_SUNOS_VTOC_16)
   1754    786      lclee 	if (label_error != EACCES) {
   1755    786      lclee #endif
   1756   8863     Edward 		if (!cl->cl_f_geometry_is_valid) {
   1757   3525   shidokht 			cmlb_build_default_label(cl, tg_cookie);
   1758    786      lclee 		}
   1759    786      lclee 		label_error = 0;
   1760    786      lclee 	}
   1761    786      lclee 
   1762    786      lclee no_solaris_partition:
   1763    786      lclee 
   1764    786      lclee #if defined(_SUNOS_VTOC_16)
   1765    786      lclee 	/*
   1766    786      lclee 	 * If we have valid geometry, set up the remaining fdisk partitions.
   1767    786      lclee 	 * Note that dkl_cylno is not used for the fdisk map entries, so
   1768    786      lclee 	 * we set it to an entirely bogus value.
   1769    786      lclee 	 */
   1770  10021  Sheshadri 	for (count = 0; count < FDISK_PARTS; count++) {
   1771   7563     Prasad 		cl->cl_map[FDISK_P1 + count].dkl_cylno = UINT16_MAX;
   1772   3525   shidokht 		cl->cl_map[FDISK_P1 + count].dkl_nblk =
   1773   3525   shidokht 		    cl->cl_fmap[count].fmap_nblk;
   1774   3525   shidokht 
   1775   3525   shidokht 		cl->cl_offset[FDISK_P1 + count] =
   1776   3525   shidokht 		    cl->cl_fmap[count].fmap_start;
   1777    786      lclee 	}
   1778    786      lclee #endif
   1779    786      lclee 
   1780    786      lclee 	for (count = 0; count < NDKMAP; count++) {
   1781    786      lclee #if defined(_SUNOS_VTOC_8)
   1782   3525   shidokht 		struct dk_map *lp  = &cl->cl_map[count];
   1783   3525   shidokht 		cl->cl_offset[count] =
   1784   3525   shidokht 		    cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect * lp->dkl_cylno;
   1785   3525   shidokht #elif defined(_SUNOS_VTOC_16)
   1786   3525   shidokht 		struct dkl_partition *vp = &cl->cl_vtoc.v_part[count];
   1787   3525   shidokht 
   1788   3525   shidokht 		cl->cl_offset[count] = vp->p_start + cl->cl_solaris_offset;
   1789    786      lclee #else
   1790    786      lclee #error "No VTOC format defined."
   1791    786      lclee #endif
   1792    786      lclee 	}
   1793    786      lclee 
   1794    786      lclee 	return (label_error);
   1795    786      lclee }
   1796    786      lclee 
   1797    786      lclee #if defined(_SUNOS_VTOC_16)
   1798    786      lclee /*
   1799    786      lclee  *    Function: cmlb_convert_geometry
   1800    786      lclee  *
   1801    786      lclee  * Description: Convert physical geometry into a dk_geom structure. In
   1802    786      lclee  *		other words, make sure we don't wrap 16-bit values.
   1803    786      lclee  *		e.g. converting from geom_cache to dk_geom
   1804    786      lclee  *
   1805    786      lclee  *     Context: Kernel thread only
   1806    786      lclee  */
   1807    786      lclee static void
   1808  10320      Larry cmlb_convert_geometry(struct cmlb_lun *cl, diskaddr_t capacity,
   1809  10320      Larry     struct dk_geom *cl_g, void *tg_cookie)
   1810  10320      Larry {
   1811  10320      Larry 
   1812  10320      Larry 	ASSERT(cl != NULL);
   1813  10320      Larry 	ASSERT(mutex_owned(CMLB_MUTEX(cl)));
   1814    786      lclee 
   1815    786      lclee 	/* Unlabeled SCSI floppy device */
   1816    786      lclee 	if (capacity <= 0x1000) {
   1817   3525   shidokht 		cl_g->dkg_nhead = 2;
   1818   3525   shidokht 		cl_g->dkg_ncyl = 80;
   1819   3525   shidokht 		cl_g->dkg_nsect = capacity / (cl_g->dkg_nhead * cl_g->dkg_ncyl);
   1820    786      lclee 		return;
   1821    786      lclee 	}
   1822    786      lclee 
   1823    786      lclee 	/*
   1824   7563     Prasad 	 * For all devices we calculate cylinders using the heads and sectors
   1825   7563     Prasad 	 * we assign based on capacity of the device.  The algorithm is
   1826   7563     Prasad 	 * designed to be compatible with the way other operating systems
   1827   7563     Prasad 	 * lay out fdisk tables for X86 and to insure that the cylinders never
   1828   7563     Prasad 	 * exceed 65535 to prevent problems with X86 ioctls that report
   1829   7563     Prasad 	 * geometry.
   1830   7563     Prasad 	 * For some smaller disk sizes we report geometry that matches those
   1831   7563     Prasad 	 * used by X86 BIOS usage. For larger disks, we use SPT that are
   1832   7563     Prasad 	 * multiples of 63, since other OSes that are not limited to 16-bits
   1833   7563     Prasad 	 * for cylinders stop at 63 SPT we make do by using multiples of 63 SPT.
   1834   7563     Prasad 	 *
   1835   7563     Prasad 	 * The following table (in order) illustrates some end result
   1836   7563     Prasad 	 * calculations:
   1837   7563     Prasad 	 *
   1838   7563     Prasad 	 * Maximum number of blocks 		nhead	nsect
   1839   7563     Prasad 	 *
   1840   7563     Prasad 	 * 2097152 (1GB)			64	32
   1841   7563     Prasad 	 * 16777216 (8GB)			128	32
   1842   7563     Prasad 	 * 1052819775 (502.02GB)		255  	63
   1843   7563     Prasad 	 * 2105639550 (0.98TB)			255	126
   1844   7563     Prasad 	 * 3158459325 (1.47TB)			255  	189
   1845   7563     Prasad 	 * 4211279100 (1.96TB)			255  	252
   1846   7563     Prasad 	 * 5264098875 (2.45TB)			255  	315
   1847   7563     Prasad 	 * ...
   1848  10320      Larry 	 *
   1849  10320      Larry 	 * For Solid State Drive(SSD), it uses 4K page size inside and may be
   1850  10320      Larry 	 * double with every new generation. If the I/O is not aligned with
   1851  10320      Larry 	 * page size on SSDs, SSDs perform a lot slower.
   1852  10320      Larry 	 * By default, Solaris partition starts from cylinder 1. It will be
   1853  10320      Larry 	 * misaligned even with 4K if using heads(255) and SPT(63). To
   1854  10320      Larry 	 * workaround the problem, if the device is SSD, we use heads(224) and
   1855  10320      Larry 	 * SPT multiple of 56. Thus the default Solaris partition starts from
   1856  10320      Larry 	 * a position that aligns with 128K on a 512 bytes sector size SSD.
   1857   7563     Prasad 	 */
   1858   7563     Prasad 
   1859   7563     Prasad 	if (capacity <= 0x200000) {
   1860   7563     Prasad 		cl_g->dkg_nhead = 64;
   1861   7563     Prasad 		cl_g->dkg_nsect = 32;
   1862   7563     Prasad 	} else if (capacity <= 0x01000000) {
   1863   7563     Prasad 		cl_g->dkg_nhead = 128;
   1864   7563     Prasad 		cl_g->dkg_nsect = 32;
   1865   7563     Prasad 	} else {
   1866  10320      Larry 		tg_attribute_t tgattribute;
   1867  10320      Larry 		int is_solid_state;
   1868  10320      Larry 		unsigned short nhead;
   1869  10320      Larry 		unsigned short nsect;
   1870  10320      Larry 
   1871  10320      Larry 		bzero(&tgattribute, sizeof (tg_attribute_t));
   1872  10320      Larry 
   1873  10320      Larry 		mutex_exit(CMLB_MUTEX(cl));
   1874  10320      Larry 		is_solid_state =
   1875  10320      Larry 		    (DK_TG_GETATTRIBUTE(cl, &tgattribute, tg_cookie) == 0) ?
   1876  10320      Larry 		    tgattribute.media_is_solid_state : FALSE;
   1877  10320      Larry 		mutex_enter(CMLB_MUTEX(cl));
   1878  10320      Larry 
   1879  10320      Larry 		if (is_solid_state) {
   1880  10320      Larry 			nhead = 224;
   1881  10320      Larry 			nsect = 56;
   1882  10320      Larry 		} else {
   1883  10320      Larry 			nhead = 255;
   1884  10320      Larry 			nsect = 63;
   1885  10320      Larry 		}
   1886  10320      Larry 
   1887  10320      Larry 		cl_g->dkg_nhead = nhead;
   1888  10320      Larry 
   1889  10320      Larry 		/* make nsect be smallest multiple of nhead */
   1890   7563     Prasad 		cl_g->dkg_nsect = ((capacity +
   1891  10320      Larry 		    (UINT16_MAX * nhead * nsect) - 1) /
   1892  10320      Larry 		    (UINT16_MAX * nhead * nsect)) * nsect;
   1893   7563     Prasad 
   1894   7563     Prasad 		if (cl_g->dkg_nsect == 0)
   1895  10320      Larry 			cl_g->dkg_nsect = (UINT16_MAX / nsect) * nsect;
   1896   7563     Prasad 	}
   1897   7563     Prasad 
   1898    786      lclee }
   1899    786      lclee #endif
   1900    786      lclee 
   1901    786      lclee /*
   1902    786      lclee  *    Function: cmlb_resync_geom_caches
   1903    786      lclee  *
   1904    786      lclee  * Description: (Re)initialize both geometry caches: the virtual geometry
   1905    786      lclee  *            information is extracted from the HBA (the "geometry"
   1906    786      lclee  *            capability), and the physical geometry cache data is
   1907    786      lclee  *            generated by issuing MODE SENSE commands.
   1908    786      lclee  *
   1909   3525   shidokht  *   Arguments:
   1910   3525   shidokht  *	cl 		driver soft state (unit) structure
   1911   3525   shidokht  *	capacity	disk capacity in #blocks
   1912   3525   shidokht  *	tg_cookie	cookie from target driver to be passed back to target
   1913   3525   shidokht  *			driver when we call back to it through tg_ops.
   1914    786      lclee  *
   1915    786      lclee  *     Context: Kernel thread only (can sleep).
   1916    786      lclee  */
   1917    786      lclee static void
   1918   3525   shidokht cmlb_resync_geom_caches(struct cmlb_lun *cl, diskaddr_t capacity,
   1919   3525   shidokht     void *tg_cookie)
   1920    786      lclee {
   1921    786      lclee 	struct	cmlb_geom 	pgeom;
   1922    786      lclee 	struct	cmlb_geom	lgeom;
   1923    786      lclee 	struct 	cmlb_geom	*pgeomp = &pgeom;
   1924    786      lclee 	unsigned short 		nhead;
   1925    786      lclee 	unsigned short 		nsect;
   1926    786      lclee 	int 			spc;
   1927    786      lclee 	int			ret;
   1928    786      lclee 
   1929   3525   shidokht 	ASSERT(cl != NULL);
   1930   3525   shidokht 	ASSERT(mutex_owned(CMLB_MUTEX(cl)));
   1931    786      lclee 
   1932    786      lclee 	/*
   1933    786      lclee 	 * Ask the controller for its logical geometry.
   1934    786      lclee 	 * Note: if the HBA does not support scsi_ifgetcap("geometry"),
   1935    786      lclee 	 * then the lgeom cache will be invalid.
   1936    786      lclee 	 */
   1937   3525   shidokht 	mutex_exit(CMLB_MUTEX(cl));
   1938    786      lclee 	bzero(&lgeom, sizeof (struct cmlb_geom));
   1939   3525   shidokht 	ret = DK_TG_GETVIRTGEOM(cl, &lgeom, tg_cookie);
   1940   3525   shidokht 	mutex_enter(CMLB_MUTEX(cl));
   1941   3525   shidokht 
   1942   3525   shidokht 	bcopy(&lgeom, &cl->cl_lgeom, sizeof (cl->cl_lgeom));
   1943    786      lclee 
   1944    786      lclee 	/*
   1945    786      lclee 	 * Initialize the pgeom cache from lgeom, so that if MODE SENSE
   1946    786      lclee 	 * doesn't work, DKIOCG_PHYSGEOM can return reasonable values.
   1947    786      lclee 	 */
   1948   3525   shidokht 	if (ret != 0 || cl->cl_lgeom.g_nsect == 0 ||
   1949   3525   shidokht 	    cl->cl_lgeom.g_nhead == 0) {
   1950    786      lclee 		/*
   1951    786      lclee 		 * Note: Perhaps this needs to be more adaptive? The rationale
   1952    786      lclee 		 * is that, if there's no HBA geometry from the HBA driver, any
   1953    786      lclee 		 * guess is good, since this is the physical geometry. If MODE
   1954    786      lclee 		 * SENSE fails this gives a max cylinder size for non-LBA access
   1955    786      lclee 		 */
   1956    786      lclee 		nhead = 255;
   1957    786      lclee 		nsect = 63;
   1958    786      lclee 	} else {
   1959   3525   shidokht 		nhead = cl->cl_lgeom.g_nhead;
   1960   3525   shidokht 		nsect = cl->cl_lgeom.g_nsect;
   1961   3525   shidokht 	}
   1962   3525   shidokht 
   1963   3525   shidokht 	if (ISCD(cl)) {
   1964    786      lclee 		pgeomp->g_nhead = 1;
   1965    786      lclee 		pgeomp->g_nsect = nsect * nhead;
   1966    786      lclee 	} else {
   1967    786      lclee 		pgeomp->g_nhead = nhead;
   1968    786      lclee 		pgeomp->g_nsect = nsect;
   1969    786      lclee 	}
   1970    786      lclee 
   1971    786      lclee 	spc = pgeomp->g_nhead * pgeomp->g_nsect;
   1972    786      lclee 	pgeomp->g_capacity = capacity;
   1973   9811  Sheshadri 	if (spc == 0)
   1974   9811  Sheshadri 		pgeomp->g_ncyl = 0;
   1975   9811  Sheshadri 	else
   1976   9811  Sheshadri 		pgeomp->g_ncyl = pgeomp->g_capacity / spc;
   1977    786      lclee 	pgeomp->g_acyl = 0;
   1978    786      lclee 
   1979    786      lclee 	/*
   1980    786      lclee 	 * Retrieve fresh geometry data from the hardware, stash it
   1981    786      lclee 	 * here temporarily before we rebuild the incore label.
   1982    786      lclee 	 *
   1983    786      lclee 	 * We want to use the MODE SENSE commands to derive the
   1984    786      lclee 	 * physical geometry of the device, but if either command
   1985    786      lclee 	 * fails, the logical geometry is used as the fallback for
   1986    786      lclee 	 * disk label geometry.
   1987    786      lclee 	 */
   1988    786      lclee 
   1989   3525   shidokht 	mutex_exit(CMLB_MUTEX(cl));
   1990   3525   shidokht 	(void) DK_TG_GETPHYGEOM(cl, pgeomp, tg_cookie);
   1991   3525   shidokht 	mutex_enter(CMLB_MUTEX(cl));
   1992    786      lclee 
   1993    786      lclee 	/*
   1994    786      lclee 	 * Now update the real copy while holding the mutex. This
   1995    786      lclee 	 * way the global copy is never in an inconsistent state.
   1996    786      lclee 	 */
   1997   3525   shidokht 	bcopy(pgeomp, &cl->cl_pgeom,  sizeof (cl->cl_pgeom));
   1998   3525   shidokht 
   1999   3525   shidokht 	cmlb_dbg(CMLB_INFO, cl, "cmlb_resync_geom_caches: "
   2000    786      lclee 	    "(cached from lgeom)\n");
   2001   3525   shidokht 	cmlb_dbg(CMLB_INFO,  cl,
   2002    786      lclee 	    "   ncyl: %ld; acyl: %d; nhead: %d; nsect: %d\n",
   2003   3525   shidokht 	    cl->cl_pgeom.g_ncyl, cl->cl_pgeom.g_acyl,
   2004   3525   shidokht 	    cl->cl_pgeom.g_nhead, cl->cl_pgeom.g_nsect);
   2005   3525   shidokht 	cmlb_dbg(CMLB_INFO,  cl, "   lbasize: %d; capacity: %ld; "
   2006   3525   shidokht 	    "intrlv: %d; rpm: %d\n", cl->cl_pgeom.g_secsize,
   2007   3525   shidokht 	    cl->cl_pgeom.g_capacity, cl->cl_pgeom.g_intrlv,
   2008   3525   shidokht 	    cl->cl_pgeom.g_rpm);
   2009    786      lclee }
   2010    786      lclee 
   2011    786      lclee 
   2012  10021  Sheshadri #if defined(__i386) || defined(__amd64)
   2013  10021  Sheshadri /*
   2014  10021  Sheshadri  *    Function: cmlb_update_ext_minor_nodes
   2015  10021  Sheshadri  *
   2016  10021  Sheshadri  * Description: Routine to add/remove extended partition device nodes
   2017  10021  Sheshadri  *
   2018  10021  Sheshadri  *   Arguments:
   2019  10021  Sheshadri  *	cl		driver soft state (unit) structure
   2020  10021  Sheshadri  *	num_parts	Number of logical drives found on the LUN
   2021  10021  Sheshadri  *
   2022  10021  Sheshadri  * Should be called with the mutex held
   2023  10021  Sheshadri  *
   2024  10021  Sheshadri  * Return Code: 0 for success
   2025  10021  Sheshadri  *
   2026  10021  Sheshadri  *     Context: User and Kernel thread
   2027  10021  Sheshadri  *
   2028  10021  Sheshadri  */
   2029  10021  Sheshadri static int
   2030  10021  Sheshadri cmlb_update_ext_minor_nodes(struct cmlb_lun *cl, int num_parts)
   2031  10021  Sheshadri {
   2032  10021  Sheshadri 	int				i, count;
   2033  10021  Sheshadri 	char				name[48];
   2034  10021  Sheshadri 	int				instance;
   2035  10021  Sheshadri 	struct driver_minor_data	*demdp, *demdpr;
   2036  10021  Sheshadri 	char				*devnm;
   2037  10021  Sheshadri 	dev_info_t			*pdip;
   2038  10021  Sheshadri 	boolean_t 			internal;
   2039  10021  Sheshadri 
   2040  10021  Sheshadri 	ASSERT(mutex_owned(CMLB_MUTEX(cl)));
   2041  10021  Sheshadri 	ASSERT(cl->cl_update_ext_minor_nodes == 1);
   2042  10021  Sheshadri 
   2043  10021  Sheshadri 	internal = VOID2BOOLEAN(
   2044  10021  Sheshadri 	    (cl->cl_alter_behavior & (CMLB_INTERNAL_MINOR_NODES)) != 0);
   2045  10021  Sheshadri 	instance = ddi_get_instance(CMLB_DEVINFO(cl));
   2046  10021  Sheshadri 	demdp = dk_ext_minor_data;
   2047  10021  Sheshadri 	demdpr = &dk_ext_minor_data[MAX_EXT_PARTS];
   2048  10021  Sheshadri 
   2049  10021  Sheshadri 
   2050  10021  Sheshadri 	if (cl->cl_logical_drive_count) {
   2051  10021  Sheshadri 		for (i = 0; i < cl->cl_logical_drive_count; i++) {
   2052  10021  Sheshadri 			(void) sprintf(name, "%s", demdp->name);
   2053  10021  Sheshadri 			ddi_remove_minor_node(CMLB_DEVINFO(cl), name);
   2054  10021  Sheshadri 			(void) sprintf(name, "%s", demdpr->name);
   2055  10021  Sheshadri 			ddi_remove_minor_node(CMLB_DEVINFO(cl), name);
   2056  10021  Sheshadri 			demdp++;
   2057  10021  Sheshadri 			demdpr++;
   2058  10021  Sheshadri 		}
   2059  10021  Sheshadri 		/* There are existing device nodes. Remove them */
   2060  10021  Sheshadri 		devnm = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
   2061  10021  Sheshadri 		(void) ddi_deviname(cl->cl_devi, devnm);
   2062  10021  Sheshadri 		pdip = ddi_get_parent(cl->cl_devi);
   2063  10021  Sheshadri 		(void) devfs_clean(pdip, devnm + 1, DV_CLEAN_FORCE);
   2064  10021  Sheshadri 		kmem_free(devnm, MAXNAMELEN + 1);
   2065  10021  Sheshadri 	}
   2066  10021  Sheshadri 
   2067  10021  Sheshadri 	demdp = dk_ext_minor_data;
   2068  10021  Sheshadri 	demdpr = &dk_ext_minor_data[MAX_EXT_PARTS];
   2069  10021  Sheshadri 
   2070  10021  Sheshadri 	for (i = 0; i < num_parts; i++) {
   2071  10021  Sheshadri 		(void) sprintf(name, "%s", demdp->name);
   2072  10021  Sheshadri 		if (cmlb_create_minor(CMLB_DEVINFO(cl), name,
   2073  10021  Sheshadri 		    demdp->type,
   2074  10021  Sheshadri 		    (instance << CMLBUNIT_SHIFT) | demdp->minor,
   2075  10021  Sheshadri 		    cl->cl_node_type, NULL, internal) == DDI_FAILURE) {
   2076  10021  Sheshadri 			/*
   2077  10021  Sheshadri 			 * Clean up any nodes that may have been
   2078  10021  Sheshadri 			 * created, in case this fails in the middle
   2079  10021  Sheshadri 			 * of the loop.
   2080  10021  Sheshadri 			 */
   2081  10021  Sheshadri 			ddi_remove_minor_node(CMLB_DEVINFO(cl), NULL);
   2082  10021  Sheshadri 			cl->cl_logical_drive_count = 0;
   2083  10021  Sheshadri 			return (ENXIO);
   2084  10021  Sheshadri 		}
   2085  10021  Sheshadri 		(void) sprintf(name, "%s", demdpr->name);
   2086  10021  Sheshadri 		if (ddi_create_minor_node(CMLB_DEVINFO(cl), name,
   2087  10021  Sheshadri 		    demdpr->type,
   2088  10021  Sheshadri 		    (instance << CMLBUNIT_SHIFT) | demdpr->minor,
   2089  10021  Sheshadri 		    cl->cl_node_type, NULL) == DDI_FAILURE) {
   2090  10021  Sheshadri 			/*
   2091  10021  Sheshadri 			 * Clean up any nodes that may have been
   2092  10021  Sheshadri 			 * created, in case this fails in the middle
   2093  10021  Sheshadri 			 * of the loop.
   2094  10021  Sheshadri 			 */
   2095  10021  Sheshadri 			ddi_remove_minor_node(CMLB_DEVINFO(cl), NULL);
   2096  10021  Sheshadri 			cl->cl_logical_drive_count = 0;
   2097  10021  Sheshadri 			return (ENXIO);
   2098  10021  Sheshadri 		}
   2099  10021  Sheshadri 		demdp++;
   2100  10021  Sheshadri 		demdpr++;
   2101  10021  Sheshadri 	}
   2102  10021  Sheshadri 
   2103  10021  Sheshadri 	/* Update the cl_map array for logical drives */
   2104  10021  Sheshadri 	for (count = 0; count < MAX_EXT_PARTS; count++) {
   2105  10021  Sheshadri 		cl->cl_map[FDISK_P4 + 1 + count].dkl_cylno = UINT32_MAX;
   2106  10021  Sheshadri 		cl->cl_map[FDISK_P4 + 1 + count].dkl_nblk =
   2107  10021  Sheshadri 		    cl->cl_fmap[FD_NUMPART + count].fmap_nblk;
   2108  10021  Sheshadri 		cl->cl_offset[FDISK_P4 + 1 + count] =
   2109  10021  Sheshadri 		    cl->cl_fmap[FD_NUMPART + count].fmap_start;
   2110  10021  Sheshadri 	}
   2111  10021  Sheshadri 
   2112  10021  Sheshadri 	cl->cl_logical_drive_count = i;
   2113  10021  Sheshadri 	cl->cl_update_ext_minor_nodes = 0;
   2114  10021  Sheshadri 	return (0);
   2115  10021  Sheshadri }
   2116  10021  Sheshadri /*
   2117  10021  Sheshadri  *    Function: cmlb_validate_ext_part
   2118  10021  Sheshadri  *
   2119  10021  Sheshadri  * Description: utility routine to validate an extended partition's
   2120  10021  Sheshadri  *		metadata as found on disk
   2121  10021  Sheshadri  *
   2122  10021  Sheshadri  *   Arguments:
   2123  10021  Sheshadri  *	cl		driver soft state (unit) structure
   2124  10021  Sheshadri  *	part		partition number of the extended partition
   2125  10021  Sheshadri  *	epart		partition number of the logical drive
   2126  10021  Sheshadri  *	start		absolute sector number of the start of the logical
   2127  10021  Sheshadri  *			drive being validated
   2128  10021  Sheshadri  *	size		size of logical drive being validated
   2129  10021  Sheshadri  *
   2130  10021  Sheshadri  * Return Code: 0 for success
   2131  10021  Sheshadri  *
   2132  10021  Sheshadri  *     Context: User and Kernel thread
   2133  10021  Sheshadri  *
   2134  10021  Sheshadri  * Algorithm :
   2135  10021  Sheshadri  * Error cases are :
   2136  10021  Sheshadri  *	1. If start block is lesser than or equal to the end block
   2137  10021  Sheshadri  *	2. If either start block or end block is beyond the bounadry
   2138  10021  Sheshadri  *	   of the extended partition.
   2139  10021  Sheshadri  *	3. start or end block overlap with existing partitions.
   2140  10021  Sheshadri  *		To check this, first make sure that the start block doesnt
   2141  10021  Sheshadri  *		overlap with existing partitions. Then, calculate the
   2142  10021  Sheshadri  *		possible end block for the given start block that doesnt
   2143  10021  Sheshadri  *		overlap with existing partitions. This can be calculated by
   2144  10021  Sheshadri  *		first setting the possible end block to the end of the
   2145  10021  Sheshadri  *		extended partition (optimistic) and then, checking if there
   2146  10021  Sheshadri  *		is any other partition that lies after the start of the
   2147  10021  Sheshadri  *		partition being validated. If so, set the possible end to
   2148  10021  Sheshadri  *		one block less than the beginning of the next nearest partition
   2149  10021  Sheshadri  *		If the actual end block is greater than the calculated end
   2150  10021  Sheshadri  *		block, we have an overlap.
   2151  10021  Sheshadri  *
   2152  10021  Sheshadri  */
   2153  10021  Sheshadri static int
   2154  10021  Sheshadri cmlb_validate_ext_part(struct cmlb_lun *cl, int part, int epart, uint32_t start,
   2155  10021  Sheshadri     uint32_t size)
   2156  10021  Sheshadri {
   2157  10021  Sheshadri 	int i;
   2158  10021  Sheshadri 	uint32_t end = start + size - 1;
   2159  10021  Sheshadri 	uint32_t ext_start = cl->cl_fmap[part].fmap_start;
   2160  10021  Sheshadri 	uint32_t ext_end = ext_start + cl->cl_fmap[part].fmap_nblk - 1;
   2161  10021  Sheshadri 	uint32_t ts, te;
   2162  10021  Sheshadri 	uint32_t poss_end = ext_end;
   2163  10021  Sheshadri 
   2164  10021  Sheshadri 	if (end <= start) {
   2165  10021  Sheshadri 		return (1);
   2166  10021  Sheshadri 	}
   2167  10021  Sheshadri 
   2168  10021  Sheshadri 	/*
   2169  10021  Sheshadri 	 * Check if the logical drive boundaries are within that of the
   2170  10021  Sheshadri 	 * extended partition.
   2171  10021  Sheshadri 	 */
   2172  10021  Sheshadri 	if (start <= ext_start || start > ext_end || end <= ext_start ||
   2173  10021  Sheshadri 	    end > ext_end) {
   2174  10021  Sheshadri 		return (1);
   2175  10021  Sheshadri 	}
   2176  10021  Sheshadri 
   2177  10021  Sheshadri 	/*
   2178  10021  Sheshadri 	 * epart will be equal to FD_NUMPART if it is the first logical drive.
   2179  10021  Sheshadri 	 * There is no need to check for overlaps with other logical drives,
   2180  10021  Sheshadri 	 * since it is the only logical drive that we have come across so far.
   2181  10021  Sheshadri 	 */
   2182  10021  Sheshadri 	if (epart == FD_NUMPART) {
   2183  10021  Sheshadri 		return (0);
   2184  10021  Sheshadri 	}
   2185  10021  Sheshadri 
   2186  10021  Sheshadri 	/* Check for overlaps with existing logical drives */
   2187  10021  Sheshadri 	i = FD_NUMPART;
   2188  10021  Sheshadri 	ts = cl->cl_fmap[FD_NUMPART].fmap_start;
   2189  10021  Sheshadri 	te = ts + cl->cl_fmap[FD_NUMPART].fmap_nblk - 1;
   2190  10021  Sheshadri 
   2191  10021  Sheshadri 	while ((i < epart) && ts && te) {
   2192  10021  Sheshadri 		if (start >= ts && start <= te) {
   2193  10021  Sheshadri 			return (1);
   2194  10021  Sheshadri 		}
   2195  10021  Sheshadri 
   2196  10021  Sheshadri 		if ((ts < poss_end) && (ts > start)) {
   2197  10021  Sheshadri 			poss_end = ts - 1;
   2198  10021  Sheshadri 		}
   2199  10021  Sheshadri 
   2200  10021  Sheshadri 		i++;
   2201  10021  Sheshadri 		ts = cl->cl_fmap[i].fmap_start;
   2202  10021  Sheshadri 		te = ts + cl->cl_fmap[i].fmap_nblk - 1;
   2203  10021  Sheshadri 	}
   2204  10021  Sheshadri 
   2205  10021  Sheshadri 	if (end > poss_end) {
   2206  10021  Sheshadri 		return (1);
   2207  10021  Sheshadri 	}
   2208  10021  Sheshadri 
   2209  10021  Sheshadri 	return (0);
   2210  10021  Sheshadri }
   2211  10021  Sheshadri 
   2212  10021  Sheshadri 
   2213  10021  Sheshadri /*
   2214  10021  Sheshadri  *    Function: cmlb_is_linux_swap
   2215  10021  Sheshadri  *
   2216  10021  Sheshadri  * Description: utility routine to verify if a partition is a linux swap
   2217  10021  Sheshadri  *		partition or not.
   2218  10021  Sheshadri  *
   2219  10021  Sheshadri  *   Arguments:
   2220  10021  Sheshadri  *	cl		driver soft state (unit) structure
   2221  10021  Sheshadri  *	part_start	absolute sector number of the start of the partition
   2222  10021  Sheshadri  *			being verified
   2223  10021  Sheshadri  *	tg_cookie	cookie from target driver to be passed back to target
   2224  10021  Sheshadri  *			driver when we call back to it through tg_ops.
   2225  10021  Sheshadri  *
   2226  10021  Sheshadri  * Return Code: 0 for success
   2227  10021  Sheshadri  *
   2228  10021  Sheshadri  *     Context: User and Kernel thread
   2229  10021  Sheshadri  *
   2230  10021  Sheshadri  * Notes:
   2231  10021  Sheshadri  *	The linux swap magic "SWAP-SPACE" or "SWAPSPACE2" is found as the
   2232  10021  Sheshadri  *	last 10 bytes of a disk block whose size is that of the linux page
   2233  10021  Sheshadri  *	size. This disk block is found at the beginning of the swap partition.
   2234  10021  Sheshadri  */
   2235  10021  Sheshadri static int
   2236  10021  Sheshadri cmlb_is_linux_swap(struct cmlb_lun *cl, uint32_t part_start, void *tg_cookie)
   2237  10021  Sheshadri {
   2238  10021  Sheshadri 	int		i;
   2239  10021  Sheshadri 	int		rval = -1;
   2240  10021  Sheshadri 	uint32_t	seek_offset;
   2241  10021  Sheshadri 	uint32_t	linux_pg_size;
   2242  10021  Sheshadri 	char 		*buf, *linux_swap_magic;
   2243  10021  Sheshadri 	int		sec_sz = cl->cl_sys_blocksize;
   2244  10021  Sheshadri 	/* Known linux kernel page sizes */
   2245  10021  Sheshadri 	uint32_t	linux_pg_size_arr[] = {4096, };
   2246  10021  Sheshadri 
   2247  10021  Sheshadri 	ASSERT(cl != NULL);
   2248  10021  Sheshadri 	ASSERT(mutex_owned(CMLB_MUTEX(cl)));
   2249  10021  Sheshadri 
   2250  10021  Sheshadri 	if ((buf = kmem_zalloc(sec_sz, KM_NOSLEEP)) == NULL) {
   2251  10021  Sheshadri 		return (ENOMEM);
   2252  10021  Sheshadri 	}
   2253  10021  Sheshadri 
   2254  10682  Sheshadri 	/*
   2255  10682  Sheshadri 	 * Check if there is a sane Solaris VTOC
   2256  10682  Sheshadri 	 * If there is a valid vtoc, no need to lookup
   2257  10682  Sheshadri 	 * for the linux swap signature.
   2258  10682  Sheshadri 	 */
   2259  10682  Sheshadri 	mutex_exit(CMLB_MUTEX(cl));
   2260  10682  Sheshadri 	rval = DK_TG_READ(cl, buf, part_start + DK_LABEL_LOC,
   2261  10682  Sheshadri 	    sec_sz, tg_cookie);
   2262  10682  Sheshadri 	mutex_enter(CMLB_MUTEX(cl));
   2263  10682  Sheshadri 	if (rval != 0) {
   2264  10682  Sheshadri 		cmlb_dbg(CMLB_ERROR,  cl,
   2265  10682  Sheshadri 		    "cmlb_is_linux_swap: disk vtoc read err\n");
   2266  10682  Sheshadri 		rval = EIO;
   2267  10682  Sheshadri 		goto done;
   2268  10682  Sheshadri 	}
   2269  10682  Sheshadri 
   2270  10682  Sheshadri 	if ((((struct dk_label *)buf)->dkl_magic == DKL_MAGIC) &&
   2271  10682  Sheshadri 	    (((struct dk_label *)buf)->dkl_vtoc.v_sanity == VTOC_SANE)) {
   2272  10682  Sheshadri 		rval = -1;
   2273  10682  Sheshadri 		goto done;
   2274  10682  Sheshadri 	}
   2275  10682  Sheshadri 
   2276  10682  Sheshadri 
   2277  10682  Sheshadri 	/* No valid vtoc, so check for linux swap signature */
   2278  10021  Sheshadri 	linux_swap_magic = buf + sec_sz - 10;
   2279  10021  Sheshadri 
   2280  10021  Sheshadri 	for (i = 0; i < sizeof (linux_pg_size_arr)/sizeof (uint32_t); i++) {
   2281  10021  Sheshadri 		linux_pg_size = linux_pg_size_arr[i];
   2282  10021  Sheshadri 		seek_offset = linux_pg_size/sec_sz - 1;
   2283  10021  Sheshadri 		seek_offset += part_start;
   2284  10021  Sheshadri 
   2285  10021  Sheshadri 		mutex_exit(CMLB_MUTEX(cl));
   2286  10021  Sheshadri 		rval = DK_TG_READ(cl, buf, seek_offset, sec_sz, tg_cookie);
   2287  10021  Sheshadri 		mutex_enter(CMLB_MUTEX(cl));
   2288  10021  Sheshadri 
   2289  10021  Sheshadri 		if (rval != 0) {
   2290  10021  Sheshadri 			cmlb_dbg(CMLB_ERROR,  cl,
   2291  10021  Sheshadri 			    "cmlb_is_linux_swap: disk read err\n");
   2292  10021  Sheshadri 			rval = EIO;
   2293  10021  Sheshadri 			break;
   2294  10021  Sheshadri 		}
   2295  10021  Sheshadri 
   2296  10021  Sheshadri 		rval = -1;
   2297  10021  Sheshadri 
   2298  10021  Sheshadri 		if ((strncmp(linux_swap_magic, "SWAP-SPACE", 10) == 0) ||
   2299  10021  Sheshadri 		    (strncmp(linux_swap_magic, "SWAPSPACE2", 10) == 0)) {
   2300  10021  Sheshadri 			/* Found a linux swap */
   2301  10021  Sheshadri 			rval = 0;
   2302  10021  Sheshadri 			break;
   2303  10021  Sheshadri 		}
   2304  10021  Sheshadri 	}
   2305  10021  Sheshadri 
   2306  10682  Sheshadri done:
   2307  10021  Sheshadri 	kmem_free(buf, sec_sz);
   2308  10021  Sheshadri 	return (rval);
   2309  10021  Sheshadri }
   2310  10021  Sheshadri #endif
   2311  10021  Sheshadri 
   2312    786      lclee /*
   2313    786      lclee  *    Function: cmlb_read_fdisk
   2314    786      lclee  *
   2315    786      lclee  * Description: utility routine to read the fdisk table.
   2316    786      lclee  *
   2317   3525   shidokht  *   Arguments:
   2318   3525   shidokht  *	cl		driver soft state (unit) structure
   2319   3525   shidokht  *	capacity	disk capacity in #blocks
   2320   3525   shidokht  *	tg_cookie	cookie from target driver to be passed back to target
   2321   3525   shidokht  *			driver when we call back to it through tg_ops.
   2322    786      lclee  *
   2323    786      lclee  * Return Code: 0 for success (includes not reading for no_fdisk_present case
   2324    786      lclee  *		errnos from tg_rw if failed to read the first block.
   2325    786      lclee  *
   2326    786      lclee  *     Context: Kernel thread only (can sleep).
   2327    786      lclee  */
   2328   3525   shidokht /*ARGSUSED*/
   2329   3525   shidokht static int
   2330   3525   shidokht cmlb_read_fdisk(struct cmlb_lun *cl, diskaddr_t capacity, void *tg_cookie)
   2331    786      lclee {
   2332    786      lclee #if defined(_NO_FDISK_PRESENT)
   2333    786      lclee 
   2334   3525   shidokht 	cl->cl_solaris_offset = 0;
   2335   3525   shidokht 	cl->cl_solaris_size = capacity;
   2336   3525   shidokht 	bzero(cl->cl_fmap, sizeof (struct fmap) * FD_NUMPART);
   2337    786      lclee 	return (0);
   2338    786      lclee 
   2339    786      lclee #elif defined(_FIRMWARE_NEEDS_FDISK)
   2340    786      lclee 
   2341    786      lclee 	struct ipart	*fdp;
   2342    786      lclee 	struct mboot	*mbp;
   2343    786      lclee 	struct ipart	fdisk[FD_NUMPART];
   2344  10021  Sheshadri 	int		i, k;
   2345    786      lclee 	char		sigbuf[2];
   2346    786      lclee 	caddr_t		bufp;
   2347    786      lclee 	int		uidx;
   2348    786      lclee 	int 		rval;
   2349    786      lclee 	int		lba = 0;
   2350    786      lclee 	uint_t		solaris_offset;	/* offset to solaris part. */
   2351    786      lclee 	daddr_t		solaris_size;	/* size of solaris partition */
   2352    786      lclee 	uint32_t	blocksize;
   2353  10021  Sheshadri #if defined(__i386) || defined(__amd64)
   2354  10021  Sheshadri 	struct ipart	eparts[2];
   2355  10021  Sheshadri 	struct ipart	*efdp1 = &eparts[0];
   2356  10021  Sheshadri 	struct ipart	*efdp2 = &eparts[1];
   2357  10021  Sheshadri 	int		ext_part_exists = 0;
   2358  10021  Sheshadri 	int		ld_count = 0;
   2359  10021  Sheshadri #endif
   2360    786      lclee 
   2361   3525   shidokht 	ASSERT(cl != NULL);
   2362   3525   shidokht 	ASSERT(mutex_owned(CMLB_MUTEX(cl)));
   2363    786      lclee 
   2364    786      lclee 	/*
   2365    786      lclee 	 * Start off assuming no fdisk table
   2366    786      lclee 	 */
   2367    786      lclee 	solaris_offset = 0;
   2368    786      lclee 	solaris_size   = capacity;
   2369    786      lclee 
   2370   3525   shidokht 	blocksize = cl->cl_tgt_blocksize;
   2371    786      lclee 
   2372    786      lclee 	bufp = kmem_zalloc(blocksize, KM_SLEEP);
   2373    786      lclee 
   2374   3525   shidokht 	mutex_exit(CMLB_MUTEX(cl));
   2375   3525   shidokht 	rval = DK_TG_READ(cl, bufp, 0, blocksize, tg_cookie);
   2376   3525   shidokht 	mutex_enter(CMLB_MUTEX(cl));
   2377   3525   shidokht 
   2378   3525   shidokht 	if (rval != 0) {
   2379   3525   shidokht 		cmlb_dbg(CMLB_ERROR,  cl,
   2380    786      lclee 		    "cmlb_read_fdisk: fdisk read err\n");
   2381   3525   shidokht 		bzero(cl->cl_fmap, sizeof (struct fmap) * FD_NUMPART);
   2382   3525   shidokht 		goto done;
   2383    786      lclee 	}
   2384    786      lclee 
   2385    786      lclee 	mbp = (struct mboot *)bufp;
   2386    786      lclee 
   2387    786      lclee 	/*
   2388    786      lclee 	 * The fdisk table does not begin on a 4-byte boundary within the
   2389    786      lclee 	 * master boot record, so we copy it to an aligned structure to avoid
   2390    786      lclee 	 * alignment exceptions on some processors.
   2391    786      lclee 	 */
   2392    786      lclee 	bcopy(&mbp->parts[0], fdisk, sizeof (fdisk));
   2393    786      lclee 
   2394    786      lclee 	/*
   2395    786      lclee 	 * Check for lba support before verifying sig; sig might not be
   2396    786      lclee 	 * there, say on a blank disk, but the max_chs mark may still
   2397    786      lclee 	 * be present.
   2398    786      lclee 	 *
   2399    786      lclee 	 * Note: LBA support and BEFs are an x86-only concept but this
   2400    786      lclee 	 * code should work OK on SPARC as well.
   2401    786      lclee 	 */
   2402    786      lclee 
   2403    786      lclee 	/*
   2404    786      lclee 	 * First, check for lba-access-ok on root node (or prom root node)
   2405    786      lclee 	 * if present there, don't need to search fdisk table.
   2406    786      lclee 	 */
   2407    786      lclee 	if (ddi_getprop(DDI_DEV_T_ANY, ddi_root_node(), 0,
   2408    786      lclee 	    "lba-access-ok", 0) != 0) {
   2409    786      lclee 		/* All drives do LBA; don't search fdisk table */
   2410    786      lclee 		lba = 1;
   2411    786      lclee 	} else {
   2412    786      lclee 		/* Okay, look for mark in fdisk table */
   2413    786      lclee 		for (fdp = fdisk, i = 0; i < FD_NUMPART; i++, fdp++) {
   2414    786      lclee 			/* accumulate "lba" value from all partitions */
   2415    786      lclee 			lba = (lba || cmlb_has_max_chs_vals(fdp));
   2416    786      lclee 		}
   2417    786      lclee 	}
   2418    786      lclee 
   2419    786      lclee 	if (lba != 0) {
   2420   3525   shidokht 		dev_t dev = cmlb_make_device(cl);
   2421   3525   shidokht 
   2422   3525   shidokht 		if (ddi_getprop(dev, CMLB_DEVINFO(cl), DDI_PROP_DONTPASS,
   2423    786      lclee 		    "lba-access-ok", 0) == 0) {
   2424    786      lclee 			/* not found; create it */
   2425   3525   shidokht 			if (ddi_prop_create(dev, CMLB_DEVINFO(cl), 0,
   2426    786      lclee 			    "lba-access-ok", (caddr_t)NULL, 0) !=
   2427    786      lclee 			    DDI_PROP_SUCCESS) {
   2428   3525   shidokht 				cmlb_dbg(CMLB_ERROR,  cl,
   2429    786      lclee 				    "cmlb_read_fdisk: Can't create lba "
   2430    786      lclee 				    "property for instance %d\n",
   2431   3525   shidokht 				    ddi_get_instance(CMLB_DEVINFO(cl)));
   2432    786      lclee 			}
   2433    786      lclee 		}
   2434    786      lclee 	}
   2435    786      lclee 
   2436    786      lclee 	bcopy(&mbp->signature, sigbuf, sizeof (sigbuf));
   2437    786      lclee 
   2438    786      lclee 	/*
   2439    786      lclee 	 * Endian-independent signature check
   2440    786      lclee 	 */
   2441    786      lclee 	if (((sigbuf[1] & 0xFF) != ((MBB_MAGIC >> 8) & 0xFF)) ||
   2442    786      lclee 	    (sigbuf[0] != (MBB_MAGIC & 0xFF))) {
   2443   3525   shidokht 		cmlb_dbg(CMLB_ERROR,  cl,
   2444    786      lclee 		    "cmlb_read_fdisk: no fdisk\n");
   2445   3525   shidokht 		bzero(cl->cl_fmap, sizeof (struct fmap) * FD_NUMPART);
   2446    786      lclee 		goto done;
   2447    786      lclee 	}
   2448    786      lclee 
   2449    786      lclee #ifdef CMLBDEBUG
   2450   3525   shidokht 	if (cmlb_level_mask & CMLB_LOGMASK_INFO) {
   2451    786      lclee 		fdp = fdisk;
   2452   3525   shidokht 		cmlb_dbg(CMLB_INFO,  cl, "cmlb_read_fdisk:\n");
   2453   3525   shidokht 		cmlb_dbg(CMLB_INFO,  cl, "         relsect    "
   2454    786      lclee 		    "numsect         sysid       bootid\n");
   2455    786      lclee 		for (i = 0; i < FD_NUMPART; i++, fdp++) {
   2456   3525   shidokht 			cmlb_dbg(CMLB_INFO,  cl,
   2457    786      lclee 			    "    %d:  %8d   %8d     0x%08x     0x%08x\n",
   2458    786      lclee 			    i, fdp->relsect, fdp->numsect,
   2459    786      lclee 			    fdp->systid, fdp->bootid);
   2460    786      lclee 		}
   2461    786      lclee 	}
   2462    786      lclee #endif
   2463    786      lclee 
   2464    786      lclee 	/*
   2465    786      lclee 	 * Try to find the unix partition
   2466    786      lclee 	 */
   2467    786      lclee 	uidx = -1;
   2468    786      lclee 	solaris_offset = 0;
   2469    786      lclee 	solaris_size   = 0;
   2470    786      lclee 
   2471    786      lclee 	for (fdp = fdisk, i = 0; i < FD_NUMPART; i++, fdp++) {
   2472   7563     Prasad 		uint32_t relsect;
   2473   7563     Prasad 		uint32_t numsect;
   2474  10021  Sheshadri 		uchar_t systid;
   2475  10021  Sheshadri #if defined(__i386) || defined(__amd64)
   2476  10021  Sheshadri 		/*
   2477  10021  Sheshadri 		 * Stores relative block offset from the beginning of the
   2478  10021  Sheshadri 		 * Extended Partition.
   2479  10021  Sheshadri 		 */
   2480  10021  Sheshadri 		int	ext_relsect = 0;
   2481  10021  Sheshadri #endif
   2482    786      lclee 
   2483    786      lclee 		if (fdp->numsect == 0) {
   2484   3525   shidokht 			cl->cl_fmap[i].fmap_start = 0;
   2485   3525   shidokht 			cl->cl_fmap[i].fmap_nblk  = 0;
   2486    786      lclee 			continue;
   2487    786      lclee 		}
   2488    786      lclee 
   2489    786      lclee 		/*
   2490    786      lclee 		 * Data in the fdisk table is little-endian.
   2491    786      lclee 		 */
   2492    786      lclee 		relsect = LE_32(fdp->relsect);
   2493    786      lclee 		numsect = LE_32(fdp->numsect);
   2494    786      lclee 
   2495   3525   shidokht 		cl->cl_fmap[i].fmap_start = relsect;
   2496   3525   shidokht 		cl->cl_fmap[i].fmap_nblk  = numsect;
   2497  10021  Sheshadri 		cl->cl_fmap[i].fmap_systid = LE_8(fdp->systid);
   2498  10021  Sheshadri 
   2499  10021  Sheshadri #if defined(__i386) || defined(__amd64)
   2500  10021  Sheshadri 		/* Support only one extended partition per LUN */
   2501  10021  Sheshadri 		if ((fdp->systid == EXTDOS || fdp->systid == FDISK_EXTLBA) &&
   2502  10021  Sheshadri 		    (ext_part_exists == 0)) {
   2503  10021  Sheshadri 			int j;
   2504  10021  Sheshadri 			uint32_t logdrive_offset;
   2505  10021  Sheshadri 			uint32_t ext_numsect;
   2506  10021  Sheshadri 			uint32_t abs_secnum;
   2507  10021  Sheshadri 
   2508  10021  Sheshadri 			ext_part_exists = 1;
   2509  10021  Sheshadri 
   2510  10021  Sheshadri 			for (j = FD_NUMPART; j < FDISK_PARTS; j++) {
   2511  10021  Sheshadri 				mutex_exit(CMLB_MUTEX(cl));
   2512  10021  Sheshadri 				rval = DK_TG_READ(cl, bufp,
   2513  10021  Sheshadri 				    (relsect + ext_relsect), blocksize,
   2514  10021  Sheshadri 				    tg_cookie);
   2515  10021  Sheshadri 				mutex_enter(CMLB_MUTEX(cl));
   2516  10021  Sheshadri 
   2517  10021  Sheshadri 				if (rval != 0) {
   2518  10021  Sheshadri 					cmlb_dbg(CMLB_ERROR,  cl,
   2519  10021  Sheshadri 					    "cmlb_read_fdisk: Extended "
   2520  10021  Sheshadri 					    "partition read err\n");
   2521  10021  Sheshadri 					goto done;
   2522  10021  Sheshadri 				}
   2523  10021  Sheshadri 				/*
   2524  10021  Sheshadri 				 * The first ipart entry provides the offset
   2525  10021  Sheshadri 				 * at which the logical drive starts off from
   2526  10021  Sheshadri 				 * the beginning of the container partition
   2527  10021  Sheshadri 				 * and the size of the logical drive.
   2528  10021  Sheshadri 				 * The second ipart entry provides the offset
   2529  10021  Sheshadri 				 * of the next container partition from the
   2530  10021  Sheshadri 				 * beginning of the extended partition.
   2531  10021  Sheshadri 				 */
   2532  10021  Sheshadri 				bcopy(&bufp[FDISK_PART_TABLE_START], eparts,
   2533  10021  Sheshadri 				    sizeof (eparts));
   2534  10021  Sheshadri 				logdrive_offset = LE_32(efdp1->relsect);
   2535  10021  Sheshadri 				ext_numsect = LE_32(efdp1->numsect);
   2536  10021  Sheshadri 				systid = LE_8(efdp1->systid);
   2537  10021  Sheshadri 				if (logdrive_offset <= 0 || ext_numsect <= 0)
   2538  10021  Sheshadri 					break;
   2539  10021  Sheshadri 				abs_secnum = relsect + ext_relsect +
   2540  10021  Sheshadri 				    logdrive_offset;
   2541  10021  Sheshadri 
   2542  10021  Sheshadri 				/* Boundary condition and overlap checking */
   2543  10021  Sheshadri 				if (cmlb_validate_ext_part(cl, i, j, abs_secnum,
   2544  10021  Sheshadri 				    ext_numsect)) {
   2545  10021  Sheshadri 					break;
   2546  10021  Sheshadri 				}
   2547  10021  Sheshadri 
   2548  10021  Sheshadri 				if ((cl->cl_fmap[j].fmap_start != abs_secnum) ||
   2549  10021  Sheshadri 				    (cl->cl_fmap[j].fmap_nblk != ext_numsect) ||
   2550  10021  Sheshadri 				    (cl->cl_fmap[j].fmap_systid != systid)) {
   2551  10021  Sheshadri 					/*
   2552  10021  Sheshadri 					 * Indicates change from previous
   2553  10021  Sheshadri 					 * partinfo. Need to recreate
   2554  10021  Sheshadri 					 * logical device nodes.
   2555  10021  Sheshadri 					 */
   2556  10021  Sheshadri 					cl->cl_update_ext_minor_nodes = 1;
   2557  10021  Sheshadri 				}
   2558  10021  Sheshadri 				cl->cl_fmap[j].fmap_start = abs_secnum;
   2559  10021  Sheshadri 				cl->cl_fmap[j].fmap_nblk  = ext_numsect;
   2560  10021  Sheshadri 				cl->cl_fmap[j].fmap_systid = systid;
   2561  10021  Sheshadri 				ld_count++;
   2562  10021  Sheshadri 
   2563  10682  Sheshadri 				if ((efdp1->systid == SUNIXOS &&
   2564  10682  Sheshadri 				    (cmlb_is_linux_swap(cl, abs_secnum,
   2565  10682  Sheshadri 				    tg_cookie) != 0)) ||
   2566  10682  Sheshadri 				    efdp1->systid == SUNIXOS2) {
   2567  10682  Sheshadri 					if (uidx == -1) {
   2568  10021  Sheshadri 						uidx = 0;
   2569  10021  Sheshadri 						solaris_offset = abs_secnum;
   2570  10021  Sheshadri 						solaris_size = ext_numsect;
   2571  10021  Sheshadri 					}
   2572  10021  Sheshadri 				}
   2573  10021  Sheshadri 
   2574  10021  Sheshadri 				if ((ext_relsect = LE_32(efdp2->relsect)) == 0)
   2575  10021  Sheshadri 					break;
   2576  10021  Sheshadri 			}
   2577  10021  Sheshadri 		}
   2578  10021  Sheshadri 
   2579  10021  Sheshadri #endif
   2580    786      lclee 
   2581    786      lclee 		if (fdp->systid != SUNIXOS &&
   2582    786      lclee 		    fdp->systid != SUNIXOS2 &&
   2583    786      lclee 		    fdp->systid != EFI_PMBR) {
   2584    786      lclee 			continue;
   2585    786      lclee 		}
   2586    786      lclee 
   2587    786      lclee 		/*
   2588    786      lclee 		 * use the last active solaris partition id found
   2589    786      lclee 		 * (there should only be 1 active partition id)
   2590    786      lclee 		 *
   2591    786      lclee 		 * if there are no active solaris partition id
   2592    786      lclee 		 * then use the first inactive solaris partition id
   2593    786      lclee 		 */
   2594    786      lclee 		if ((uidx == -1) || (fdp->bootid == ACTIVE)) {
   2595  10021  Sheshadri #if defined(__i386) || defined(__amd64)
   2596  10682  Sheshadri 			if (fdp->systid != SUNIXOS ||
   2597  10682  Sheshadri 			    (fdp->systid == SUNIXOS &&
   2598  10682  Sheshadri 			    (cmlb_is_linux_swap(cl, relsect,
   2599  10682  Sheshadri 			    tg_cookie) != 0))) {
   2600  10021  Sheshadri #endif
   2601  10021  Sheshadri 				uidx = i;
   2602  10021  Sheshadri 				solaris_offset = relsect;
   2603  10021  Sheshadri 				solaris_size   = numsect;
   2604  10021  Sheshadri #if defined(__i386) || defined(__amd64)
   2605  10021  Sheshadri 			}
   2606  10021  Sheshadri #endif
   2607  10021  Sheshadri 		}
   2608  10021  Sheshadri 	}
   2609  10021  Sheshadri #if defined(__i386) || defined(__amd64)
   2610  10021  Sheshadri 	if (ld_count < cl->cl_logical_drive_count) {
   2611  10021  Sheshadri 		/*
   2612  10021  Sheshadri 		 * Some/all logical drives were deleted. Clear out
   2613  10021  Sheshadri 		 * the fmap entries correspoding to those deleted drives.
   2614  10021  Sheshadri 		 */
   2615  10021  Sheshadri 		for (k = ld_count + FD_NUMPART;
   2616  10021  Sheshadri 		    k < cl->cl_logical_drive_count + FD_NUMPART; k++) {
   2617  10021  Sheshadri 			cl->cl_fmap[k].fmap_start = 0;
   2618  10021  Sheshadri 			cl->cl_fmap[k].fmap_nblk  = 0;
   2619  10021  Sheshadri 			cl->cl_fmap[k].fmap_systid = 0;
   2620  10021  Sheshadri 		}
   2621  10021  Sheshadri 		cl->cl_update_ext_minor_nodes = 1;
   2622  10021  Sheshadri 	}
   2623  10021  Sheshadri 	if (cl->cl_update_ext_minor_nodes) {
   2624  10021  Sheshadri 		rval = cmlb_update_ext_minor_nodes(cl, ld_count);
   2625  10021  Sheshadri 		if (rval != 0) {
   2626  10021  Sheshadri 			goto done;
   2627  10021  Sheshadri 		}
   2628  10021  Sheshadri 	}
   2629  10021  Sheshadri #endif
   2630   3525   shidokht 	cmlb_dbg(CMLB_INFO,  cl, "fdisk 0x%x 0x%lx",
   2631   3525   shidokht 	    cl->cl_solaris_offset, cl->cl_solaris_size);
   2632    786      lclee done:
   2633    786      lclee 
   2634    786      lclee 	/*
   2635    786      lclee 	 * Clear the VTOC info, only if the Solaris partition entry
   2636    786      lclee 	 * has moved, changed size, been deleted, or if the size of
   2637    786      lclee 	 * the partition is too small to even fit the label sector.
   2638    786      lclee 	 */
   2639   3525   shidokht 	if ((cl->cl_solaris_offset != solaris_offset) ||
   2640   3525   shidokht 	    (cl->cl_solaris_size != solaris_size) ||
   2641    786      lclee 	    solaris_size <= DK_LABEL_LOC) {
   2642   3525   shidokht 		cmlb_dbg(CMLB_INFO,  cl, "fdisk moved 0x%x 0x%lx",
   2643   3525   shidokht 		    solaris_offset, solaris_size);
   2644   3525   shidokht 		bzero(&cl->cl_g, sizeof (struct dk_geom));
   2645   3525   shidokht 		bzero(&cl->cl_vtoc, sizeof (struct dk_vtoc));
   2646   3525   shidokht 		bzero(&cl->cl_map, NDKMAP * (sizeof (struct dk_map)));
   2647   8863     Edward 		cl->cl_f_geometry_is_valid = B_FALSE;
   2648   3525   shidokht 	}
   2649   3525   shidokht 	cl->cl_solaris_offset = solaris_offset;
   2650   3525   shidokht 	cl->cl_solaris_size = solaris_size;
   2651    786      lclee 	kmem_free(bufp, blocksize);
   2652    786      lclee 	return (rval);
   2653    786      lclee 
   2654    786      lclee #else	/* #elif defined(_FIRMWARE_NEEDS_FDISK) */
   2655    786      lclee #error "fdisk table presence undetermined for this platform."
   2656    786      lclee #endif	/* #if defined(_NO_FDISK_PRESENT) */
   2657    786      lclee }
   2658    786      lclee 
   2659    786      lclee static void
   2660    786      lclee cmlb_swap_efi_gpt(efi_gpt_t *e)
   2661    786      lclee {
   2662    786      lclee 	_NOTE(ASSUMING_PROTECTED(*e))
   2663    786      lclee 	e->efi_gpt_Signature = LE_64(e->efi_gpt_Signature);
   2664    786      lclee 	e->efi_gpt_Revision = LE_32(e->efi_gpt_Revision);
   2665    786      lclee 	e->efi_gpt_HeaderSize = LE_32(e->efi_gpt_HeaderSize);
   2666    786      lclee 	e->efi_gpt_HeaderCRC32 = LE_32(e->efi_gpt_HeaderCRC32);
   2667    786      lclee 	e->efi_gpt_MyLBA = LE_64(e->efi_gpt_MyLBA);
   2668    786      lclee 	e->efi_gpt_AlternateLBA = LE_64(e->efi_gpt_AlternateLBA);
   2669    786      lclee 	e->efi_gpt_FirstUsableLBA = LE_64(e->efi_gpt_FirstUsableLBA);
   2670    786      lclee 	e->efi_gpt_LastUsableLBA = LE_64(e->efi_gpt_LastUsableLBA);
   2671    786      lclee 	UUID_LE_CONVERT(e->efi_gpt_DiskGUID, e->efi_gpt_DiskGUID);
   2672    786      lclee 	e->efi_gpt_PartitionEntryLBA = LE_64(e->efi_gpt_PartitionEntryLBA);
   2673    786      lclee 	e->efi_gpt_NumberOfPartitionEntries =
   2674    786      lclee 	    LE_32(e->efi_gpt_NumberOfPartitionEntries);
   2675    786      lclee 	e->efi_gpt_SizeOfPartitionEntry =
   2676    786      lclee 	    LE_32(e->efi_gpt_SizeOfPartitionEntry);
   2677    786      lclee 	e->efi_gpt_PartitionEntryArrayCRC32 =
   2678    786      lclee 	    LE_32(e->efi_gpt_PartitionEntryArrayCRC32);
   2679    786      lclee }
   2680    786      lclee 
   2681    786      lclee static void
   2682    786      lclee cmlb_swap_efi_gpe(int nparts, efi_gpe_t *p)
   2683    786      lclee {
   2684    786      lclee 	int i;
   2685    786      lclee 
   2686    786      lclee 	_NOTE(ASSUMING_PROTECTED(*p))
   2687    786      lclee 	for (i = 0; i < nparts; i++) {
   2688    786      lclee 		UUID_LE_CONVERT(p[i].efi_gpe_PartitionTypeGUID,
   2689    786      lclee 		    p[i].efi_gpe_PartitionTypeGUID);
   2690    786      lclee 		p[i].efi_gpe_StartingLBA = LE_64(p[i].efi_gpe_StartingLBA);
   2691    786      lclee 		p[i].efi_gpe_EndingLBA = LE_64(p[i].efi_gpe_EndingLBA);
   2692    786      lclee 		/* PartitionAttrs */
   2693    786      lclee 	}
   2694    786      lclee }
   2695    786      lclee 
   2696    786      lclee static int
   2697    786      lclee cmlb_validate_efi(efi_gpt_t *labp)
   2698    786      lclee {
   2699    786      lclee 	if (labp->efi_gpt_Signature != EFI_SIGNATURE)
   2700    786      lclee 		return (EINVAL);
   2701    786      lclee 	/* at least 96 bytes in this version of the spec. */
   2702    786      lclee 	if (sizeof (efi_gpt_t) - sizeof (labp->efi_gpt_Reserved2) >
   2703    786      lclee 	    labp->efi_gpt_HeaderSize)
   2704    786      lclee 		return (EINVAL);
   2705    786      lclee 	/* this should be 128 bytes */
   2706    786      lclee 	if (labp->efi_gpt_SizeOfPartitionEntry != sizeof (efi_gpe_t))
   2707    786      lclee 		return (EINVAL);
   2708    786      lclee 	return (0);
   2709    786      lclee }
   2710    786      lclee 
   2711   5624   shidokht /*
   2712   8863     Edward  * This function returns B_FALSE if there is a valid MBR signature and no
   2713   8863     Edward  * partition table entries of type EFI_PMBR (0xEE). Otherwise it returns B_TRUE.
   2714   5624   shidokht  *
   2715   5624   shidokht  * The EFI spec (1.10 and later) requires having a Protective MBR (PMBR) to
   2716   5624   shidokht  * recognize the disk as GPT partitioned. However, some other OS creates an MBR
   2717   5624   shidokht  * where a PMBR entry is not the only one. Also, if the first block has been
   2718   5624   shidokht  * corrupted, currently best attempt to allow data access would be to try to
   2719   5624   shidokht  * check for GPT headers. Hence in case of more than one partition entry, but
   2720   5624   shidokht  * at least one EFI_PMBR partition type or no valid magic number, the function
   2721   8863     Edward  * returns B_TRUE to continue with looking for GPT header.
   2722   8863     Edward  */
   2723   8863     Edward 
   2724   8863     Edward static boolean_t
   2725   8863     Edward cmlb_check_efi_mbr(uchar_t *buf, boolean_t *is_mbr)
   2726   5624   shidokht {
   2727   5624   shidokht 	struct ipart	*fdp;
   2728   5624   shidokht 	struct mboot	*mbp = (struct mboot *)buf;
   2729   5624   shidokht 	struct ipart	fdisk[FD_NUMPART];
   2730   5624   shidokht 	int		i;
   2731   5624   shidokht 
   2732   7563     Prasad 	if (is_mbr != NULL)
   2733   8863     Edward 		*is_mbr = B_TRUE;
   2734   7563     Prasad 
   2735   7563     Prasad 	if (LE_16(mbp->signature) != MBB_MAGIC) {
   2736   7563     Prasad 		if (is_mbr != NULL)
   2737   8863     Edward 			*is_mbr = B_FALSE;
   2738   8863     Edward 		return (B_TRUE);
   2739   7563     Prasad 	}
   2740   5624   shidokht 
   2741   5624   shidokht 	bcopy(&mbp->parts[0], fdisk, sizeof (fdisk));
   2742   5624   shidokht 
   2743   5624   shidokht 	for (fdp = fdisk, i = 0; i < FD_NUMPART; i++, fdp++) {
   2744   5624   shidokht 		if (fdp->systid == EFI_PMBR)
   2745   8863     Edward 			return (B_TRUE);
   2746   8863     Edward 	}
   2747   8863     Edward 
   2748   8863     Edward 	return (B_FALSE);
   2749   5624   shidokht }
   2750   5624   shidokht 
   2751    786      lclee static int
   2752   3525   shidokht cmlb_use_efi(struct cmlb_lun *cl, diskaddr_t capacity, int flags,
   2753   3525   shidokht     void *tg_cookie)
   2754    786      lclee {
   2755    786      lclee 	int		i;
   2756    786      lclee 	int		rval = 0;
   2757    786      lclee 	efi_gpe_t	*partitions;
   2758    786      lclee 	uchar_t		*buf;
   2759    786      lclee 	uint_t		lbasize;	/* is really how much to read */
   2760   3525   shidokht 	diskaddr_t	cap = 0;
   2761    786      lclee 	uint_t		nparts;
   2762    786      lclee 	diskaddr_t	gpe_lba;
   2763   6590   yl194034 	diskaddr_t	alternate_lba;
   2764   1071   shidokht 	int		iofailed = 0;
   2765   3525   shidokht 	struct uuid	uuid_type_reserved = EFI_RESERVED;
   2766   7563     Prasad #if defined(_FIRMWARE_NEEDS_FDISK)
   2767   8863     Edward 	boolean_t 	is_mbr;
   2768   7563     Prasad #endif
   2769   3525   shidokht 
   2770   3525   shidokht 	ASSERT(mutex_owned(CMLB_MUTEX(cl)));
   2771   3525   shidokht 
   2772   3525   shidokht 	lbasize = cl->cl_sys_blocksize;
   2773   3525   shidokht 
   2774   3525   shidokht 	cl->cl_reserved = -1;
   2775   3525   shidokht 	mutex_exit(CMLB_MUTEX(cl));
   2776    786      lclee 
   2777    786      lclee 	buf = kmem_zalloc(EFI_MIN_ARRAY_SIZE, KM_SLEEP);
   2778   3525   shidokht 
   2779   7563     Prasad 	rval = DK_TG_READ(cl, buf,  0, lbasize, tg_cookie);
   2780    786      lclee 	if (rval) {
   2781   1071   shidokht 		iofailed = 1;
   2782    786      lclee 		goto done_err;
   2783    786      lclee 	}
   2784    786      lclee 	if (((struct dk_label *)buf)->dkl_magic == DKL_MAGIC) {
   2785    786      lclee 		/* not ours */
   2786    786      lclee 		rval = ESRCH;
   2787   5624   shidokht 		goto done_err;
   2788   5624   shidokht 	}
   2789   5624   shidokht 
   2790   7563     Prasad #if defined(_FIRMWARE_NEEDS_FDISK)
   2791   8863     Edward 	if (!cmlb_check_efi_mbr(buf, &is_mbr)) {
   2792   8863     Edward 		if (is_mbr)
   2793   7563     Prasad 			rval = ESRCH;
   2794   7563     Prasad 		else
   2795   7563     Prasad 			rval = EINVAL;
   2796   7563     Prasad 		goto done_err;
   2797   7563     Prasad 	}
   2798   7563     Prasad #else
   2799   8863     Edward 	if (!cmlb_check_efi_mbr(buf, NULL)) {
   2800   5624   shidokht 		rval = EINVAL;
   2801    786      lclee 		goto done_err;
   2802    786      lclee 	}
   2803   7563     Prasad 
   2804   7563     Prasad #endif
   2805    786      lclee 
   2806   3525   shidokht 	rval = DK_TG_READ(cl, buf, 1, lbasize, tg_cookie);
   2807    786      lclee 	if (rval) {
   2808   1071   shidokht 		iofailed = 1;
   2809    786      lclee 		goto done_err;
   2810    786      lclee 	}
   2811    786      lclee 	cmlb_swap_efi_gpt((efi_gpt_t *)buf);
   2812    786      lclee 
   2813    786      lclee 	if ((rval = cmlb_validate_efi((efi_gpt_t *)buf)) != 0) {
   2814    786      lclee 		/*
   2815    786      lclee 		 * Couldn't read the primary, try the backup.  Our
   2816    786      lclee 		 * capacity at this point could be based on CHS, so
   2817    786      lclee 		 * check what the device reports.
   2818    786      lclee 		 */
   2819   3525   shidokht 		rval = DK_TG_GETCAP(cl, &cap, tg_cookie);
   2820    786      lclee 		if (rval) {
   2821   1071   shidokht 			iofailed = 1;
   2822    786      lclee 			goto done_err;
   2823    786      lclee 		}
   2824   3525   shidokht 
   2825   3525   shidokht 		/*
   2826   3525   shidokht 		 * CMLB_OFF_BY_ONE case, we check the next to last block first
   2827   3525   shidokht 		 * for backup GPT header, otherwise check the last block.
   2828   3525   shidokht 		 */
   2829   3525   shidokht 
   2830   3525   shidokht 		if ((rval = DK_TG_READ(cl, buf,
   2831   3525   shidokht 		    cap - ((cl->cl_alter_behavior & CMLB_OFF_BY_ONE) ? 2 : 1),
   2832   3525   shidokht 		    lbasize, tg_cookie))
   2833   3525   shidokht 		    != 0) {
   2834   1071   shidokht 			iofailed = 1;
   2835    786      lclee 			goto done_err;
   2836    786      lclee 		}
   2837    786      lclee 		cmlb_swap_efi_gpt((efi_gpt_t *)buf);
   2838   3525   shidokht 
   2839   3525   shidokht 		if ((rval = cmlb_validate_efi((efi_gpt_t *)buf)) != 0) {
   2840   3525   shidokht 
   2841   3525   shidokht 			if (!(cl->cl_alter_behavior & CMLB_OFF_BY_ONE))
   2842   3525   shidokht 				goto done_err;
   2843   3525   shidokht 			if ((rval = DK_TG_READ(cl, buf, cap - 1, lbasize,
   2844   3525   shidokht 			    tg_cookie)) != 0)
   2845   3525   shidokht 				goto done_err;
   2846   3525   shidokht 			cmlb_swap_efi_gpt((efi_gpt_t *)buf);
   2847   3525   shidokht 			if ((rval = cmlb_validate_efi((efi_gpt_t *)buf)) != 0)
   2848   3525   shidokht 				goto done_err;
   2849   3525   shidokht 		}
   2850   3525   shidokht 		if (!(flags & CMLB_SILENT))
   2851   3525   shidokht 			cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl), CE_WARN,
   2852   3525   shidokht 			    "primary label corrupt; using backup\n");
   2853    786      lclee 	}
   2854    786      lclee 
   2855    786      lclee 	nparts = ((efi_gpt_t *)buf)->efi_gpt_NumberOfPartitionEntries;
   2856    786      lclee 	gpe_lba = ((efi_gpt_t *)buf)->efi_gpt_PartitionEntryLBA;
   2857   6590   yl194034 	alternate_lba = ((efi_gpt_t *)buf)->efi_gpt_AlternateLBA;
   2858    786      lclee 
   2859   3525   shidokht 	rval = DK_TG_READ(cl, buf, gpe_lba, EFI_MIN_ARRAY_SIZE, tg_cookie);
   2860    786      lclee 	if (rval) {
   2861   1071   shidokht 		iofailed = 1;
   2862    786      lclee 		goto done_err;
   2863    786      lclee 	}
   2864    786      lclee 	partitions = (efi_gpe_t *)buf;
   2865    786      lclee 
   2866    786      lclee 	if (nparts > MAXPART) {
   2867    786      lclee 		nparts = MAXPART;
   2868    786      lclee 	}
   2869    786      lclee 	cmlb_swap_efi_gpe(nparts, partitions);
   2870    786      lclee 
   2871   3525   shidokht 	mutex_enter(CMLB_MUTEX(cl));
   2872    786      lclee 
   2873    786      lclee 	/* Fill in partition table. */
   2874    786      lclee 	for (i = 0; i < nparts; i++) {
   2875    786      lclee 		if (partitions->efi_gpe_StartingLBA != 0 ||
   2876    786      lclee 		    partitions->efi_gpe_EndingLBA != 0) {
   2877   3525   shidokht 			cl->cl_map[i].dkl_cylno =
   2878    786      lclee 			    partitions->efi_gpe_StartingLBA;
   2879   3525   shidokht 			cl->cl_map[i].dkl_nblk =
   2880    786      lclee 			    partitions->efi_gpe_EndingLBA -
   2881    786      lclee 			    partitions->efi_gpe_StartingLBA + 1;
   2882   3525   shidokht 			cl->cl_offset[i] =
   2883    786      lclee 			    partitions->efi_gpe_StartingLBA;
   2884    786      lclee 		}
   2885   3525   shidokht 
   2886   3525   shidokht 		if (cl->cl_reserved == -1) {
   2887   3525   shidokht 			if (bcmp(&partitions->efi_gpe_PartitionTypeGUID,
   2888   3525   shidokht 			    &uuid_type_reserved, sizeof (struct uuid)) == 0) {
   2889   3525   shidokht 				cl->cl_reserved = i;
   2890   3525   shidokht 			}
   2891   3525   shidokht 		}
   2892    786      lclee 		if (i == WD_NODE) {
   2893    786      lclee 			/*
   2894    786      lclee 			 * minor number 7 corresponds to the whole disk
   2895   6590   yl194034 			 * if the disk capacity is expanded after disk is
   2896   6590   yl194034 			 * labeled, minor number 7 represents the capacity
   2897   6590   yl194034 			 * indicated by the disk label.
   2898    786      lclee 			 */
   2899   3525   shidokht 			cl->cl_map[i].dkl_cylno = 0;
   2900   6590   yl194034 			if (alternate_lba == 1) {
   2901   6590   yl194034 				/*
   2902   6590   yl194034 				 * We are using backup label. Since we can
   2903   6590   yl194034 				 * find a valid label at the end of disk,
   2904   6590   yl194034 				 * the disk capacity is not expanded.
   2905   6590   yl194034 				 */
   2906   6590   yl194034 				cl->cl_map[i].dkl_nblk = capacity;
   2907   6590   yl194034 			} else {
   2908   6590   yl194034 				cl->cl_map[i].dkl_nblk = alternate_lba + 1;
   2909   6590   yl194034 			}
   2910   3525   shidokht 			cl->cl_offset[i] = 0;
   2911    786      lclee 		}
   2912    786      lclee 		partitions++;
   2913    786      lclee 	}
   2914   3525   shidokht 	cl->cl_solaris_offset = 0;
   2915   3525   shidokht 	cl->cl_solaris_size = capacity;
   2916   7563     Prasad 	cl->cl_label_from_media = CMLB_LABEL_EFI;
   2917   8863     Edward 	cl->cl_f_geometry_is_valid = B_TRUE;
   2918   3525   shidokht 
   2919   3525   shidokht 	/* clear the vtoc label */
   2920   3525   shidokht 	bzero(&cl->cl_vtoc, sizeof (struct dk_vtoc));
   2921   3525   shidokht 
   2922    786      lclee 	kmem_free(buf, EFI_MIN_ARRAY_SIZE);
   2923    786      lclee 	return (0);
   2924    786      lclee 
   2925    786      lclee done_err:
   2926    786      lclee 	kmem_free(buf, EFI_MIN_ARRAY_SIZE);
   2927   3525   shidokht 	mutex_enter(CMLB_MUTEX(cl));
   2928   3525   shidokht done_err1:
   2929    786      lclee 	/*
   2930    786      lclee 	 * if we didn't find something that could look like a VTOC
   2931    786      lclee 	 * and the disk is over 1TB, we know there isn't a valid label.
   2932    786      lclee 	 * Otherwise let cmlb_uselabel decide what to do.  We only
   2933    786      lclee 	 * want to invalidate this if we're certain the label isn't
   2934    786      lclee 	 * valid because cmlb_prop_op will now fail, which in turn
   2935    786      lclee 	 * causes things like opens and stats on the partition to fail.
   2936    786      lclee 	 */
   2937   7563     Prasad 	if ((capacity > CMLB_EXTVTOC_LIMIT) && (rval != ESRCH) && !iofailed) {
   2938   8863     Edward 		cl->cl_f_geometry_is_valid = B_FALSE;
   2939    786      lclee 	}
   2940    786      lclee 	return (rval);
   2941    786      lclee }
   2942    786      lclee 
   2943    786      lclee 
   2944    786      lclee /*
   2945    786      lclee  *    Function: cmlb_uselabel
   2946    786      lclee  *
   2947    786      lclee  * Description: Validate the disk label and update the relevant data (geometry,
   2948    786      lclee  *		partition, vtoc, and capacity data) in the cmlb_lun struct.
   2949    786      lclee  *		Marks the geometry of the unit as being valid.
   2950    786      lclee  *
   2951   3525   shidokht  *   Arguments: cl: unit struct.
   2952    786      lclee  *		dk_label: disk label
   2953    786      lclee  *
   2954    786      lclee  * Return Code: CMLB_LABEL_IS_VALID: Label read from disk is OK; geometry,
   2955    786      lclee  *		partition, vtoc, and capacity data are good.
   2956    786      lclee  *
   2957    786      lclee  *		CMLB_LABEL_IS_INVALID: Magic number or checksum error in the
   2958    786      lclee  *		label; or computed capacity does not jibe with capacity
   2959    786      lclee  *		reported from the READ CAPACITY command.
   2960    786      lclee  *
   2961    786      lclee  *     Context: Kernel thread only (can sleep).
   2962    786      lclee  */
   2963    786      lclee static int
   2964   3525   shidokht cmlb_uselabel(struct cmlb_lun *cl, struct dk_label *labp, int flags)
   2965    786      lclee {
   2966    786      lclee 	short		*sp;
   2967    786      lclee 	short		sum;
   2968    786      lclee 	short		count;
   2969    786      lclee 	int		label_error = CMLB_LABEL_IS_VALID;
   2970    786      lclee 	int		i;
   2971    786      lclee 	diskaddr_t	label_capacity;
   2972   7563     Prasad 	uint32_t	part_end;
   2973    786      lclee 	diskaddr_t	track_capacity;
   2974    786      lclee #if defined(_SUNOS_VTOC_16)
   2975    786      lclee 	struct	dkl_partition	*vpartp;
   2976    786      lclee #endif
   2977   3525   shidokht 	ASSERT(cl != NULL);
   2978   3525   shidokht 	ASSERT(mutex_owned(CMLB_MUTEX(cl)));
   2979    786      lclee 
   2980    786      lclee 	/* Validate the magic number of the label. */
   2981    786      lclee 	if (labp->dkl_magic != DKL_MAGIC) {
   2982    786      lclee #if defined(__sparc)
   2983   3525   shidokht 		if (!ISREMOVABLE(cl) && !ISHOTPLUGGABLE(cl)) {
   2984   3525   shidokht 			if (!(flags & CMLB_SILENT))
   2985   3525   shidokht 				cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl),
   2986   3525   shidokht 				    CE_WARN,
   2987   3525   shidokht 				    "Corrupt label; wrong magic number\n");
   2988    786      lclee 		}
   2989    786      lclee #endif
   2990    786      lclee 		return (CMLB_LABEL_IS_INVALID);
   2991    786      lclee 	}
   2992    786      lclee 
   2993    786      lclee 	/* Validate the checksum of the label. */
   2994    786      lclee 	sp  = (short *)labp;
   2995    786      lclee 	sum = 0;
   2996    786      lclee 	count = sizeof (struct dk_label) / sizeof (short);
   2997    786      lclee 	while (count--)	 {
   2998    786      lclee 		sum ^= *sp++;
   2999    786      lclee 	}
   3000    786      lclee 
   3001    786      lclee 	if (sum != 0) {
   3002    786      lclee #if defined(_SUNOS_VTOC_16)
   3003   3525   shidokht 		if (!ISCD(cl)) {
   3004    786      lclee #elif defined(_SUNOS_VTOC_8)
   3005   3525   shidokht 		if (!ISREMOVABLE(cl) && !ISHOTPLUGGABLE(cl)) {
   3006   3525   shidokht #endif
   3007   3525   shidokht 			if (!(flags & CMLB_SILENT))
   3008   3525   shidokht 				cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl),
   3009   3525   shidokht 				    CE_WARN,
   3010   3525   shidokht 				    "Corrupt label - label checksum failed\n");
   3011    786      lclee 		}
   3012    786      lclee 		return (CMLB_LABEL_IS_INVALID);
   3013    786      lclee 	}
   3014    786      lclee 
   3015    786      lclee 
   3016    786      lclee 	/*
   3017    786      lclee 	 * Fill in geometry structure with data from label.
   3018    786      lclee 	 */
   3019   3525   shidokht 	bzero(&cl->cl_g, sizeof (struct dk_geom));
   3020   3525   shidokht 	cl->cl_g.dkg_ncyl   = labp->dkl_ncyl;
   3021   3525   shidokht 	cl->cl_g.dkg_acyl   = labp->dkl_acyl;
   3022   3525   shidokht 	cl->cl_g.dkg_bcyl   = 0;
   3023   3525   shidokht 	cl->cl_g.dkg_nhead  = labp->dkl_nhead;
   3024   3525   shidokht 	cl->cl_g.dkg_nsect  = labp->dkl_nsect;
   3025   3525   shidokht 	cl->cl_g.dkg_intrlv = labp->dkl_intrlv;
   3026   3525   shidokht 
   3027   3525   shidokht #if defined(_SUNOS_VTOC_8)
   3028   3525   shidokht 	cl->cl_g.dkg_gap1   = labp->dkl_gap1;
   3029   3525   shidokht 	cl->cl_g.dkg_gap2   = labp->dkl_gap2;
   3030   3525   shidokht 	cl->cl_g.dkg_bhead  = labp->dkl_bhead;
   3031   3525   shidokht #endif
   3032   3525   shidokht #if defined(_SUNOS_VTOC_16)
   3033   3525   shidokht 	cl->cl_dkg_skew = labp->dkl_skew;
   3034   3525   shidokht #endif
   3035   3525   shidokht 
   3036   3525   shidokht #if defined(__i386) || defined(__amd64)
   3037   3525   shidokht 	cl->cl_g.dkg_apc = labp->dkl_apc;
   3038    786      lclee #endif
   3039    786      lclee 
   3040    786      lclee 	/*
   3041    786      lclee 	 * Currently we rely on the values in the label being accurate. If
   3042    786      lclee 	 * dkl_rpm or dkl_pcly are zero in the label, use a default value.
   3043    786      lclee 	 *
   3044    786      lclee 	 * Note: In the future a MODE SENSE may be used to retrieve this data,
   3045    786      lclee 	 * although this command is optional in SCSI-2.
   3046    786      lclee 	 */
   3047   3525   shidokht 	cl->cl_g.dkg_rpm  = (labp->dkl_rpm  != 0) ? labp->dkl_rpm  : 3600;
   3048   3525   shidokht 	cl->cl_g.dkg_pcyl = (labp->dkl_pcyl != 0) ? labp->dkl_pcyl :
   3049   3525   shidokht 	    (cl->cl_g.dkg_ncyl + cl->cl_g.dkg_acyl);
   3050    786      lclee 
   3051    786      lclee 	/*
   3052    786      lclee 	 * The Read and Write reinstruct values may not be valid
   3053    786      lclee 	 * for older disks.
   3054    786      lclee 	 */
   3055   3525   shidokht 	cl->cl_g.dkg_read_reinstruct  = labp->dkl_read_reinstruct;
   3056   3525   shidokht 	cl->cl_g.dkg_write_reinstruct = labp->dkl_write_reinstruct;
   3057    786      lclee 
   3058    786      lclee 	/* Fill in partition table. */
   3059    786      lclee #if defined(_SUNOS_VTOC_8)
   3060    786      lclee 	for (i = 0; i < NDKMAP; i++) {
   3061   3525   shidokht 		cl->cl_map[i].dkl_cylno = labp->dkl_map[i].dkl_cylno;
   3062   3525   shidokht 		cl->cl_map[i].dkl_nblk  = labp->dkl_map[i].dkl_nblk;
   3063    786      lclee 	}
   3064    786      lclee #endif
   3065    786      lclee #if  defined(_SUNOS_VTOC_16)
   3066    786      lclee 	vpartp		= labp->dkl_vtoc.v_part;
   3067    786      lclee 	track_capacity	= labp->dkl_nhead * labp->dkl_nsect;
   3068    786      lclee 
   3069   3525   shidokht 	/* Prevent divide by zero */
   3070   3525   shidokht 	if (track_capacity == 0) {
   3071   3525   shidokht 		if (!(flags & CMLB_SILENT))
   3072   3525   shidokht 			cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl), CE_WARN,
   3073   3525   shidokht 			    "Corrupt label - zero nhead or nsect value\n");
   3074   3525   shidokht 
   3075   3525   shidokht 		return (CMLB_LABEL_IS_INVALID);
   3076   3525   shidokht 	}
   3077   3525   shidokht 
   3078    786      lclee 	for (i = 0; i < NDKMAP; i++, vpartp++) {
   3079   3525   shidokht 		cl->cl_map[i].dkl_cylno = vpartp->p_start / track_capacity;
   3080   3525   shidokht 		cl->cl_map[i].dkl_nblk  = vpartp->p_size;
   3081    786      lclee 	}
   3082    786      lclee #endif
   3083    786      lclee 
   3084    786      lclee 	/* Fill in VTOC Structure. */
   3085   3525   shidokht 	bcopy(&labp->dkl_vtoc, &cl->cl_vtoc, sizeof (struct dk_vtoc));
   3086    786      lclee #if defined(_SUNOS_VTOC_8)
   3087    786      lclee 	/*
   3088    786      lclee 	 * The 8-slice vtoc does not include the ascii label; save it into
   3089    786      lclee 	 * the device's soft state structure here.
   3090    786      lclee 	 */
   3091   3525   shidokht 	bcopy(labp->dkl_asciilabel, cl->cl_asciilabel, LEN_DKL_ASCII);
   3092   3525   shidokht #endif
   3093   3525   shidokht 
   3094   3525   shidokht 	/* Now look for a valid capacity. */
   3095   3525   shidokht 	track_capacity	= (cl->cl_g.dkg_nhead * cl->cl_g.dkg_nsect);
   3096   3525   shidokht 	label_capacity	= (cl->cl_g.dkg_ncyl  * track_capacity);
   3097   3525   shidokht 
   3098   3525   shidokht 	if (cl->cl_g.dkg_acyl) {
   3099   3525   shidokht #if defined(__i386) || defined(__amd64)
   3100   3525   shidokht 		/* we may have > 1 alts cylinder */
   3101   3525   shidokht 		label_capacity += (track_capacity * cl->cl_g.dkg_acyl);
   3102   3525   shidokht #else
   3103   3525   shidokht 		label_capacity += track_capacity;
   3104   3525   shidokht #endif
   3105   3525   shidokht 	}
   3106   3525   shidokht 
   3107   3525   shidokht 	/*
   3108   3525   shidokht 	 * Force check here to ensure the computed capacity is valid.
   3109   3525   shidokht 	 * If capacity is zero, it indicates an invalid label and
   3110   3525   shidokht 	 * we should abort updating the relevant data then.
   3111   3525   shidokht 	 */
   3112   3525   shidokht 	if (label_capacity == 0) {
   3113   3525   shidokht 		if (!(flags & CMLB_SILENT))
   3114   3525   shidokht 			cmlb_log(CMLB_DEVINFO(cl), CMLB_LABEL(cl), CE_WARN,
   3115   3525   shidokht 			    "Corrupt label - no valid capacity could be "
   3116   3525   shidokht 			    "retrieved\n");
   3117   3525   shidokht</