Home | History | Annotate | Download | only in sys
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #ifndef	_VDSK_COMMON_H
     28 #define	_VDSK_COMMON_H
     29 
     30 #ifdef __cplusplus
     31 extern "C" {
     32 #endif
     33 
     34 /*
     35  * This header file contains the private LDoms Virtual Disk (vDisk) definitions
     36  * common to both the server (vds) and the client (vdc)
     37  */
     38 
     39 #include <sys/efi_partition.h>
     40 #include <sys/machparam.h>
     41 #include <sys/vtoc.h>
     42 
     43 #include <sys/ldc.h>
     44 #include <sys/vio_common.h>
     45 #include <sys/vio_mailbox.h>
     46 
     47 /*
     48  * vDisk definitions
     49  */
     50 
     51 /*
     52  * The number of Descriptor Ring entries
     53  *
     54  * Constraints:
     55  * 	- overall DRing size must be greater than 8K (MMU_PAGESIZE)
     56  *	- overall DRing size should be 8K aligned (desirable but not enforced)
     57  *	- DRing entry must be 8 byte aligned
     58  */
     59 #define	VD_DRING_LEN		512
     60 
     61 /*
     62  *
     63  */
     64 #define	VD_DRING_ENTRY_SZ	(sizeof (vd_dring_entry_t) + 		\
     65 		(sizeof (ldc_mem_cookie_t) * (VD_MAX_COOKIES - 1)))
     66 
     67 /*
     68  * The maximum block size we can transmit using one Descriptor Ring entry
     69  *
     70  * Currently no FS uses more than 128K and it doesn't look like they
     71  * will either as there is no perf gain to be had by larger values.
     72  * ( see ZFS comment at definition of SPA_MAXBLOCKSIZE ).
     73  *
     74  * We choose 256K to give us some headroom.
     75  */
     76 #define	VD_MAX_BLOCK_SIZE	(256 * 1024)
     77 
     78 #define	VD_MAX_COOKIES		((VD_MAX_BLOCK_SIZE / PAGESIZE) + 1)
     79 #define	VD_USEC_TIMEOUT		20000
     80 #define	VD_LDC_IDS_PROP		"ldc-ids"
     81 #define	VD_LDC_MTU		256
     82 
     83 /*
     84  * Flags used by ioctl routines to indicate if a copyin/copyout is needed
     85  */
     86 #define	VD_COPYOUT		0x1
     87 #define	VD_COPYIN		0x2
     88 
     89 /*
     90  * vDisk operations on physical devices
     91  */
     92 #define	VD_OP_BREAD		0x01	/* Block Read */
     93 #define	VD_OP_BWRITE		0x02	/* Block Write */
     94 #define	VD_OP_FLUSH		0x03	/* Flush disk write cache contents */
     95 #define	VD_OP_GET_WCE		0x04	/* Get disk W$ status */
     96 #define	VD_OP_SET_WCE		0x05	/* Enable/Disable disk W$ */
     97 #define	VD_OP_GET_VTOC		0x06	/* Get VTOC */
     98 #define	VD_OP_SET_VTOC		0x07	/* Set VTOC */
     99 #define	VD_OP_GET_DISKGEOM	0x08	/* Get disk geometry */
    100 #define	VD_OP_SET_DISKGEOM	0x09	/* Set disk geometry */
    101 #define	VD_OP_SCSICMD		0x0a	/* SCSI control command */
    102 #define	VD_OP_GET_DEVID		0x0b	/* Get device id */
    103 #define	VD_OP_GET_EFI 		0x0c	/* Get EFI */
    104 #define	VD_OP_SET_EFI 		0x0d	/* Set EFI */
    105 #define	VD_OP_RESET		0x0e	/* Reset disk */
    106 #define	VD_OP_GET_ACCESS	0x0f	/* Get disk access */
    107 #define	VD_OP_SET_ACCESS	0x10	/* Set disk access */
    108 #define	VD_OP_GET_CAPACITY	0x11	/* Get disk capacity */
    109 #define	VD_OP_MASK		0xFF	/* mask of all possible operations */
    110 #define	VD_OP_COUNT		0x11	/* Number of operations */
    111 
    112 /*
    113  * Status for the VD_OP_GET_ACCESS operation
    114  */
    115 #define	VD_ACCESS_DENIED	0x00	/* access is not allowed */
    116 #define	VD_ACCESS_ALLOWED	0x01	/* access is allowed */
    117 
    118 /*
    119  * Flags for the VD_OP_SET_ACCESS operation
    120  */
    121 #define	VD_ACCESS_SET_CLEAR	0x00	/* clear exclusive access rights */
    122 #define	VD_ACCESS_SET_EXCLUSIVE	0x01	/* set exclusive access rights */
    123 #define	VD_ACCESS_SET_PREEMPT	0x02	/* forcefully set access rights */
    124 #define	VD_ACCESS_SET_PRESERVE	0x04	/* preserve access rights */
    125 
    126 /*
    127  * This is a mask of all the basic operations supported by all
    128  * disk types (v1.0).
    129  */
    130 #define	VD_OP_MASK_READ			\
    131 	((1 << VD_OP_BREAD) |			\
    132 	(1 << VD_OP_GET_WCE) |			\
    133 	(1 << VD_OP_GET_VTOC) |			\
    134 	(1 << VD_OP_GET_DISKGEOM) |		\
    135 	(1 << VD_OP_GET_DEVID) |		\
    136 	(1 << VD_OP_GET_EFI))
    137 
    138 #define	VD_OP_MASK_WRITE			\
    139 	((1 << VD_OP_BWRITE) |			\
    140 	(1 << VD_OP_FLUSH) |			\
    141 	(1 << VD_OP_SET_WCE) |			\
    142 	(1 << VD_OP_SET_VTOC) |			\
    143 	(1 << VD_OP_SET_DISKGEOM) |		\
    144 	(1 << VD_OP_SET_EFI))
    145 
    146 /*
    147  * Mask for additional operations provided for SCSI disks (v1.1)
    148  */
    149 #define	VD_OP_MASK_SCSI				\
    150 	((1 << VD_OP_SCSICMD) |			\
    151 	(1 << VD_OP_RESET) |			\
    152 	(1 << VD_OP_GET_ACCESS) |		\
    153 	(1 << VD_OP_SET_ACCESS))
    154 
    155 /*
    156  * macro to check if the operation 'op' is supported by checking the list
    157  * of operations supported which is exported by the vDisk server.
    158  */
    159 #define	VD_OP_SUPPORTED(ops_bitmask, op)	((ops_bitmask) & (1 << (op)))
    160 
    161 /*
    162  * Slice for absolute disk transaction.
    163  */
    164 #define	VD_SLICE_NONE		0xFF
    165 
    166 /*
    167  * EFI disks do not have a slice 7. Actually that slice is used to represent
    168  * the whole disk.
    169  */
    170 #define	VD_EFI_WD_SLICE	7
    171 
    172 /*
    173  * Definitions of the various ways vds can export disk support to vdc.
    174  */
    175 typedef enum vd_disk_type {
    176 	VD_DISK_TYPE_UNK = 0,		/* Unknown device type */
    177 	VD_DISK_TYPE_SLICE,		/* slice in block device */
    178 	VD_DISK_TYPE_DISK		/* entire disk (slice 2) */
    179 } vd_disk_type_t;
    180 
    181 /*
    182  * Definitions of the various disk label that vDisk supports.
    183  */
    184 typedef enum vd_disk_label {
    185 	VD_DISK_LABEL_UNK = 0,		/* Unknown disk label */
    186 	VD_DISK_LABEL_VTOC,		/* VTOC disk label */
    187 	VD_DISK_LABEL_EFI		/* EFI disk label */
    188 } vd_disk_label_t;
    189 
    190 /*
    191  * vDisk Descriptor payload
    192  */
    193 typedef struct vd_dring_payload {
    194 	uint64_t	req_id;		/* The request ID being processed */
    195 	uint8_t		operation;	/* operation for server to perform */
    196 	uint8_t		slice;		/* The disk slice being accessed */
    197 	uint16_t	resv1;		/* padding */
    198 	uint32_t	status;		/* "errno" of server operation */
    199 	uint64_t	addr;		/* LP64	diskaddr_t (block I/O) */
    200 	uint64_t	nbytes;		/* LP64 size_t */
    201 	uint32_t	ncookies;	/* Number of cookies used */
    202 	uint32_t	resv2;		/* padding */
    203 
    204 	ldc_mem_cookie_t	cookie[1];	/* variable sized array */
    205 } vd_dring_payload_t;
    206 
    207 
    208 /*
    209  * vDisk Descriptor entry
    210  */
    211 typedef struct vd_dring_entry {
    212 	vio_dring_entry_hdr_t		hdr;		/* common header */
    213 	vd_dring_payload_t		payload;	/* disk specific data */
    214 } vd_dring_entry_t;
    215 
    216 /*
    217  * vDisk logical partition
    218  */
    219 typedef struct vd_slice {
    220 	daddr_t	start;		/* block number of slice start */
    221 	daddr_t nblocks;	/* number of blocks in the slice */
    222 } vd_slice_t;
    223 
    224 
    225 /*
    226  * vDisk control operation structures
    227  */
    228 
    229 /*
    230  * vDisk geometry definition (VD_OP_GET_DISKGEOM and VD_OP_SET_DISKGEOM)
    231  */
    232 typedef struct vd_geom {
    233 	uint16_t	ncyl;		/* number of data cylinders */
    234 	uint16_t	acyl;		/* number of alternate cylinders */
    235 	uint16_t	bcyl;		/* cyl offset for fixed head area */
    236 	uint16_t	nhead;		/* number of heads */
    237 	uint16_t	nsect;		/* number of data sectors per track */
    238 	uint16_t	intrlv;		/* interleave factor */
    239 	uint16_t	apc;		/* alternates per cyl (SCSI only) */
    240 	uint16_t	rpm;		/* revolutions per minute */
    241 	uint16_t	pcyl;		/* number of physical cylinders */
    242 	uint16_t	write_reinstruct;	/* # sectors to skip, writes */
    243 	uint16_t	read_reinstruct;	/* # sectors to skip, reads */
    244 } vd_geom_t;
    245 
    246 
    247 /*
    248  * vDisk partition definition
    249  */
    250 typedef struct vd_partition {
    251 	uint16_t	id_tag;		/* ID tag of partition */
    252 	uint16_t	perm;		/* permission flags for partition */
    253 	uint32_t	reserved;	/* padding */
    254 	uint64_t	start;		/* block number of partition start */
    255 	uint64_t	nblocks;	/* number of blocks in partition */
    256 } vd_partition_t;
    257 
    258 /*
    259  * vDisk VTOC definition (VD_OP_GET_VTOC and VD_OP_SET_VTOC)
    260  */
    261 #define	VD_VOLNAME_LEN		8	/* length of volume_name field */
    262 #define	VD_ASCIILABEL_LEN	128	/* length of ascii_label field */
    263 typedef struct vd_vtoc {
    264 	char		volume_name[VD_VOLNAME_LEN];	/* volume name */
    265 	uint16_t	sector_size;		/* sector size in bytes */
    266 	uint16_t	num_partitions;		/* number of partitions */
    267 	char		ascii_label[VD_ASCIILABEL_LEN];	/* ASCII label */
    268 	vd_partition_t	partition[V_NUMPAR];	/* partition headers */
    269 } vd_vtoc_t;
    270 
    271 
    272 /*
    273  * vDisk EFI definition (VD_OP_GET_EFI and VD_OP_SET_EFI)
    274  */
    275 typedef struct vd_efi {
    276 	uint64_t	lba;		/* lba of the request */
    277 	uint64_t	length;		/* length of data */
    278 	char		data[1];	/* data of the request */
    279 } vd_efi_t;
    280 
    281 
    282 /*
    283  * vDisk DEVID definition (VD_OP_GET_DEVID)
    284  */
    285 #define	VD_DEVID_SIZE(l)	(sizeof (vd_devid_t) - 1 + l)
    286 #define	VD_DEVID_DEFAULT_LEN	128
    287 
    288 typedef struct vd_devid {
    289 	uint16_t	reserved;	/* padding */
    290 	uint16_t	type;		/* type of device id */
    291 	uint32_t	length;		/* length the device id */
    292 	char		id[1];		/* device id */
    293 } vd_devid_t;
    294 
    295 /*
    296  * vDisk CAPACITY definition (VD_OP_GET_CAPACITY)
    297  */
    298 typedef struct vd_capacity {
    299 	uint32_t	vdisk_block_size;	/* block size in bytes */
    300 	uint32_t	reserved;		/* reserved */
    301 	uint64_t	vdisk_size;		/* disk size in blocks */
    302 } vd_capacity_t;
    303 
    304 /* Identifier for unknown disk size */
    305 #define	VD_SIZE_UNKNOWN		-1
    306 
    307 /*
    308  * vDisk SCSI definition (VD_OP_SCSICMD)
    309  */
    310 typedef struct vd_scsi {
    311 	uint8_t		cmd_status;	/* command completion status */
    312 	uint8_t		sense_status;	/* sense command completion status */
    313 	uint8_t		task_attribute;	/* task attribute */
    314 	uint8_t		task_priority;	/* task priority */
    315 	uint8_t		crn;		/* command reference number */
    316 	uint8_t		reserved;	/* reserved */
    317 	uint16_t	timeout;	/* command timeout */
    318 	uint64_t	options;	/* options */
    319 	uint64_t	cdb_len;	/* CDB data length */
    320 	uint64_t	sense_len;	/* sense request length */
    321 	uint64_t	datain_len;	/* data in buffer length */
    322 	uint64_t	dataout_len;	/* data out buffer length */
    323 	char		data[1];	/* data (CDB, sense, data in/out */
    324 } vd_scsi_t;
    325 
    326 /* Minimum size of the vd_scsi structure */
    327 #define	VD_SCSI_SIZE	(sizeof (vd_scsi_t) - sizeof (uint64_t))
    328 
    329 /*
    330  * Macros to access data buffers in a vd_scsi structure. When using these
    331  * macros, the vd_scsi structure needs to be populated with the sizes of
    332  * data buffers allocated in the structure.
    333  */
    334 #define	VD_SCSI_DATA_CDB(vscsi)		\
    335 	((union scsi_cdb *)(uintptr_t)((vscsi)->data))
    336 
    337 #define	VD_SCSI_DATA_SENSE(vscsi) 	\
    338 	((struct scsi_extended_sense *)(uintptr_t)((vscsi)->data + \
    339 	    P2ROUNDUP((vscsi)->cdb_len, sizeof (uint64_t))))
    340 
    341 #define	VD_SCSI_DATA_IN(vscsi)		\
    342 	((uintptr_t)((vscsi)->data +	\
    343 	    P2ROUNDUP((vscsi)->cdb_len, sizeof (uint64_t)) + 	\
    344 	    P2ROUNDUP((vscsi)->sense_len, sizeof (uint64_t))))
    345 
    346 #define	VD_SCSI_DATA_OUT(vscsi)		\
    347 	((uintptr_t)((vscsi)->data +	\
    348 	    P2ROUNDUP((vscsi)->cdb_len, sizeof (uint64_t)) + 	\
    349 	    P2ROUNDUP((vscsi)->sense_len, sizeof (uint64_t)) + 	\
    350 	    P2ROUNDUP((vscsi)->datain_len, sizeof (uint64_t))))
    351 
    352 /* vDisk SCSI task attribute */
    353 #define	VD_SCSI_TASK_SIMPLE	0x01	/* simple task */
    354 #define	VD_SCSI_TASK_ORDERED	0x02	/* ordered task */
    355 #define	VD_SCSI_TASK_HQUEUE	0x03	/* head of queue task */
    356 #define	VD_SCSI_TASK_ACA	0x04	/* ACA task */
    357 
    358 /* vDisk SCSI options */
    359 #define	VD_SCSI_OPT_CRN		0x01	/* request has a CRN */
    360 #define	VD_SCSI_OPT_NORETRY	0x02	/* do not attempt any retry */
    361 
    362 /*
    363  * Copy the contents of a vd_geom_t to the contents of a dk_geom struct
    364  */
    365 #define	VD_GEOM2DK_GEOM(vd_geom, dk_geom)				\
    366 {									\
    367 	bzero((dk_geom), sizeof (*(dk_geom)));				\
    368 	(dk_geom)->dkg_ncyl		= (vd_geom)->ncyl;		\
    369 	(dk_geom)->dkg_acyl		= (vd_geom)->acyl;		\
    370 	(dk_geom)->dkg_bcyl		= (vd_geom)->bcyl;		\
    371 	(dk_geom)->dkg_nhead		= (vd_geom)->nhead;		\
    372 	(dk_geom)->dkg_nsect		= (vd_geom)->nsect;		\
    373 	(dk_geom)->dkg_intrlv		= (vd_geom)->intrlv;		\
    374 	(dk_geom)->dkg_apc		= (vd_geom)->apc;		\
    375 	(dk_geom)->dkg_rpm		= (vd_geom)->rpm;		\
    376 	(dk_geom)->dkg_pcyl		= (vd_geom)->pcyl;		\
    377 	(dk_geom)->dkg_write_reinstruct	= (vd_geom)->write_reinstruct;	\
    378 	(dk_geom)->dkg_read_reinstruct	= (vd_geom)->read_reinstruct;	\
    379 }
    380 
    381 /*
    382  * Copy the contents of a vd_vtoc_t to the contents of a vtoc struct
    383  */
    384 #define	VD_VTOC2VTOC(vd_vtoc, vtoc)					\
    385 {									\
    386 	bzero((vtoc), sizeof (*(vtoc)));				\
    387 	bcopy((vd_vtoc)->volume_name, (vtoc)->v_volume,			\
    388 	    MIN(sizeof ((vd_vtoc)->volume_name),			\
    389 		sizeof ((vtoc)->v_volume)));				\
    390 	bcopy((vd_vtoc)->ascii_label, (vtoc)->v_asciilabel,		\
    391 	    MIN(sizeof ((vd_vtoc)->ascii_label),			\
    392 		sizeof ((vtoc)->v_asciilabel)));			\
    393 	(vtoc)->v_sanity	= VTOC_SANE;				\
    394 	(vtoc)->v_version	= V_VERSION;				\
    395 	(vtoc)->v_sectorsz	= (vd_vtoc)->sector_size;		\
    396 	(vtoc)->v_nparts	= (vd_vtoc)->num_partitions;		\
    397 	for (int i = 0; i < (vd_vtoc)->num_partitions; i++) {		\
    398 		(vtoc)->v_part[i].p_tag	= (vd_vtoc)->partition[i].id_tag; \
    399 		(vtoc)->v_part[i].p_flag = (vd_vtoc)->partition[i].perm; \
    400 		(vtoc)->v_part[i].p_start = (vd_vtoc)->partition[i].start; \
    401 		(vtoc)->v_part[i].p_size = (vd_vtoc)->partition[i].nblocks; \
    402 	}								\
    403 }
    404 
    405 /*
    406  * Copy the contents of a dk_geom struct to the contents of a vd_geom_t
    407  */
    408 #define	DK_GEOM2VD_GEOM(dk_geom, vd_geom)				\
    409 {									\
    410 	bzero((vd_geom), sizeof (*(vd_geom)));				\
    411 	(vd_geom)->ncyl			= (dk_geom)->dkg_ncyl;		\
    412 	(vd_geom)->acyl			= (dk_geom)->dkg_acyl;		\
    413 	(vd_geom)->bcyl			= (dk_geom)->dkg_bcyl;		\
    414 	(vd_geom)->nhead		= (dk_geom)->dkg_nhead;		\
    415 	(vd_geom)->nsect		= (dk_geom)->dkg_nsect;		\
    416 	(vd_geom)->intrlv		= (dk_geom)->dkg_intrlv;	\
    417 	(vd_geom)->apc			= (dk_geom)->dkg_apc;		\
    418 	(vd_geom)->rpm			= (dk_geom)->dkg_rpm;		\
    419 	(vd_geom)->pcyl			= (dk_geom)->dkg_pcyl;		\
    420 	(vd_geom)->write_reinstruct	= (dk_geom)->dkg_write_reinstruct; \
    421 	(vd_geom)->read_reinstruct	= (dk_geom)->dkg_read_reinstruct; \
    422 }
    423 
    424 /*
    425  * Copy the contents of a vtoc struct to the contents of a vd_vtoc_t
    426  */
    427 #define	VTOC2VD_VTOC(vtoc, vd_vtoc)					\
    428 {									\
    429 	bzero((vd_vtoc), sizeof (*(vd_vtoc)));				\
    430 	bcopy((vtoc)->v_volume, (vd_vtoc)->volume_name,			\
    431 	    MIN(sizeof ((vtoc)->v_volume),				\
    432 		sizeof ((vd_vtoc)->volume_name)));			\
    433 	bcopy((vtoc)->v_asciilabel, (vd_vtoc)->ascii_label,		\
    434 	    MIN(sizeof ((vtoc)->v_asciilabel),				\
    435 		sizeof ((vd_vtoc)->ascii_label)));			\
    436 	(vd_vtoc)->sector_size			= (vtoc)->v_sectorsz;	\
    437 	(vd_vtoc)->num_partitions		= (vtoc)->v_nparts;	\
    438 	for (int i = 0; i < (vtoc)->v_nparts; i++) {			\
    439 		(vd_vtoc)->partition[i].id_tag	= (vtoc)->v_part[i].p_tag; \
    440 		(vd_vtoc)->partition[i].perm	= (vtoc)->v_part[i].p_flag; \
    441 		(vd_vtoc)->partition[i].start	= (vtoc)->v_part[i].p_start; \
    442 		(vd_vtoc)->partition[i].nblocks	= (vtoc)->v_part[i].p_size; \
    443 	}								\
    444 }
    445 
    446 /*
    447  * Copy the contents of a vd_efi_t to the contents of a dk_efi_t.
    448  * Note that (dk_efi)->dki_data and (vd_efi)->data should be correctly
    449  * initialized prior to using this macro.
    450  */
    451 #define	VD_EFI2DK_EFI(vd_efi, dk_efi)					\
    452 {									\
    453 	(dk_efi)->dki_lba	= (vd_efi)->lba;			\
    454 	(dk_efi)->dki_length	= (vd_efi)->length;			\
    455 	bcopy((vd_efi)->data, (dk_efi)->dki_data, (dk_efi)->dki_length); \
    456 }
    457 
    458 /*
    459  * Copy the contents of dk_efi_t to the contents of vd_efi_t.
    460  * Note that (dk_efi)->dki_data and (vd_efi)->data should be correctly
    461  * initialized prior to using this macro.
    462  */
    463 #define	DK_EFI2VD_EFI(dk_efi, vd_efi)					\
    464 {									\
    465 	(vd_efi)->lba		= (dk_efi)->dki_lba;			\
    466 	(vd_efi)->length	= (dk_efi)->dki_length;			\
    467 	bcopy((dk_efi)->dki_data, (vd_efi)->data, (vd_efi)->length);	\
    468 }
    469 
    470 #define	VD_MEDIATYPE2DK_MEDIATYPE(mt)					\
    471 	((mt) == VD_MEDIA_FIXED ? DK_FIXED_DISK :			\
    472 	    (mt) == VD_MEDIA_CD ? DK_CDROM :				\
    473 	    (mt) == VD_MEDIA_DVD ? DK_DVDROM :				\
    474 	    DK_UNKNOWN)
    475 
    476 /*
    477  * If the media type returned by the DKIOCGMEDIAINFO ioctl is greater than
    478  * 0xFFFF then this is not an optical media and we consider that this is
    479  * a fixed media.
    480  *
    481  * Otherwise, we have an optical media. If this is a SCSI media then the media
    482  * type is actually the profile number returned by the SCSI GET CONFIGURATION
    483  * command. In that case, the possible values we can have are described in the
    484  * SCSI Multi-Media Commands (MMC) documentation.
    485  *
    486  * Not all SCSI optical media profile numbers are defined in Solaris. However
    487  * undefined profiles are essentially different variants of DVD (like Blu-Ray
    488  * or HD-DVD). So we consider that any optical media that we can not explicitly
    489  * identify is a DVD.
    490  */
    491 #define	DK_MEDIA_OPTICAL_MAX	0xFFFF
    492 
    493 #define	DK_MEDIATYPE2VD_MEDIATYPE(mt)					\
    494 	(((mt) > DK_MEDIA_OPTICAL_MAX)? VD_MEDIA_FIXED :		\
    495 	    (mt) == DK_REMOVABLE_DISK ? VD_MEDIA_FIXED :		\
    496 	    (mt) == DK_MO_ERASABLE ? VD_MEDIA_FIXED :			\
    497 	    (mt) == DK_MO_WRITEONCE ? VD_MEDIA_FIXED :			\
    498 	    (mt) == DK_AS_MO ? VD_MEDIA_FIXED :				\
    499 	    (mt) == DK_CDROM ? VD_MEDIA_CD :				\
    500 	    (mt) == DK_CDR ? VD_MEDIA_CD :				\
    501 	    (mt) == DK_CDRW ? VD_MEDIA_CD :				\
    502 	    VD_MEDIA_DVD)
    503 
    504 /*
    505  * Hooks for EFI support
    506  */
    507 
    508 /*
    509  * The EFI alloc_and_read() function will use some ioctls to get EFI data
    510  * but the device reference we will use is different depending if the command
    511  * is issued from the vDisk server side (vds) or from the vDisk client side
    512  * (vdc). The vd_efi_dev structure is filled by vdc/vds to indicate the ioctl
    513  * function to call back and to provide information about the virtual disk.
    514  */
    515 typedef int (*vd_efi_ioctl_func)(void *, int, uintptr_t);
    516 
    517 typedef	struct vd_efi_dev {
    518 	void *vdisk;			/* opaque pointer to the vdisk */
    519 	size_t block_size;		/* vdisk block size */
    520 	size_t disk_size;		/* vdisk size in blocks */
    521 	vd_efi_ioctl_func vdisk_ioctl;	/* vdisk ioctl function */
    522 } vd_efi_dev_t;
    523 
    524 #define	VDSK_EFI_DEV_SET(efi_dev, vdsk, ioctl, bsize, dsize)	\
    525 	(efi_dev).vdisk = vdsk;					\
    526 	(efi_dev).vdisk_ioctl = ioctl;				\
    527 	(efi_dev).block_size = bsize;				\
    528 	(efi_dev).disk_size = dsize;
    529 
    530 
    531 int vd_efi_alloc_and_read(vd_efi_dev_t *dev, efi_gpt_t **gpt, efi_gpe_t **gpe);
    532 void vd_efi_free(vd_efi_dev_t *dev, efi_gpt_t *gpt, efi_gpe_t *gpe);
    533 
    534 /*
    535  * Macros to update the I/O statistics kstat consumed by iostat(1m).
    536  */
    537 
    538 /*
    539  * Given a pointer to the instance private data of a vDisk driver (vd),
    540  * the type of operation and the number of bytes read/written, this macro
    541  * updates the I/O statistics in the kstat.
    542  */
    543 #define	VD_UPDATE_IO_STATS(vd, op, len)					\
    544 	{								\
    545 		ASSERT((vd) != NULL);					\
    546 		ASSERT(MUTEX_HELD(&(vd)->lock));			\
    547 		ASSERT(((op) == VD_OP_BREAD) || ((op) == VD_OP_BWRITE));\
    548 		if ((vd)->io_stats != NULL) { 				\
    549 			kstat_io_t *kip = KSTAT_IO_PTR((vd)->io_stats);	\
    550 			if ((op) == VD_OP_BREAD) {			\
    551 				kip->reads++;				\
    552 				kip->nread += (len);			\
    553 			} else {					\
    554 				kip->writes++;				\
    555 				kip->nwritten += (len);			\
    556 			}						\
    557 		}							\
    558 	}
    559 
    560 /*
    561  * These wrapper macros take a pointer to the I/O statistics kstat and
    562  * update the queue length statistics. These are 'safe' wrappers which
    563  * check to see if the kstat was created when the vDisk instance was
    564  * added (i.e. is not NULL).
    565  */
    566 #define	VD_KSTAT_WAITQ_ENTER(vd)					\
    567 	if ((vd)->io_stats != NULL) {					\
    568 		ASSERT(MUTEX_HELD(&(vd)->lock));			\
    569 		kstat_waitq_enter(KSTAT_IO_PTR((vd)->io_stats));	\
    570 	}
    571 
    572 #define	VD_KSTAT_WAITQ_EXIT(vd)						\
    573 	if ((vd)->io_stats != NULL) {					\
    574 		ASSERT(MUTEX_HELD(&(vd)->lock));			\
    575 		kstat_waitq_exit(KSTAT_IO_PTR((vd)->io_stats));		\
    576 	}
    577 
    578 #define	VD_KSTAT_WAITQ_TO_RUNQ(vd)					\
    579 	if ((vd)->io_stats != NULL) {					\
    580 		ASSERT(MUTEX_HELD(&(vd)->lock));			\
    581 		kstat_waitq_to_runq(KSTAT_IO_PTR((vd)->io_stats));	\
    582 	}
    583 
    584 #define	VD_KSTAT_RUNQ_ENTER(vd)						\
    585 	if ((vd)->io_stats != NULL) {					\
    586 		ASSERT(MUTEX_HELD(&(vd)->lock));			\
    587 		kstat_runq_enter(KSTAT_IO_PTR((vd)->io_stats));		\
    588 	}
    589 
    590 #define	VD_KSTAT_RUNQ_EXIT(vd)						\
    591 	if ((vd)->io_stats != NULL) {					\
    592 		ASSERT(MUTEX_HELD(&(vd)->lock));			\
    593 		kstat_runq_exit(KSTAT_IO_PTR((vd)->io_stats));		\
    594 	}
    595 
    596 /*
    597  * Given a pointer to the instance private data of a vDisk driver (vd) and
    598  * the name of the error stats entry we wish to update, increment that value
    599  */
    600 #define	VD_UPDATE_ERR_STATS(vd, stat_entry)				\
    601 {									\
    602 	ASSERT((vd) != NULL);						\
    603 	ASSERT(MUTEX_HELD(&(vd)->lock));				\
    604 	if ((vd)->err_stats != NULL) {					\
    605 		vd_err_stats_t	*stp;					\
    606 		stp = (vd_err_stats_t *)(vd)->err_stats->ks_data;	\
    607 		stp->stat_entry.value.ui32++;				\
    608 	}								\
    609 }
    610 
    611 /* Structure to record vDisk error statistics */
    612 typedef struct vd_err_stats {
    613 	struct kstat_named	vd_softerrs;	/* Softerrs */
    614 	struct kstat_named	vd_transerrs;	/* Transport errs */
    615 	struct kstat_named	vd_protoerrs;	/* VIO Protocol errs */
    616 	struct kstat_named	vd_vid;		/* Vendor ID */
    617 	struct kstat_named	vd_pid;		/* Product ID */
    618 	struct kstat_named	vd_capacity;	/* Capacity of the disk */
    619 } vd_err_stats_t;
    620 
    621 
    622 #ifdef	__cplusplus
    623 }
    624 #endif
    625 
    626 #endif	/* _VDSK_COMMON_H */
    627