xref: /titanic_44/usr/src/uts/sun4v/sys/vdsk_common.h (revision fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bb)
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 2007 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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 #ifdef __cplusplus
33 extern "C" {
34 #endif
35 
36 /*
37  * This header file contains the private LDoms Virtual Disk (vDisk) definitions
38  * common to both the server (vds) and the client (vdc)
39  */
40 
41 #include <sys/efi_partition.h>
42 #include <sys/machparam.h>
43 #include <sys/vtoc.h>
44 
45 #include <sys/ldc.h>
46 #include <sys/vio_common.h>
47 #include <sys/vio_mailbox.h>
48 
49 /*
50  * vDisk definitions
51  */
52 
53 /*
54  * The number of Descriptor Ring entries
55  *
56  * Constraints:
57  * 	- overall DRing size must be greater than 8K (MMU_PAGESIZE)
58  *	- overall DRing size should be 8K aligned (desirable but not enforced)
59  *	- DRing entry must be 8 byte aligned
60  */
61 #define	VD_DRING_LEN		512
62 
63 /*
64  *
65  */
66 #define	VD_DRING_ENTRY_SZ	(sizeof (vd_dring_entry_t) + 		\
67 		(sizeof (ldc_mem_cookie_t) * (VD_MAX_COOKIES - 1)))
68 
69 /*
70  * The maximum block size we can transmit using one Descriptor Ring entry
71  *
72  * Currently no FS uses more than 128K and it doesn't look like they
73  * will either as there is no perf gain to be had by larger values.
74  * ( see ZFS comment at definition of SPA_MAXBLOCKSIZE ).
75  *
76  * We choose 256K to give us some headroom.
77  */
78 #define	VD_MAX_BLOCK_SIZE	(256 * 1024)
79 
80 #define	VD_MAX_COOKIES		((VD_MAX_BLOCK_SIZE / PAGESIZE) + 1)
81 #define	VD_USEC_TIMEOUT		20000
82 #define	VD_LDC_IDS_PROP		"ldc-ids"
83 #define	VD_LDC_MTU		256
84 
85 /*
86  * Flags used by ioctl routines to indicate if a copyin/copyout is needed
87  */
88 #define	VD_COPYOUT		0x1
89 #define	VD_COPYIN		0x2
90 
91 /*
92  * vDisk operations on physical devices
93  */
94 #define	VD_OP_BREAD		0x01	/* Block Read */
95 #define	VD_OP_BWRITE		0x02	/* Block Write */
96 #define	VD_OP_FLUSH		0x03	/* Flush disk write cache contents */
97 #define	VD_OP_GET_WCE		0x04	/* Get disk W$ status */
98 #define	VD_OP_SET_WCE		0x05	/* Enable/Disable disk W$ */
99 #define	VD_OP_GET_VTOC		0x06	/* Get VTOC */
100 #define	VD_OP_SET_VTOC		0x07	/* Set VTOC */
101 #define	VD_OP_GET_DISKGEOM	0x08	/* Get disk geometry */
102 #define	VD_OP_SET_DISKGEOM	0x09	/* Set disk geometry */
103 #define	VD_OP_SCSICMD		0x0a	/* SCSI control command */
104 #define	VD_OP_GET_DEVID		0x0b	/* Get device id */
105 #define	VD_OP_GET_EFI 		0x0c	/* Get EFI */
106 #define	VD_OP_SET_EFI 		0x0d	/* Set EFI */
107 #define	VD_OP_MASK		0xFF	/* mask of all possible operations */
108 #define	VD_OP_COUNT		13	/* Number of operations */
109 
110 /*
111  * This is a mask of all the basic operations supported by all
112  * disk types (v1.0).
113  */
114 #define	VD_OP_MASK_READ			\
115 	((1 << VD_OP_BREAD) |			\
116 	(1 << VD_OP_GET_WCE) |			\
117 	(1 << VD_OP_GET_VTOC) |			\
118 	(1 << VD_OP_GET_DISKGEOM) |		\
119 	(1 << VD_OP_GET_DEVID) |		\
120 	(1 << VD_OP_GET_EFI))
121 
122 #define	VD_OP_MASK_WRITE			\
123 	((1 << VD_OP_BWRITE) |			\
124 	(1 << VD_OP_FLUSH) |			\
125 	(1 << VD_OP_SET_WCE) |			\
126 	(1 << VD_OP_SET_VTOC) |			\
127 	(1 << VD_OP_SET_DISKGEOM) |		\
128 	(1 << VD_OP_SET_EFI))
129 
130 
131 /*
132  * macro to check if the operation 'op' is supported by checking the list
133  * of operations supported which is exported by the vDisk server.
134  */
135 #define	VD_OP_SUPPORTED(ops_bitmask, op)	((ops_bitmask) & (1 << (op)))
136 
137 /*
138  * Slice for absolute disk transaction.
139  */
140 #define	VD_SLICE_NONE		0xFF
141 
142 /*
143  * EFI disks do not have a slice 7. Actually that slice is used to represent
144  * the whole disk.
145  */
146 #define	VD_EFI_WD_SLICE	7
147 
148 /*
149  * Definitions of the various ways vds can export disk support to vdc.
150  */
151 typedef enum vd_disk_type {
152 	VD_DISK_TYPE_UNK = 0,		/* Unknown device type */
153 	VD_DISK_TYPE_SLICE,		/* slice in block device */
154 	VD_DISK_TYPE_DISK		/* entire disk (slice 2) */
155 } vd_disk_type_t;
156 
157 /*
158  * Definitions of the various disk label that vDisk supports.
159  */
160 typedef enum vd_disk_label {
161 	VD_DISK_LABEL_UNK = 0,		/* Unknown disk label */
162 	VD_DISK_LABEL_VTOC,		/* VTOC disk label */
163 	VD_DISK_LABEL_EFI		/* EFI disk label */
164 } vd_disk_label_t;
165 
166 /*
167  * vDisk Descriptor payload
168  */
169 typedef struct vd_dring_payload {
170 	uint64_t	req_id;		/* The request ID being processed */
171 	uint8_t		operation;	/* operation for server to perform */
172 	uint8_t		slice;		/* The disk slice being accessed */
173 	uint16_t	resv1;		/* padding */
174 	uint32_t	status;		/* "errno" of server operation */
175 	uint64_t	addr;		/* LP64	diskaddr_t (block I/O) */
176 	uint64_t	nbytes;		/* LP64 size_t */
177 	uint32_t	ncookies;	/* Number of cookies used */
178 	uint32_t	resv2;		/* padding */
179 
180 	ldc_mem_cookie_t	cookie[1];	/* variable sized array */
181 } vd_dring_payload_t;
182 
183 
184 /*
185  * vDisk Descriptor entry
186  */
187 typedef struct vd_dring_entry {
188 	vio_dring_entry_hdr_t		hdr;		/* common header */
189 	vd_dring_payload_t		payload;	/* disk specific data */
190 } vd_dring_entry_t;
191 
192 
193 /*
194  * vDisk control operation structures
195  */
196 
197 /*
198  * vDisk geometry definition (VD_OP_GET_DISKGEOM and VD_OP_SET_DISKGEOM)
199  */
200 typedef struct vd_geom {
201 	uint16_t	ncyl;		/* number of data cylinders */
202 	uint16_t	acyl;		/* number of alternate cylinders */
203 	uint16_t	bcyl;		/* cyl offset for fixed head area */
204 	uint16_t	nhead;		/* number of heads */
205 	uint16_t	nsect;		/* number of data sectors per track */
206 	uint16_t	intrlv;		/* interleave factor */
207 	uint16_t	apc;		/* alternates per cyl (SCSI only) */
208 	uint16_t	rpm;		/* revolutions per minute */
209 	uint16_t	pcyl;		/* number of physical cylinders */
210 	uint16_t	write_reinstruct;	/* # sectors to skip, writes */
211 	uint16_t	read_reinstruct;	/* # sectors to skip, reads */
212 } vd_geom_t;
213 
214 
215 /*
216  * vDisk partition definition
217  */
218 typedef struct vd_partition {
219 	uint16_t	id_tag;		/* ID tag of partition */
220 	uint16_t	perm;		/* permission flags for partition */
221 	uint32_t	reserved;	/* padding */
222 	uint64_t	start;		/* block number of partition start */
223 	uint64_t	nblocks;	/* number of blocks in partition */
224 } vd_partition_t;
225 
226 /*
227  * vDisk VTOC definition (VD_OP_GET_VTOC and VD_OP_SET_VTOC)
228  */
229 #define	VD_VOLNAME_LEN		8	/* length of volume_name field */
230 #define	VD_ASCIILABEL_LEN	128	/* length of ascii_label field */
231 typedef struct vd_vtoc {
232 	char		volume_name[VD_VOLNAME_LEN];	/* volume name */
233 	uint16_t	sector_size;		/* sector size in bytes */
234 	uint16_t	num_partitions;		/* number of partitions */
235 	char		ascii_label[VD_ASCIILABEL_LEN];	/* ASCII label */
236 	vd_partition_t	partition[V_NUMPAR];	/* partition headers */
237 } vd_vtoc_t;
238 
239 
240 /*
241  * vDisk EFI definition (VD_OP_GET_EFI and VD_OP_SET_EFI)
242  */
243 typedef struct vd_efi {
244 	uint64_t	lba;		/* lba of the request */
245 	uint64_t	length;		/* length of data */
246 	char		data[1];	/* data of the request */
247 } vd_efi_t;
248 
249 
250 /*
251  * vDisk DEVID definition (VD_OP_GET_DEVID)
252  */
253 #define	VD_DEVID_SIZE(l)	(sizeof (vd_devid_t) - 1 + l)
254 #define	VD_DEVID_DEFAULT_LEN	128
255 
256 typedef struct vd_devid {
257 	uint16_t	reserved;	/* padding */
258 	uint16_t	type;		/* type of device id */
259 	uint32_t	length;		/* length the device id */
260 	char		id[1];		/* device id */
261 } vd_devid_t;
262 
263 /*
264  * Copy the contents of a vd_geom_t to the contents of a dk_geom struct
265  */
266 #define	VD_GEOM2DK_GEOM(vd_geom, dk_geom)				\
267 {									\
268 	bzero((dk_geom), sizeof (*(dk_geom)));				\
269 	(dk_geom)->dkg_ncyl		= (vd_geom)->ncyl;		\
270 	(dk_geom)->dkg_acyl		= (vd_geom)->acyl;		\
271 	(dk_geom)->dkg_bcyl		= (vd_geom)->bcyl;		\
272 	(dk_geom)->dkg_nhead		= (vd_geom)->nhead;		\
273 	(dk_geom)->dkg_nsect		= (vd_geom)->nsect;		\
274 	(dk_geom)->dkg_intrlv		= (vd_geom)->intrlv;		\
275 	(dk_geom)->dkg_apc		= (vd_geom)->apc;		\
276 	(dk_geom)->dkg_rpm		= (vd_geom)->rpm;		\
277 	(dk_geom)->dkg_pcyl		= (vd_geom)->pcyl;		\
278 	(dk_geom)->dkg_write_reinstruct	= (vd_geom)->write_reinstruct;	\
279 	(dk_geom)->dkg_read_reinstruct	= (vd_geom)->read_reinstruct;	\
280 }
281 
282 /*
283  * Copy the contents of a vd_vtoc_t to the contents of a vtoc struct
284  */
285 #define	VD_VTOC2VTOC(vd_vtoc, vtoc)					\
286 {									\
287 	bzero((vtoc), sizeof (*(vtoc)));				\
288 	bcopy((vd_vtoc)->volume_name, (vtoc)->v_volume,			\
289 	    MIN(sizeof ((vd_vtoc)->volume_name),			\
290 		sizeof ((vtoc)->v_volume)));				\
291 	bcopy((vd_vtoc)->ascii_label, (vtoc)->v_asciilabel,		\
292 	    MIN(sizeof ((vd_vtoc)->ascii_label),			\
293 		sizeof ((vtoc)->v_asciilabel)));			\
294 	(vtoc)->v_sanity	= VTOC_SANE;				\
295 	(vtoc)->v_version	= V_VERSION;				\
296 	(vtoc)->v_sectorsz	= (vd_vtoc)->sector_size;		\
297 	(vtoc)->v_nparts	= (vd_vtoc)->num_partitions;		\
298 	for (int i = 0; i < (vd_vtoc)->num_partitions; i++) {		\
299 		(vtoc)->v_part[i].p_tag	= (vd_vtoc)->partition[i].id_tag; \
300 		(vtoc)->v_part[i].p_flag = (vd_vtoc)->partition[i].perm; \
301 		(vtoc)->v_part[i].p_start = (vd_vtoc)->partition[i].start; \
302 		(vtoc)->v_part[i].p_size = (vd_vtoc)->partition[i].nblocks; \
303 	}								\
304 }
305 
306 /*
307  * Copy the contents of a dk_geom struct to the contents of a vd_geom_t
308  */
309 #define	DK_GEOM2VD_GEOM(dk_geom, vd_geom)				\
310 {									\
311 	bzero((vd_geom), sizeof (*(vd_geom)));				\
312 	(vd_geom)->ncyl			= (dk_geom)->dkg_ncyl;		\
313 	(vd_geom)->acyl			= (dk_geom)->dkg_acyl;		\
314 	(vd_geom)->bcyl			= (dk_geom)->dkg_bcyl;		\
315 	(vd_geom)->nhead		= (dk_geom)->dkg_nhead;		\
316 	(vd_geom)->nsect		= (dk_geom)->dkg_nsect;		\
317 	(vd_geom)->intrlv		= (dk_geom)->dkg_intrlv;	\
318 	(vd_geom)->apc			= (dk_geom)->dkg_apc;		\
319 	(vd_geom)->rpm			= (dk_geom)->dkg_rpm;		\
320 	(vd_geom)->pcyl			= (dk_geom)->dkg_pcyl;		\
321 	(vd_geom)->write_reinstruct	= (dk_geom)->dkg_write_reinstruct; \
322 	(vd_geom)->read_reinstruct	= (dk_geom)->dkg_read_reinstruct; \
323 }
324 
325 /*
326  * Copy the contents of a vtoc struct to the contents of a vd_vtoc_t
327  */
328 #define	VTOC2VD_VTOC(vtoc, vd_vtoc)					\
329 {									\
330 	bzero((vd_vtoc), sizeof (*(vd_vtoc)));				\
331 	bcopy((vtoc)->v_volume, (vd_vtoc)->volume_name,			\
332 	    MIN(sizeof ((vtoc)->v_volume),				\
333 		sizeof ((vd_vtoc)->volume_name)));			\
334 	bcopy((vtoc)->v_asciilabel, (vd_vtoc)->ascii_label,		\
335 	    MIN(sizeof ((vtoc)->v_asciilabel),				\
336 		sizeof ((vd_vtoc)->ascii_label)));			\
337 	(vd_vtoc)->sector_size			= (vtoc)->v_sectorsz;	\
338 	(vd_vtoc)->num_partitions		= (vtoc)->v_nparts;	\
339 	for (int i = 0; i < (vtoc)->v_nparts; i++) {			\
340 		(vd_vtoc)->partition[i].id_tag	= (vtoc)->v_part[i].p_tag; \
341 		(vd_vtoc)->partition[i].perm	= (vtoc)->v_part[i].p_flag; \
342 		(vd_vtoc)->partition[i].start	= (vtoc)->v_part[i].p_start; \
343 		(vd_vtoc)->partition[i].nblocks	= (vtoc)->v_part[i].p_size; \
344 	}								\
345 }
346 
347 /*
348  * Copy the contents of a vd_efi_t to the contents of a dk_efi_t.
349  * Note that (dk_efi)->dki_data and (vd_efi)->data should be correctly
350  * initialized prior to using this macro.
351  */
352 #define	VD_EFI2DK_EFI(vd_efi, dk_efi)					\
353 {									\
354 	(dk_efi)->dki_lba	= (vd_efi)->lba;			\
355 	(dk_efi)->dki_length	= (vd_efi)->length;			\
356 	bcopy((vd_efi)->data, (dk_efi)->dki_data, (dk_efi)->dki_length); \
357 }
358 
359 /*
360  * Copy the contents of dk_efi_t to the contents of vd_efi_t.
361  * Note that (dk_efi)->dki_data and (vd_efi)->data should be correctly
362  * initialized prior to using this macro.
363  */
364 #define	DK_EFI2VD_EFI(dk_efi, vd_efi)					\
365 {									\
366 	(vd_efi)->lba		= (dk_efi)->dki_lba;			\
367 	(vd_efi)->length	= (dk_efi)->dki_length;			\
368 	bcopy((dk_efi)->dki_data, (vd_efi)->data, (vd_efi)->length);	\
369 }
370 
371 #define	VD_MEDIATYPE2DK_MEDIATYPE(mt)					\
372 	((mt) == VD_MEDIA_FIXED ? DK_FIXED_DISK :			\
373 	    (mt) == VD_MEDIA_CD ? DK_CDROM :				\
374 	    (mt) == VD_MEDIA_DVD ? DK_DVDROM :				\
375 	    DK_UNKNOWN)
376 
377 #define	DK_MEDIATYPE2VD_MEDIATYPE(mt)					\
378 	((mt) == DK_REMOVABLE_DISK ? VD_MEDIA_FIXED :			\
379 	    (mt) == DK_MO_ERASABLE ? VD_MEDIA_FIXED :			\
380 	    (mt) == DK_MO_WRITEONCE ? VD_MEDIA_FIXED :			\
381 	    (mt) == DK_AS_MO ? VD_MEDIA_FIXED :				\
382 	    (mt) == DK_CDROM ? VD_MEDIA_CD :				\
383 	    (mt) == DK_CDR ? VD_MEDIA_CD :				\
384 	    (mt) == DK_CDRW ? VD_MEDIA_CD :				\
385 	    (mt) == DK_DVDROM ? VD_MEDIA_DVD :				\
386 	    (mt) == DK_DVDR ? VD_MEDIA_DVD :				\
387 	    (mt) == DK_DVDRAM ? VD_MEDIA_DVD :				\
388 	    (mt) == DK_FIXED_DISK ? VD_MEDIA_FIXED :			\
389 	    (mt) == DK_FLOPPY ? VD_MEDIA_FIXED :			\
390 	    (mt) == DK_ZIP ? VD_MEDIA_FIXED :				\
391 	    (mt) == DK_JAZ ? VD_MEDIA_FIXED :				\
392 	    VD_MEDIA_FIXED)
393 
394 /*
395  * Hooks for EFI support
396  */
397 
398 /*
399  * The EFI alloc_and_read() function will use some ioctls to get EFI data
400  * but the device reference we will use is different depending if the command
401  * is issued from the vDisk server side (vds) or from the vDisk client side
402  * (vdc). From the server side (vds), we will have a layered device reference
403  * (ldi_handle_t) while on the client side (vdc) we will have a regular device
404  * reference (dev_t).
405  */
406 #ifdef _SUN4V_VDS
407 int vds_efi_alloc_and_read(ldi_handle_t dev, struct dk_gpt **vtoc,
408     size_t *vtoc_len);
409 #else
410 void vdc_efi_init(int (*func)(dev_t, int, caddr_t, int));
411 void vdc_efi_fini(void);
412 int vdc_efi_alloc_and_read(dev_t dev, struct dk_gpt **vtoc,
413     size_t *vtoc_len);
414 #endif
415 
416 void vd_efi_free(struct dk_gpt *ptr, size_t length);
417 void vd_efi_to_vtoc(struct dk_gpt *efi, struct vtoc *vtoc);
418 
419 #ifdef	__cplusplus
420 }
421 #endif
422 
423 #endif	/* _VDSK_COMMON_H */
424