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