xref: /illumos-gate/usr/src/uts/sun4v/sys/vdsk_common.h (revision bbf21555)
11ae08745Sheppo /*
21ae08745Sheppo  * CDDL HEADER START
31ae08745Sheppo  *
41ae08745Sheppo  * The contents of this file are subject to the terms of the
51ae08745Sheppo  * Common Development and Distribution License (the "License").
61ae08745Sheppo  * You may not use this file except in compliance with the License.
71ae08745Sheppo  *
81ae08745Sheppo  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91ae08745Sheppo  * or http://www.opensolaris.org/os/licensing.
101ae08745Sheppo  * See the License for the specific language governing permissions
111ae08745Sheppo  * and limitations under the License.
121ae08745Sheppo  *
131ae08745Sheppo  * When distributing Covered Code, include this CDDL HEADER in each
141ae08745Sheppo  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151ae08745Sheppo  * If applicable, add the following below this CDDL HEADER, with the
161ae08745Sheppo  * fields enclosed by brackets "[]" replaced with your own identifying
171ae08745Sheppo  * information: Portions Copyright [yyyy] [name of copyright owner]
181ae08745Sheppo  *
191ae08745Sheppo  * CDDL HEADER END
201ae08745Sheppo  */
211ae08745Sheppo 
221ae08745Sheppo /*
23ca6d1280SAlexandre Chartre  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
241ae08745Sheppo  */
251ae08745Sheppo 
261ae08745Sheppo #ifndef	_VDSK_COMMON_H
271ae08745Sheppo #define	_VDSK_COMMON_H
281ae08745Sheppo 
291ae08745Sheppo #ifdef __cplusplus
301ae08745Sheppo extern "C" {
311ae08745Sheppo #endif
321ae08745Sheppo 
331ae08745Sheppo /*
341ae08745Sheppo  * This header file contains the private LDoms Virtual Disk (vDisk) definitions
351ae08745Sheppo  * common to both the server (vds) and the client (vdc)
361ae08745Sheppo  */
371ae08745Sheppo 
384bac2208Snarayan #include <sys/efi_partition.h>
391ae08745Sheppo #include <sys/machparam.h>
401ae08745Sheppo #include <sys/vtoc.h>
411ae08745Sheppo 
421ae08745Sheppo #include <sys/ldc.h>
431ae08745Sheppo #include <sys/vio_common.h>
441ae08745Sheppo #include <sys/vio_mailbox.h>
451ae08745Sheppo 
461ae08745Sheppo /*
471ae08745Sheppo  * vDisk definitions
481ae08745Sheppo  */
491ae08745Sheppo 
501ae08745Sheppo /*
511ae08745Sheppo  * The number of Descriptor Ring entries
521ae08745Sheppo  *
531ae08745Sheppo  * Constraints:
541ae08745Sheppo  * 	- overall DRing size must be greater than 8K (MMU_PAGESIZE)
551ae08745Sheppo  *	- overall DRing size should be 8K aligned (desirable but not enforced)
561ae08745Sheppo  *	- DRing entry must be 8 byte aligned
571ae08745Sheppo  */
581ae08745Sheppo #define	VD_DRING_LEN		512
591ae08745Sheppo 
601ae08745Sheppo /*
611ae08745Sheppo  *
621ae08745Sheppo  */
631ae08745Sheppo #define	VD_DRING_ENTRY_SZ	(sizeof (vd_dring_entry_t) + 		\
641ae08745Sheppo 		(sizeof (ldc_mem_cookie_t) * (VD_MAX_COOKIES - 1)))
651ae08745Sheppo 
661ae08745Sheppo /*
671ae08745Sheppo  * The maximum block size we can transmit using one Descriptor Ring entry
681ae08745Sheppo  *
691ae08745Sheppo  * Currently no FS uses more than 128K and it doesn't look like they
701ae08745Sheppo  * will either as there is no perf gain to be had by larger values.
711ae08745Sheppo  * ( see ZFS comment at definition of SPA_MAXBLOCKSIZE ).
721ae08745Sheppo  *
731ae08745Sheppo  * We choose 256K to give us some headroom.
741ae08745Sheppo  */
751ae08745Sheppo #define	VD_MAX_BLOCK_SIZE	(256 * 1024)
761ae08745Sheppo 
771ae08745Sheppo #define	VD_MAX_COOKIES		((VD_MAX_BLOCK_SIZE / PAGESIZE) + 1)
781ae08745Sheppo #define	VD_USEC_TIMEOUT		20000
791ae08745Sheppo #define	VD_LDC_IDS_PROP		"ldc-ids"
80e1ebb9ecSlm #define	VD_LDC_MTU		256
811ae08745Sheppo 
821ae08745Sheppo /*
831ae08745Sheppo  * Flags used by ioctl routines to indicate if a copyin/copyout is needed
841ae08745Sheppo  */
851ae08745Sheppo #define	VD_COPYOUT		0x1
861ae08745Sheppo #define	VD_COPYIN		0x2
871ae08745Sheppo 
881ae08745Sheppo /*
891ae08745Sheppo  * vDisk operations on physical devices
901ae08745Sheppo  */
911ae08745Sheppo #define	VD_OP_BREAD		0x01	/* Block Read */
921ae08745Sheppo #define	VD_OP_BWRITE		0x02	/* Block Write */
931ae08745Sheppo #define	VD_OP_FLUSH		0x03	/* Flush disk write cache contents */
941ae08745Sheppo #define	VD_OP_GET_WCE		0x04	/* Get disk W$ status */
951ae08745Sheppo #define	VD_OP_SET_WCE		0x05	/* Enable/Disable disk W$ */
961ae08745Sheppo #define	VD_OP_GET_VTOC		0x06	/* Get VTOC */
971ae08745Sheppo #define	VD_OP_SET_VTOC		0x07	/* Set VTOC */
981ae08745Sheppo #define	VD_OP_GET_DISKGEOM	0x08	/* Get disk geometry */
991ae08745Sheppo #define	VD_OP_SET_DISKGEOM	0x09	/* Set disk geometry */
1001ae08745Sheppo #define	VD_OP_SCSICMD		0x0a	/* SCSI control command */
1014bac2208Snarayan #define	VD_OP_GET_DEVID		0x0b	/* Get device id */
1024bac2208Snarayan #define	VD_OP_GET_EFI 		0x0c	/* Get EFI */
1034bac2208Snarayan #define	VD_OP_SET_EFI 		0x0d	/* Set EFI */
1042f5224aeSachartre #define	VD_OP_RESET		0x0e	/* Reset disk */
1052f5224aeSachartre #define	VD_OP_GET_ACCESS	0x0f	/* Get disk access */
1062f5224aeSachartre #define	VD_OP_SET_ACCESS	0x10	/* Set disk access */
1072f5224aeSachartre #define	VD_OP_GET_CAPACITY	0x11	/* Get disk capacity */
1081ae08745Sheppo #define	VD_OP_MASK		0xFF	/* mask of all possible operations */
1092f5224aeSachartre #define	VD_OP_COUNT		0x11	/* Number of operations */
1102f5224aeSachartre 
1112f5224aeSachartre /*
1122f5224aeSachartre  * Status for the VD_OP_GET_ACCESS operation
1132f5224aeSachartre  */
1142f5224aeSachartre #define	VD_ACCESS_DENIED	0x00	/* access is not allowed */
1152f5224aeSachartre #define	VD_ACCESS_ALLOWED	0x01	/* access is allowed */
1162f5224aeSachartre 
1172f5224aeSachartre /*
1182f5224aeSachartre  * Flags for the VD_OP_SET_ACCESS operation
1192f5224aeSachartre  */
1202f5224aeSachartre #define	VD_ACCESS_SET_CLEAR	0x00	/* clear exclusive access rights */
1212f5224aeSachartre #define	VD_ACCESS_SET_EXCLUSIVE	0x01	/* set exclusive access rights */
1222f5224aeSachartre #define	VD_ACCESS_SET_PREEMPT	0x02	/* forcefully set access rights */
1232f5224aeSachartre #define	VD_ACCESS_SET_PRESERVE	0x04	/* preserve access rights */
1244bac2208Snarayan 
12517cadca8Slm /*
12617cadca8Slm  * This is a mask of all the basic operations supported by all
12717cadca8Slm  * disk types (v1.0).
12817cadca8Slm  */
12917cadca8Slm #define	VD_OP_MASK_READ			\
13017cadca8Slm 	((1 << VD_OP_BREAD) |			\
13117cadca8Slm 	(1 << VD_OP_GET_WCE) |			\
13217cadca8Slm 	(1 << VD_OP_GET_VTOC) |			\
13317cadca8Slm 	(1 << VD_OP_GET_DISKGEOM) |		\
13417cadca8Slm 	(1 << VD_OP_GET_DEVID) |		\
13517cadca8Slm 	(1 << VD_OP_GET_EFI))
13617cadca8Slm 
13717cadca8Slm #define	VD_OP_MASK_WRITE			\
13817cadca8Slm 	((1 << VD_OP_BWRITE) |			\
13917cadca8Slm 	(1 << VD_OP_FLUSH) |			\
14017cadca8Slm 	(1 << VD_OP_SET_WCE) |			\
14117cadca8Slm 	(1 << VD_OP_SET_VTOC) |			\
14217cadca8Slm 	(1 << VD_OP_SET_DISKGEOM) |		\
14317cadca8Slm 	(1 << VD_OP_SET_EFI))
14417cadca8Slm 
1452f5224aeSachartre /*
1462f5224aeSachartre  * Mask for additional operations provided for SCSI disks (v1.1)
1472f5224aeSachartre  */
1482f5224aeSachartre #define	VD_OP_MASK_SCSI				\
1492f5224aeSachartre 	((1 << VD_OP_SCSICMD) |			\
1502f5224aeSachartre 	(1 << VD_OP_RESET) |			\
1512f5224aeSachartre 	(1 << VD_OP_GET_ACCESS) |		\
152de3a5331SRamesh Chitrothu 	(1 << VD_OP_SET_ACCESS))
15317cadca8Slm 
15417cadca8Slm /*
15517cadca8Slm  * macro to check if the operation 'op' is supported by checking the list
15617cadca8Slm  * of operations supported which is exported by the vDisk server.
15717cadca8Slm  */
15817cadca8Slm #define	VD_OP_SUPPORTED(ops_bitmask, op)	((ops_bitmask) & (1 << (op)))
15917cadca8Slm 
16087a7269eSachartre /*
16187a7269eSachartre  * Slice for absolute disk transaction.
16287a7269eSachartre  */
16387a7269eSachartre #define	VD_SLICE_NONE		0xFF
16487a7269eSachartre 
1654bac2208Snarayan /*
1664bac2208Snarayan  * EFI disks do not have a slice 7. Actually that slice is used to represent
1674bac2208Snarayan  * the whole disk.
1684bac2208Snarayan  */
1694bac2208Snarayan #define	VD_EFI_WD_SLICE	7
1701ae08745Sheppo 
1711ae08745Sheppo /*
1721ae08745Sheppo  * Definitions of the various ways vds can export disk support to vdc.
1731ae08745Sheppo  */
1741ae08745Sheppo typedef enum vd_disk_type {
1751ae08745Sheppo 	VD_DISK_TYPE_UNK = 0,		/* Unknown device type */
1761ae08745Sheppo 	VD_DISK_TYPE_SLICE,		/* slice in block device */
1771ae08745Sheppo 	VD_DISK_TYPE_DISK		/* entire disk (slice 2) */
1781ae08745Sheppo } vd_disk_type_t;
1791ae08745Sheppo 
1804bac2208Snarayan /*
1814bac2208Snarayan  * Definitions of the various disk label that vDisk supports.
1824bac2208Snarayan  */
1834bac2208Snarayan typedef enum vd_disk_label {
1844bac2208Snarayan 	VD_DISK_LABEL_UNK = 0,		/* Unknown disk label */
1854bac2208Snarayan 	VD_DISK_LABEL_VTOC,		/* VTOC disk label */
1864bac2208Snarayan 	VD_DISK_LABEL_EFI		/* EFI disk label */
1874bac2208Snarayan } vd_disk_label_t;
1884bac2208Snarayan 
1891ae08745Sheppo /*
1901ae08745Sheppo  * vDisk Descriptor payload
1911ae08745Sheppo  */
1921ae08745Sheppo typedef struct vd_dring_payload {
1931ae08745Sheppo 	uint64_t	req_id;		/* The request ID being processed */
1941ae08745Sheppo 	uint8_t		operation;	/* operation for server to perform */
1951ae08745Sheppo 	uint8_t		slice;		/* The disk slice being accessed */
1961ae08745Sheppo 	uint16_t	resv1;		/* padding */
1971ae08745Sheppo 	uint32_t	status;		/* "errno" of server operation */
1981ae08745Sheppo 	uint64_t	addr;		/* LP64	diskaddr_t (block I/O) */
1991ae08745Sheppo 	uint64_t	nbytes;		/* LP64 size_t */
2001ae08745Sheppo 	uint32_t	ncookies;	/* Number of cookies used */
2011ae08745Sheppo 	uint32_t	resv2;		/* padding */
2021ae08745Sheppo 
2031ae08745Sheppo 	ldc_mem_cookie_t	cookie[1];	/* variable sized array */
2041ae08745Sheppo } vd_dring_payload_t;
2051ae08745Sheppo 
2061ae08745Sheppo 
2071ae08745Sheppo /*
2081ae08745Sheppo  * vDisk Descriptor entry
2091ae08745Sheppo  */
2101ae08745Sheppo typedef struct vd_dring_entry {
2111ae08745Sheppo 	vio_dring_entry_hdr_t		hdr;		/* common header */
2121ae08745Sheppo 	vd_dring_payload_t		payload;	/* disk specific data */
2131ae08745Sheppo } vd_dring_entry_t;
2141ae08745Sheppo 
215edcc0754Sachartre /*
216edcc0754Sachartre  * vDisk logical partition
217edcc0754Sachartre  */
218edcc0754Sachartre typedef struct vd_slice {
219edcc0754Sachartre 	daddr_t	start;		/* block number of slice start */
220edcc0754Sachartre 	daddr_t nblocks;	/* number of blocks in the slice */
221edcc0754Sachartre } vd_slice_t;
222edcc0754Sachartre 
2231ae08745Sheppo 
2241ae08745Sheppo /*
2251ae08745Sheppo  * vDisk control operation structures
2261ae08745Sheppo  */
2271ae08745Sheppo 
2281ae08745Sheppo /*
2290a55fbb7Slm  * vDisk geometry definition (VD_OP_GET_DISKGEOM and VD_OP_SET_DISKGEOM)
2300a55fbb7Slm  */
2310a55fbb7Slm typedef struct vd_geom {
2320a55fbb7Slm 	uint16_t	ncyl;		/* number of data cylinders */
2330a55fbb7Slm 	uint16_t	acyl;		/* number of alternate cylinders */
2340a55fbb7Slm 	uint16_t	bcyl;		/* cyl offset for fixed head area */
2350a55fbb7Slm 	uint16_t	nhead;		/* number of heads */
2360a55fbb7Slm 	uint16_t	nsect;		/* number of data sectors per track */
2370a55fbb7Slm 	uint16_t	intrlv;		/* interleave factor */
2380a55fbb7Slm 	uint16_t	apc;		/* alternates per cyl (SCSI only) */
2390a55fbb7Slm 	uint16_t	rpm;		/* revolutions per minute */
2400a55fbb7Slm 	uint16_t	pcyl;		/* number of physical cylinders */
2410a55fbb7Slm 	uint16_t	write_reinstruct;	/* # sectors to skip, writes */
2420a55fbb7Slm 	uint16_t	read_reinstruct;	/* # sectors to skip, reads */
2430a55fbb7Slm } vd_geom_t;
2440a55fbb7Slm 
2450a55fbb7Slm 
2460a55fbb7Slm /*
2470a55fbb7Slm  * vDisk partition definition
2481ae08745Sheppo  */
2491ae08745Sheppo typedef struct vd_partition {
2500a55fbb7Slm 	uint16_t	id_tag;		/* ID tag of partition */
2510a55fbb7Slm 	uint16_t	perm;		/* permission flags for partition */
2521ae08745Sheppo 	uint32_t	reserved;	/* padding */
2530a55fbb7Slm 	uint64_t	start;		/* block number of partition start */
2540a55fbb7Slm 	uint64_t	nblocks;	/* number of blocks in partition */
2551ae08745Sheppo } vd_partition_t;
2561ae08745Sheppo 
2570a55fbb7Slm /*
2580a55fbb7Slm  * vDisk VTOC definition (VD_OP_GET_VTOC and VD_OP_SET_VTOC)
2590a55fbb7Slm  */
2600a55fbb7Slm #define	VD_VOLNAME_LEN		8	/* length of volume_name field */
2610a55fbb7Slm #define	VD_ASCIILABEL_LEN	128	/* length of ascii_label field */
2621ae08745Sheppo typedef struct vd_vtoc {
2630a55fbb7Slm 	char		volume_name[VD_VOLNAME_LEN];	/* volume name */
2640a55fbb7Slm 	uint16_t	sector_size;		/* sector size in bytes */
2650a55fbb7Slm 	uint16_t	num_partitions;		/* number of partitions */
2660a55fbb7Slm 	char		ascii_label[VD_ASCIILABEL_LEN];	/* ASCII label */
2670a55fbb7Slm 	vd_partition_t	partition[V_NUMPAR];	/* partition headers */
2681ae08745Sheppo } vd_vtoc_t;
2691ae08745Sheppo 
2701ae08745Sheppo 
2714bac2208Snarayan /*
2724bac2208Snarayan  * vDisk EFI definition (VD_OP_GET_EFI and VD_OP_SET_EFI)
2734bac2208Snarayan  */
2744bac2208Snarayan typedef struct vd_efi {
2754bac2208Snarayan 	uint64_t	lba;		/* lba of the request */
2764bac2208Snarayan 	uint64_t	length;		/* length of data */
2774bac2208Snarayan 	char		data[1];	/* data of the request */
2784bac2208Snarayan } vd_efi_t;
2794bac2208Snarayan 
2804bac2208Snarayan 
2814bac2208Snarayan /*
2824bac2208Snarayan  * vDisk DEVID definition (VD_OP_GET_DEVID)
2834bac2208Snarayan  */
2844bac2208Snarayan #define	VD_DEVID_SIZE(l)	(sizeof (vd_devid_t) - 1 + l)
2854bac2208Snarayan #define	VD_DEVID_DEFAULT_LEN	128
2864bac2208Snarayan 
2874bac2208Snarayan typedef struct vd_devid {
2884bac2208Snarayan 	uint16_t	reserved;	/* padding */
2894bac2208Snarayan 	uint16_t	type;		/* type of device id */
2904bac2208Snarayan 	uint32_t	length;		/* length the device id */
2914bac2208Snarayan 	char		id[1];		/* device id */
2924bac2208Snarayan } vd_devid_t;
2934bac2208Snarayan 
2942f5224aeSachartre /*
2952f5224aeSachartre  * vDisk CAPACITY definition (VD_OP_GET_CAPACITY)
2962f5224aeSachartre  */
2972f5224aeSachartre typedef struct vd_capacity {
2982f5224aeSachartre 	uint32_t	vdisk_block_size;	/* block size in bytes */
2992f5224aeSachartre 	uint32_t	reserved;		/* reserved */
3002f5224aeSachartre 	uint64_t	vdisk_size;		/* disk size in blocks */
3012f5224aeSachartre } vd_capacity_t;
3022f5224aeSachartre 
3032f5224aeSachartre /* Identifier for unknown disk size */
3042f5224aeSachartre #define	VD_SIZE_UNKNOWN		-1
3052f5224aeSachartre 
3062f5224aeSachartre /*
3072f5224aeSachartre  * vDisk SCSI definition (VD_OP_SCSICMD)
3082f5224aeSachartre  */
3092f5224aeSachartre typedef struct vd_scsi {
3102f5224aeSachartre 	uint8_t		cmd_status;	/* command completion status */
3112f5224aeSachartre 	uint8_t		sense_status;	/* sense command completion status */
3122f5224aeSachartre 	uint8_t		task_attribute;	/* task attribute */
3132f5224aeSachartre 	uint8_t		task_priority;	/* task priority */
3142f5224aeSachartre 	uint8_t		crn;		/* command reference number */
3152f5224aeSachartre 	uint8_t		reserved;	/* reserved */
3162f5224aeSachartre 	uint16_t	timeout;	/* command timeout */
3172f5224aeSachartre 	uint64_t	options;	/* options */
3182f5224aeSachartre 	uint64_t	cdb_len;	/* CDB data length */
3192f5224aeSachartre 	uint64_t	sense_len;	/* sense request length */
3202f5224aeSachartre 	uint64_t	datain_len;	/* data in buffer length */
3212f5224aeSachartre 	uint64_t	dataout_len;	/* data out buffer length */
3222f5224aeSachartre 	char		data[1];	/* data (CDB, sense, data in/out */
3232f5224aeSachartre } vd_scsi_t;
3242f5224aeSachartre 
3252f5224aeSachartre /* Minimum size of the vd_scsi structure */
3262f5224aeSachartre #define	VD_SCSI_SIZE	(sizeof (vd_scsi_t) - sizeof (uint64_t))
3272f5224aeSachartre 
3282f5224aeSachartre /*
3292f5224aeSachartre  * Macros to access data buffers in a vd_scsi structure. When using these
3302f5224aeSachartre  * macros, the vd_scsi structure needs to be populated with the sizes of
3312f5224aeSachartre  * data buffers allocated in the structure.
3322f5224aeSachartre  */
3332f5224aeSachartre #define	VD_SCSI_DATA_CDB(vscsi)		\
3342f5224aeSachartre 	((union scsi_cdb *)(uintptr_t)((vscsi)->data))
3352f5224aeSachartre 
3362f5224aeSachartre #define	VD_SCSI_DATA_SENSE(vscsi) 	\
3372f5224aeSachartre 	((struct scsi_extended_sense *)(uintptr_t)((vscsi)->data + \
3382f5224aeSachartre 	    P2ROUNDUP((vscsi)->cdb_len, sizeof (uint64_t))))
3392f5224aeSachartre 
3402f5224aeSachartre #define	VD_SCSI_DATA_IN(vscsi)		\
3412f5224aeSachartre 	((uintptr_t)((vscsi)->data +	\
3422f5224aeSachartre 	    P2ROUNDUP((vscsi)->cdb_len, sizeof (uint64_t)) + 	\
3432f5224aeSachartre 	    P2ROUNDUP((vscsi)->sense_len, sizeof (uint64_t))))
3442f5224aeSachartre 
3452f5224aeSachartre #define	VD_SCSI_DATA_OUT(vscsi)		\
3462f5224aeSachartre 	((uintptr_t)((vscsi)->data +	\
3472f5224aeSachartre 	    P2ROUNDUP((vscsi)->cdb_len, sizeof (uint64_t)) + 	\
3482f5224aeSachartre 	    P2ROUNDUP((vscsi)->sense_len, sizeof (uint64_t)) + 	\
3492f5224aeSachartre 	    P2ROUNDUP((vscsi)->datain_len, sizeof (uint64_t))))
3502f5224aeSachartre 
3512f5224aeSachartre /* vDisk SCSI task attribute */
3522f5224aeSachartre #define	VD_SCSI_TASK_SIMPLE	0x01	/* simple task */
3532f5224aeSachartre #define	VD_SCSI_TASK_ORDERED	0x02	/* ordered task */
3542f5224aeSachartre #define	VD_SCSI_TASK_HQUEUE	0x03	/* head of queue task */
3552f5224aeSachartre #define	VD_SCSI_TASK_ACA	0x04	/* ACA task */
3562f5224aeSachartre 
3572f5224aeSachartre /* vDisk SCSI options */
3582f5224aeSachartre #define	VD_SCSI_OPT_CRN		0x01	/* request has a CRN */
3592f5224aeSachartre #define	VD_SCSI_OPT_NORETRY	0x02	/* do not attempt any retry */
3602f5224aeSachartre 
3611ae08745Sheppo /*
3620a55fbb7Slm  * Copy the contents of a vd_geom_t to the contents of a dk_geom struct
3631ae08745Sheppo  */
3640a55fbb7Slm #define	VD_GEOM2DK_GEOM(vd_geom, dk_geom)				\
3650a55fbb7Slm {									\
3660a55fbb7Slm 	bzero((dk_geom), sizeof (*(dk_geom)));				\
3670a55fbb7Slm 	(dk_geom)->dkg_ncyl		= (vd_geom)->ncyl;		\
3680a55fbb7Slm 	(dk_geom)->dkg_acyl		= (vd_geom)->acyl;		\
3690a55fbb7Slm 	(dk_geom)->dkg_bcyl		= (vd_geom)->bcyl;		\
3700a55fbb7Slm 	(dk_geom)->dkg_nhead		= (vd_geom)->nhead;		\
3710a55fbb7Slm 	(dk_geom)->dkg_nsect		= (vd_geom)->nsect;		\
3720a55fbb7Slm 	(dk_geom)->dkg_intrlv		= (vd_geom)->intrlv;		\
3730a55fbb7Slm 	(dk_geom)->dkg_apc		= (vd_geom)->apc;		\
3740a55fbb7Slm 	(dk_geom)->dkg_rpm		= (vd_geom)->rpm;		\
3750a55fbb7Slm 	(dk_geom)->dkg_pcyl		= (vd_geom)->pcyl;		\
3760a55fbb7Slm 	(dk_geom)->dkg_write_reinstruct	= (vd_geom)->write_reinstruct;	\
3770a55fbb7Slm 	(dk_geom)->dkg_read_reinstruct	= (vd_geom)->read_reinstruct;	\
3780a55fbb7Slm }
3790a55fbb7Slm 
3800a55fbb7Slm /*
3810a55fbb7Slm  * Copy the contents of a vd_vtoc_t to the contents of a vtoc struct
3820a55fbb7Slm  */
3830a55fbb7Slm #define	VD_VTOC2VTOC(vd_vtoc, vtoc)					\
3840a55fbb7Slm {									\
3850a55fbb7Slm 	bzero((vtoc), sizeof (*(vtoc)));				\
3860a55fbb7Slm 	bcopy((vd_vtoc)->volume_name, (vtoc)->v_volume,			\
3870a55fbb7Slm 	    MIN(sizeof ((vd_vtoc)->volume_name),			\
3880a55fbb7Slm 		sizeof ((vtoc)->v_volume)));				\
3890a55fbb7Slm 	bcopy((vd_vtoc)->ascii_label, (vtoc)->v_asciilabel,		\
3900a55fbb7Slm 	    MIN(sizeof ((vd_vtoc)->ascii_label),			\
3910a55fbb7Slm 		sizeof ((vtoc)->v_asciilabel)));			\
3920a55fbb7Slm 	(vtoc)->v_sanity	= VTOC_SANE;				\
3930a55fbb7Slm 	(vtoc)->v_version	= V_VERSION;				\
3940a55fbb7Slm 	(vtoc)->v_sectorsz	= (vd_vtoc)->sector_size;		\
3950a55fbb7Slm 	(vtoc)->v_nparts	= (vd_vtoc)->num_partitions;		\
3960a55fbb7Slm 	for (int i = 0; i < (vd_vtoc)->num_partitions; i++) {		\
3970a55fbb7Slm 		(vtoc)->v_part[i].p_tag	= (vd_vtoc)->partition[i].id_tag; \
3980a55fbb7Slm 		(vtoc)->v_part[i].p_flag = (vd_vtoc)->partition[i].perm; \
3990a55fbb7Slm 		(vtoc)->v_part[i].p_start = (vd_vtoc)->partition[i].start; \
4000a55fbb7Slm 		(vtoc)->v_part[i].p_size = (vd_vtoc)->partition[i].nblocks; \
4010a55fbb7Slm 	}								\
4020a55fbb7Slm }
4030a55fbb7Slm 
4040a55fbb7Slm /*
4050a55fbb7Slm  * Copy the contents of a dk_geom struct to the contents of a vd_geom_t
4060a55fbb7Slm  */
4070a55fbb7Slm #define	DK_GEOM2VD_GEOM(dk_geom, vd_geom)				\
4080a55fbb7Slm {									\
4090a55fbb7Slm 	bzero((vd_geom), sizeof (*(vd_geom)));				\
4100a55fbb7Slm 	(vd_geom)->ncyl			= (dk_geom)->dkg_ncyl;		\
4110a55fbb7Slm 	(vd_geom)->acyl			= (dk_geom)->dkg_acyl;		\
4120a55fbb7Slm 	(vd_geom)->bcyl			= (dk_geom)->dkg_bcyl;		\
4130a55fbb7Slm 	(vd_geom)->nhead		= (dk_geom)->dkg_nhead;		\
4140a55fbb7Slm 	(vd_geom)->nsect		= (dk_geom)->dkg_nsect;		\
4150a55fbb7Slm 	(vd_geom)->intrlv		= (dk_geom)->dkg_intrlv;	\
4160a55fbb7Slm 	(vd_geom)->apc			= (dk_geom)->dkg_apc;		\
4170a55fbb7Slm 	(vd_geom)->rpm			= (dk_geom)->dkg_rpm;		\
4180a55fbb7Slm 	(vd_geom)->pcyl			= (dk_geom)->dkg_pcyl;		\
4190a55fbb7Slm 	(vd_geom)->write_reinstruct	= (dk_geom)->dkg_write_reinstruct; \
4200a55fbb7Slm 	(vd_geom)->read_reinstruct	= (dk_geom)->dkg_read_reinstruct; \
4210a55fbb7Slm }
4220a55fbb7Slm 
4230a55fbb7Slm /*
4240a55fbb7Slm  * Copy the contents of a vtoc struct to the contents of a vd_vtoc_t
4250a55fbb7Slm  */
4260a55fbb7Slm #define	VTOC2VD_VTOC(vtoc, vd_vtoc)					\
4270a55fbb7Slm {									\
4280a55fbb7Slm 	bzero((vd_vtoc), sizeof (*(vd_vtoc)));				\
4290a55fbb7Slm 	bcopy((vtoc)->v_volume, (vd_vtoc)->volume_name,			\
4300a55fbb7Slm 	    MIN(sizeof ((vtoc)->v_volume),				\
4310a55fbb7Slm 		sizeof ((vd_vtoc)->volume_name)));			\
4320a55fbb7Slm 	bcopy((vtoc)->v_asciilabel, (vd_vtoc)->ascii_label,		\
4330a55fbb7Slm 	    MIN(sizeof ((vtoc)->v_asciilabel),				\
4340a55fbb7Slm 		sizeof ((vd_vtoc)->ascii_label)));			\
4350a55fbb7Slm 	(vd_vtoc)->sector_size			= (vtoc)->v_sectorsz;	\
4360a55fbb7Slm 	(vd_vtoc)->num_partitions		= (vtoc)->v_nparts;	\
4370a55fbb7Slm 	for (int i = 0; i < (vtoc)->v_nparts; i++) {			\
4380a55fbb7Slm 		(vd_vtoc)->partition[i].id_tag	= (vtoc)->v_part[i].p_tag; \
4390a55fbb7Slm 		(vd_vtoc)->partition[i].perm	= (vtoc)->v_part[i].p_flag; \
4400a55fbb7Slm 		(vd_vtoc)->partition[i].start	= (vtoc)->v_part[i].p_start; \
4410a55fbb7Slm 		(vd_vtoc)->partition[i].nblocks	= (vtoc)->v_part[i].p_size; \
4420a55fbb7Slm 	}								\
4430a55fbb7Slm }
4441ae08745Sheppo 
4454bac2208Snarayan /*
4464bac2208Snarayan  * Copy the contents of a vd_efi_t to the contents of a dk_efi_t.
4474bac2208Snarayan  * Note that (dk_efi)->dki_data and (vd_efi)->data should be correctly
4484bac2208Snarayan  * initialized prior to using this macro.
4494bac2208Snarayan  */
4504bac2208Snarayan #define	VD_EFI2DK_EFI(vd_efi, dk_efi)					\
4514bac2208Snarayan {									\
4524bac2208Snarayan 	(dk_efi)->dki_lba	= (vd_efi)->lba;			\
4534bac2208Snarayan 	(dk_efi)->dki_length	= (vd_efi)->length;			\
4544bac2208Snarayan 	bcopy((vd_efi)->data, (dk_efi)->dki_data, (dk_efi)->dki_length); \
4554bac2208Snarayan }
4564bac2208Snarayan 
4574bac2208Snarayan /*
4584bac2208Snarayan  * Copy the contents of dk_efi_t to the contents of vd_efi_t.
4594bac2208Snarayan  * Note that (dk_efi)->dki_data and (vd_efi)->data should be correctly
4604bac2208Snarayan  * initialized prior to using this macro.
4614bac2208Snarayan  */
4624bac2208Snarayan #define	DK_EFI2VD_EFI(dk_efi, vd_efi)					\
4634bac2208Snarayan {									\
4644bac2208Snarayan 	(vd_efi)->lba		= (dk_efi)->dki_lba;			\
4654bac2208Snarayan 	(vd_efi)->length	= (dk_efi)->dki_length;			\
4664bac2208Snarayan 	bcopy((dk_efi)->dki_data, (vd_efi)->data, (vd_efi)->length);	\
4674bac2208Snarayan }
4684bac2208Snarayan 
46917cadca8Slm #define	VD_MEDIATYPE2DK_MEDIATYPE(mt)					\
47017cadca8Slm 	((mt) == VD_MEDIA_FIXED ? DK_FIXED_DISK :			\
47117cadca8Slm 	    (mt) == VD_MEDIA_CD ? DK_CDROM :				\
47217cadca8Slm 	    (mt) == VD_MEDIA_DVD ? DK_DVDROM :				\
47317cadca8Slm 	    DK_UNKNOWN)
47417cadca8Slm 
47511f54b6eSAlexandre Chartre /*
47611f54b6eSAlexandre Chartre  * If the media type returned by the DKIOCGMEDIAINFO ioctl is greater than
47711f54b6eSAlexandre Chartre  * 0xFFFF then this is not an optical media and we consider that this is
47811f54b6eSAlexandre Chartre  * a fixed media.
47911f54b6eSAlexandre Chartre  *
48011f54b6eSAlexandre Chartre  * Otherwise, we have an optical media. If this is a SCSI media then the media
48111f54b6eSAlexandre Chartre  * type is actually the profile number returned by the SCSI GET CONFIGURATION
48211f54b6eSAlexandre Chartre  * command. In that case, the possible values we can have are described in the
48311f54b6eSAlexandre Chartre  * SCSI Multi-Media Commands (MMC) documentation.
48411f54b6eSAlexandre Chartre  *
48511f54b6eSAlexandre Chartre  * Not all SCSI optical media profile numbers are defined in Solaris. However
48611f54b6eSAlexandre Chartre  * undefined profiles are essentially different variants of DVD (like Blu-Ray
48711f54b6eSAlexandre Chartre  * or HD-DVD). So we consider that any optical media that we can not explicitly
48811f54b6eSAlexandre Chartre  * identify is a DVD.
48911f54b6eSAlexandre Chartre  */
49011f54b6eSAlexandre Chartre #define	DK_MEDIA_OPTICAL_MAX	0xFFFF
49111f54b6eSAlexandre Chartre 
49217cadca8Slm #define	DK_MEDIATYPE2VD_MEDIATYPE(mt)					\
49311f54b6eSAlexandre Chartre 	(((mt) > DK_MEDIA_OPTICAL_MAX)? VD_MEDIA_FIXED :		\
49411f54b6eSAlexandre Chartre 	    (mt) == DK_REMOVABLE_DISK ? VD_MEDIA_FIXED :		\
49517cadca8Slm 	    (mt) == DK_MO_ERASABLE ? VD_MEDIA_FIXED :			\
49617cadca8Slm 	    (mt) == DK_MO_WRITEONCE ? VD_MEDIA_FIXED :			\
49717cadca8Slm 	    (mt) == DK_AS_MO ? VD_MEDIA_FIXED :				\
49817cadca8Slm 	    (mt) == DK_CDROM ? VD_MEDIA_CD :				\
49917cadca8Slm 	    (mt) == DK_CDR ? VD_MEDIA_CD :				\
50017cadca8Slm 	    (mt) == DK_CDRW ? VD_MEDIA_CD :				\
50111f54b6eSAlexandre Chartre 	    VD_MEDIA_DVD)
50217cadca8Slm 
5034bac2208Snarayan /*
5044bac2208Snarayan  * Hooks for EFI support
5054bac2208Snarayan  */
5064bac2208Snarayan 
5074bac2208Snarayan /*
5084bac2208Snarayan  * The EFI alloc_and_read() function will use some ioctls to get EFI data
5094bac2208Snarayan  * but the device reference we will use is different depending if the command
5104bac2208Snarayan  * is issued from the vDisk server side (vds) or from the vDisk client side
511edcc0754Sachartre  * (vdc). The vd_efi_dev structure is filled by vdc/vds to indicate the ioctl
512edcc0754Sachartre  * function to call back and to provide information about the virtual disk.
513edcc0754Sachartre  */
514edcc0754Sachartre typedef int (*vd_efi_ioctl_func)(void *, int, uintptr_t);
515edcc0754Sachartre 
516edcc0754Sachartre typedef	struct vd_efi_dev {
517edcc0754Sachartre 	void *vdisk;			/* opaque pointer to the vdisk */
518edcc0754Sachartre 	size_t block_size;		/* vdisk block size */
519edcc0754Sachartre 	size_t disk_size;		/* vdisk size in blocks */
520edcc0754Sachartre 	vd_efi_ioctl_func vdisk_ioctl;	/* vdisk ioctl function */
521edcc0754Sachartre } vd_efi_dev_t;
522edcc0754Sachartre 
52365908c77Syu, larry liu - Sun Microsystems - Beijing China #define	VDSK_EFI_DEV_SET(efi_dev, vdsk, ioctl, bsize, dsize)	\
52465908c77Syu, larry liu - Sun Microsystems - Beijing China 	(efi_dev).vdisk = vdsk;					\
52565908c77Syu, larry liu - Sun Microsystems - Beijing China 	(efi_dev).vdisk_ioctl = ioctl;				\
52665908c77Syu, larry liu - Sun Microsystems - Beijing China 	(efi_dev).block_size = bsize;				\
52765908c77Syu, larry liu - Sun Microsystems - Beijing China 	(efi_dev).disk_size = dsize;
528edcc0754Sachartre 
529edcc0754Sachartre 
530edcc0754Sachartre int vd_efi_alloc_and_read(vd_efi_dev_t *dev, efi_gpt_t **gpt, efi_gpe_t **gpe);
531edcc0754Sachartre void vd_efi_free(vd_efi_dev_t *dev, efi_gpt_t *gpt, efi_gpe_t *gpe);
5324bac2208Snarayan 
533366a92acSlm /*
534*bbf21555SRichard Lowe  * Macros to update the I/O statistics kstat consumed by iostat(8).
535366a92acSlm  */
536366a92acSlm 
537366a92acSlm /*
538366a92acSlm  * Given a pointer to the instance private data of a vDisk driver (vd),
539366a92acSlm  * the type of operation and the number of bytes read/written, this macro
540366a92acSlm  * updates the I/O statistics in the kstat.
541366a92acSlm  */
542366a92acSlm #define	VD_UPDATE_IO_STATS(vd, op, len)					\
543366a92acSlm 	{								\
544366a92acSlm 		ASSERT((vd) != NULL);					\
545366a92acSlm 		ASSERT(MUTEX_HELD(&(vd)->lock));			\
546366a92acSlm 		ASSERT(((op) == VD_OP_BREAD) || ((op) == VD_OP_BWRITE));\
547366a92acSlm 		if ((vd)->io_stats != NULL) { 				\
548366a92acSlm 			kstat_io_t *kip = KSTAT_IO_PTR((vd)->io_stats);	\
549366a92acSlm 			if ((op) == VD_OP_BREAD) {			\
550366a92acSlm 				kip->reads++;				\
551366a92acSlm 				kip->nread += (len);			\
552366a92acSlm 			} else {					\
553366a92acSlm 				kip->writes++;				\
554366a92acSlm 				kip->nwritten += (len);			\
555366a92acSlm 			}						\
556366a92acSlm 		}							\
557366a92acSlm 	}
558366a92acSlm 
559366a92acSlm /*
560366a92acSlm  * These wrapper macros take a pointer to the I/O statistics kstat and
561366a92acSlm  * update the queue length statistics. These are 'safe' wrappers which
562366a92acSlm  * check to see if the kstat was created when the vDisk instance was
563366a92acSlm  * added (i.e. is not NULL).
564366a92acSlm  */
56590e2f9dcSlm #define	VD_KSTAT_WAITQ_ENTER(vd)					\
56690e2f9dcSlm 	if ((vd)->io_stats != NULL) {					\
56790e2f9dcSlm 		ASSERT(MUTEX_HELD(&(vd)->lock));			\
56890e2f9dcSlm 		kstat_waitq_enter(KSTAT_IO_PTR((vd)->io_stats));	\
569366a92acSlm 	}
570366a92acSlm 
57190e2f9dcSlm #define	VD_KSTAT_WAITQ_EXIT(vd)						\
57290e2f9dcSlm 	if ((vd)->io_stats != NULL) {					\
57390e2f9dcSlm 		ASSERT(MUTEX_HELD(&(vd)->lock));			\
57490e2f9dcSlm 		kstat_waitq_exit(KSTAT_IO_PTR((vd)->io_stats));		\
575366a92acSlm 	}
576366a92acSlm 
57790e2f9dcSlm #define	VD_KSTAT_WAITQ_TO_RUNQ(vd)					\
57890e2f9dcSlm 	if ((vd)->io_stats != NULL) {					\
57990e2f9dcSlm 		ASSERT(MUTEX_HELD(&(vd)->lock));			\
58090e2f9dcSlm 		kstat_waitq_to_runq(KSTAT_IO_PTR((vd)->io_stats));	\
581366a92acSlm 	}
582366a92acSlm 
583ca6d1280SAlexandre Chartre #define	VD_KSTAT_RUNQ_BACK_TO_WAITQ(vd)					\
584ca6d1280SAlexandre Chartre 	if ((vd)->io_stats != NULL) {					\
585ca6d1280SAlexandre Chartre 		ASSERT(MUTEX_HELD(&(vd)->lock));			\
586ca6d1280SAlexandre Chartre 		kstat_runq_back_to_waitq(KSTAT_IO_PTR((vd)->io_stats));	\
587ca6d1280SAlexandre Chartre 	}
588ca6d1280SAlexandre Chartre 
58990e2f9dcSlm #define	VD_KSTAT_RUNQ_ENTER(vd)						\
59090e2f9dcSlm 	if ((vd)->io_stats != NULL) {					\
59190e2f9dcSlm 		ASSERT(MUTEX_HELD(&(vd)->lock));			\
59290e2f9dcSlm 		kstat_runq_enter(KSTAT_IO_PTR((vd)->io_stats));		\
593366a92acSlm 	}
594366a92acSlm 
59590e2f9dcSlm #define	VD_KSTAT_RUNQ_EXIT(vd)						\
59690e2f9dcSlm 	if ((vd)->io_stats != NULL) {					\
59790e2f9dcSlm 		ASSERT(MUTEX_HELD(&(vd)->lock));			\
59890e2f9dcSlm 		kstat_runq_exit(KSTAT_IO_PTR((vd)->io_stats));		\
599366a92acSlm 	}
600366a92acSlm 
601366a92acSlm /*
602366a92acSlm  * Given a pointer to the instance private data of a vDisk driver (vd) and
603366a92acSlm  * the name of the error stats entry we wish to update, increment that value
604366a92acSlm  */
605366a92acSlm #define	VD_UPDATE_ERR_STATS(vd, stat_entry)				\
606366a92acSlm {									\
607366a92acSlm 	ASSERT((vd) != NULL);						\
608366a92acSlm 	ASSERT(MUTEX_HELD(&(vd)->lock));				\
609366a92acSlm 	if ((vd)->err_stats != NULL) {					\
610366a92acSlm 		vd_err_stats_t	*stp;					\
611366a92acSlm 		stp = (vd_err_stats_t *)(vd)->err_stats->ks_data;	\
612366a92acSlm 		stp->stat_entry.value.ui32++;				\
613366a92acSlm 	}								\
614366a92acSlm }
615366a92acSlm 
616366a92acSlm /* Structure to record vDisk error statistics */
617366a92acSlm typedef struct vd_err_stats {
618366a92acSlm 	struct kstat_named	vd_softerrs;	/* Softerrs */
619366a92acSlm 	struct kstat_named	vd_transerrs;	/* Transport errs */
620366a92acSlm 	struct kstat_named	vd_protoerrs;	/* VIO Protocol errs */
621366a92acSlm 	struct kstat_named	vd_vid;		/* Vendor ID */
622366a92acSlm 	struct kstat_named	vd_pid;		/* Product ID */
623366a92acSlm 	struct kstat_named	vd_capacity;	/* Capacity of the disk */
624366a92acSlm } vd_err_stats_t;
625366a92acSlm 
6261ae08745Sheppo 
6271ae08745Sheppo #ifdef	__cplusplus
6281ae08745Sheppo }
6291ae08745Sheppo #endif
6301ae08745Sheppo 
6311ae08745Sheppo #endif	/* _VDSK_COMMON_H */
632