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